From 6342f303afac1774ea47037e32dfe9655c4b5152 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Wed, 17 Jul 2024 22:18:09 +0700 Subject: [PATCH 01/12] Address PK issues for show create table queries --- tests/WP_SQLite_Translator_Tests.php | 29 +-- .../sqlite/class-wp-sqlite-translator.php | 195 +++++++++++++----- 2 files changed, 161 insertions(+), 63 deletions(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index 7a334eeb..65694e44 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -278,12 +278,13 @@ public function testShowCreateTable1() { $results = $this->engine->get_query_results(); # TODO: Should we fix mismatch with original `option_value` text NOT NULL,` without default? $this->assertEquals( - "CREATE TABLE _tmp_table ( - `ID` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + "CREATE TABLE `_tmp_table` ( + `ID` bigint NOT NULL DEFAULT 0 AUTO_INCREMENT, `option_name` varchar(255) DEFAULT '', `option_value` text NOT NULL DEFAULT '', - KEY _tmp_table__composite (option_name, option_value), - UNIQUE KEY _tmp_table__option_name (option_name) + PRIMARY KEY (`ID`), + KEY `_tmp_table__composite` (`option_name`, `option_value`), + UNIQUE KEY `_tmp_table__option_name` (`option_name`) );", $results[0]->{'Create Table'} ); @@ -306,12 +307,13 @@ public function testShowCreateTableQuoted() { $results = $this->engine->get_query_results(); # TODO: Should we fix mismatch with original `option_value` text NOT NULL,` without default? $this->assertEquals( - "CREATE TABLE _tmp_table ( - `ID` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + "CREATE TABLE `_tmp_table` ( + `ID` bigint NOT NULL DEFAULT 0 AUTO_INCREMENT, `option_name` varchar(255) DEFAULT '', `option_value` text NOT NULL DEFAULT '', - KEY _tmp_table__composite (option_name, option_value), - UNIQUE KEY _tmp_table__option_name (option_name) + PRIMARY KEY (`ID`), + KEY `_tmp_table__composite` (`option_name`, `option_value`), + UNIQUE KEY `_tmp_table__option_name` (`option_name`) );", $results[0]->{'Create Table'} ); @@ -329,8 +331,8 @@ public function testShowCreateTableSimpleTable() { ); $results = $this->engine->get_query_results(); $this->assertEquals( - 'CREATE TABLE _tmp_table ( - `ID` bigint NOT NULL + 'CREATE TABLE `_tmp_table` ( + `ID` bigint NOT NULL DEFAULT 0 );', $results[0]->{'Create Table'} ); @@ -358,11 +360,12 @@ public function testShowCreateTableWithAlterAndCreateIndex() { ); $results = $this->engine->get_query_results(); $this->assertEquals( - 'CREATE TABLE _tmp_table ( - `ID` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + 'CREATE TABLE `_tmp_table` ( + `ID` bigint NOT NULL DEFAULT 0 AUTO_INCREMENT, `option_name` smallint NOT NULL DEFAULT 14, `option_value` text NOT NULL DEFAULT \'\', - KEY _tmp_table__option_name (option_name) + PRIMARY KEY (`ID`), + KEY `_tmp_table__option_name` (`option_name`) );', $results[0]->{'Create Table'} ); diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index ac6a170c..c26dcdc8 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3338,56 +3338,7 @@ private function execute_show() { return; case 'CREATE TABLE': - // Value is unquoted table name - $table_name = $this->rewriter->consume()->value; - $columns = $this->get_columns_from( $table_name ); - $keys = $this->get_keys( $table_name ); - - if ( empty( $columns ) ) { - $this->set_results_from_fetched_data( - array() - ); - return; - } - - foreach ( $columns as $column ) { - $column = (array) $column; - $definition = ''; - $definition .= '`' . $column['Field'] . '` '; - $definition .= $this->get_cached_mysql_data_type( - $table_name, - $column['Field'] - ) ?? $column['Type']; - $definition .= 'PRI' === $column['Key'] ? ' PRIMARY KEY' : ''; - $definition .= 'PRI' === $column['Key'] && 'INTEGER' === $column['Type'] ? ' AUTO_INCREMENT' : ''; - $definition .= 'NO' === $column['Null'] ? ' NOT NULL' : ''; - $definition .= $column['Default'] ? ' DEFAULT ' . $column['Default'] : ''; - $entries[] = $definition; - } - foreach ( $keys as $key ) { - $key = (array) $key; - $definition = ''; - $definition .= '1' === $key['index']['unique'] ? 'UNIQUE ' : ''; - $definition .= 'KEY '; - $definition .= $key['index']['name']; - $definition .= ' ('; - $definition .= implode( - ', ', - array_column( $key['columns'], 'name' ) - ); - $definition .= ')'; - $entries[] = $definition; - } - $create_table = "CREATE TABLE $table_name (\n\t"; - $create_table .= implode( ",\n\t", $entries ); - $create_table .= "\n);"; - $this->set_results_from_fetched_data( - array( - (object) array( - 'Create Table' => $create_table, - ), - ) - ); + $this->generate_create_statement(); return; case 'TABLE STATUS': // FROM `database`. @@ -3488,6 +3439,149 @@ private function execute_show() { } } + private function generate_create_statement() { + $table_name = $this->rewriter->consume()->value; + $columns = $this->get_table_columns( $table_name ); + + if ( empty( $columns ) ) { + $this->set_results_from_fetched_data( array() ); + return; + } + + $column_definitions = $this->get_column_definitions( $table_name, $columns ); + $key_definitions = $this->get_key_definitions( $table_name ); + $pk_definition = $this->get_primary_key_definition( $columns ); + + if ( $pk_definition ) { + array_unshift( $key_definitions, $pk_definition ); + } + + $sql_parts = array( + "CREATE TABLE `$table_name` (", + "\t" . implode( ",\n\t", array_merge( $column_definitions, $key_definitions ) ), + ');', + ); + + $this->set_results_from_fetched_data( + array( + (object) array( + 'Create Table' => implode( "\n", $sql_parts ), + ), + ) + ); + } + + /** + * Get columns from pragma table info for the given table. + * + * @param string $table_name + * + * @return stdClass[] + */ + protected function get_table_columns( $table_name ) { + return $this->execute_sqlite_query( "PRAGMA table_info(\"$table_name\");" ) + ->fetchAll( $this->pdo_fetch_mode ); + } + + /** + * Get the column definitions for a create statement + * + * @param string $table_name + * @param array $columns + * + * @return array An array of column definitions + */ + protected function get_column_definitions( $table_name, $columns ) { + $auto_increment_column = $this->get_autoincrement_column( $table_name ); + $column_definitions = array(); + foreach ( $columns as $column ) { + $definition = array(); + $definition[] = '`' . $column->name . '`'; + $definition[] = $this->get_cached_mysql_data_type( $table_name, $column->name ) ?? $column->name; + + if ( '1' === $column->notnull ) { + $definition[] = 'NOT NULL'; + } + + if ( '' !== $column->dflt_value ) { + $definition[] = 'DEFAULT ' . $column->dflt_value; // quotes? + } + + if ( $auto_increment_column && strtolower( $auto_increment_column ) === strtolower( $column->name ) ) { + $definition[] = 'AUTO_INCREMENT'; + } + $column_definitions[] = implode( ' ', $definition ); + } + + return $column_definitions; + } + + /** + * Get the key definitions for a create statement + * + * @param $table_name + * + * @return array An array of key definitions + */ + private function get_key_definitions( $table_name ) { + $key_definitions = array(); + foreach ( $this->get_keys( $table_name ) as $key ) { + $key_definition = array(); + if ( $key['index']['unique'] ) { + $key_definition[] = 'UNIQUE'; + } + + $key_definition[] = 'KEY'; + + $key_definition[] = sprintf( '`%s`', $key['index']['name'] ); + + $key_definition[] = '(' . implode( ', ', array_map( function ( $column ) { + return sprintf('`%s`', $column['name'] ); + }, $key['columns'] ) ) . ')'; + + $key_definitions[] = implode( ' ', $key_definition ); + } + + return $key_definitions; + } + + /** + * Get the definition for the primary key(s) of a table. + * + * @param array $columns result from PRAGMA table_info() query + * + * @return string|null definition for the primary key(s) + */ + private function get_primary_key_definition( $columns ) { + $primary_keys = array(); + foreach ( $columns as $column ) { + if ( '0' !== $column->pk ) { + $primary_keys[] = $column->name; + } + } + + return ! empty( $primary_keys ) + ? sprintf( 'PRIMARY KEY (`%s`)', implode( ', ', $primary_keys ) ) + : null; + } + + /** + * Get the auto-increment column from a table. + * + * @param $table_name + * + * @return string|null + */ + private function get_autoincrement_column( $table_name ) { + preg_match( + '/"([^"]+)"\s+integer\s+primary\s+key\s+autoincrement/i', + $this->get_sqlite_create_table( $table_name ), + $matches + ); + + return $matches[1] ?? null; + } + /** * Gets the columns from a table. * @@ -3509,6 +3603,7 @@ private function get_columns_from( $table_name ) { 'pk' => null, ); $columns = $stmt->fetchAll( $this->pdo_fetch_mode ); + $columns = array_map( function ( $row ) use ( $name_map ) { $new = array(); From a5e0f2cf6e76161a0c46200804163c281a4a8081 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Wed, 17 Jul 2024 23:07:20 +0700 Subject: [PATCH 02/12] Skip the unique key if it is equal to the PK --- .../sqlite/class-wp-sqlite-translator.php | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index c26dcdc8..aa23a27e 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -886,6 +886,7 @@ private function execute_create_table() { implode( ",\n", $definitions ) . ')' ); + $this->execute_sqlite_query( $create_query ); $this->results = $this->last_exec_returned; $this->return_value = $this->results; @@ -897,6 +898,7 @@ private function execute_create_table() { $unique = 'UNIQUE '; } $index_name = "{$table->name}__{$constraint->name}"; + $this->execute_sqlite_query( "CREATE $unique INDEX \"$index_name\" ON \"{$table->name}\" (\"" . implode( '", "', $constraint->columns ) . '")' ); @@ -3449,7 +3451,7 @@ private function generate_create_statement() { } $column_definitions = $this->get_column_definitions( $table_name, $columns ); - $key_definitions = $this->get_key_definitions( $table_name ); + $key_definitions = $this->get_key_definitions( $table_name, $columns ); $pk_definition = $this->get_primary_key_definition( $columns ); if ( $pk_definition ) { @@ -3523,9 +3525,24 @@ protected function get_column_definitions( $table_name, $columns ) { * * @return array An array of key definitions */ - private function get_key_definitions( $table_name ) { + private function get_key_definitions( $table_name, $columns ) { $key_definitions = array(); + + $pks = array(); + foreach ( $columns as $column ) { + if ( '0' !== $column->pk ) { + $pks[] = $column->name; + } + } + foreach ( $this->get_keys( $table_name ) as $key ) { + // If the PK columns are the same as the unique key columns, skip the key. + // This is because the PK is already unique in MySQL. + $key_equals_pk = ! array_diff( $pks, array_column( $key['columns'], 'name' ) ); + if ( $key['index']['unique'] && $key_equals_pk ) { + continue; + } + $key_definition = array(); if ( $key['index']['unique'] ) { $key_definition[] = 'UNIQUE'; @@ -3535,9 +3552,14 @@ private function get_key_definitions( $table_name ) { $key_definition[] = sprintf( '`%s`', $key['index']['name'] ); - $key_definition[] = '(' . implode( ', ', array_map( function ( $column ) { - return sprintf('`%s`', $column['name'] ); - }, $key['columns'] ) ) . ')'; + $cols = array_map( + function ( $column ) { + return sprintf( '`%s`', $column['name'] ); + }, + $key['columns'] + ); + + $key_definition[] = '(' . implode( ', ', $cols ) . ')'; $key_definitions[] = implode( ' ', $key_definition ); } @@ -3556,12 +3578,12 @@ private function get_primary_key_definition( $columns ) { $primary_keys = array(); foreach ( $columns as $column ) { if ( '0' !== $column->pk ) { - $primary_keys[] = $column->name; + $primary_keys[] = sprintf('`%s`', $column->name ); } } return ! empty( $primary_keys ) - ? sprintf( 'PRIMARY KEY (`%s`)', implode( ', ', $primary_keys ) ) + ? sprintf( 'PRIMARY KEY (%s)', implode( ', ', $primary_keys ) ) : null; } From e3c0e60b7e4cc37c822fdf0fcca8eb8ab3676767 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Wed, 17 Jul 2024 23:15:16 +0700 Subject: [PATCH 03/12] Fix code style issues --- wp-includes/sqlite/class-wp-sqlite-translator.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index aa23a27e..0a9021e1 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3578,7 +3578,7 @@ private function get_primary_key_definition( $columns ) { $primary_keys = array(); foreach ( $columns as $column ) { if ( '0' !== $column->pk ) { - $primary_keys[] = sprintf('`%s`', $column->name ); + $primary_keys[] = sprintf( '`%s`', $column->name ); } } @@ -3625,7 +3625,6 @@ private function get_columns_from( $table_name ) { 'pk' => null, ); $columns = $stmt->fetchAll( $this->pdo_fetch_mode ); - $columns = array_map( function ( $row ) use ( $name_map ) { $new = array(); From 2073f9d59f8f516d92477bfb4fb848a4422b8698 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Thu, 18 Jul 2024 16:48:22 +0700 Subject: [PATCH 04/12] Add additional check for autoindex --- wp-includes/sqlite/class-wp-sqlite-translator.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index 0a9021e1..939dc327 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3539,7 +3539,8 @@ private function get_key_definitions( $table_name, $columns ) { // If the PK columns are the same as the unique key columns, skip the key. // This is because the PK is already unique in MySQL. $key_equals_pk = ! array_diff( $pks, array_column( $key['columns'], 'name' ) ); - if ( $key['index']['unique'] && $key_equals_pk ) { + $is_auto_index = strpos( $key['index']['name'], 'sqlite_autoindex_' ) === 0; + if ( $is_auto_index && $key['index']['unique'] && $key_equals_pk ) { continue; } From a31fa983115ab62d9f962eefc71fb89904aa8ef9 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Thu, 18 Jul 2024 17:57:29 +0700 Subject: [PATCH 05/12] Skip default value for auto increment columns --- tests/WP_SQLite_Translator_Tests.php | 6 +++--- wp-includes/sqlite/class-wp-sqlite-translator.php | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index f8b7234c..ba4e9795 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -279,7 +279,7 @@ public function testShowCreateTable1() { # TODO: Should we fix mismatch with original `option_value` text NOT NULL,` without default? $this->assertEquals( "CREATE TABLE `_tmp_table` ( - `ID` bigint NOT NULL DEFAULT 0 AUTO_INCREMENT, + `ID` bigint NOT NULL AUTO_INCREMENT, `option_name` varchar(255) DEFAULT '', `option_value` text NOT NULL DEFAULT '', PRIMARY KEY (`ID`), @@ -308,7 +308,7 @@ public function testShowCreateTableQuoted() { # TODO: Should we fix mismatch with original `option_value` text NOT NULL,` without default? $this->assertEquals( "CREATE TABLE `_tmp_table` ( - `ID` bigint NOT NULL DEFAULT 0 AUTO_INCREMENT, + `ID` bigint NOT NULL AUTO_INCREMENT, `option_name` varchar(255) DEFAULT '', `option_value` text NOT NULL DEFAULT '', PRIMARY KEY (`ID`), @@ -361,7 +361,7 @@ public function testShowCreateTableWithAlterAndCreateIndex() { $results = $this->engine->get_query_results(); $this->assertEquals( 'CREATE TABLE `_tmp_table` ( - `ID` bigint NOT NULL DEFAULT 0 AUTO_INCREMENT, + `ID` bigint NOT NULL AUTO_INCREMENT, `option_name` smallint NOT NULL DEFAULT 14, `option_value` text NOT NULL DEFAULT \'\', PRIMARY KEY (`ID`), diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index 3dabf33d..609d72fb 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3498,6 +3498,7 @@ protected function get_column_definitions( $table_name, $columns ) { $auto_increment_column = $this->get_autoincrement_column( $table_name ); $column_definitions = array(); foreach ( $columns as $column ) { + $is_auto_incr = $auto_increment_column && strtolower( $auto_increment_column ) === strtolower( $column->name ); $definition = array(); $definition[] = '`' . $column->name . '`'; $definition[] = $this->get_cached_mysql_data_type( $table_name, $column->name ) ?? $column->name; @@ -3506,11 +3507,11 @@ protected function get_column_definitions( $table_name, $columns ) { $definition[] = 'NOT NULL'; } - if ( '' !== $column->dflt_value ) { + if ( '' !== $column->dflt_value && ! $is_auto_incr ) { $definition[] = 'DEFAULT ' . $column->dflt_value; // quotes? } - if ( $auto_increment_column && strtolower( $auto_increment_column ) === strtolower( $column->name ) ) { + if ( $is_auto_incr ) { $definition[] = 'AUTO_INCREMENT'; } $column_definitions[] = implode( ' ', $definition ); From 9c5d31b22425f2b448068c22ce57440fe987708f Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Thu, 18 Jul 2024 17:59:28 +0700 Subject: [PATCH 06/12] Remove comment --- wp-includes/sqlite/class-wp-sqlite-translator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index 609d72fb..ce496d02 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3508,7 +3508,7 @@ protected function get_column_definitions( $table_name, $columns ) { } if ( '' !== $column->dflt_value && ! $is_auto_incr ) { - $definition[] = 'DEFAULT ' . $column->dflt_value; // quotes? + $definition[] = 'DEFAULT ' . $column->dflt_value; } if ( $is_auto_incr ) { From b5bb9f5d98867158745de3479acde16cf42b0aee Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Thu, 18 Jul 2024 20:24:43 +0700 Subject: [PATCH 07/12] Ensure PKs are ordered correctly in create statement --- tests/WP_SQLite_Translator_Tests.php | 23 +++++++++++++++++++ .../sqlite/class-wp-sqlite-translator.php | 16 +++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index ba4e9795..fc86b027 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -371,6 +371,29 @@ public function testShowCreateTableWithAlterAndCreateIndex() { ); } + public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() { + $this->assertQuery( + 'CREATE TABLE `_tmp_table` ( + `ID_A` BIGINT NOT NULL, + `ID_B` BIGINT NOT NULL, + PRIMARY KEY (`ID_B`, `ID_A`) + );' + ); + + $this->assertQuery( + 'SHOW CREATE TABLE _tmp_table;' + ); + $results = $this->engine->get_query_results(); + $this->assertEquals( +'CREATE TABLE `_tmp_table` ( + `ID_A` bigint NOT NULL DEFAULT 0, + `ID_B` bigint NOT NULL DEFAULT 0, + PRIMARY KEY (`ID_B`, `ID_A`) +);', + $results[0]->{'Create Table'} + ); + } + public function testSelectIndexHintForce() { $this->assertQuery( "INSERT INTO _options (option_name) VALUES ('first');" ); $result = $this->assertQuery( diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index ce496d02..6297a4bf 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3579,6 +3579,15 @@ function ( $column ) { */ private function get_primary_key_definition( $columns ) { $primary_keys = array(); + + // Sort the columns by primary key order. + usort( + $columns, + function ( $a, $b ) { + return $a->pk - $b->pk; + } + ); + foreach ( $columns as $column ) { if ( '0' !== $column->pk ) { $primary_keys[] = sprintf( '`%s`', $column->name ); @@ -3627,8 +3636,8 @@ private function get_columns_from( $table_name ) { 'notnull' => null, 'pk' => null, ); - $columns = $stmt->fetchAll( $this->pdo_fetch_mode ); - $columns = array_map( + + return array_map( function ( $row ) use ( $name_map ) { $new = array(); $is_object = is_object( $row ); @@ -3647,9 +3656,8 @@ function ( $row ) use ( $name_map ) { } return $is_object ? (object) $new : $new; }, - $columns + $this->get_table_columns( $table_name ) ); - return $columns; } /** From de96e2a56ebe72f001a7c312020186bb5800a600 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Thu, 18 Jul 2024 20:26:32 +0700 Subject: [PATCH 08/12] Expand the test case --- tests/WP_SQLite_Translator_Tests.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index fc86b027..973edbaa 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -376,7 +376,8 @@ public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() { 'CREATE TABLE `_tmp_table` ( `ID_A` BIGINT NOT NULL, `ID_B` BIGINT NOT NULL, - PRIMARY KEY (`ID_B`, `ID_A`) + `ID_C` BIGINT NOT NULL, + PRIMARY KEY (`ID_B`, `ID_A`, `ID_C`) );' ); @@ -388,7 +389,8 @@ public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() { 'CREATE TABLE `_tmp_table` ( `ID_A` bigint NOT NULL DEFAULT 0, `ID_B` bigint NOT NULL DEFAULT 0, - PRIMARY KEY (`ID_B`, `ID_A`) + `ID_C` bigint NOT NULL DEFAULT 0, + PRIMARY KEY (`ID_B`, `ID_A`, `ID_C`) );', $results[0]->{'Create Table'} ); From 80b4cfdf0a419997c867cdf962b9300eb74caf08 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Thu, 18 Jul 2024 23:56:15 +0700 Subject: [PATCH 09/12] Fix linting issue --- tests/WP_SQLite_Translator_Tests.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index 973edbaa..d299ef57 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -386,7 +386,7 @@ public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() { ); $results = $this->engine->get_query_results(); $this->assertEquals( -'CREATE TABLE `_tmp_table` ( + 'CREATE TABLE `_tmp_table` ( `ID_A` bigint NOT NULL DEFAULT 0, `ID_B` bigint NOT NULL DEFAULT 0, `ID_C` bigint NOT NULL DEFAULT 0, From 6d1551501652c474c1203694c0437cbd6f5494bb Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Fri, 19 Jul 2024 14:40:06 +0700 Subject: [PATCH 10/12] Add comments to clarify methods --- .../sqlite/class-wp-sqlite-translator.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index 6297a4bf..938aa741 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -3442,6 +3442,11 @@ private function execute_show() { } } + /** + * Generates a MySQL compatible create statement for a SHOW CREATE TABLE query. + * + * @return void + */ private function generate_create_statement() { $table_name = $this->rewriter->consume()->value; $columns = $this->get_table_columns( $table_name ); @@ -3475,7 +3480,7 @@ private function generate_create_statement() { } /** - * Get columns from pragma table info for the given table. + * Get raw columns details from pragma table info for the given table. * * @param string $table_name * @@ -3523,7 +3528,8 @@ protected function get_column_definitions( $table_name, $columns ) { /** * Get the key definitions for a create statement * - * @param $table_name + * @param string $table_name + * @param array $columns * * @return array An array of key definitions */ @@ -3617,16 +3623,15 @@ private function get_autoincrement_column( $table_name ) { } /** - * Gets the columns from a table. + * Gets the columns from a table for the SHOW COLUMNS query. + * + * The output is identical to the output of the MySQL `SHOW COLUMNS` query. * * @param string $table_name The table name. * * @return array The columns. */ private function get_columns_from( $table_name ) { - $stmt = $this->execute_sqlite_query( - "PRAGMA table_info(\"$table_name\");" - ); /* @todo we may need to add the Extra column if anybdy needs it. 'auto_increment' is the value */ $name_map = array( 'name' => 'Field', From 891cc639263ffd03c29d7ac6ec7b18151400c305 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Fri, 19 Jul 2024 15:25:29 +0700 Subject: [PATCH 11/12] Add a unit test to ensure queries with PKs at column level still work --- tests/WP_SQLite_Translator_Tests.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index d299ef57..de79d08d 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -396,6 +396,16 @@ public function testShowCreateTableWithPrimaryKeyColumnsReverseOrdered() { ); } + public function testShowCreateTableWithColumnKeys() { + $this->assertQuery( + "CREATE TABLE _tmp_table ( + `ID` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL, + `option_name` varchar(255) DEFAULT '', + `option_value` text NOT NULL DEFAULT '', + KEY _tmp_table__composite (option_name, option_value), + UNIQUE KEY _tmp_table__option_name (option_name) );" ); + } + public function testSelectIndexHintForce() { $this->assertQuery( "INSERT INTO _options (option_name) VALUES ('first');" ); $result = $this->assertQuery( From 1e4f8e32c00fb0e04fe1f92255fca8383db4e1e5 Mon Sep 17 00:00:00 2001 From: Jeroen Pfeil Date: Fri, 19 Jul 2024 16:05:58 +0700 Subject: [PATCH 12/12] Fix linting error --- tests/WP_SQLite_Translator_Tests.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index de79d08d..353b5b12 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -403,7 +403,8 @@ public function testShowCreateTableWithColumnKeys() { `option_name` varchar(255) DEFAULT '', `option_value` text NOT NULL DEFAULT '', KEY _tmp_table__composite (option_name, option_value), - UNIQUE KEY _tmp_table__option_name (option_name) );" ); + UNIQUE KEY _tmp_table__option_name (option_name) );" + ); } public function testSelectIndexHintForce() {