Skip to content

Commit

Permalink
feat: add NUMERIC column support
Browse files Browse the repository at this point in the history
  • Loading branch information
taka-oyama committed Nov 28, 2023
1 parent 062a5f5 commit 363b747
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/Query/Processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace Colopl\Spanner\Query;

use Google\Cloud\Spanner\Numeric;
use Google\Cloud\Spanner\Timestamp;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\Processors\Processor as BaseProcessor;
Expand All @@ -37,6 +38,9 @@ public function processSelect(Builder $query, $results): array
$dt->setTimezone(date_default_timezone_get());
$results[$index][$k] = $dt;
}
if ($v instanceof Numeric) {
$results[$index][$k] = $v->formatAsString();
}
}
}
return $results;
Expand Down
35 changes: 35 additions & 0 deletions src/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,30 @@ public function binary($column, $length = null)
return $this->addColumn('binary', $column, compact('length'));
}

/**
* @param string $column
* @param int $total
* @param int $places
* @param bool $unsigned
* @return ColumnDefinition
*/
public function decimal($column, $total = 38, $places = 9, $unsigned = false)
{
if ($total !== 38) {
$this->markAsNotSupported('decimal with precision other than 38');
}

if ($places !== 9) {
$this->markAsNotSupported('decimal with scale other than 9');
}

if ($unsigned) {
$this->markAsNotSupported('unsigned decimal');
}

return parent::decimal($column, $total, $places, $unsigned);
}

/**
* @param string $column
* @return ColumnDefinition
Expand Down Expand Up @@ -140,6 +164,17 @@ public function floatArray($column)
]);
}

/**
* @param string $column
* @return ColumnDefinition
*/
public function decimalArray($column)
{
return $this->addColumn('array', $column, [
'arrayType' => 'decimal'
]);
}

/**
* @param string $column
* @param int|string|null $length
Expand Down
23 changes: 23 additions & 0 deletions src/Schema/Grammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,17 @@ protected function typeDouble(Fluent $column)
return 'float64';
}

/**
* Create the column definition for a decimal type.
*
* @param Fluent<string, mixed> $column
* @return string
*/
protected function typeDecimal(Fluent $column)
{
return "numeric";
}

/**
* Create the column definition for a date type.
*
Expand Down Expand Up @@ -555,6 +566,7 @@ protected function formatDefaultValue(Fluent $column, string $type, mixed $value
'bool' => $this->formatBoolValue($column, $value),
'date' => $this->formatDateValue($column, $value),
'float64' => $this->formatFloatValue($column, $value),
'numeric' => $this->formatNumericValue($column, $value),
'int64' => $this->formatIntValue($column, $value),
'string' => $this->formatStringValue($column, $value),
'timestamp' => $this->formatTimestampValue($column, $value),
Expand Down Expand Up @@ -613,6 +625,17 @@ protected function formatFloatValue(Fluent $column, mixed $value): string
return (string)$value;
}

/**
* @param Fluent<string, mixed> $column
* @param mixed $value
* @return string
*/
protected function formatNumericValue(Fluent $column, mixed $value): string
{
assert(is_numeric($value));
return (string)$value;
}

/**
* @param Fluent<string, mixed> $column
* @param mixed $value
Expand Down
21 changes: 17 additions & 4 deletions tests/Query/BuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,17 @@
namespace Colopl\Spanner\Tests\Query;

use BadMethodCallException;
use Colopl\Spanner\Connection;
use Colopl\Spanner\Query\Builder;
use Colopl\Spanner\Schema\Blueprint;
use Colopl\Spanner\Tests\TestCase;
use Colopl\Spanner\TimestampBound\ExactStaleness;
use Google\Cloud\Spanner\Bytes;
use Google\Cloud\Spanner\Duration;
use Google\Cloud\Spanner\Numeric;
use Illuminate\Support\Str;
use const Grpc\STATUS_ALREADY_EXISTS;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Database\QueryException;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use const Grpc\STATUS_ALREADY_EXISTS;

class BuilderTest extends TestCase
{
Expand Down Expand Up @@ -428,6 +426,21 @@ public function testInterleaveTable(): void
$this->assertDatabaseMissing($childTableName, $childUserItems[0]);
}

public function test_insert_numeric_types(): void
{
$conn = $this->getDefaultConnection();
$tableName = self::TABLE_NAME_TEST;
$qb = $conn->table($tableName);

$row = $this->generateTestRow();
$qb->insert($row);

$insertedRow = $qb->get()->first();
$numeric = $insertedRow['numericTest'];
$this->assertSame('123.456', $numeric);
$this->assertNull($insertedRow['nullableNumericTest']);
}

public function testInsertDatetime(): void
{
date_default_timezone_set('Asia/Tokyo');
Expand Down
6 changes: 6 additions & 0 deletions tests/Schema/BlueprintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function testCreateTable(): void
$table->uuid('id');
$table->integer('int');
$table->float('float');
$table->decimal('decimal');
$table->string('name');
$table->text('text');
$table->dateTime('started_at');
Expand All @@ -52,6 +53,7 @@ public function testCreateTable(): void
'`id` string(36) not null',
'`int` int64 not null',
'`float` float64 not null',
'`decimal` numeric not null',
'`name` string(255) not null',
'`text` string(max) not null',
'`started_at` timestamp not null',
Expand Down Expand Up @@ -218,6 +220,7 @@ public function test_array_types(): void
$table->integerArray('int_array')->nullable();
$table->booleanArray('bool_array')->nullable();
$table->floatArray('float_array')->nullable();
$table->decimalArray('decimal_array')->nullable();
$table->stringArray('string_array_undef')->nullable();
$table->stringArray('string_array_1', 1)->nullable();
$table->stringArray('string_array_max', 'max')->nullable();
Expand All @@ -234,6 +237,7 @@ public function test_array_types(): void
'`int_array` array<int64>',
'`bool_array` array<bool>',
'`float_array` array<float64>',
'`decimal_array` array<numeric>',
'`string_array_undef` array<string(255)>',
'`string_array_1` array<string(1)>',
'`string_array_max` array<string(max)>',
Expand Down Expand Up @@ -405,6 +409,7 @@ public function test_default_values(): void
$table->bigInteger('bigint')->default(1);
$table->float('float')->default(0.1);
$table->double('double')->default(0.1);
$table->decimal('decimal')->default(123.456);
$table->boolean('bool')->default(true);
$table->string('string')->default('a');
$table->text('string_max')->default('a');
Expand Down Expand Up @@ -436,6 +441,7 @@ public function test_default_values(): void
'`bigint` int64 not null default (1)',
'`float` float64 not null default (0.1)',
'`double` float64 not null default (0.1)',
'`decimal` numeric not null default (123.456)',
'`bool` bool not null default (true)',
'`string` string(255) not null default ("a")',
'`string_max` string(max) not null default ("a")',
Expand Down
3 changes: 3 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Colopl\Spanner\SpannerServiceProvider;
use Google\Cloud\Spanner\Bytes;
use Google\Cloud\Spanner\Date;
use Google\Cloud\Spanner\Numeric;
use Google\Cloud\Spanner\SpannerClient;
use Illuminate\Foundation\Application;
use Ramsey\Uuid\Uuid;
Expand Down Expand Up @@ -62,6 +63,8 @@ protected function generateTestRow(): array
'nullableIntTest' => null,
'floatTest' => 123.456,
'nullableFloatTest' => null,
'numericTest' => new Numeric('123.456'),
'nullableNumericTest' => null,
'timestampTest' => new \DateTimeImmutable(),
'nullableTimestampTest' => null,
'dateTest' => new Date(new \DateTimeImmutable()),
Expand Down
2 changes: 2 additions & 0 deletions tests/test.ddl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ CREATE TABLE `Test` (
`nullableIntTest` INT64,
`floatTest` FLOAT64 NOT NULL,
`nullableFloatTest` FLOAT64,
`numericTest` NUMERIC NOT NULL,
`nullableNumericTest` NUMERIC,
`timestampTest` TIMESTAMP NOT NULL,
`nullableTimestampTest` TIMESTAMP,
`dateTest` DATE NOT NULL,
Expand Down

0 comments on commit 363b747

Please sign in to comment.