Skip to content

Commit 2555473

Browse files
[11.x] Non-default schema names (#50019)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * fix rename table on sqlsrv * wip * wip * fix rename column and rename index on sqlsrv * fix drop primary on pgsql * wip * wip * wip * wip * wip * wip * enable prefix tests * wip * wip * fix prefix auto-increment starting value on pgsql * use blueprint prefix on sqlite * use wrapTable where ever possible * wip * wip * fix index name with schema name+prefix * fix schema name+prefix * wip * fix wrapping table * fix auto-increment starting value on pgsql * wip * fix tests
1 parent a5f53e5 commit 2555473

File tree

9 files changed

+505
-40
lines changed

9 files changed

+505
-40
lines changed

src/Illuminate/Database/Grammar.php

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,38 @@ public function wrapArray(array $values)
4343
*/
4444
public function wrapTable($table)
4545
{
46-
if (! $this->isExpression($table)) {
47-
return $this->wrap($this->tablePrefix.$table, true);
46+
if ($this->isExpression($table)) {
47+
return $this->getValue($table);
4848
}
4949

50-
return $this->getValue($table);
50+
// If the table being wrapped has an alias we'll need to separate the pieces
51+
// so we can prefix the table and then wrap each of the segments on their
52+
// own and then join these both back together using the "as" connector.
53+
if (stripos($table, ' as ') !== false) {
54+
return $this->wrapAliasedTable($table);
55+
}
56+
57+
// If the table being wrapped has a custom schema name specified, we need to
58+
// prefix the last segment as the table name then wrap each segment alone
59+
// and eventually join them both back together using the dot connector.
60+
if (str_contains($table, '.')) {
61+
$table = substr_replace($table, '.'.$this->tablePrefix, strrpos($table, '.'), 1);
62+
63+
return collect(explode('.', $table))
64+
->map($this->wrapValue(...))
65+
->implode('.');
66+
}
67+
68+
return $this->wrapValue($this->tablePrefix.$table);
5169
}
5270

5371
/**
5472
* Wrap a value in keyword identifiers.
5573
*
5674
* @param \Illuminate\Contracts\Database\Query\Expression|string $value
57-
* @param bool $prefixAlias
5875
* @return string
5976
*/
60-
public function wrap($value, $prefixAlias = false)
77+
public function wrap($value)
6178
{
6279
if ($this->isExpression($value)) {
6380
return $this->getValue($value);
@@ -67,7 +84,7 @@ public function wrap($value, $prefixAlias = false)
6784
// the pieces so we can wrap each of the segments of the expression on its
6885
// own, and then join these both back together using the "as" connector.
6986
if (stripos($value, ' as ') !== false) {
70-
return $this->wrapAliasedValue($value, $prefixAlias);
87+
return $this->wrapAliasedValue($value);
7188
}
7289

7390
// If the given value is a JSON selector we will wrap it differently than a
@@ -84,23 +101,28 @@ public function wrap($value, $prefixAlias = false)
84101
* Wrap a value that has an alias.
85102
*
86103
* @param string $value
87-
* @param bool $prefixAlias
88104
* @return string
89105
*/
90-
protected function wrapAliasedValue($value, $prefixAlias = false)
106+
protected function wrapAliasedValue($value)
91107
{
92108
$segments = preg_split('/\s+as\s+/i', $value);
93109

94-
// If we are wrapping a table we need to prefix the alias with the table prefix
95-
// as well in order to generate proper syntax. If this is a column of course
96-
// no prefix is necessary. The condition will be true when from wrapTable.
97-
if ($prefixAlias) {
98-
$segments[1] = $this->tablePrefix.$segments[1];
99-
}
100-
101110
return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[1]);
102111
}
103112

113+
/**
114+
* Wrap a table that has an alias.
115+
*
116+
* @param string $value
117+
* @return string
118+
*/
119+
protected function wrapAliasedTable($value)
120+
{
121+
$segments = preg_split('/\s+as\s+/i', $value);
122+
123+
return $this->wrapTable($segments[0]).' as '.$this->wrapValue($this->tablePrefix.$segments[1]);
124+
}
125+
104126
/**
105127
* Wrap the given value segments.
106128
*

src/Illuminate/Database/Schema/Blueprint.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,11 @@ protected function dropIndexCommand($command, $type, $index)
15991599
*/
16001600
protected function createIndexName($type, array $columns)
16011601
{
1602-
$index = strtolower($this->prefix.$this->table.'_'.implode('_', $columns).'_'.$type);
1602+
$table = str_contains($this->table, '.')
1603+
? substr_replace($this->table, '.'.$this->prefix, strrpos($this->table, '.'), 1)
1604+
: $this->prefix.$this->table;
1605+
1606+
$index = strtolower($table.'_'.implode('_', $columns).'_'.$type);
16031607

16041608
return str_replace(['-', '.'], '_', $index);
16051609
}

src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ public function compileAutoIncrementStartingValues(Blueprint $blueprint, Fluent
230230
{
231231
if ($command->column->autoIncrement
232232
&& $value = $command->column->get('startingValue', $command->column->get('from'))) {
233-
return 'alter sequence '.$blueprint->getTable().'_'.$command->column->name.'_seq restart with '.$value;
233+
$table = last(explode('.', $blueprint->getTable()));
234+
235+
return 'alter sequence '.$blueprint->getPrefix().$table.'_'.$command->column->name.'_seq restart with '.$value;
234236
}
235237
}
236238

@@ -483,7 +485,8 @@ public function compileDropColumn(Blueprint $blueprint, Fluent $command)
483485
*/
484486
public function compileDropPrimary(Blueprint $blueprint, Fluent $command)
485487
{
486-
$index = $this->wrap("{$blueprint->getPrefix()}{$blueprint->getTable()}_pkey");
488+
$table = last(explode('.', $blueprint->getTable()));
489+
$index = $this->wrap("{$blueprint->getPrefix()}{$table}_pkey");
487490

488491
return 'alter table '.$this->wrapTable($blueprint)." drop constraint {$index}";
489492
}

src/Illuminate/Database/Schema/Grammars/SQLiteGrammar.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,8 @@ public function compileChange(Blueprint $blueprint, Fluent $command, Connection
295295
fn ($index) => $this->{'compile'.ucfirst($index->name)}($blueprint, $index)
296296
)->all();
297297

298-
$tempTable = $this->wrap('__temp__'.$this->getTablePrefix().$table);
299-
$table = $this->wrap($this->getTablePrefix().$table);
298+
$tempTable = $this->wrap('__temp__'.$blueprint->getPrefix().$table);
299+
$table = $this->wrapTable($blueprint);
300300
$columnNames = implode(', ', $columnNames);
301301

302302
$foreignKeyConstraintsEnabled = $connection->scalar('pragma foreign_keys');

src/Illuminate/Database/Schema/Grammars/SqlServerGrammar.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ public function compileAdd(Blueprint $blueprint, Fluent $command)
215215
*/
216216
public function compileRenameColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
217217
{
218-
return sprintf("sp_rename '%s', %s, 'COLUMN'",
219-
$this->wrap($blueprint->getTable().'.'.$command->from),
218+
return sprintf("sp_rename %s, %s, N'COLUMN'",
219+
$this->quoteString($this->wrapTable($blueprint).'.'.$this->wrap($command->from)),
220220
$this->wrap($command->to)
221221
);
222222
}
@@ -358,7 +358,7 @@ public function compileDrop(Blueprint $blueprint, Fluent $command)
358358
public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
359359
{
360360
return sprintf('if object_id(%s, \'U\') is not null drop table %s',
361-
$this->quoteString($this->getTablePrefix().$blueprint->getTable()),
361+
$this->quoteString($this->wrapTable($blueprint)),
362362
$this->wrapTable($blueprint)
363363
);
364364
}
@@ -403,7 +403,7 @@ public function compileDropDefaultConstraint(Blueprint $blueprint, Fluent $comma
403403
: "'".implode("','", $command->columns)."'";
404404

405405
$table = $this->wrapTable($blueprint);
406-
$tableName = $this->quoteString($this->getTablePrefix().$blueprint->getTable());
406+
$tableName = $this->quoteString($this->wrapTable($blueprint));
407407

408408
$sql = "DECLARE @sql NVARCHAR(MAX) = '';";
409409
$sql .= "SELECT @sql += 'ALTER TABLE $table DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' ";
@@ -491,9 +491,10 @@ public function compileDropForeign(Blueprint $blueprint, Fluent $command)
491491
*/
492492
public function compileRename(Blueprint $blueprint, Fluent $command)
493493
{
494-
$from = $this->wrapTable($blueprint);
495-
496-
return "sp_rename {$from}, ".$this->wrapTable($command->to);
494+
return sprintf('sp_rename %s, %s',
495+
$this->quoteString($this->wrapTable($blueprint)),
496+
$this->wrapTable($command->to)
497+
);
497498
}
498499

499500
/**
@@ -505,8 +506,8 @@ public function compileRename(Blueprint $blueprint, Fluent $command)
505506
*/
506507
public function compileRenameIndex(Blueprint $blueprint, Fluent $command)
507508
{
508-
return sprintf("sp_rename N'%s', %s, N'INDEX'",
509-
$this->wrap($blueprint->getTable().'.'.$command->from),
509+
return sprintf("sp_rename %s, %s, N'INDEX'",
510+
$this->quoteString($this->wrapTable($blueprint).'.'.$this->wrap($command->from)),
510511
$this->wrap($command->to)
511512
);
512513
}

tests/Database/DatabaseSchemaBlueprintTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public function testRenameColumn()
181181
$this->assertEquals(['alter table "users" rename column "foo" to "bar"'], $blueprint->toSql($connection, new SQLiteGrammar));
182182

183183
$blueprint = clone $base;
184-
$this->assertEquals(['sp_rename \'"users"."foo"\', "bar", \'COLUMN\''], $blueprint->toSql($connection, new SqlServerGrammar));
184+
$this->assertEquals(['sp_rename N\'"users"."foo"\', "bar", N\'COLUMN\''], $blueprint->toSql($connection, new SqlServerGrammar));
185185
}
186186

187187
public function testNativeRenameColumnOnMysql57()

tests/Database/DatabaseSqlServerSchemaGrammarTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ public function testDropTableIfExists()
8383
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
8484

8585
$this->assertCount(1, $statements);
86-
$this->assertSame('if object_id(N\'users\', \'U\') is not null drop table "users"', $statements[0]);
86+
$this->assertSame('if object_id(N\'"users"\', \'U\') is not null drop table "users"', $statements[0]);
8787

8888
$blueprint = new Blueprint('users');
8989
$blueprint->dropIfExists();
9090
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar()->setTablePrefix('prefix_'));
9191

9292
$this->assertCount(1, $statements);
93-
$this->assertSame('if object_id(N\'prefix_users\', \'U\') is not null drop table "prefix_users"', $statements[0]);
93+
$this->assertSame('if object_id(N\'"prefix_users"\', \'U\') is not null drop table "prefix_users"', $statements[0]);
9494
}
9595

9696
public function testDropColumn()
@@ -124,7 +124,7 @@ public function testDropColumnDropsCreatesSqlToDropDefaultConstraints()
124124
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
125125

126126
$this->assertCount(1, $statements);
127-
$this->assertSame("DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"foo\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'foo') AND [name] in ('bar') AND [default_object_id] <> 0;EXEC(@sql);alter table \"foo\" drop column \"bar\"", $statements[0]);
127+
$this->assertSame("DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"foo\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'\"foo\"') AND [name] in ('bar') AND [default_object_id] <> 0;EXEC(@sql);alter table \"foo\" drop column \"bar\"", $statements[0]);
128128
}
129129

130130
public function testDropPrimary()
@@ -185,7 +185,7 @@ public function testDropConstrainedForeignId()
185185

186186
$this->assertCount(2, $statements);
187187
$this->assertSame('alter table "users" drop constraint "users_foo_foreign"', $statements[0]);
188-
$this->assertSame('DECLARE @sql NVARCHAR(MAX) = \'\';SELECT @sql += \'ALTER TABLE "users" DROP CONSTRAINT \' + OBJECT_NAME([default_object_id]) + \';\' FROM sys.columns WHERE [object_id] = OBJECT_ID(N\'users\') AND [name] in (\'foo\') AND [default_object_id] <> 0;EXEC(@sql);alter table "users" drop column "foo"', $statements[1]);
188+
$this->assertSame('DECLARE @sql NVARCHAR(MAX) = \'\';SELECT @sql += \'ALTER TABLE "users" DROP CONSTRAINT \' + OBJECT_NAME([default_object_id]) + \';\' FROM sys.columns WHERE [object_id] = OBJECT_ID(N\'"users"\') AND [name] in (\'foo\') AND [default_object_id] <> 0;EXEC(@sql);alter table "users" drop column "foo"', $statements[1]);
189189
}
190190

191191
public function testDropTimestamps()
@@ -226,7 +226,7 @@ public function testRenameTable()
226226
$statements = $blueprint->toSql($this->getConnection(), $this->getGrammar());
227227

228228
$this->assertCount(1, $statements);
229-
$this->assertSame('sp_rename "users", "foo"', $statements[0]);
229+
$this->assertSame('sp_rename N\'"users"\', "foo"', $statements[0]);
230230
}
231231

232232
public function testRenameIndex()

tests/Integration/Database/DatabaseSchemaBlueprintTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public function testNativeColumnModifyingOnSqlServer()
190190
});
191191

192192
$this->assertEquals([
193-
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'users') AND [name] in ('added_at') AND [default_object_id] <> 0;EXEC(@sql)",
193+
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'\"users\"') AND [name] in ('added_at') AND [default_object_id] <> 0;EXEC(@sql)",
194194
'alter table "users" alter column "added_at" datetime2(4) not null',
195195
'alter table "users" add default CURRENT_TIMESTAMP for "added_at"',
196196
], $blueprint->toSql($connection, new SqlServerGrammar));
@@ -200,7 +200,7 @@ public function testNativeColumnModifyingOnSqlServer()
200200
});
201201

202202
$this->assertEquals([
203-
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'users') AND [name] in ('name') AND [default_object_id] <> 0;EXEC(@sql)",
203+
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'\"users\"') AND [name] in ('name') AND [default_object_id] <> 0;EXEC(@sql)",
204204
'alter table "users" alter column "name" nchar(40) collate unicode null',
205205
'alter table "users" add default \'easy\' for "name"',
206206
], $blueprint->toSql($connection, new SqlServerGrammar));
@@ -210,7 +210,7 @@ public function testNativeColumnModifyingOnSqlServer()
210210
});
211211

212212
$this->assertEquals([
213-
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'users') AND [name] in ('foo') AND [default_object_id] <> 0;EXEC(@sql)",
213+
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'\"users\"') AND [name] in ('foo') AND [default_object_id] <> 0;EXEC(@sql)",
214214
'alter table "users" alter column "foo" int not null',
215215
], $blueprint->toSql($connection, new SqlServerGrammar));
216216
}
@@ -448,7 +448,7 @@ public function testAddUniqueIndexWithoutNameWorks()
448448
$queries = $blueprintSqlServer->toSql(DB::connection(), new SqlServerGrammar);
449449

450450
$expected = [
451-
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'users') AND [name] in ('name') AND [default_object_id] <> 0;EXEC(@sql)",
451+
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'\"users\"') AND [name] in ('name') AND [default_object_id] <> 0;EXEC(@sql)",
452452
'alter table "users" alter column "name" nvarchar(255) null',
453453
'create unique index "users_name_unique" on "users" ("name")',
454454
];
@@ -512,7 +512,7 @@ public function testAddUniqueIndexWithNameWorks()
512512
$queries = $blueprintSqlServer->toSql(DB::connection(), new SqlServerGrammar);
513513

514514
$expected = [
515-
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'users') AND [name] in ('name') AND [default_object_id] <> 0;EXEC(@sql)",
515+
"DECLARE @sql NVARCHAR(MAX) = '';SELECT @sql += 'ALTER TABLE \"users\" DROP CONSTRAINT ' + OBJECT_NAME([default_object_id]) + ';' FROM sys.columns WHERE [object_id] = OBJECT_ID(N'\"users\"') AND [name] in ('name') AND [default_object_id] <> 0;EXEC(@sql)",
516516
'alter table "users" alter column "name" int null',
517517
'create unique index "index1" on "users" ("name")',
518518
];

0 commit comments

Comments
 (0)