From bc7afc15c6912ca8a6d6894d6e6bc1b2b013b5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Tue, 21 Nov 2023 13:47:50 +0100 Subject: [PATCH] Move schema part to the index In SQLite, creating an index in another schema is done by prepending the index name with the schema, while the table name must be unprefixed. --- psalm.xml.dist | 1 + src/Platforms/SqlitePlatform.php | 45 +++++++++++++++++++ tests/Functional/Platform/OtherSchemaTest.php | 37 +++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 tests/Functional/Platform/OtherSchemaTest.php diff --git a/psalm.xml.dist b/psalm.xml.dist index 567ecc381ae..8b16d961b51 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -326,6 +326,7 @@ + diff --git a/src/Platforms/SqlitePlatform.php b/src/Platforms/SqlitePlatform.php index 5acefc5c82f..f11e537e60e 100644 --- a/src/Platforms/SqlitePlatform.php +++ b/src/Platforms/SqlitePlatform.php @@ -18,6 +18,7 @@ use Doctrine\DBAL\Types; use Doctrine\DBAL\Types\IntegerType; use Doctrine\Deprecations\Deprecation; +use InvalidArgumentException; use function array_combine; use function array_keys; @@ -26,12 +27,14 @@ use function array_unique; use function array_values; use function count; +use function explode; use function implode; use function is_numeric; use function sprintf; use function sqrt; use function str_replace; use function strlen; +use function strpos; use function strtolower; use function trim; @@ -918,6 +921,48 @@ public function getCreateTablesSQL(array $tables): array return $sql; } + /** + * {@inheritDoc} + */ + public function getCreateIndexSQL(Index $index, $table) + { + if ($table instanceof Table) { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/issues/4798', + 'Passing $table as a Table object to %s is deprecated. Pass it as a quoted name instead.', + __METHOD__, + ); + + $table = $table->getQuotedName($this); + } + + $name = $index->getQuotedName($this); + $columns = $index->getColumns(); + + if (strpos($table, '.') !== false) { + [$schema, $table] = explode('.', $table); + $name = $schema . '.' . $name; + } + + if (count($columns) === 0) { + throw new InvalidArgumentException(sprintf( + 'Incomplete or invalid index definition %s on table %s', + $name, + $table, + )); + } + + if ($index->isPrimary()) { + return $this->getCreatePrimaryKeySQL($index, $table); + } + + $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; + $query .= ' (' . $this->getIndexFieldDeclarationListSQL($index) . ')' . $this->getPartialIndexSQL($index); + + return $query; + } + /** * {@inheritDoc} */ diff --git a/tests/Functional/Platform/OtherSchemaTest.php b/tests/Functional/Platform/OtherSchemaTest.php new file mode 100644 index 00000000000..93fad96872b --- /dev/null +++ b/tests/Functional/Platform/OtherSchemaTest.php @@ -0,0 +1,37 @@ +connection->getDatabasePlatform(); + if (! ($databasePlatform instanceof SqlitePlatform)) { + self::markTestSkipped('This test requires SQLite'); + } + + $this->connection->executeStatement("ATTACH DATABASE '/tmp/test_other_schema.sqlite' AS other"); + $databasePlatform->disableSchemaEmulation(); + + $table = new Table('other.test_other_schema'); + $table->addColumn('id', Types::INTEGER); + $table->addIndex(['id']); + + $this->dropAndCreateTable($table); + $this->connection->insert('other.test_other_schema', ['id' => 1]); + + self::assertEquals(1, $this->connection->fetchOne('SELECT COUNT(*) FROM other.test_other_schema')); + $connection = DriverManager::getConnection( + ['url' => 'sqlite:////tmp/test_other_schema.sqlite'], + ); + $onlineTable = $connection->createSchemaManager()->introspectTable('test_other_schema'); + self::assertCount(1, $onlineTable->getIndexes()); + } +}