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
42 changes: 31 additions & 11 deletions src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public function compilePrimary(Blueprint $blueprint, Fluent $command)
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
* @return string
* @return string[]
*/
public function compileUnique(Blueprint $blueprint, Fluent $command)
{
Expand All @@ -333,12 +333,29 @@ public function compileUnique(Blueprint $blueprint, Fluent $command)
$uniqueStatement .= ' nulls '.($command->nullsNotDistinct ? 'not distinct' : 'distinct');
}

$sql = sprintf('alter table %s add constraint %s %s (%s)',
$this->wrapTable($blueprint),
$this->wrap($command->index),
$uniqueStatement,
$this->columnize($command->columns)
);
if ($command->online || $command->algorithm) {
$createIndexSql = sprintf('create unique index %s%s on %s%s (%s)',
$command->online ? 'concurrently ' : '',
$this->wrap($command->index),
$this->wrapTable($blueprint),
$command->algorithm ? ' using '.$command->algorithm : '',
$this->columnize($command->columns)
);

$sql = sprintf('alter table %s add constraint %s unique using index %s',
$this->wrapTable($blueprint),
$this->wrap($command->index),
$this->wrap($command->index)
);
} else {
$sql = sprintf(
'alter table %s add constraint %s %s (%s)',
$this->wrapTable($blueprint),
$this->wrap($command->index),
$uniqueStatement,
$this->columnize($command->columns)
);
}

if (! is_null($command->deferrable)) {
$sql .= $command->deferrable ? ' deferrable' : ' not deferrable';
Expand All @@ -348,7 +365,7 @@ public function compileUnique(Blueprint $blueprint, Fluent $command)
$sql .= $command->initiallyImmediate ? ' initially immediate' : ' initially deferred';
}

return $sql;
return isset($createIndexSql) ? [$createIndexSql, $sql] : [$sql];
}

/**
Expand All @@ -360,7 +377,8 @@ public function compileUnique(Blueprint $blueprint, Fluent $command)
*/
public function compileIndex(Blueprint $blueprint, Fluent $command)
{
return sprintf('create index %s on %s%s (%s)',
return sprintf('create index %s%s on %s%s (%s)',
$command->online ? 'concurrently ' : '',
$this->wrap($command->index),
$this->wrapTable($blueprint),
$command->algorithm ? ' using '.$command->algorithm : '',
Expand All @@ -385,7 +403,8 @@ public function compileFulltext(Blueprint $blueprint, Fluent $command)
return "to_tsvector({$this->quoteString($language)}, {$this->wrap($column)})";
}, $command->columns);

return sprintf('create index %s on %s using gin ((%s))',
return sprintf('create index %s%s on %s using gin ((%s))',
$command->online ? 'concurrently ' : '',
$this->wrap($command->index),
$this->wrapTable($blueprint),
implode(' || ', $columns)
Expand Down Expand Up @@ -421,7 +440,8 @@ protected function compileIndexWithOperatorClass(Blueprint $blueprint, Fluent $c
{
$columns = $this->columnizeWithOperatorClass($command->columns, $command->operatorClass);

return sprintf('create index %s on %s%s (%s)',
return sprintf('create index %s%s on %s%s (%s)',
$command->online ? 'concurrently ' : '',
$this->wrap($command->index),
$this->wrapTable($blueprint),
$command->algorithm ? ' using '.$command->algorithm : '',
Expand Down
10 changes: 6 additions & 4 deletions src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,11 @@ public function compilePrimary(Blueprint $blueprint, Fluent $command)
*/
public function compileUnique(Blueprint $blueprint, Fluent $command)
{
return sprintf('create unique index %s on %s (%s)',
return sprintf('create unique index %s on %s (%s)%s',
$this->wrap($command->index),
$this->wrapTable($blueprint),
$this->columnize($command->columns)
$this->columnize($command->columns),
$command->online ? ' with (online = on)' : ''
);
}

Expand All @@ -288,10 +289,11 @@ public function compileUnique(Blueprint $blueprint, Fluent $command)
*/
public function compileIndex(Blueprint $blueprint, Fluent $command)
{
return sprintf('create index %s on %s (%s)',
return sprintf('create index %s on %s (%s)%s',
$this->wrap($command->index),
$this->wrapTable($blueprint),
$this->columnize($command->columns)
$this->columnize($command->columns),
$command->online ? ' with (online = on)' : ''
);
}

Expand Down
1 change: 1 addition & 0 deletions src/Illuminate/Database/Schema/IndexDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* @method $this deferrable(bool $value = true) Specify that the unique index is deferrable (PostgreSQL)
* @method $this initiallyImmediate(bool $value = true) Specify the default time to check the unique index constraint (PostgreSQL)
* @method $this nullsNotDistinct(bool $value = true) Specify that the null values should not be treated as distinct (PostgreSQL)
* @method $this online(bool $value = true) Specify that index creation should not lock the table (PostgreSQL/SqlServer)
*/
class IndexDefinition extends Fluent
{
Expand Down
61 changes: 61 additions & 0 deletions tests/Database/DatabasePostgresSchemaGrammarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,17 @@ public function testAddingUniqueKeyWithNullsDistinct()
$this->assertSame('alter table "users" add constraint "bar" unique nulls distinct ("foo")', $statements[0]);
}

public function testAddingUniqueKeyOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
$blueprint->unique('foo')->online();
$statements = $blueprint->toSql();

$this->assertCount(2, $statements);
$this->assertSame('create unique index concurrently "users_foo_unique" on "users" ("foo")', $statements[0]);
$this->assertSame('alter table "users" add constraint "users_foo_unique" unique using index "users_foo_unique"', $statements[1]);
}

public function testAddingIndex()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
Expand All @@ -327,6 +338,16 @@ public function testAddingIndexWithAlgorithm()
$this->assertSame('create index "baz" on "users" using hash ("foo", "bar")', $statements[0]);
}

public function testAddingIndexOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
$blueprint->index('foo', 'baz')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create index concurrently "baz" on "users" ("foo")', $statements[0]);
}

public function testAddingFulltextIndex()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
Expand Down Expand Up @@ -357,6 +378,16 @@ public function testAddingFulltextIndexWithLanguage()
$this->assertSame('create index "users_body_fulltext" on "users" using gin ((to_tsvector(\'spanish\', "body")))', $statements[0]);
}

public function testAddingFulltextIndexOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
$blueprint->fulltext('body')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create index concurrently "users_body_fulltext" on "users" using gin ((to_tsvector(\'english\', "body")))', $statements[0]);
}

public function testAddingFulltextIndexWithFluency()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
Expand All @@ -377,6 +408,16 @@ public function testAddingSpatialIndex()
$this->assertSame('create index "geo_coordinates_spatialindex" on "geo" using gist ("coordinates")', $statements[0]);
}

public function testAddingSpatialIndexOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'geo');
$blueprint->spatialIndex('coordinates')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create index concurrently "geo_coordinates_spatialindex" on "geo" using gist ("coordinates")', $statements[0]);
}

public function testAddingFluentSpatialIndex()
{
$blueprint = new Blueprint($this->getConnection(), 'geo');
Expand Down Expand Up @@ -407,6 +448,16 @@ public function testAddingSpatialIndexWithOperatorClassMultipleColumns()
$this->assertSame('create index "my_index" on "geo" using gist ("coordinates" point_ops, "location" point_ops)', $statements[0]);
}

public function testAddingSpatialIndexWithOperatorClassOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'geo');
$blueprint->spatialIndex('coordinates', 'my_index', 'point_ops')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create index concurrently "my_index" on "geo" using gist ("coordinates" point_ops)', $statements[0]);
}

public function testAddingRawIndex()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
Expand All @@ -417,6 +468,16 @@ public function testAddingRawIndex()
$this->assertSame('create index "raw_index" on "users" ((function(column)))', $statements[0]);
}

public function testAddingRawIndexOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
$blueprint->rawIndex('(function(column))', 'raw_index')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create index concurrently "raw_index" on "users" ((function(column)))', $statements[0]);
}

public function testAddingIncrementingID()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
Expand Down
20 changes: 20 additions & 0 deletions tests/Database/DatabaseSqlServerSchemaGrammarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,16 @@ public function testAddingUniqueKey()
$this->assertSame('create unique index "bar" on "users" ("foo")', $statements[0]);
}

public function testAddingUniqueKeyOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
$blueprint->unique('foo', 'bar')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create unique index "bar" on "users" ("foo") with (online = on)', $statements[0]);
}

public function testAddingIndex()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
Expand All @@ -293,6 +303,16 @@ public function testAddingIndex()
$this->assertSame('create index "baz" on "users" ("foo", "bar")', $statements[0]);
}

public function testAddingIndexOnline()
{
$blueprint = new Blueprint($this->getConnection(), 'users');
$blueprint->index(['foo', 'bar'], 'baz')->online();
$statements = $blueprint->toSql();

$this->assertCount(1, $statements);
$this->assertSame('create index "baz" on "users" ("foo", "bar") with (online = on)', $statements[0]);
}

public function testAddingSpatialIndex()
{
$blueprint = new Blueprint($this->getConnection(), 'geo');
Expand Down
23 changes: 23 additions & 0 deletions tests/Integration/Database/Postgres/PostgresSchemaBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,27 @@ public function testGetRawIndex()

$this->assertSame([], collect($indexes)->firstWhere('name', 'table_raw_index')['columns']);
}

public function testCreateIndexesOnline()
{
Schema::create('public.table', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title', 200);
$table->text('body');

$table->unique('title')->online();
$table->index(['created_at'])->online();
$table->fullText(['body'])->online();
$table->rawIndex("DATE_TRUNC('year'::text,created_at)", 'table_raw_index')->online();
});

$indexes = Schema::getIndexes('public.table');
$indexNames = collect($indexes)->pluck('name');

$this->assertContains('public_table_title_unique', $indexNames);
$this->assertContains('public_table_created_at_index', $indexNames);
$this->assertContains('public_table_body_fulltext', $indexNames);
$this->assertContains('table_raw_index', $indexNames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,22 @@ public function testComputedColumnsListing()
$userColumns = Schema::getColumns('users');
$this->assertNull($userColumns[1]['generation']);
}

public function testCreateIndexesOnline()
{
Schema::create('table', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title', 200);

$table->unique('title')->online();
$table->index(['created_at'])->online();
});

$indexes = Schema::getIndexes('table');
$indexNames = collect($indexes)->pluck('name');

$this->assertContains('table_title_unique', $indexNames);
$this->assertContains('table_created_at_index', $indexNames);
}
}
Loading