From 7d27f0e413e6f515c7bbda1c770b7fda7f754ffb Mon Sep 17 00:00:00 2001 From: jharder Date: Tue, 7 May 2024 09:44:07 -0600 Subject: [PATCH 1/3] Quote database name in case of illegal characters In MySQL a hyphen (-) in a database name is not prohibited but requires the name to be escaped with backtick (`). The methods setConnection() and createDatabase() passed the database name unaltered which caused migrations to fail for systems with hyphens in the database name. This change wraps the database name in quoteTableName(), and also identified a couple other cases where the name should be or was inconsistently quoted. --- src/Db/Adapter/MysqlAdapter.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Db/Adapter/MysqlAdapter.php b/src/Db/Adapter/MysqlAdapter.php index 9f5d43c8..7bec599b 100644 --- a/src/Db/Adapter/MysqlAdapter.php +++ b/src/Db/Adapter/MysqlAdapter.php @@ -107,7 +107,7 @@ public function connect(): void */ public function setConnection(Connection $connection): AdapterInterface { - $connection->execute(sprintf('USE %s', $this->getOption('database'))); + $connection->execute(sprintf('USE %s', $this->quoteTableName($this->getOption('database')))); return parent::setConnection($connection); } @@ -811,7 +811,7 @@ protected function getForeignKeys(string $tableName): array REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_SCHEMA = %s + AND TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s' ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", empty($schema) ? 'DATABASE()' : "'$schema'", @@ -1242,15 +1242,15 @@ public function createDatabase(string $name, array $options = []): void if (isset($options['collation'])) { $this->execute(sprintf( - 'CREATE DATABASE `%s` DEFAULT CHARACTER SET `%s` COLLATE `%s`', - $name, + 'CREATE DATABASE %s DEFAULT CHARACTER SET `%s` COLLATE `%s`', + $this->quoteTableName($name), $charset, $options['collation'] )); } else { - $this->execute(sprintf('CREATE DATABASE `%s` DEFAULT CHARACTER SET `%s`', $name, $charset)); + $this->execute(sprintf('CREATE DATABASE %s DEFAULT CHARACTER SET `%s`', $this->quoteTableName($name), $charset)); } - $this->execute(sprintf('USE %s', $name)); + $this->execute(sprintf('USE %s', $this->quoteTableName($name))); } /** @@ -1279,7 +1279,7 @@ public function hasDatabase(string $name): bool */ public function dropDatabase(string $name): void { - $this->execute(sprintf('DROP DATABASE IF EXISTS `%s`', $name)); + $this->execute(sprintf('DROP DATABASE IF EXISTS %s', $this->quoteTableName($name))); $this->createdTables = []; } From c34e8e5f19e317fb6f3aa32660fe204fd5b2b205 Mon Sep 17 00:00:00 2001 From: jharder Date: Tue, 7 May 2024 09:58:32 -0600 Subject: [PATCH 2/3] Add test for database with hyphen in name Adding a test case to cover databases with hyphen in its name. --- tests/TestCase/Db/Adapter/MysqlAdapterTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/TestCase/Db/Adapter/MysqlAdapterTest.php b/tests/TestCase/Db/Adapter/MysqlAdapterTest.php index d239f90f..c16d4a8e 100644 --- a/tests/TestCase/Db/Adapter/MysqlAdapterTest.php +++ b/tests/TestCase/Db/Adapter/MysqlAdapterTest.php @@ -104,6 +104,14 @@ public function testSchemaTableIsCreatedWithPrimaryKey() $this->assertTrue($this->adapter->hasIndex($this->adapter->getSchemaTableName(), ['version'])); } + public function testDatabaseNameWithEscapedCharacter() + { + $this->adapter->dropDatabase($this->config['database'] . '-test'); + $this->adapter->createDatabase($this->config['database'] . '-test', ['charset' => 'utf8mb4']); + $this->assertTrue($this->adapter->hasDatabase($this->config['database'] . '-test')); + $this->adapter->dropDatabase($this->config['database'] . '-test'); + } + public function testQuoteTableName() { $this->assertEquals('`test_table`', $this->adapter->quoteTableName('test_table')); From 9521d4b805d3eea6de36e4defb3f5e982f5ac8d6 Mon Sep 17 00:00:00 2001 From: jharder Date: Tue, 7 May 2024 10:27:24 -0600 Subject: [PATCH 3/3] Remove quote marks in SQL Looks like the TABLE_SCHEMA was being quoted already, so this double-quoted and caused some tests to fail. --- src/Db/Adapter/MysqlAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Db/Adapter/MysqlAdapter.php b/src/Db/Adapter/MysqlAdapter.php index 7bec599b..3bf1aa3a 100644 --- a/src/Db/Adapter/MysqlAdapter.php +++ b/src/Db/Adapter/MysqlAdapter.php @@ -811,7 +811,7 @@ protected function getForeignKeys(string $tableName): array REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME IS NOT NULL - AND TABLE_SCHEMA = '%s' + AND TABLE_SCHEMA = %s AND TABLE_NAME = '%s' ORDER BY POSITION_IN_UNIQUE_CONSTRAINT", empty($schema) ? 'DATABASE()' : "'$schema'",