From 0be19ab9280fb7e8be65d447d55f49123da8eb8e Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Thu, 19 Dec 2024 09:37:24 +0100 Subject: [PATCH] wip --- tests/WP_SQLite_Driver_Tests.php | 74 ++++---- tests/WP_SQLite_Driver_Translation_Tests.php | 21 +++ .../sqlite-ast/class-wp-sqlite-driver.php | 177 ++++++++++++++---- ...s-wp-sqlite-information-schema-builder.php | 117 ++++++------ 4 files changed, 263 insertions(+), 126 deletions(-) diff --git a/tests/WP_SQLite_Driver_Tests.php b/tests/WP_SQLite_Driver_Tests.php index 7a1cd755..3233ea4f 100644 --- a/tests/WP_SQLite_Driver_Tests.php +++ b/tests/WP_SQLite_Driver_Tests.php @@ -785,7 +785,7 @@ public function testCreateTable() { ), (object) array( 'Field' => 'user_status', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => '0', @@ -848,8 +848,8 @@ enum_column ENUM('a', 'b', 'c') NOT NULL DEFAULT 'a', 'Type' => 'bigint(20) unsigned', 'Null' => 'NO', 'Key' => 'PRI', - 'Default' => '0', - 'Extra' => '', + 'Default' => null, + 'Extra' => 'auto_increment', ), (object) array( 'Field' => 'decimal_column', @@ -969,7 +969,7 @@ public function testAlterTableAddAndDropColumn() { ), (object) array( 'Field' => 'column2', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'YES', 'Key' => '', 'Default' => null, @@ -1049,10 +1049,10 @@ public function testColumnWithOnUpdate() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', - 'Default' => '0', + 'Default' => null, 'Extra' => '', ), (object) array( @@ -1061,7 +1061,7 @@ public function testColumnWithOnUpdate() { 'Null' => 'YES', 'Key' => '', 'Default' => null, - 'Extra' => '', + 'Extra' => 'on update CURRENT_TIMESTAMP', ), ), $results @@ -1076,10 +1076,10 @@ public function testColumnWithOnUpdate() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', - 'Default' => '0', + 'Default' => null, 'Extra' => '', ), (object) array( @@ -1088,7 +1088,7 @@ public function testColumnWithOnUpdate() { 'Null' => 'YES', 'Key' => '', 'Default' => null, - 'Extra' => '', + 'Extra' => 'on update CURRENT_TIMESTAMP', ), (object) array( 'Field' => 'updated_at', @@ -1096,7 +1096,7 @@ public function testColumnWithOnUpdate() { 'Null' => 'YES', 'Key' => '', 'Default' => null, - 'Extra' => '', + 'Extra' => 'on update CURRENT_TIMESTAMP', ), ), $results @@ -1147,7 +1147,7 @@ public function testColumnWithOnUpdate() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => '0', @@ -1218,10 +1218,10 @@ public function testChangeColumnWithOnUpdate() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', - 'Default' => '0', + 'Default' => null, 'Extra' => '', ), (object) array( @@ -1251,10 +1251,10 @@ public function testChangeColumnWithOnUpdate() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', - 'Default' => '0', + 'Default' => null, 'Extra' => '', ), (object) array( @@ -1263,7 +1263,7 @@ public function testChangeColumnWithOnUpdate() { 'Null' => 'YES', 'Key' => '', 'Default' => null, - 'Extra' => '', + 'Extra' => 'on update CURRENT_TIMESTAMP', ), ), $results @@ -1283,10 +1283,10 @@ public function testChangeColumnWithOnUpdate() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', - 'Default' => '0', + 'Default' => null, 'Extra' => '', ), (object) array( @@ -1325,7 +1325,7 @@ public function testAlterTableWithColumnFirstAndAfter() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => null, @@ -1360,7 +1360,7 @@ public function testAlterTableWithColumnFirstAndAfter() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => null, @@ -1403,7 +1403,7 @@ public function testAlterTableWithColumnFirstAndAfter() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => '0', @@ -1446,7 +1446,7 @@ public function testAlterTableWithColumnFirstAndAfter() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => '0', @@ -1500,7 +1500,7 @@ public function testAlterTableWithMultiColumnFirstAndAfter() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => null, @@ -1546,7 +1546,7 @@ public function testAlterTableWithMultiColumnFirstAndAfter() { array( (object) array( 'Field' => 'id', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => null, @@ -1554,7 +1554,7 @@ public function testAlterTableWithMultiColumnFirstAndAfter() { ), (object) array( 'Field' => 'new1', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => null, @@ -1562,7 +1562,7 @@ public function testAlterTableWithMultiColumnFirstAndAfter() { ), (object) array( 'Field' => 'new2', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => '', @@ -1570,7 +1570,7 @@ public function testAlterTableWithMultiColumnFirstAndAfter() { ), (object) array( 'Field' => 'new3', - 'Type' => 'int', + 'Type' => 'int(11)', 'Null' => 'NO', 'Key' => '', 'Default' => '', @@ -2167,15 +2167,14 @@ public function testNestedTransactionWorkComplexModify() { $fields = $this->engine->get_query_results(); $this->assertEquals( - $fields, array( (object) array( 'Field' => 'ID', - 'Type' => 'integer', + 'Type' => 'int', 'Null' => 'NO', 'Key' => 'PRI', - 'Default' => '0', - 'Extra' => '', + 'Default' => null, + 'Extra' => 'auto_increment', ), (object) array( 'Field' => 'option_name', @@ -2193,7 +2192,8 @@ public function testNestedTransactionWorkComplexModify() { 'Default' => '', 'Extra' => '', ), - ) + ), + $fields ); } @@ -2408,7 +2408,7 @@ public function testDescribeAccurate() { array( (object) array( 'Field' => 'object_id', - 'Type' => 'bigint unsigned', + 'Type' => 'bigint(20) unsigned', 'Null' => 'NO', 'Key' => 'PRI', 'Default' => '0', @@ -2416,7 +2416,7 @@ public function testDescribeAccurate() { ), (object) array( 'Field' => 'term_taxonomy_id', - 'Type' => 'bigint unsigned', + 'Type' => 'bigint(20) unsigned', 'Null' => 'NO', 'Key' => 'PRI', 'Default' => '0', @@ -2426,7 +2426,7 @@ public function testDescribeAccurate() { 'Field' => 'term_name', 'Type' => 'varchar(11)', 'Null' => 'NO', - 'Key' => '', + 'Key' => 'MUL', 'Default' => '0', 'Extra' => '', ), @@ -2457,7 +2457,7 @@ public function testAlterTableAddColumnChangesMySQLDataType() { array( (object) array( 'Field' => 'object_id', - 'Type' => 'bigint unsigned', + 'Type' => 'bigint(20) unsigned', 'Null' => 'NO', 'Key' => '', 'Default' => '0', diff --git a/tests/WP_SQLite_Driver_Translation_Tests.php b/tests/WP_SQLite_Driver_Translation_Tests.php index 1af25d14..ac3bf376 100644 --- a/tests/WP_SQLite_Driver_Translation_Tests.php +++ b/tests/WP_SQLite_Driver_Translation_Tests.php @@ -495,6 +495,27 @@ public function testAlterTableAddColumn(): void { ); } + public function testAlterTableAddColumnWithNotNull(): void { + $this->assertQuery( + 'ALTER TABLE "t" ADD COLUMN "a" INTEGER NOT NULL', + 'ALTER TABLE t ADD a INT NOT NULL' + ); + } + + public function testAlterTableAddColumnWithDefault(): void { + $this->assertQuery( + 'ALTER TABLE "t" ADD COLUMN "a" INTEGER DEFAULT 0', + 'ALTER TABLE t ADD a INT DEFAULT 0' + ); + } + + public function testAlterTableAddColumnWithNotNullAndDefault(): void { + $this->assertQuery( + 'ALTER TABLE "t" ADD COLUMN "a" INTEGER NOT NULL DEFAULT 0', + 'ALTER TABLE t ADD a INT NOT NULL DEFAULT 0' + ); + } + public function testAlterTableAddMultipleColumns(): void { $this->driver->get_pdo()->exec( 'CREATE TABLE t (id INT)' ); $this->assertQuery( diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php b/wp-includes/sqlite-ast/class-wp-sqlite-driver.php index 4d3d4ed7..c3343d3d 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-driver.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-driver.php @@ -901,6 +901,10 @@ private function execute_mysql_query( WP_Parser_Node $ast ) { */ $this->results = 0; break; + case 'showStatement': + $this->query_type = 'SHOW'; + $this->execute_show_statement( $ast ); + break; case 'utilityStatement': $this->query_type = 'DESCRIBE'; $subtree = $ast->get_child_node(); @@ -1125,48 +1129,114 @@ function ( $column ) { return array_merge( array( $sql ), $create_index_sqls ); } - private function get_sqlite_column_definition( array $column, bool $has_compound_primary_key ): string { - $sql = ' '; - $sql .= sprintf( '"%s"', str_replace( '"', '""', $column['COLUMN_NAME'] ) ); - - $type = self::DATA_TYPE_STRING_MAP[ $column['DATA_TYPE'] ]; + private function get_mysql_create_table_statement( string $table_name ): string { + // 1. Get table info. + $table_info = $this->execute_sqlite_query( + ' + SELECT * + FROM _mysql_information_schema_tables + WHERE table_type = "BASE TABLE" + AND table_schema = ? + AND table_name = ? + ', + array( $this->db_name, $table_name ) + )->fetch( PDO::FETCH_ASSOC ); - /* - * In SQLite, there is a PRIMARY KEY quirk for backward compatibility. - * This applies to ROWID tables and single-column primary keys only: - * 1. "INTEGER PRIMARY KEY" creates an alias of ROWID. - * 2. "INT PRIMARY KEY" will not alias of ROWID. - * - * Therefore, we want to: - * 1. Use "INT PRIMARY KEY" when we have a single-column integer - * PRIMARY KEY without AUTOINCREMENT (to avoid the ROWID alias). - * 2. Use "INTEGER PRIMARY KEY" otherwise. - * - * See: - * - https://www.sqlite.org/autoinc.html - * - https://www.sqlite.org/lang_createtable.html - */ - if ( - 'INTEGER' === $type - && 'PRI' === $column['COLUMN_KEY'] - && 'auto_increment' !== $column['EXTRA'] - && ! $has_compound_primary_key - ) { - $type = 'INT'; + if ( false === $table_info ) { + throw new Exception( 'Table not found in information_schema' ); } - $sql .= ' ' . $type; - if ( 'NO' === $column['IS_NULLABLE'] ) { - $sql .= ' NOT NULL'; + // 2. Get column info. + $column_info = $this->execute_sqlite_query( + 'SELECT * FROM _mysql_information_schema_columns WHERE table_schema = ? AND table_name = ?', + array( $this->db_name, $table_name ) + )->fetchAll( PDO::FETCH_ASSOC ); + + // 3. Get index info, grouped by index name. + $constraint_info = $this->execute_sqlite_query( + 'SELECT * FROM _mysql_information_schema_statistics WHERE table_schema = ? AND table_name = ?', + array( $this->db_name, $table_name ) + )->fetchAll( PDO::FETCH_ASSOC ); + + $grouped_constraints = array(); + foreach ( $constraint_info as $constraint ) { + $name = $constraint['INDEX_NAME']; + $seq = $constraint['SEQ_IN_INDEX']; + $grouped_constraints[ $name ][ $seq ] = $constraint; } - if ( 'auto_increment' === $column['EXTRA'] ) { - $has_autoincrement = true; - $sql .= ' PRIMARY KEY AUTOINCREMENT'; + + // 4. Generate CREATE TABLE statement columns. + $rows = array(); + foreach ( $column_info as $column ) { + $sql = ' '; + $sql .= sprintf( '"%s"', str_replace( '"', '""', $column['COLUMN_NAME'] ) ); + + $sql .= ' ' . $column['COLUMN_TYPE']; + if ( 'NO' === $column['IS_NULLABLE'] ) { + $sql .= ' NOT NULL'; + } + if ( 'auto_increment' === $column['EXTRA'] ) { + $sql .= ' AUTO_INCREMENT'; + } + if ( null !== $column['COLUMN_DEFAULT'] ) { + // @TODO: Correctly quote based on the data type. + $sql .= ' DEFAULT ' . $this->pdo->quote( $column['COLUMN_DEFAULT'] ); + } + $rows[] = $sql; } - if ( null !== $column['COLUMN_DEFAULT'] ) { - // @TODO: Correctly quote based on the data type. - $sql .= ' DEFAULT ' . $this->pdo->quote( $column['COLUMN_DEFAULT'] ); + + // 4. Generate CREATE TABLE statement constraints, collect indexes. + $create_index_sqls = array(); + foreach ( $grouped_constraints as $constraint ) { + ksort( $constraint ); + $info = $constraint[1]; + + if ( 'PRIMARY' === $info['INDEX_NAME'] ) { + $sql = ' PRIMARY KEY ('; + $sql .= implode( + ', ', + array_map( + function ( $column ) { + return sprintf( '"%s"', str_replace( '"', '""', $column['COLUMN_NAME'] ) ); + }, + $constraint + ) + ); + $sql .= ')'; + $rows[] = $sql; + } else { + $is_unique = '0' === $info['NON_UNIQUE']; + + $sql = sprintf( ' %sKEY', $is_unique ? 'UNIQUE ' : '' ); + $sql .= sprintf( ' "%s"', $info['INDEX_NAME'] ); + $sql .= sprintf( ' ON "%s" (', $table_name ); + $sql .= implode( + ', ', + array_map( + function ( $column ) { + return sprintf( '"%s"', str_replace( '"', '""', $column['COLUMN_NAME'] ) ); + }, + $constraint + ) + ); + $sql .= ')'; + + $rows[] = $sql; + } } + + // 5. Compose the CREATE TABLE statement. + $sql = sprintf( 'CREATE TABLE "%s" (%s', str_replace( '"', '""', $table_name ), "\n" ); + $sql .= implode( ",\n", $rows ); + $sql .= "\n)"; + + $sql .= sprintf( ' ENGINE=%s', $table_info['ENGINE'] ); + + $collation = $table_info['TABLE_COLLATION']; + $charset = substr( $collation, 0, strpos( $collation, '_' ) ); + $sql .= sprintf( ' DEFAULT CHARSET=%s', $charset ); + $sql .= sprintf( ' COLLATE=%s', $collation ); + var_dump( $sql ); return $sql; } @@ -1319,6 +1389,41 @@ private function execute_describe_statement( WP_Parser_Node $node ): void { $this->set_results_from_fetched_data( $column_info ); } + private function execute_show_statement( WP_Parser_Node $node ): void { + $tokens = $node->get_child_tokens(); + $keyword1 = $tokens[1]; + $keyword2 = $tokens[2] ?? null; + + switch ( $keyword1->id ) { + case WP_MySQL_Lexer::CREATE_SYMBOL: + if ( WP_MySQL_Lexer::TABLE_SYMBOL === $keyword2->id ) { + $table_name = $this->translate( $node->get_child_node( 'tableRef' ) ); + $table_name = trim( $table_name, '`"' ); + $sql = $this->get_mysql_create_table_statement( $table_name ); + $this->set_results_from_fetched_data( + array( + (object) array( + 'Create Table' => $sql, + ), + ) + ); + } elseif ( WP_MySQL_Lexer::PROCEDURE_SYMBOL === $keyword2->id ) { + $this->results = true; + return; + } + // Fall through to default. + case WP_MySQL_Lexer::GRANTS_SYMBOL: + $this->set_results_from_fetched_data( + array( + (object) array( + 'Grants for root@localhost' => 'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `root`@`localhost` WITH GRANT OPTION', + ), + ) + ); + return; + } + } + private function translate( $ast ) { if ( null === $ast ) { return null; diff --git a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php index 27318f39..bcc6f503 100644 --- a/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php +++ b/wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php @@ -432,8 +432,9 @@ public function record_alter_table( WP_Parser_Node $node ): void { // DROP if ( WP_MySQL_Lexer::DROP_SYMBOL === $first_token->id ) { // DROP [COLUMN] - $name = $this->translate( $action->get_child_node( 'columnInternalRef' ) ); - if ( null !== $name ) { + $column_ref = $action->get_child_node( 'columnInternalRef' ); + if ( null !== $column_ref ) { + $name = $this->get_value( $column_ref ); // @TODO } } @@ -571,22 +572,14 @@ private function create_constraint( string $table_name, WP_Parser_Node $constrai throw new \Exception( 'FOREIGN KEY and CHECK constraints are not supported yet.' ); } - // Collect constraint columns. - $columns = array(); - foreach ( $constraint->get_descendant_nodes( 'keyListVariants' ) as $key ) { - $column_name = $this->get_index_column_name( $key ); - $columns[ $column_name ] = $key; - } - // Fetch column info. $column_info = $this->query( ' SELECT column_name, data_type, is_nullable, character_maximum_length FROM _mysql_information_schema_columns WHERE table_name = ? - AND column_name IN (' . implode( ', ', array_fill( 0, count( $columns ), '?' ) ) . ') ', - array_merge( array( $table_name ), array_keys( $columns ) ) + array( $table_name ) )->fetchAll( PDO::FETCH_ASSOC ); $column_info_map = array_combine( @@ -603,9 +596,20 @@ private function create_constraint( string $table_name, WP_Parser_Node $constrai $index_name = $this->get_index_name( $constraint ); $index_type = $this->get_index_type( $constraint, $keyword, $has_spatial_column ); + $key_list = $constraint->get_child_node( 'keyListVariants' )->get_child(); + if ( 'keyListWithExpression' === $key_list->rule_name ) { + $key_parts = array(); + foreach ( $key_list->get_descendant_nodes( 'keyPartOrExpression' ) as $key_part ) { + $key_parts[] = $key_part->get_child(); + } + } else { + $key_parts = $key_list->get_descendant_nodes( 'keyPart' ); + } + $seq_in_index = 1; - foreach ( $columns as $column_name => $key ) { - $collation = $this->get_index_column_collation( $key, $index_type ); + foreach ( $key_parts as $key_part ) { + $column_name = $this->get_index_column_name( $key_part ); + $collation = $this->get_index_column_collation( $key_part, $index_type ); if ( 'PRIMARY' === $index_name || 'NO' === $column_info_map[ $column_name ]['IS_NULLABLE'] @@ -616,7 +620,7 @@ private function create_constraint( string $table_name, WP_Parser_Node $constrai } $sub_part = $this->get_index_column_sub_part( - $key, + $key_part, $column_info_map[ $column_name ]['CHARACTER_MAXIMUM_LENGTH'], $has_spatial_column ); @@ -643,39 +647,51 @@ private function create_constraint( string $table_name, WP_Parser_Node $constrai 'expression' => null, // @TODO ) ); + + $seq_in_index += 1; } - /* - * Update column info for PRIMARY and UNIQUE constraints. - * A) COLUMN_KEY (priority from 1 to 4): - * 1. "PRI": Column is any component of a PRIMARY KEY. - * 2. "UNI": Column is the first column of a UNIQUE KEY. - * 3. "MUL": Column is the first column of a non-unique index. - * 4. "": Column is not indexed. - * - * B) IS_NULLABLE: In COLUMNS, "YES"/"NO". In STATISTICS, "YES"/"". - */ // @TODO: Add schema check, list only affected columns. + $this->sync_column_key_info( $table_name ); + } + + /** + * Update column info for PRIMARY and UNIQUE constraints. + * A) COLUMN_KEY (priority from 1 to 4): + * 1. "PRI": Column is any component of a PRIMARY KEY. + * 2. "UNI": Column is the first column of a UNIQUE KEY. + * 3. "MUL": Column is the first column of a non-unique index. + * 4. "": Column is not indexed. + * + * B) IS_NULLABLE: In COLUMNS, "YES"/"NO". In STATISTICS, "YES"/"". + */ + private function sync_column_key_info( string $table_name ): void { $this->query( " + WITH s AS ( + SELECT + column_name, + CASE + WHEN MAX(index_name = 'PRIMARY') THEN 'PRI' + WHEN MAX(non_unique = 0 AND seq_in_index = 1) THEN 'UNI' + WHEN MAX(seq_in_index = 1) THEN 'MUL' + ELSE '' + END AS column_key + FROM _mysql_information_schema_statistics + WHERE table_schema = ? + AND table_name = ? + GROUP BY column_name + ) UPDATE _mysql_information_schema_columns AS c SET - column_key = CASE - WHEN s.index_name = 'PRIMARY' THEN 'PRI' - WHEN s.non_unique = 0 AND s.seq_in_index = 1 THEN 'UNI' - WHEN s.seq_in_index = 1 THEN 'MUL' - ELSE '' - END, - is_nullable = CASE - WHEN s.nullable = 'YES' THEN 'YES' - ELSE 'NO' - END - FROM _mysql_information_schema_statistics AS s - WHERE c.table_name = ? - AND c.table_name = s.table_name - AND c.column_name = s.column_name + column_key = s.column_key, + is_nullable = IIF(s.column_key = 'PRI', 'NO', c.is_nullable) + FROM s + WHERE c.table_schema = ? + AND c.table_name = ? + AND s.column_name = c.column_name ", - array( $table_name ) + array( $this->db_name, $table_name, $this->db_name, $table_name ) ); } @@ -882,20 +898,16 @@ private function get_column_data_types( WP_Parser_Node $node ): array { if ( null !== $field_length ) { if ( 'decimal' === $type || 'float' === $type || 'double' === $type ) { $full_type .= rtrim( $this->get_value( $field_length ), ')' ) . ',0)'; - } elseif ( - WP_MySQL_Lexer::TINYINT_SYMBOL === $token->id - || WP_MySQL_Lexer::SMALLINT_SYMBOL === $token->id - || WP_MySQL_Lexer::MEDIUMINT_SYMBOL === $token->id - || WP_MySQL_Lexer::INT_SYMBOL === $token->id - || WP_MySQL_Lexer::INTEGER_SYMBOL === $token->id - || WP_MySQL_Lexer::BIGINT_SYMBOL === $token->id - ) { - // As of MySQL 8.0.17, the display width attribute is deprecated - // for integer data types and is not stored anymore. - // @TODO: Is it important to store it for older versions? } else { $full_type .= $this->get_value( $field_length ); } + /* + * As of MySQL 8.0.17, the display width attribute is deprecated for + * integer types (tinyint, smallint, mediumint, int/integer, bigint) + * and is not stored anymore. However, it may be important for older + * versions and WP's dbDelta, so it is safer to keep it at the moment. + * @TODO: Investigate if it is important to keep this. + */ } $precision = $type_node->get_descendant_node( 'precision' ); @@ -1251,11 +1263,10 @@ private function get_index_type( } private function get_index_column_name( WP_Parser_Node $node ): ?string { - $key_part = $node->get_descendant_node( 'keyPart' ); - if ( null === $key_part ) { + if ( 'keyPart' !== $node->rule_name ) { return null; } - return $this->get_value( $key_part->get_descendant_node( 'identifier' ) ); + return $this->get_value( $node->get_descendant_node( 'identifier' ) ); } private function get_index_column_collation( WP_Parser_Node $node, string $index_type ): ?string {