diff --git a/src/Illuminate/Database/Schema/ColumnDefinition.php b/src/Illuminate/Database/Schema/ColumnDefinition.php index 6eee91c21337..5f9df78bc231 100644 --- a/src/Illuminate/Database/Schema/ColumnDefinition.php +++ b/src/Illuminate/Database/Schema/ColumnDefinition.php @@ -14,15 +14,17 @@ * @method $this comment(string $comment) Add a comment to the column (MySQL/PostgreSQL) * @method $this default(mixed $value) Specify a "default" value for the column * @method $this first() Place the column "first" in the table (MySQL) - * @method $this from(int $startingValue) Set the starting value of an auto-incrementing field (MySQL/PostgreSQL) - * @method $this instant() Specify that algorithm=instant should be used for the column operation (MySQL) + * @method $this from(int $startingValue) Set the starting value of an auto-incrementing field (MySQL / PostgreSQL) + * @method $this fulltext(bool|string $indexName = null) Add a fulltext index * @method $this generatedAs(string|\Illuminate\Contracts\Database\Query\Expression $expression = null) Create a SQL compliant identity column (PostgreSQL) + * @method $this instant() Specify that algorithm=instant should be used for the column operation (MySQL) * @method $this index(bool|string $indexName = null) Add an index + * @method $this instant() Specify that algorithm=instant should be used for the column operation (MySQL) * @method $this invisible() Specify that the column should be invisible to "SELECT *" (MySQL) + * @method $this lock(string $value) Specify the DDL lock mode for the column operation (MySQL) * @method $this nullable(bool $value = true) Allow NULL values to be inserted into the column * @method $this persisted() Mark the computed generated column as persistent (SQL Server) * @method $this primary(bool $value = true) Add a primary index - * @method $this fulltext(bool|string $indexName = null) Add a fulltext index * @method $this spatialIndex(bool|string $indexName = null) Add a spatial index * @method $this startingValue(int $startingValue) Set the starting value of an auto-incrementing field (MySQL/PostgreSQL) * @method $this storedAs(string|\Illuminate\Contracts\Database\Query\Expression $expression) Create a stored generated column (MySQL/PostgreSQL/SQLite) diff --git a/src/Illuminate/Database/Schema/ForeignKeyDefinition.php b/src/Illuminate/Database/Schema/ForeignKeyDefinition.php index 1ce0361b9377..e483a241f403 100644 --- a/src/Illuminate/Database/Schema/ForeignKeyDefinition.php +++ b/src/Illuminate/Database/Schema/ForeignKeyDefinition.php @@ -7,6 +7,7 @@ /** * @method ForeignKeyDefinition deferrable(bool $value = true) Set the foreign key as deferrable (PostgreSQL) * @method ForeignKeyDefinition initiallyImmediate(bool $value = true) Set the default time to check the constraint (PostgreSQL) + * @method ForeignKeyDefinition lock(string $value) Specify the DDL lock mode for the foreign key operation (MySQL) * @method ForeignKeyDefinition on(string $table) Specify the referenced table * @method ForeignKeyDefinition onDelete(string $action) Add an ON DELETE action * @method ForeignKeyDefinition onUpdate(string $action) Add an ON UPDATE action diff --git a/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php b/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php index bc0dcf50ed74..30b559eb6e65 100755 --- a/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php +++ b/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php @@ -310,10 +310,11 @@ protected function compileCreateEngine($sql, Blueprint $blueprint) */ public function compileAdd(Blueprint $blueprint, Fluent $command) { - return sprintf('alter table %s add %s%s', + return sprintf('alter table %s add %s%s%s', $this->wrapTable($blueprint), $this->getColumn($blueprint, $command->column), - $command->column->instant ? ', algorithm=instant' : '' + $command->column->instant ? ', algorithm=instant' : '', + $command->column->lock ? ', lock='.$command->column->lock : '' ); } @@ -410,6 +411,10 @@ public function compileChange(Blueprint $blueprint, Fluent $command) $sql .= ', algorithm=instant'; } + if ($column->lock) { + $sql .= ', lock='.$column->lock; + } + return $sql; } @@ -422,10 +427,11 @@ public function compileChange(Blueprint $blueprint, Fluent $command) */ public function compilePrimary(Blueprint $blueprint, Fluent $command) { - return sprintf('alter table %s add primary key %s(%s)', + return sprintf('alter table %s add primary key %s(%s)%s', $this->wrapTable($blueprint), $command->algorithm ? 'using '.$command->algorithm : '', - $this->columnize($command->columns) + $this->columnize($command->columns), + $command->lock ? ', lock='.$command->lock : '' ); } @@ -487,12 +493,13 @@ public function compileSpatialIndex(Blueprint $blueprint, Fluent $command) */ protected function compileKey(Blueprint $blueprint, Fluent $command, $type) { - return sprintf('alter table %s add %s %s%s(%s)', + return sprintf('alter table %s add %s %s%s(%s)%s', $this->wrapTable($blueprint), $type, $this->wrap($command->index), $command->algorithm ? ' using '.$command->algorithm : '', - $this->columnize($command->columns) + $this->columnize($command->columns), + $command->lock ? ', lock='.$command->lock : '' ); } @@ -531,7 +538,17 @@ public function compileDropColumn(Blueprint $blueprint, Fluent $command) { $columns = $this->prefixArray('drop', $this->wrapArray($command->columns)); - return 'alter table '.$this->wrapTable($blueprint).' '.implode(', ', $columns).($command->instant ? ', algorithm=instant' : ''); + $sql = 'alter table '.$this->wrapTable($blueprint).' '.implode(', ', $columns); + + if ($command->instant) { + $sql .= ', algorithm=instant'; + } + + if ($command->lock) { + $sql .= ', lock='.$command->lock; + } + + return $sql; } /** @@ -598,6 +615,24 @@ public function compileDropSpatialIndex(Blueprint $blueprint, Fluent $command) return $this->compileDropIndex($blueprint, $command); } + /** + * Compile a foreign key command. + * + * @param \Illuminate\Database\Schema\Blueprint $blueprint + * @param \Illuminate\Support\Fluent $command + * @return string + */ + public function compileForeign(Blueprint $blueprint, Fluent $command) + { + $sql = parent::compileForeign($blueprint, $command); + + if ($command->lock) { + $sql .= ', lock='.$command->lock; + } + + return $sql; + } + /** * Compile a drop foreign key command. * diff --git a/src/Illuminate/Database/Schema/IndexDefinition.php b/src/Illuminate/Database/Schema/IndexDefinition.php index 96dba99ee566..ccbb7ebea495 100644 --- a/src/Illuminate/Database/Schema/IndexDefinition.php +++ b/src/Illuminate/Database/Schema/IndexDefinition.php @@ -6,9 +6,10 @@ /** * @method $this algorithm(string $algorithm) Specify an algorithm for the index (MySQL/PostgreSQL) - * @method $this language(string $language) Specify a language for the full text index (PostgreSQL) * @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 language(string $language) Specify a language for the full text index (PostgreSQL) + * @method $this lock(string $value) Specify the DDL lock mode for the index operation (MySQL) * @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) */ diff --git a/tests/Database/DatabaseMySqlSchemaGrammarTest.php b/tests/Database/DatabaseMySqlSchemaGrammarTest.php index f83dac6c957c..e446c2a913a4 100755 --- a/tests/Database/DatabaseMySqlSchemaGrammarTest.php +++ b/tests/Database/DatabaseMySqlSchemaGrammarTest.php @@ -1629,6 +1629,116 @@ public function testDroppingColumnWithAlgorithm() $this->assertSame('alter table `users` drop `name`, algorithm=instant', $statements[0]); } + public function testAddingColumnWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->string('name')->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add `name` varchar(255) not null, lock=none', $statements[0]); + } + + public function testChangingColumnWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->string('name', 100)->change()->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` modify `name` varchar(100) not null, lock=none', $statements[0]); + } + + public function testDroppingColumnWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->dropColumn('name')->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` drop `name`, lock=none', $statements[0]); + } + + public function testColumnWithBothAlgorithmAndLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->string('name')->instant()->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add `name` varchar(255) not null, algorithm=instant, lock=none', $statements[0]); + } + + public function testAddingIndexWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->index('name')->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add index `users_name_index`(`name`), lock=none', $statements[0]); + } + + public function testAddingUniqueIndexWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->unique('email')->lock('shared'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add unique `users_email_unique`(`email`), lock=shared', $statements[0]); + } + + public function testAddingPrimaryKeyWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->primary('id')->lock('exclusive'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add primary key (`id`), lock=exclusive', $statements[0]); + } + + public function testAddingForeignKeyWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->foreign('user_id')->references('id')->on('accounts')->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add constraint `users_user_id_foreign` foreign key (`user_id`) references `accounts` (`id`), lock=none', $statements[0]); + } + + public function testAddingFullTextIndexWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->fullText('content')->lock('shared'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add fulltext `users_content_fulltext`(`content`), lock=shared', $statements[0]); + } + + public function testAddingSpatialIndexWithLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->spatialIndex('location')->lock('default'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add spatial index `users_location_spatialindex`(`location`), lock=default', $statements[0]); + } + + public function testIndexWithAlgorithmAndLock() + { + $blueprint = new Blueprint($this->getConnection(), 'users'); + $blueprint->index('name', 'custom_idx')->algorithm('btree')->lock('none'); + $statements = $blueprint->toSql(); + + $this->assertCount(1, $statements); + $this->assertSame('alter table `users` add index `custom_idx` using btree(`name`), lock=none', $statements[0]); + } + public function getGrammar(?Connection $connection = null) { return new MySqlGrammar($connection ?? $this->getConnection());