Skip to content

Commit 79c478e

Browse files
committed
fix: "artisan db:wipe" command does not drop tables in all schemas
Fixes #41483
1 parent 0256484 commit 79c478e

File tree

3 files changed

+46
-19
lines changed

3 files changed

+46
-19
lines changed

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

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
272272
*/
273273
public function compileDropAllTables($tables)
274274
{
275-
return 'drop table "'.implode('","', $tables).'" cascade';
275+
return 'drop table '.implode(',', $this->escapeObjectReferences($tables)).' cascade';
276276
}
277277

278278
/**
@@ -283,7 +283,7 @@ public function compileDropAllTables($tables)
283283
*/
284284
public function compileDropAllViews($views)
285285
{
286-
return 'drop view "'.implode('","', $views).'" cascade';
286+
return 'drop view '.implode(',', $this->escapeObjectReferences($views)).' cascade';
287287
}
288288

289289
/**
@@ -294,7 +294,7 @@ public function compileDropAllViews($views)
294294
*/
295295
public function compileDropAllTypes($types)
296296
{
297-
return 'drop type "'.implode('","', $types).'" cascade';
297+
return 'drop type '.implode(',', $this->escapeObjectReferences($types)).' cascade';
298298
}
299299

300300
/**
@@ -305,7 +305,7 @@ public function compileDropAllTypes($types)
305305
*/
306306
public function compileGetAllTables($searchPath)
307307
{
308-
return "select tablename from pg_catalog.pg_tables where schemaname in ('".implode("','", (array) $searchPath)."')";
308+
return "select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('".implode("','", (array) $searchPath)."')";
309309
}
310310

311311
/**
@@ -316,7 +316,7 @@ public function compileGetAllTables($searchPath)
316316
*/
317317
public function compileGetAllViews($searchPath)
318318
{
319-
return "select viewname from pg_catalog.pg_views where schemaname in ('".implode("','", (array) $searchPath)."')";
319+
return "select viewname, schemaname from pg_catalog.pg_views where schemaname in ('".implode("','", (array) $searchPath)."')";
320320
}
321321

322322
/**
@@ -1070,4 +1070,31 @@ protected function modifyStoredAs(Blueprint $blueprint, Fluent $column)
10701070
return " generated always as ({$column->storedAs}) stored";
10711071
}
10721072
}
1073+
1074+
/**
1075+
* Escape database object references consitently, schema-qualified or not.
1076+
*
1077+
* @param array $objects
1078+
* @return array
1079+
*/
1080+
protected function escapeObjectReferences(array $objects): array
1081+
{
1082+
$escapedObjects = [];
1083+
1084+
foreach ($objects as $object) {
1085+
$parts = explode('.', $object);
1086+
1087+
$newParts = [];
1088+
1089+
array_walk($parts, function (&$part) use (&$newParts) {
1090+
$part = str_replace(['"', "'"], '', $part);
1091+
1092+
$newParts[] = $part;
1093+
});
1094+
1095+
$escapedObjects[] = '"'.implode('"."', $parts).'"';
1096+
}
1097+
1098+
return $escapedObjects;
1099+
}
10731100
}

src/Illuminate/Database/Schema/PostgresBuilder.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function dropAllTables()
6767
foreach ($this->getAllTables() as $row) {
6868
$row = (array) $row;
6969

70-
$table = reset($row);
70+
$table = '"'.$row['schemaname'].'"."'.$row['tablename'].'"';
7171

7272
if (! in_array($table, $excludedTables)) {
7373
$tables[] = $table;
@@ -95,7 +95,7 @@ public function dropAllViews()
9595
foreach ($this->getAllViews() as $row) {
9696
$row = (array) $row;
9797

98-
$views[] = reset($row);
98+
$views[] = '"'.$row['schemaname'].'"."'.$row['viewname'].'"';
9999
}
100100

101101
if (empty($views)) {

tests/Database/DatabasePostgresBuilderTest.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,10 @@ public function testDropAllTablesWhenSearchPathIsString()
238238
$connection->shouldReceive('getConfig')->with('dont_drop')->andReturn(['foo']);
239239
$grammar = m::mock(PostgresGrammar::class);
240240
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
241-
$grammar->shouldReceive('compileGetAllTables')->with(['public'])->andReturn("select tablename from pg_catalog.pg_tables where schemaname in ('public')");
242-
$connection->shouldReceive('select')->with("select tablename from pg_catalog.pg_tables where schemaname in ('public')")->andReturn(['users']);
243-
$grammar->shouldReceive('compileDropAllTables')->with(['users'])->andReturn('drop table "'.implode('","', ['users']).'" cascade');
244-
$connection->shouldReceive('statement')->with('drop table "'.implode('","', ['users']).'" cascade');
241+
$grammar->shouldReceive('compileGetAllTables')->with(['public'])->andReturn("select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('public')");
242+
$connection->shouldReceive('select')->with("select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('public')")->andReturn([['schemaname' => 'public', 'tablename' => 'users']]);
243+
$grammar->shouldReceive('compileDropAllTables')->with(['"public"."users"'])->andReturn('drop table "public"."users" cascade');
244+
$connection->shouldReceive('statement')->with('drop table "public"."users" cascade');
245245
$builder = $this->getBuilder($connection);
246246

247247
$builder->dropAllTables();
@@ -255,10 +255,10 @@ public function testDropAllTablesWhenSearchPathIsStringOfMany()
255255
$connection->shouldReceive('getConfig')->with('dont_drop')->andReturn(['foo']);
256256
$grammar = m::mock(PostgresGrammar::class);
257257
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
258-
$grammar->shouldReceive('compileGetAllTables')->with(['foouser', 'public', 'foo_bar-Baz.Áüõß'])->andReturn("select tablename from pg_catalog.pg_tables where schemaname in ('foouser','public','foo_bar-Baz.Áüõß')");
259-
$connection->shouldReceive('select')->with("select tablename from pg_catalog.pg_tables where schemaname in ('foouser','public','foo_bar-Baz.Áüõß')")->andReturn(['users', 'users']);
260-
$grammar->shouldReceive('compileDropAllTables')->with(['users', 'users'])->andReturn('drop table "'.implode('","', ['users', 'users']).'" cascade');
261-
$connection->shouldReceive('statement')->with('drop table "'.implode('","', ['users', 'users']).'" cascade');
258+
$grammar->shouldReceive('compileGetAllTables')->with(['foouser', 'public', 'foo_bar-Baz.Áüõß'])->andReturn("select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('foouser','public','foo_bar-Baz.Áüõß')");
259+
$connection->shouldReceive('select')->with("select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('foouser','public','foo_bar-Baz.Áüõß')")->andReturn([['schemaname' => 'users', 'tablename' => 'users']]);
260+
$grammar->shouldReceive('compileDropAllTables')->with(['"users"."users"'])->andReturn('drop table "users"."users" cascade');
261+
$connection->shouldReceive('statement')->with('drop table "users"."users" cascade');
262262
$builder = $this->getBuilder($connection);
263263

264264
$builder->dropAllTables();
@@ -277,10 +277,10 @@ public function testDropAllTablesWhenSearchPathIsArrayOfMany()
277277
$connection->shouldReceive('getConfig')->with('dont_drop')->andReturn(['foo']);
278278
$grammar = m::mock(PostgresGrammar::class);
279279
$connection->shouldReceive('getSchemaGrammar')->once()->andReturn($grammar);
280-
$grammar->shouldReceive('compileGetAllTables')->with(['foouser', 'dev', 'test', 'spaced schema'])->andReturn("select tablename from pg_catalog.pg_tables where schemaname in ('foouser','dev','test','spaced schema')");
281-
$connection->shouldReceive('select')->with("select tablename from pg_catalog.pg_tables where schemaname in ('foouser','dev','test','spaced schema')")->andReturn(['users', 'users']);
282-
$grammar->shouldReceive('compileDropAllTables')->with(['users', 'users'])->andReturn('drop table "'.implode('","', ['users', 'users']).'" cascade');
283-
$connection->shouldReceive('statement')->with('drop table "'.implode('","', ['users', 'users']).'" cascade');
280+
$grammar->shouldReceive('compileGetAllTables')->with(['foouser', 'dev', 'test', 'spaced schema'])->andReturn("select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('foouser','dev','test','spaced schema')");
281+
$connection->shouldReceive('select')->with("select tablename, schemaname from pg_catalog.pg_tables where schemaname in ('foouser','dev','test','spaced schema')")->andReturn([['schemaname' => 'users', 'tablename' => 'users']]);
282+
$grammar->shouldReceive('compileDropAllTables')->with(['"users"."users"'])->andReturn('drop table "users"."users" cascade');
283+
$connection->shouldReceive('statement')->with('drop table "users"."users" cascade');
284284
$builder = $this->getBuilder($connection);
285285

286286
$builder->dropAllTables();

0 commit comments

Comments
 (0)