Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,20 @@ For more detailed instructions, see `Colopl\Spanner\Tests\Eloquent\ModelTest`.

### Migrations

Since Cloud Spanner does not support AUTO_INCREMENT attribute, `Blueprint::increments` (and all of its variants) will
create a column of type `STRING(36) DEFAULT (GENERATE_UUID())` to generate and fill the column with a UUID
and flag it as a primary key.
Since Spanner recommends using UUID as a primary key, `Blueprint::increments` (and all of its variants) will create a
column of type `STRING(36) DEFAULT (GENERATE_UUID())` to generate and fill the column with a UUID
and flag it as a primary key. If you want to use `AUTO_INCREMENT`, you can do so by specifying it directly like this:

```php
// `default_sequence_kind` must be set in order to use auto increment
$schemaBuilder->setDatabaseOptions([
'default_sequence_kind' => 'bit_reversed_positive',
]);

$schemaBuilder->create('user', function (Blueprint $table) {
$table->integer('id')->primary()->autoIncrement();
});
```

### Transactions
Google Cloud Spanner sometimes requests transaction retries (e.g. `UNAVAILABLE`, and `ABORTED`), even if the logic is correct. For that reason, please do not manage transactions manually.
Expand Down
2 changes: 1 addition & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ services:
depends_on:
- emulator
emulator:
image: "gcr.io/cloud-spanner-emulator/emulator:1.5.30"
image: "gcr.io/cloud-spanner-emulator/emulator:1.5.33"
3 changes: 1 addition & 2 deletions src/Schema/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
use Illuminate\Database\Schema\Blueprint as BaseBlueprint;
use Illuminate\Database\Schema\ColumnDefinition;
use Illuminate\Support\Fluent;
use LogicException;

/**
* @method IndexDefinition index(string|string[] $columns, string|null $name = null)
Expand All @@ -37,7 +36,7 @@ class Blueprint extends BaseBlueprint
*/
public function bigInteger($column, $autoIncrement = false, $unsigned = false): IntColumnDefinition
{
$definition = new IntColumnDefinition($this, ['type' => __FUNCTION__, 'name' => $column]);
$definition = new IntColumnDefinition($this, ['type' => __FUNCTION__, 'name' => $column, 'autoIncrement' => $autoIncrement]);
$this->addColumnDefinition($definition);
return $definition;
}
Expand Down
19 changes: 19 additions & 0 deletions src/Schema/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
use Closure;
use Colopl\Spanner\Connection;
use Illuminate\Database\Schema\Builder as BaseBuilder;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

/**
* @property Grammar $grammar
Expand All @@ -40,6 +42,23 @@ class Builder extends BaseBuilder
*/
public static $defaultMorphKeyType = 'uuid';

/**
* @param array<string, scalar|null> $options
* @return void
*/
public function setDatabaseOptions(array $options): void
{
$connection = $this->connection;
$name = Str::afterLast($connection->getDatabaseName(), '/');
$line = implode(', ', Arr::map($options, fn($v, $k) => "$k = " . match (true) {
is_null($v) => 'null',
is_bool($v) => $v ? 'true' : 'false',
is_string($v) => $this->grammar->quoteString($v),
default => $v,
}));
$connection->statement("ALTER DATABASE `{$name}` SET OPTIONS ({$line})");
}

/**
* @deprecated Use Blueprint::dropIndex() instead. Will be removed in v10.0.
*
Expand Down
3 changes: 3 additions & 0 deletions src/Schema/ColumnDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,13 @@
* @property int|null $precision
* @property int|null $scale
* @property bool|null $useCurrent
* @property bool|null $autoIncrement
* @property string|Expression|true|null $generatedAs
* @property string|null $virtualAs
* @property bool|null $storedAs
* @property int|null $startingValue
* @property bool|null $primary
* @property bool|null $change
*/
class ColumnDefinition extends BaseColumnDefinition
{
Expand Down
21 changes: 19 additions & 2 deletions src/Schema/Grammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
use Colopl\Spanner\Concerns\SharedGrammarCalls;
use DateTimeInterface;
use Illuminate\Contracts\Database\Query\Expression as ExpressionContract;
use Illuminate\Database\Connection;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Grammars\Grammar as BaseGrammar;
Expand All @@ -37,7 +36,7 @@ class Grammar extends BaseGrammar
/**
* @inheritdoc
*/
protected $modifiers = ['Nullable', 'Default', 'GeneratedAs', 'Invisible', 'UseSequence'];
protected $modifiers = ['Nullable', 'Default', 'GeneratedAs', 'Invisible', 'Increment', 'UseSequence'];

/**
* Compile the query to determine the tables.
Expand Down Expand Up @@ -884,6 +883,24 @@ protected function modifyInvisible(Blueprint $blueprint, Fluent $column)
: null;
}

/**
* @param Blueprint $blueprint
* @param ColumnDefinition $column
* @return string|null
*/
protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
{
if ($column->type !== 'bigInteger') {
return null;
}

if ($column->autoIncrement !== true) {
return null;
}

return ' auto_increment';
}

/**
* Get the SQL for an identity column modifier.
*
Expand Down
2 changes: 0 additions & 2 deletions src/Schema/IntColumnDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

namespace Colopl\Spanner\Schema;

use Illuminate\Database\Schema\ColumnDefinition;

/**
* @property string $name
* @property string|null $useSequence
Expand Down
27 changes: 27 additions & 0 deletions tests/Schema/BlueprintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,33 @@ public function test_create_with_all_valid_types(): void
], $statements);
}

public function test_create_with_autoIncrement(): void
{
$conn = $this->getDefaultConnection();
$tableName = $this->generateTableName();

$blueprint = new Blueprint($conn, $tableName, function (Blueprint $table) {
$table->bigInteger('id', true)->primary();
$table->string('name');
});
$blueprint->create();

$queries = $blueprint->toSql();
$this->assertSame(
'create table `' . $tableName . '` (' . implode(', ', [
'`id` int64 not null auto_increment',
'`name` string(255) not null',
]) . ') primary key (`id`)',
$queries[0],
);

$conn->runDdlBatch($queries);
$conn->table($tableName)->insert(['name' => 't']);
$row = $conn->table($tableName)->first();
$this->assertIsInt($row['id']);
$this->assertSame('t', $row['name']);
}

public function test_create_with_generateUuid(): void
{
$conn = $this->getDefaultConnection();
Expand Down
6 changes: 6 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,13 @@ protected function setUpDatabaseOnce(Connection $conn): void
}
if (!$conn->databaseExists()) {
$conn->createDatabase($this->getTestDatabaseDDLs());

// Configure database to use bit-reversed sequences for auto-increment columns
$conn->getSchemaBuilder()->setDatabaseOptions([
'default_sequence_kind' => 'bit_reversed_positive',
]);
}

$this->beforeApplicationDestroyed(fn() => $this->cleanupDatabase($conn));
}

Expand Down