Skip to content

Commit

Permalink
Build temporary table name for SQLite from unqualified table name
Browse files Browse the repository at this point in the history
In some situations, SqlitePlatform::getAlterTableSQL() relies on
a temporary table to store data from the original table while it
gets recreated. The name of this temporary table is built by
concatenating a prefix (__temp__) with the name of the original table.
When the original table name is foo.bar, there is an issue because
then the temporary table name becomes __temp__foo.bar which implies schema.table. Use the unqualified table name
so that the temporary table becomes __temp__bar.
  • Loading branch information
mvorisek committed Apr 6, 2024
1 parent e5db00e commit 87289d4
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/Platforms/SqlitePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,12 @@ public function getAlterTableSQL(TableDiff $diff)
$sql = [];
$tableSql = [];
if (! $this->onSchemaAlterTable($diff, $tableSql)) {
$dataTable = new Table('__temp__' . $table->getName());
$tableName = $table->getName();
if (strpos($tableName, '.') !== false) {
[, $tableName] = explode('.', $tableName, 2);
}

$dataTable = new Table('__temp__' . $tableName);

$newTable = new Table(
$table->getQuotedName($this),
Expand Down
26 changes: 26 additions & 0 deletions tests/Functional/Schema/SqliteSchemaManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\BlobType;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;

use function array_keys;
use function array_shift;
use function assert;
use function dirname;

class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
Expand Down Expand Up @@ -216,6 +220,28 @@ public function testNonSimpleAlterTableCreatedFromDDL(): void
self::assertSame(['name'], $index->getColumns());
}

public function testAlterTableWithSchema(): void
{
$databasePlatform = $this->connection->getDatabasePlatform();
assert($databasePlatform instanceof SqlitePlatform);
$databasePlatform->disableSchemaEmulation();

$this->dropTableIfExists('t');

$table = new Table('main.t');
$table->addColumn('a', Types::INTEGER);
$this->schemaManager->createTable($table);

self::assertSame(['a'], array_keys($this->schemaManager->listTableColumns('t')));

$tableDiff = new TableDiff('t');
$tableDiff->fromTable = $table;
$tableDiff->renamedColumns['a'] = new Column('b', Type::getType(Types::INTEGER));
$this->schemaManager->alterTable($tableDiff);

self::assertSame(['b'], array_keys($this->schemaManager->listTableColumns('t')));
}

public function testIntrospectMultipleAnonymousForeignKeyConstraints(): void
{
$this->dropTableIfExists('album');
Expand Down
20 changes: 20 additions & 0 deletions tests/Platforms/SqlitePlatformTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,26 @@ public function getAlterTableRenameColumnSQL(): array
];
}

public function testGeneratesAlterTableRenameColumnSQLWithSchema(): void
{
$this->platform->disableSchemaEmulation();

$table = new Table('main.t');
$table->addColumn('a', Types::INTEGER);

$tableDiff = new TableDiff('t');
$tableDiff->fromTable = $table;
$tableDiff->renamedColumns['a'] = new Column('b', Type::getType(Types::INTEGER));

self::assertSame([
'CREATE TEMPORARY TABLE __temp__t AS SELECT a FROM main.t',
'DROP TABLE main.t',
'CREATE TABLE main.t (b INTEGER NOT NULL)',
'INSERT INTO main.t (b) SELECT a FROM __temp__t',
'DROP TABLE __temp__t',
], $this->platform->getAlterTableSQL($tableDiff));
}

/**
* {@inheritDoc}
*/
Expand Down

0 comments on commit 87289d4

Please sign in to comment.