diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index d0e5c193..42985c5b 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -1027,6 +1027,279 @@ public function testAlterTableAddNotNullVarcharColumn() { ); } + public function testAlterTableWithColumnFirstAndAfter() { + $this->assertQuery( + "CREATE TABLE _tmp_table ( + id int(11) NOT NULL, + name varchar(20) NOT NULL default '' + );" + ); + + // ADD COLUMN with FIRST + $this->assertQuery( + "ALTER TABLE _tmp_table ADD COLUMN new_first_column VARCHAR(255) NOT NULL DEFAULT '' FIRST" + ); + $results = $this->assertQuery( 'DESCRIBE _tmp_table;' ); + $this->assertEquals( + array( + (object) array( + 'Field' => 'id', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '0', + 'Extra' => '', + ), + (object) array( + 'Field' => 'name', + 'Type' => 'varchar(20)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => null, + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_first_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + ), + $results + ); + + // ADD COLUMN with AFTER + $this->assertQuery( + "ALTER TABLE _tmp_table ADD COLUMN new_column VARCHAR(255) NOT NULL DEFAULT '' AFTER id" + ); + $results = $this->assertQuery( 'DESCRIBE _tmp_table;' ); + $this->assertEquals( + array( + (object) array( + 'Field' => 'id', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '0', + 'Extra' => '', + ), + (object) array( + 'Field' => 'name', + 'Type' => 'varchar(20)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => null, + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_first_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + ), + $results + ); + + // CHANGE with FIRST + $this->assertQuery( + "ALTER TABLE _tmp_table CHANGE id id int(11) NOT NULL DEFAULT '0' FIRST" + ); + $results = $this->assertQuery( 'DESCRIBE _tmp_table;' ); + $this->assertEquals( + array( + (object) array( + 'Field' => 'id', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '0', + 'Extra' => '', + ), + (object) array( + 'Field' => 'name', + 'Type' => 'varchar(20)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => null, + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_first_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + ), + $results + ); + + // CHANGE with AFTER + $this->assertQuery( + "ALTER TABLE _tmp_table CHANGE id id int(11) NOT NULL DEFAULT '0' AFTER name" + ); + $results = $this->assertQuery( 'DESCRIBE _tmp_table;' ); + $this->assertEquals( + array( + (object) array( + 'Field' => 'id', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '0', + 'Extra' => '', + ), + (object) array( + 'Field' => 'name', + 'Type' => 'varchar(20)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => null, + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_first_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new_column', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + ), + $results + ); + } + + public function testAlterTableWithMultiColumnFirstAndAfter() { + $this->assertQuery( + 'CREATE TABLE _tmp_table ( + id int(11) NOT NULL + );' + ); + + // ADD COLUMN + $this->assertQuery( + 'ALTER TABLE _tmp_table + ADD COLUMN new1 varchar(255) NOT NULL, + ADD COLUMN new2 varchar(255) NOT NULL FIRST, + ADD COLUMN new3 varchar(255) NOT NULL AFTER new1' + ); + $results = $this->assertQuery( 'DESCRIBE _tmp_table;' ); + $this->assertEquals( + array( + (object) array( + 'Field' => 'id', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '0', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new1', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => null, + 'Extra' => '', + ), + (object) array( + 'Field' => 'new2', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new3', + 'Type' => 'varchar(255)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + ), + $results + ); + + // CHANGE + $this->assertQuery( + 'ALTER TABLE _tmp_table + CHANGE new1 new1 int(11) NOT NULL FIRST, + CHANGE new2 new2 int(11) NOT NULL, + CHANGE new3 new3 int(11) NOT NULL AFTER new2' + ); + $results = $this->assertQuery( 'DESCRIBE _tmp_table;' ); + $this->assertEquals( + array( + (object) array( + 'Field' => 'id', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '0', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new1', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => null, + 'Extra' => '', + ), + (object) array( + 'Field' => 'new2', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + (object) array( + 'Field' => 'new3', + 'Type' => 'int(11)', + 'Null' => 'NO', + 'Key' => '', + 'Default' => '', + 'Extra' => '', + ), + ), + $results + ); + } + public function testAlterTableAddIndex() { $result = $this->assertQuery( "CREATE TABLE _tmp_table ( diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index 431c9c0e..1be5c875 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -2939,6 +2939,35 @@ private function execute_alter() { WP_SQLite_Token::FLAG_KEYWORD_DATA_TYPE ) ); + + // Drop "FIRST" and "AFTER ", as these are not supported in SQLite. + $column_position = $this->rewriter->peek( + array( + 'type' => WP_SQLite_Token::TYPE_KEYWORD, + 'value' => array( 'FIRST', 'AFTER' ), + ) + ); + + $comma = $this->rewriter->peek( + array( + 'type' => WP_SQLite_Token::TYPE_OPERATOR, + 'value' => ',', + ) + ); + + if ( $column_position && ( ! $comma || $column_position->position < $comma->position ) ) { + $this->rewriter->consume( + array( + 'type' => WP_SQLite_Token::TYPE_KEYWORD, + 'value' => array( 'FIRST', 'AFTER' ), + ) + ); + $this->rewriter->drop_last(); + if ( 'AFTER' === strtoupper( $column_position->value ) ) { + $this->rewriter->skip(); + } + } + $this->update_data_type_cache( $this->table_name, $column_name,