From 025ec94dec58e2b4a3c83728e1d359fcdb141b0d Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Fri, 24 May 2024 16:29:13 +0200 Subject: [PATCH 01/12] Add support for creating temporary tables in schema This allows creating temporary tables in PostgreSQL specifying also the on commit options. --- docs/en/reference/schema-representation.rst | 13 +++++- src/Platforms/PostgreSQLPlatform.php | 11 ++++- tests/Platforms/PostgreSQLPlatformTest.php | 52 +++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/docs/en/reference/schema-representation.rst b/docs/en/reference/schema-representation.rst index f5aa7f4e0ac..fdabcd44bfc 100644 --- a/docs/en/reference/schema-representation.rst +++ b/docs/en/reference/schema-representation.rst @@ -93,7 +93,18 @@ and absolutely not portable. - **engine** (string): The DB engine used for the table. Currently only supported on MySQL. - **unlogged** (boolean): Set a PostgreSQL table type as - `unlogged `_ + `unlogged `_ + +- **temporary** (boolean): Set a PostgreSQL table type as + `temporary `_ + +- **on_commit** (string): Set a PostgreSQL table + `commit options `_, + only used if **temporary** is true + + - ``preserve``: preserve rows on commit + - ``delete``: delete rows on commit + - ``drop``: drop rows on commit Column ~~~~~~ diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php index 166ee7547fb..a1296878ff8 100644 --- a/src/Platforms/PostgreSQLPlatform.php +++ b/src/Platforms/PostgreSQLPlatform.php @@ -391,9 +391,18 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; } + $temporary = isset($options['temporary']) && $options['temporary'] === true ? ' TEMPORARY' : ''; + + $onCommit = $options['temporary'] ?? false ? match ($options['on_commit'] ?? '') { + 'preserve' => ' ON COMMIT PRESERVE ROWS', + 'delete' => ' ON COMMIT DELETE ROWS', + 'drop' => ' ON COMMIT DROP', + default => '' + } : ''; + $unlogged = isset($options['unlogged']) && $options['unlogged'] === true ? ' UNLOGGED' : ''; - $query = 'CREATE' . $unlogged . ' TABLE ' . $name . ' (' . $queryFields . ')'; + $query = 'CREATE' . $temporary . $unlogged . ' TABLE ' . $name . ' (' . $queryFields . ')' . $onCommit; $sql = [$query]; diff --git a/tests/Platforms/PostgreSQLPlatformTest.php b/tests/Platforms/PostgreSQLPlatformTest.php index e3b78ebb0e7..362110af1a5 100644 --- a/tests/Platforms/PostgreSQLPlatformTest.php +++ b/tests/Platforms/PostgreSQLPlatformTest.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Generator; use PHPUnit\Framework\Attributes\DataProvider; use UnexpectedValueException; @@ -191,6 +192,57 @@ public function testGenerateTableWithAutoincrement(): void ); } + #[DataProvider('pgTemporaryProvider')] + public function testGenerateTemporaryTable( + bool $temporary, + string|null $onCommit, + string $expectedSQL, + ): void { + $table = new Table('mytable'); + $table->addOption('temporary', $temporary); + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', 'string'); + + self::assertEquals( + [$expectedSQL], + $this->platform->getCreateTableSQL($table), + ); + } + + public static function pgTemporaryProvider(): Generator + { + yield 'temporary, no on commit option' => [true, null, 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, empty on commit option' => + [true, '', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, invalid on commit option' => + [true, 'invalid', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'non temporary' => [false, null, 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, preserve rows on commit' => + [true, 'preserve', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL) ON COMMIT PRESERVE ROWS']; + + yield 'non temporary, preserve rows on commit omitted' => + [false, 'preserve', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, delete rows on commit' => + [true, 'delete', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL) ON COMMIT DELETE ROWS']; + + yield 'non temporary, delete rows on commit omitted' => + [false, 'delete', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, drop on commit' => + [true, 'drop', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL) ON COMMIT DROP']; + + yield 'non temporary, drop on commit omitted' => + [false, 'drop', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + } + public function testGenerateUnloggedTable(): void { $table = new Table('mytable'); From 8b893ae16f53dbf9d84e342e57cd8ffaeee41ea6 Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 27 May 2024 18:51:01 +0200 Subject: [PATCH 02/12] Fixed error in on_commit option parsing --- src/Platforms/PostgreSQLPlatform.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php index a1296878ff8..ba4510aad89 100644 --- a/src/Platforms/PostgreSQLPlatform.php +++ b/src/Platforms/PostgreSQLPlatform.php @@ -393,12 +393,13 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $temporary = isset($options['temporary']) && $options['temporary'] === true ? ' TEMPORARY' : ''; - $onCommit = $options['temporary'] ?? false ? match ($options['on_commit'] ?? '') { + $onCommit = isset($options['temporary']) && $options['temporary'] === true + ? match ($options['on_commit']) { 'preserve' => ' ON COMMIT PRESERVE ROWS', 'delete' => ' ON COMMIT DELETE ROWS', 'drop' => ' ON COMMIT DROP', default => '' - } : ''; + } : ''; $unlogged = isset($options['unlogged']) && $options['unlogged'] === true ? ' UNLOGGED' : ''; From 2e1be8f4151fde9dbd12114a203d1afd6f4997dd Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Fri, 24 May 2024 16:29:13 +0200 Subject: [PATCH 03/12] Add support for creating temporary tables in schema This allows creating temporary tables in PostgreSQL specifying also the on commit options. --- docs/en/reference/schema-representation.rst | 13 +++++- src/Platforms/PostgreSQLPlatform.php | 11 ++++- tests/Platforms/PostgreSQLPlatformTest.php | 52 +++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/docs/en/reference/schema-representation.rst b/docs/en/reference/schema-representation.rst index f5aa7f4e0ac..fdabcd44bfc 100644 --- a/docs/en/reference/schema-representation.rst +++ b/docs/en/reference/schema-representation.rst @@ -93,7 +93,18 @@ and absolutely not portable. - **engine** (string): The DB engine used for the table. Currently only supported on MySQL. - **unlogged** (boolean): Set a PostgreSQL table type as - `unlogged `_ + `unlogged `_ + +- **temporary** (boolean): Set a PostgreSQL table type as + `temporary `_ + +- **on_commit** (string): Set a PostgreSQL table + `commit options `_, + only used if **temporary** is true + + - ``preserve``: preserve rows on commit + - ``delete``: delete rows on commit + - ``drop``: drop rows on commit Column ~~~~~~ diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php index f409f0aa701..a234716401c 100644 --- a/src/Platforms/PostgreSQLPlatform.php +++ b/src/Platforms/PostgreSQLPlatform.php @@ -382,9 +382,18 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; } + $temporary = isset($options['temporary']) && $options['temporary'] === true ? ' TEMPORARY' : ''; + + $onCommit = $options['temporary'] ?? false ? match ($options['on_commit'] ?? '') { + 'preserve' => ' ON COMMIT PRESERVE ROWS', + 'delete' => ' ON COMMIT DELETE ROWS', + 'drop' => ' ON COMMIT DROP', + default => '' + } : ''; + $unlogged = isset($options['unlogged']) && $options['unlogged'] === true ? ' UNLOGGED' : ''; - $query = 'CREATE' . $unlogged . ' TABLE ' . $name . ' (' . $queryFields . ')'; + $query = 'CREATE' . $temporary . $unlogged . ' TABLE ' . $name . ' (' . $queryFields . ')' . $onCommit; $sql = [$query]; diff --git a/tests/Platforms/PostgreSQLPlatformTest.php b/tests/Platforms/PostgreSQLPlatformTest.php index e3b78ebb0e7..362110af1a5 100644 --- a/tests/Platforms/PostgreSQLPlatformTest.php +++ b/tests/Platforms/PostgreSQLPlatformTest.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Generator; use PHPUnit\Framework\Attributes\DataProvider; use UnexpectedValueException; @@ -191,6 +192,57 @@ public function testGenerateTableWithAutoincrement(): void ); } + #[DataProvider('pgTemporaryProvider')] + public function testGenerateTemporaryTable( + bool $temporary, + string|null $onCommit, + string $expectedSQL, + ): void { + $table = new Table('mytable'); + $table->addOption('temporary', $temporary); + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', 'string'); + + self::assertEquals( + [$expectedSQL], + $this->platform->getCreateTableSQL($table), + ); + } + + public static function pgTemporaryProvider(): Generator + { + yield 'temporary, no on commit option' => [true, null, 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, empty on commit option' => + [true, '', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, invalid on commit option' => + [true, 'invalid', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'non temporary' => [false, null, 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, preserve rows on commit' => + [true, 'preserve', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL) ON COMMIT PRESERVE ROWS']; + + yield 'non temporary, preserve rows on commit omitted' => + [false, 'preserve', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, delete rows on commit' => + [true, 'delete', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL) ON COMMIT DELETE ROWS']; + + yield 'non temporary, delete rows on commit omitted' => + [false, 'delete', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + + yield 'temporary, drop on commit' => + [true, 'drop', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL) ON COMMIT DROP']; + + yield 'non temporary, drop on commit omitted' => + [false, 'drop', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; + } + public function testGenerateUnloggedTable(): void { $table = new Table('mytable'); From 00561f875d6b907fafe90c58b98fb058427871ce Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 27 May 2024 18:51:01 +0200 Subject: [PATCH 04/12] Fixed error in on_commit option parsing --- src/Platforms/PostgreSQLPlatform.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php index a234716401c..de62accce14 100644 --- a/src/Platforms/PostgreSQLPlatform.php +++ b/src/Platforms/PostgreSQLPlatform.php @@ -384,12 +384,13 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $temporary = isset($options['temporary']) && $options['temporary'] === true ? ' TEMPORARY' : ''; - $onCommit = $options['temporary'] ?? false ? match ($options['on_commit'] ?? '') { + $onCommit = isset($options['temporary']) && $options['temporary'] === true + ? match ($options['on_commit']) { 'preserve' => ' ON COMMIT PRESERVE ROWS', 'delete' => ' ON COMMIT DELETE ROWS', 'drop' => ' ON COMMIT DROP', default => '' - } : ''; + } : ''; $unlogged = isset($options['unlogged']) && $options['unlogged'] === true ? ' UNLOGGED' : ''; From 91c522c198814721f8d98b4a145c4e0d4e654c67 Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:17:24 +0200 Subject: [PATCH 05/12] Implement better sanity checks on option parsing --- src/Platforms/PostgreSQLPlatform.php | 21 ++++++++++--- tests/Platforms/PostgreSQLPlatformTest.php | 35 ++++++++++++++++++++-- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php index 6bcec00ffcf..ade0b0c910a 100644 --- a/src/Platforms/PostgreSQLPlatform.php +++ b/src/Platforms/PostgreSQLPlatform.php @@ -5,6 +5,7 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Platforms\Keywords\KeywordList; use Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords; use Doctrine\DBAL\Schema\ForeignKeyConstraint; @@ -383,16 +384,28 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; } - $temporary = isset($options['temporary']) && $options['temporary'] === true ? ' TEMPORARY' : ''; + $temporary = $options['temporary'] ?? false; + if (! is_bool($temporary)) { + throw new InvalidArgumentException(sprintf( + 'invalid temporary specification for table %s', + $name, + )); + } - $onCommit = isset($options['temporary']) && $options['temporary'] === true - ? match ($options['on_commit']) { + $onCommit = $temporary + ? match ($options['on_commit'] ?? '') { + '' => '', 'preserve' => ' ON COMMIT PRESERVE ROWS', 'delete' => ' ON COMMIT DELETE ROWS', 'drop' => ' ON COMMIT DROP', - default => '' + default => throw new InvalidArgumentException(sprintf( + 'invalid on commit clause on table %s', + $name, + )) } : ''; + $temporary = $temporary ? ' TEMPORARY' : ''; + $unlogged = isset($options['unlogged']) && $options['unlogged'] === true ? ' UNLOGGED' : ''; $query = 'CREATE' . $temporary . $unlogged . ' TABLE ' . $name . ' (' . $queryFields . ')' . $onCommit; diff --git a/tests/Platforms/PostgreSQLPlatformTest.php b/tests/Platforms/PostgreSQLPlatformTest.php index 362110af1a5..97102513499 100644 --- a/tests/Platforms/PostgreSQLPlatformTest.php +++ b/tests/Platforms/PostgreSQLPlatformTest.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Tests\Platforms; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\PostgreSQLPlatform; use Doctrine\DBAL\Schema\Column; @@ -219,9 +220,6 @@ public static function pgTemporaryProvider(): Generator yield 'temporary, empty on commit option' => [true, '', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; - yield 'temporary, invalid on commit option' => - [true, 'invalid', 'CREATE TEMPORARY TABLE mytable (foo VARCHAR NOT NULL)']; - yield 'non temporary' => [false, null, 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; yield 'temporary, preserve rows on commit' => @@ -243,6 +241,37 @@ public static function pgTemporaryProvider(): Generator [false, 'drop', 'CREATE TABLE mytable (foo VARCHAR NOT NULL)']; } + #[DataProvider('pgInvalidTemporaryProvider')] + public function testInvalidTemporaryTableOptions( + string $table, + mixed $temporary, + string|null $onCommit, + string $expectedException, + string $expectedMessage, + ): void { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedMessage); + + $table = new Table($table); + $table->addOption('temporary', $temporary); + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', 'string'); + + $this->platform->getCreateTableSQL($table); + } + + public static function pgInvalidTemporaryProvider(): Generator + { + yield 'valid temporary specification, invalid on commit option' => + ['mytable', true, 'invalid', InvalidArgumentException::class, 'invalid on commit clause on table mytable']; + + yield 'invalid temporary specification' => + ['mytable', 'invalid', '', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; + } + public function testGenerateUnloggedTable(): void { $table = new Table('mytable'); From 6d69ff05855df4240a0838e71267f7984990e09e Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:18:18 +0200 Subject: [PATCH 06/12] Implement temporary tables option for MySQL an MariaDB platforms --- src/Platforms/AbstractMySQLPlatform.php | 12 ++++- .../AbstractMySQLPlatformTestCase.php | 49 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/Platforms/AbstractMySQLPlatform.php b/src/Platforms/AbstractMySQLPlatform.php index 55cebe7ae9f..2cea57db80b 100644 --- a/src/Platforms/AbstractMySQLPlatform.php +++ b/src/Platforms/AbstractMySQLPlatform.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Platforms\Keywords\KeywordList; use Doctrine\DBAL\Platforms\Keywords\MySQLKeywords; use Doctrine\DBAL\Schema\AbstractAsset; @@ -24,6 +25,7 @@ use function count; use function implode; use function in_array; +use function is_bool; use function is_numeric; use function sprintf; use function str_replace; @@ -254,7 +256,15 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $sql = ['CREATE']; - if (! empty($options['temporary'])) { + $temporary = $options['temporary'] ?? false; + if (! is_bool($temporary)) { + throw new InvalidArgumentException(sprintf( + 'invalid temporary specification for table %s', + $name, + )); + } + + if ($temporary === true) { $sql[] = 'TEMPORARY'; } diff --git a/tests/Platforms/AbstractMySQLPlatformTestCase.php b/tests/Platforms/AbstractMySQLPlatformTestCase.php index 9c569cece8d..544abb87b03 100644 --- a/tests/Platforms/AbstractMySQLPlatformTestCase.php +++ b/tests/Platforms/AbstractMySQLPlatformTestCase.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Tests\Platforms; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Exception\InvalidColumnDeclaration; use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\MySQL; @@ -14,6 +15,8 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Types; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use function array_shift; @@ -176,6 +179,52 @@ public function testGetDateTimeTypeDeclarationSql(): void self::assertEquals('DATETIME', $this->platform->getDateTimeTypeDeclarationSQL([])); } + #[DataProvider('mysqlTemporaryProvider')] + public function testGenerateTemporaryTable( + bool $temporary, + string $expectedSQL, + ): void { + $table = new Table('mytable'); + $table->addOption('temporary', $temporary); + + $table->addColumn('foo', Types::STRING, ['length' => 255]); + + self::assertEquals( + [$expectedSQL], + $this->platform->getCreateTableSQL($table), + ); + } + + public static function mysqlTemporaryProvider(): Generator + { + yield 'temporary' => [true, 'CREATE TEMPORARY TABLE mytable (foo VARCHAR(255) NOT NULL)']; + yield 'non temporary' => [false, 'CREATE TABLE mytable (foo VARCHAR(255) NOT NULL)']; + } + + #[DataProvider('mysqlInvalidTemporaryProvider')] + public function testInvalidTemporaryTableOptions( + string $table, + mixed $temporary, + string $expectedException, + string $expectedMessage, + ): void { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedMessage); + + $table = new Table($table); + $table->addOption('temporary', $temporary); + + $table->addColumn('foo', Types::STRING, ['length' => 255]); + + $this->platform->getCreateTableSQL($table); + } + + public static function mysqlInvalidTemporaryProvider(): Generator + { + yield 'invalid temporary specification' => + ['mytable', 'invalid', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; + } + /** @return string[] */ protected function getQuotedColumnInPrimaryKeySQL(): array { From 3ed2b9642aafdd05289b7114213b80f87cff9c2c Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:18:27 +0200 Subject: [PATCH 07/12] Implement temporary tables option for DB2 platform --- src/Platforms/DB2Platform.php | 49 ++++++++++++++++++---- tests/Platforms/DB2PlatformTest.php | 65 +++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 8 deletions(-) diff --git a/src/Platforms/DB2Platform.php b/src/Platforms/DB2Platform.php index b66bf1c6b21..387951c0be8 100644 --- a/src/Platforms/DB2Platform.php +++ b/src/Platforms/DB2Platform.php @@ -5,6 +5,7 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Platforms\Exception\NotSupported; use Doctrine\DBAL\Platforms\Keywords\DB2Keywords; use Doctrine\DBAL\Platforms\Keywords\KeywordList; @@ -20,6 +21,8 @@ use Doctrine\DBAL\Types\Types; use function array_merge; +use function array_unique; +use function array_values; use function count; use function current; use function explode; @@ -241,20 +244,50 @@ public function getIndexDeclarationSQL(Index $index): string */ protected function _getCreateTableSQL(string $name, array $columns, array $options = []): array { - $indexes = []; - if (isset($options['indexes'])) { - $indexes = $options['indexes']; + $columnListSql = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $definition) { + $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($definition); + } } - $options['indexes'] = []; + if (isset($options['primary']) && ! empty($options['primary'])) { + $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')'; + } + + $statement = match ($options['temporary'] ?? '') { + '' => 'CREATE TABLE ', + 'created' => 'CREATE GLOBAL TEMPORARY TABLE ', + 'declared' => 'DECLARE GLOBAL TEMPORARY TABLE ', + default => throw new InvalidArgumentException(sprintf( + 'invalid temporary specification for table %s', + $name, + )) + }; + + $query = $statement . $name . ' (' . $columnListSql; + $check = $this->getCheckDeclarationSQL($columns); + + if (! empty($check)) { + $query .= ', ' . $check; + } - $sqls = parent::_getCreateTableSQL($name, $columns, $options); + $query .= ')'; + + $sql = [$query]; + + if (isset($options['foreignKeys'])) { + foreach ($options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $name); + } + } - foreach ($indexes as $definition) { - $sqls[] = $this->getCreateIndexSQL($definition, $name); + foreach ($options['indexes'] ?? [] as $definition) { + $sql[] = $this->getCreateIndexSQL($definition, $name); } - return $sqls; + return $sql; } /** diff --git a/tests/Platforms/DB2PlatformTest.php b/tests/Platforms/DB2PlatformTest.php index 4000b3f4cca..72e6b8450e1 100644 --- a/tests/Platforms/DB2PlatformTest.php +++ b/tests/Platforms/DB2PlatformTest.php @@ -4,6 +4,7 @@ namespace Doctrine\DBAL\Tests\Platforms; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Exception\InvalidColumnDeclaration; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\DB2Platform; @@ -14,6 +15,7 @@ use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Generator; use PHPUnit\Framework\Attributes\DataProvider; /** @extends AbstractPlatformTestCase */ @@ -465,6 +467,69 @@ public function testGeneratesAlterColumnSQL( self::assertSame($expectedSQL, $this->platform->getAlterTableSQL($tableDiff)); } + #[DataProvider('db2TemporaryProvider')] + public function testGenerateTemporaryTable( + string|null $temporary, + string $table, + string $expectedSQL, + ): void { + $table = new Table($table); + if ($temporary !== null) { + $table->addOption('temporary', $temporary); + } + + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', Types::INTEGER); + + self::assertEquals( + [$expectedSQL], + $this->platform->getCreateTableSQL($table), + ); + } + + public static function db2TemporaryProvider(): Generator + { + yield 'null temporary' => [null, 'mytable', 'CREATE TABLE mytable (foo INTEGER NOT NULL)']; + yield 'empty temporary' => ['', 'mytable', 'CREATE TABLE mytable (foo INTEGER NOT NULL)']; + + yield 'created temporary' => + ['created', 'mytable', 'CREATE GLOBAL TEMPORARY TABLE mytable (foo INTEGER NOT NULL)']; + + yield 'declared temporary' => + ['declared', 'mytable', 'DECLARE GLOBAL TEMPORARY TABLE mytable (foo INTEGER NOT NULL)']; + } + + #[DataProvider('db2InvalidTemporaryProvider')] + public function testInvalidTemporaryTableOptions( + string $table, + mixed $temporary, + string|null $onCommit, + string $expectedException, + string $expectedMessage, + ): void { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedMessage); + + $table = new Table($table); + $table->addOption('temporary', $temporary); + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', Types::INTEGER); + + $this->platform->getCreateTableSQL($table); + } + + public static function db2InvalidTemporaryProvider(): Generator + { + yield 'invalid temporary specification' => + ['mytable', 'invalid', '', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; + } + /** @return mixed[][] */ public static function getGeneratesAlterColumnSQL(): iterable { From 4283b371fc9430daaaa37c40ee56305f213efb9a Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:18:41 +0200 Subject: [PATCH 08/12] Implement temporary tables option for Oracle platform --- src/Platforms/OraclePlatform.php | 67 ++++++++++++++++-- tests/Platforms/OraclePlatformTest.php | 96 ++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 5 deletions(-) diff --git a/src/Platforms/OraclePlatform.php b/src/Platforms/OraclePlatform.php index 692516efcc2..3cb10eea479 100644 --- a/src/Platforms/OraclePlatform.php +++ b/src/Platforms/OraclePlatform.php @@ -5,6 +5,7 @@ namespace Doctrine\DBAL\Platforms; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Exception\InvalidColumnType\ColumnLengthRequired; use Doctrine\DBAL\Platforms\Keywords\KeywordList; use Doctrine\DBAL\Platforms\Keywords\OracleKeywords; @@ -17,15 +18,18 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\BinaryType; use Doctrine\DBAL\Types\Types; -use InvalidArgumentException; use function array_merge; +use function array_unique; +use function array_values; use function count; use function explode; use function implode; use function sprintf; use function str_contains; +use function str_starts_with; use function strlen; +use function strtolower; use function strtoupper; use function substr; @@ -313,9 +317,62 @@ public function getListSequencesSQL(string $database): string */ protected function _getCreateTableSQL(string $name, array $columns, array $options = []): array { - $indexes = $options['indexes'] ?? []; - $options['indexes'] = []; - $sql = parent::_getCreateTableSQL($name, $columns, $options); + $columnListSql = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $definition) { + $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($definition); + } + } + + if (isset($options['primary']) && ! empty($options['primary'])) { + $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')'; + } + + $temporary = match ($options['temporary'] ?? '') { + '' => '', + 'global' => 'GLOBAL TEMPORARY ', + 'private' => 'PRIVATE TEMPORARY ', + default => throw new InvalidArgumentException(sprintf( + 'invalid temporary specification for table %s', + $name, + )) + }; + + if (($options['temporary'] ?? '') === 'private' && str_starts_with('ora$ptt_', strtolower($name)) === false) { + throw new InvalidArgumentException(sprintf( + 'invalid name "%s" for private temporary table', + $name, + )); + } + + $onCommit = $temporary !== '' + ? match ($options['on_commit'] ?? '') { + '' => '', + 'preserve' => ' ON COMMIT PRESERVE ROWS', + 'delete' => ' ON COMMIT DELETE ROWS', + default => throw new InvalidArgumentException(sprintf( + 'invalid on commit clause on table %s', + $name, + )) + } : ''; + + $query = 'CREATE ' . $temporary . 'TABLE ' . $name . ' (' . $columnListSql; + $check = $this->getCheckDeclarationSQL($columns); + + if (! empty($check)) { + $query .= ', ' . $check; + } + + $query .= ')' . $onCommit; + + $sql = [$query]; + + if (isset($options['foreignKeys'])) { + foreach ($options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $name); + } + } foreach ($columns as $column) { if (isset($column['sequence'])) { @@ -331,7 +388,7 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $sql = array_merge($sql, $this->getCreateAutoincrementSql($column['name'], $name)); } - foreach ($indexes as $index) { + foreach ($options['indexes'] as $index) { $sql[] = $this->getCreateIndexSQL($index, $name); } diff --git a/tests/Platforms/OraclePlatformTest.php b/tests/Platforms/OraclePlatformTest.php index dfb5b85036b..14d102e3949 100644 --- a/tests/Platforms/OraclePlatformTest.php +++ b/tests/Platforms/OraclePlatformTest.php @@ -5,6 +5,7 @@ namespace Doctrine\DBAL\Tests\Platforms; use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Exception\InvalidColumnDeclaration; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\OraclePlatform; @@ -15,6 +16,7 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Generator; use PHPUnit\Framework\Attributes\DataProvider; use function sprintf; @@ -123,6 +125,100 @@ public function testSupportsSavePoints(): void self::assertTrue($this->platform->supportsSavepoints()); } + #[DataProvider('oraTemporaryProvider')] + public function testGenerateTemporaryTable( + string|null $temporary, + string|null $onCommit, + string $table, + string $expectedSQL, + ): void { + $table = new Table($table); + if ($temporary !== null) { + $table->addOption('temporary', $temporary); + } + + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', Types::INTEGER); + + self::assertEquals( + [$expectedSQL], + $this->platform->getCreateTableSQL($table), + ); + } + + public static function oraTemporaryProvider(): Generator + { + yield 'null temporary' => [null, null, 'mytable', 'CREATE TABLE mytable (foo NUMBER(10) NOT NULL)']; + yield 'empty temporary' => ['', null, 'mytable', 'CREATE TABLE mytable (foo NUMBER(10) NOT NULL)']; + + yield 'global temporary, no on commit option' => + ['global', null, 'mytable', 'CREATE GLOBAL TEMPORARY TABLE mytable (foo NUMBER(10) NOT NULL)']; + + yield 'global temporary, empty on commit option' => + ['global', '', 'mytable', 'CREATE GLOBAL TEMPORARY TABLE mytable (foo NUMBER(10) NOT NULL)']; + + yield 'global temporary, preserve rows on commit' => + ['global', 'preserve', 'mytable', 'CREATE GLOBAL TEMPORARY TABLE mytable (foo NUMBER(10) NOT NULL) ON COMMIT PRESERVE ROWS']; + + yield 'global temporary, delete rows on commit' => + ['global', 'delete', 'mytable', 'CREATE GLOBAL TEMPORARY TABLE mytable (foo NUMBER(10) NOT NULL) ON COMMIT DELETE ROWS']; + + yield 'private temporary, no on commit option' => + ['private', null, 'ORA$PTT', 'CREATE PRIVATE TEMPORARY TABLE ORA$PTT (foo NUMBER(10) NOT NULL)']; + + yield 'private temporary, empty on commit option' => + ['private', '', 'ORA$PTT', 'CREATE PRIVATE TEMPORARY TABLE ORA$PTT (foo NUMBER(10) NOT NULL)']; + + yield 'private temporary, preserve rows on commit' => + ['private', 'preserve', 'ORA$PTT', 'CREATE PRIVATE TEMPORARY TABLE ORA$PTT (foo NUMBER(10) NOT NULL) ON COMMIT PRESERVE ROWS']; + + yield 'private temporary, delete rows on commit' => + ['private', 'delete', 'ORA$PTT', 'CREATE PRIVATE TEMPORARY TABLE ORA$PTT (foo NUMBER(10) NOT NULL) ON COMMIT DELETE ROWS']; + + yield 'non temporary, preserve rows on commit omitted' => + [null, 'preserve', 'mytable', 'CREATE TABLE mytable (foo NUMBER(10) NOT NULL)']; + + yield 'non temporary, delete rows on commit omitted' => + [null, 'delete', 'mytable', 'CREATE TABLE mytable (foo NUMBER(10) NOT NULL)']; + } + + #[DataProvider( 'oraInvalidTemporaryProvider' )] + public function testInvalidTemporaryTableOptions( + string $table, + mixed $temporary, + string|null $onCommit, + string $expectedException, + string $expectedMessage, + ): void { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedMessage); + + $table = new Table($table); + $table->addOption('temporary', $temporary); + if ($onCommit !== null) { + $table->addOption('on_commit', $onCommit); + } + + $table->addColumn('foo', Types::INTEGER); + + $this->platform->getCreateTableSQL($table); + } + + public static function oraInvalidTemporaryProvider(): Generator + { + yield 'valid temporary specification, invalid on commit option' => + ['mytable', 'global', 'invalid', InvalidArgumentException::class, 'invalid on commit clause on table mytable']; + + yield 'invalid temporary specification' => + ['mytable', 'invalid', '', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; + + yield 'invalid table name for private temporary table' => + ['mytable', 'private', '', InvalidArgumentException::class, 'invalid name "mytable" for private temporary table']; + } + protected function supportsCommentOnStatement(): bool { return true; From e5124090ce5d271e4fc1bb177f2e246c19da14e7 Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:18:52 +0200 Subject: [PATCH 09/12] Implement temporary tables option for SQLite platform --- src/Platforms/SQLitePlatform.php | 13 ++++++- tests/Platforms/SQLitePlatformTest.php | 49 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Platforms/SQLitePlatform.php b/src/Platforms/SQLitePlatform.php index 32f28f28af6..b26b5e261cc 100644 --- a/src/Platforms/SQLitePlatform.php +++ b/src/Platforms/SQLitePlatform.php @@ -32,6 +32,7 @@ use function count; use function explode; use function implode; +use function is_bool; use function sprintf; use function str_replace; use function strpos; @@ -293,7 +294,17 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio $tableComment = $this->getInlineTableCommentSQL($comment); } - $query = ['CREATE TABLE ' . $name . ' ' . $tableComment . '(' . $queryFields . ')']; + $temporary = $options['temporary'] ?? false; + if (! is_bool($temporary)) { + throw new \Doctrine\DBAL\Exception\InvalidArgumentException(sprintf( + 'invalid temporary specification for table %s', + $name, + )); + } + + $temporary = $temporary ? 'TEMPORARY ' : ''; + + $query = ['CREATE ' . $temporary . 'TABLE ' . $name . ' ' . $tableComment . '(' . $queryFields . ')']; if (isset($options['alter']) && $options['alter'] === true) { return $query; diff --git a/tests/Platforms/SQLitePlatformTest.php b/tests/Platforms/SQLitePlatformTest.php index 5d400c37eae..0a907f70747 100644 --- a/tests/Platforms/SQLitePlatformTest.php +++ b/tests/Platforms/SQLitePlatformTest.php @@ -5,6 +5,7 @@ namespace Doctrine\DBAL\Tests\Platforms; use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Exception\InvalidArgumentException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\SQLite; use Doctrine\DBAL\Platforms\SQLitePlatform; @@ -17,6 +18,8 @@ use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Generator; +use PHPUnit\Framework\Attributes\DataProvider; use function implode; @@ -635,4 +638,50 @@ public function testGetCreateTableSQLWithColumnCollation(): void $this->platform->getCreateTableSQL($table), ); } + + #[DataProvider('sqliteTemporaryProvider')] + public function testGenerateTemporaryTable( + bool $temporary, + string $expectedSQL, + ): void { + $table = new Table('mytable'); + $table->addOption('temporary', $temporary); + + $table->addColumn('foo', Types::STRING, ['length' => 255]); + + self::assertEquals( + [$expectedSQL], + $this->platform->getCreateTableSQL($table), + ); + } + + public static function sqliteTemporaryProvider(): Generator + { + yield 'temporary' => [true, 'CREATE TEMPORARY TABLE mytable (foo VARCHAR(255) NOT NULL)']; + yield 'non temporary' => [false, 'CREATE TABLE mytable (foo VARCHAR(255) NOT NULL)']; + } + + #[DataProvider('sqliteInvalidTemporaryProvider')] + public function testInvalidTemporaryTableOptions( + string $table, + mixed $temporary, + string $expectedException, + string $expectedMessage, + ): void { + $this->expectException($expectedException); + $this->expectExceptionMessage($expectedMessage); + + $table = new Table($table); + $table->addOption('temporary', $temporary); + + $table->addColumn('foo', Types::STRING, ['length' => 255]); + + $this->platform->getCreateTableSQL($table); + } + + public static function sqliteInvalidTemporaryProvider(): Generator + { + yield 'invalid temporary specification' => + ['mytable', 'invalid', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; + } } From 7f8f8fb60dd990844984d0d6405845d9656777cc Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:35:32 +0200 Subject: [PATCH 10/12] Document options for all platforms --- docs/en/reference/schema-representation.rst | 26 ++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/docs/en/reference/schema-representation.rst b/docs/en/reference/schema-representation.rst index fdabcd44bfc..20dd4c26d0e 100644 --- a/docs/en/reference/schema-representation.rst +++ b/docs/en/reference/schema-representation.rst @@ -95,16 +95,30 @@ and absolutely not portable. - **unlogged** (boolean): Set a PostgreSQL table type as `unlogged `_ -- **temporary** (boolean): Set a PostgreSQL table type as - `temporary `_ +- **temporary** (boolean or string): Set table type as temporary + Supported on DB2, MySQL, MariaDB, Oracle, PostgreSQL and SQLite. SQL Server does not have a specific DML for temporary tables. -- **on_commit** (string): Set a PostgreSQL table - `commit options `_, - only used if **temporary** is true + Option values for MySQL, MariaDB, PostgreSQL and SQLite: + + - true (bool) + - false (bool) + + Option values for Oracle: + + - global (string): emits CREATE GLOBAL TEMPORARY TABLE statement + - private (string): emits CREATE PRIVATE TEMPORARY TABLE statement, table name must begin with PRIVATE_TEMP_TABLE_PREFIX, default 'ORA$PTT' + + Option values for DB2: + + - created (string): emits CREATE GLOBAL TEMPORARY TABLE statement + - declared (string): emits DECLARE GLOBAL TEMPORARY TABLE statement + +- **on_commit** (string): declare table's commit options, only used if option **temporary** is set. + Supported on Oracle and PostgreSQL - ``preserve``: preserve rows on commit - ``delete``: delete rows on commit - - ``drop``: drop rows on commit + - ``drop``: drop table on commit - only supported by PostgreSQL Column ~~~~~~ From 7e3133b253959f30f3bba7301cea8ca62d039afb Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 17:36:51 +0200 Subject: [PATCH 11/12] Minor cosmetic fix --- docs/en/reference/schema-representation.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en/reference/schema-representation.rst b/docs/en/reference/schema-representation.rst index 20dd4c26d0e..b0cf904ac67 100644 --- a/docs/en/reference/schema-representation.rst +++ b/docs/en/reference/schema-representation.rst @@ -100,18 +100,18 @@ and absolutely not portable. Option values for MySQL, MariaDB, PostgreSQL and SQLite: - - true (bool) - - false (bool) + - ``true`` (bool) + - ``false`` (bool) Option values for Oracle: - - global (string): emits CREATE GLOBAL TEMPORARY TABLE statement - - private (string): emits CREATE PRIVATE TEMPORARY TABLE statement, table name must begin with PRIVATE_TEMP_TABLE_PREFIX, default 'ORA$PTT' + - ``global`` (string): emits CREATE GLOBAL TEMPORARY TABLE statement + - ``private`` (string): emits CREATE PRIVATE TEMPORARY TABLE statement, table name must begin with PRIVATE_TEMP_TABLE_PREFIX, default 'ORA$PTT' Option values for DB2: - - created (string): emits CREATE GLOBAL TEMPORARY TABLE statement - - declared (string): emits DECLARE GLOBAL TEMPORARY TABLE statement + - ``created`` (string): emits CREATE GLOBAL TEMPORARY TABLE statement + - ``declared`` (string): emits DECLARE GLOBAL TEMPORARY TABLE statement - **on_commit** (string): declare table's commit options, only used if option **temporary** is set. Supported on Oracle and PostgreSQL From af36e6e07a725607756d15c388ad56f23bbacfe8 Mon Sep 17 00:00:00 2001 From: Alessandro Morelli Date: Mon, 19 Aug 2024 20:34:54 +0200 Subject: [PATCH 12/12] Remove data providers with single set of data --- .../AbstractMySQLPlatformTestCase.php | 23 ++++---------- tests/Platforms/DB2PlatformTest.php | 31 ++++--------------- tests/Platforms/SQLitePlatformTest.php | 23 ++++---------- 3 files changed, 18 insertions(+), 59 deletions(-) diff --git a/tests/Platforms/AbstractMySQLPlatformTestCase.php b/tests/Platforms/AbstractMySQLPlatformTestCase.php index 544abb87b03..80b9d27a2e1 100644 --- a/tests/Platforms/AbstractMySQLPlatformTestCase.php +++ b/tests/Platforms/AbstractMySQLPlatformTestCase.php @@ -201,30 +201,19 @@ public static function mysqlTemporaryProvider(): Generator yield 'non temporary' => [false, 'CREATE TABLE mytable (foo VARCHAR(255) NOT NULL)']; } - #[DataProvider('mysqlInvalidTemporaryProvider')] - public function testInvalidTemporaryTableOptions( - string $table, - mixed $temporary, - string $expectedException, - string $expectedMessage, - ): void { - $this->expectException($expectedException); - $this->expectExceptionMessage($expectedMessage); + public function testInvalidTemporaryTableOptions(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('invalid temporary specification for table mytable'); - $table = new Table($table); - $table->addOption('temporary', $temporary); + $table = new Table('mytable'); + $table->addOption('temporary', 'invalid'); $table->addColumn('foo', Types::STRING, ['length' => 255]); $this->platform->getCreateTableSQL($table); } - public static function mysqlInvalidTemporaryProvider(): Generator - { - yield 'invalid temporary specification' => - ['mytable', 'invalid', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; - } - /** @return string[] */ protected function getQuotedColumnInPrimaryKeySQL(): array { diff --git a/tests/Platforms/DB2PlatformTest.php b/tests/Platforms/DB2PlatformTest.php index 72e6b8450e1..0dc467d976c 100644 --- a/tests/Platforms/DB2PlatformTest.php +++ b/tests/Platforms/DB2PlatformTest.php @@ -478,10 +478,6 @@ public function testGenerateTemporaryTable( $table->addOption('temporary', $temporary); } - if ($onCommit !== null) { - $table->addOption('on_commit', $onCommit); - } - $table->addColumn('foo', Types::INTEGER); self::assertEquals( @@ -502,34 +498,19 @@ public static function db2TemporaryProvider(): Generator ['declared', 'mytable', 'DECLARE GLOBAL TEMPORARY TABLE mytable (foo INTEGER NOT NULL)']; } - #[DataProvider('db2InvalidTemporaryProvider')] - public function testInvalidTemporaryTableOptions( - string $table, - mixed $temporary, - string|null $onCommit, - string $expectedException, - string $expectedMessage, - ): void { - $this->expectException($expectedException); - $this->expectExceptionMessage($expectedMessage); + public function testInvalidTemporaryTableOptions(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('invalid temporary specification for table mytable'); - $table = new Table($table); - $table->addOption('temporary', $temporary); - if ($onCommit !== null) { - $table->addOption('on_commit', $onCommit); - } + $table = new Table('mytable'); + $table->addOption('temporary', 'invalid'); $table->addColumn('foo', Types::INTEGER); $this->platform->getCreateTableSQL($table); } - public static function db2InvalidTemporaryProvider(): Generator - { - yield 'invalid temporary specification' => - ['mytable', 'invalid', '', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; - } - /** @return mixed[][] */ public static function getGeneratesAlterColumnSQL(): iterable { diff --git a/tests/Platforms/SQLitePlatformTest.php b/tests/Platforms/SQLitePlatformTest.php index 0a907f70747..469e032ce0d 100644 --- a/tests/Platforms/SQLitePlatformTest.php +++ b/tests/Platforms/SQLitePlatformTest.php @@ -661,27 +661,16 @@ public static function sqliteTemporaryProvider(): Generator yield 'non temporary' => [false, 'CREATE TABLE mytable (foo VARCHAR(255) NOT NULL)']; } - #[DataProvider('sqliteInvalidTemporaryProvider')] - public function testInvalidTemporaryTableOptions( - string $table, - mixed $temporary, - string $expectedException, - string $expectedMessage, - ): void { - $this->expectException($expectedException); - $this->expectExceptionMessage($expectedMessage); + public function testInvalidTemporaryTableOptions(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('invalid temporary specification for table mytable'); - $table = new Table($table); - $table->addOption('temporary', $temporary); + $table = new Table('mytable'); + $table->addOption('temporary', 'invalid'); $table->addColumn('foo', Types::STRING, ['length' => 255]); $this->platform->getCreateTableSQL($table); } - - public static function sqliteInvalidTemporaryProvider(): Generator - { - yield 'invalid temporary specification' => - ['mytable', 'invalid', InvalidArgumentException::class, 'invalid temporary specification for table mytable']; - } }