Skip to content

Commit c915b32

Browse files
committed
Support PostgreSQL ALTER DROP INDEX
1 parent 9d3cfe8 commit c915b32

2 files changed

Lines changed: 173 additions & 1 deletion

File tree

packages/mysql-on-sqlite/src/postgresql/class-wp-postgresql-driver.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,10 @@ public function query( string $query, $fetch_mode = PDO::FETCH_OBJ, ...$fetch_mo
551551
if ( null !== $alter_query ) {
552552
$result = $this->execute_postgresql_statements( $alter_query['statements'] );
553553
$this->apply_mysql_dbdelta_alter_metadata( $alter_query['metadata'] );
554+
if ( 'drop_index' === ( $alter_query['metadata']['operation'] ?? '' ) ) {
555+
$this->last_result = 0;
556+
return $this->last_result;
557+
}
554558
return $result;
555559
}
556560

@@ -2524,6 +2528,11 @@ private function apply_mysql_dbdelta_alter_metadata( array $metadata ): void {
25242528
return;
25252529
}
25262530

2531+
if ( 'drop_index' === $metadata['operation'] ) {
2532+
$this->apply_mysql_drop_index_metadata( $metadata );
2533+
return;
2534+
}
2535+
25272536
if ( 'set_default' === $metadata['operation'] ) {
25282537
$this->connection->query(
25292538
sprintf(
@@ -3371,6 +3380,29 @@ private function translate_mysql_dbdelta_alter_table_query( string $query ): ?ar
33713380
);
33723381
}
33733382

3383+
if ( preg_match( '/^DROP\s+PRIMARY\s+KEY$/is', $clause ) ) {
3384+
throw new InvalidArgumentException( 'Unsupported ALTER TABLE statement.' );
3385+
}
3386+
3387+
if ( preg_match( '/^DROP\s+(?:INDEX|KEY)\s+(?:`(?P<index_quoted>[^`]+)`|(?P<index>[A-Za-z0-9_]+))$/is', $clause, $drop_index_matches ) ) {
3388+
$index_name = '' !== ( $drop_index_matches['index_quoted'] ?? '' ) ? $drop_index_matches['index_quoted'] : $drop_index_matches['index'];
3389+
$drop_index_query = $this->get_mysql_drop_index_translation(
3390+
array(
3391+
'schema' => null,
3392+
'table' => $table_name,
3393+
),
3394+
$index_name,
3395+
'ALTER TABLE'
3396+
);
3397+
3398+
$drop_index_query['metadata']['operation'] = 'drop_index';
3399+
return $drop_index_query;
3400+
}
3401+
3402+
if ( preg_match( '/^DROP\s+(?:INDEX|KEY)\b/is', $clause ) ) {
3403+
throw new InvalidArgumentException( 'Unsupported ALTER TABLE statement.' );
3404+
}
3405+
33743406
if ( preg_match( '/^ALTER\s+COLUMN\s+(?:`(?P<column_quoted>[^`]+)`|(?P<column>[A-Za-z0-9_]+))\s+SET\s+DEFAULT\s+(?P<default>.+)$/is', $clause, $default_matches ) ) {
33753407
$column_name = '' !== ( $default_matches['column_quoted'] ?? '' ) ? $default_matches['column_quoted'] : $default_matches['column'];
33763408
$default = $this->translate_mysql_default_fragment( $default_matches['default'] );
@@ -3770,7 +3802,23 @@ private function translate_mysql_drop_index_query( string $query ): ?array {
37703802
throw new InvalidArgumentException( 'Unsupported DROP INDEX statement.' );
37713803
}
37723804

3773-
$table_schema = $this->get_mysql_writable_table_backend_schema( $table_reference, 'DROP INDEX' );
3805+
return $this->get_mysql_drop_index_translation( $table_reference, $index_name, 'DROP INDEX' );
3806+
}
3807+
3808+
/**
3809+
* Build PostgreSQL DROP INDEX SQL and metadata cleanup target.
3810+
*
3811+
* @param array{schema: string|null, table: string} $table_reference MySQL table reference.
3812+
* @param string $index_name MySQL index name.
3813+
* @param string $statement_type Statement type for fail-closed error messages.
3814+
* @return array{statements: string[], metadata: array} Drop index translation.
3815+
*/
3816+
private function get_mysql_drop_index_translation( array $table_reference, string $index_name, string $statement_type ): array {
3817+
if ( 'PRIMARY' === strtoupper( $index_name ) ) {
3818+
throw new InvalidArgumentException( 'Unsupported ' . $statement_type . ' statement.' );
3819+
}
3820+
3821+
$table_schema = $this->get_mysql_writable_table_backend_schema( $table_reference, $statement_type );
37743822
$table_name = $table_reference['table'];
37753823

37763824
return array(

packages/mysql-on-sqlite/tests/WP_PostgreSQL_Driver_Tests.php

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,130 @@ public function test_standalone_drop_index_updates_postgresql_and_mysql_metadata
11931193
$this->assertSame( array( 'PRIMARY' ), array_column( $indexes, 'key_name' ) );
11941194
}
11951195

1196+
/**
1197+
* Tests ALTER TABLE DROP INDEX removes PostgreSQL schema and MySQL metadata.
1198+
*/
1199+
public function test_alter_table_drop_index_updates_postgresql_and_mysql_metadata(): void {
1200+
$driver = $this->create_driver();
1201+
1202+
$driver->query(
1203+
'CREATE TABLE wptests_alter_drop_index (
1204+
id int NOT NULL,
1205+
option_name varchar(191) NOT NULL,
1206+
PRIMARY KEY (id)
1207+
)'
1208+
);
1209+
$driver->store_mysql_schema_metadata(
1210+
'CREATE TABLE wptests_alter_drop_index (
1211+
id int NOT NULL,
1212+
option_name varchar(191) NOT NULL,
1213+
PRIMARY KEY (id)
1214+
)'
1215+
);
1216+
$driver->query( 'CREATE INDEX option_name ON wptests_alter_drop_index (option_name)' );
1217+
1218+
$this->assertSame( 0, $driver->query( 'ALTER TABLE wptests_alter_drop_index DROP INDEX option_name' ) );
1219+
$this->assertSame(
1220+
array(
1221+
array(
1222+
'sql' => 'DROP INDEX "wptests_alter_drop_index__option_name"',
1223+
'params' => array(),
1224+
),
1225+
),
1226+
$driver->get_last_postgresql_queries()
1227+
);
1228+
1229+
$indexes = $this->get_mysql_index_metadata_rows( $driver, 'wptests_alter_drop_index' );
1230+
$this->assertSame( array( 'PRIMARY' ), array_column( $indexes, 'key_name' ) );
1231+
}
1232+
1233+
/**
1234+
* Tests ALTER TABLE DROP INDEX accepts backticked identifiers.
1235+
*/
1236+
public function test_alter_table_drop_index_accepts_backticked_identifiers(): void {
1237+
$driver = $this->create_driver();
1238+
1239+
$driver->query(
1240+
'CREATE TABLE wptests_alter_drop_backtick_index (
1241+
option_name varchar(191) NOT NULL
1242+
)'
1243+
);
1244+
$driver->store_mysql_schema_metadata(
1245+
'CREATE TABLE wptests_alter_drop_backtick_index (
1246+
option_name varchar(191) NOT NULL
1247+
)'
1248+
);
1249+
$driver->query( 'CREATE INDEX option_name ON wptests_alter_drop_backtick_index (option_name)' );
1250+
1251+
$this->assertSame( 0, $driver->query( 'ALTER TABLE `wptests_alter_drop_backtick_index` DROP INDEX `option_name`' ) );
1252+
$this->assertSame(
1253+
array(
1254+
array(
1255+
'sql' => 'DROP INDEX "wptests_alter_drop_backtick_index__option_name"',
1256+
'params' => array(),
1257+
),
1258+
),
1259+
$driver->get_last_postgresql_queries()
1260+
);
1261+
1262+
$this->assertSame( array(), $this->get_mysql_index_metadata_rows( $driver, 'wptests_alter_drop_backtick_index' ) );
1263+
}
1264+
1265+
/**
1266+
* Tests ALTER TABLE DROP KEY removes PostgreSQL schema and MySQL metadata.
1267+
*/
1268+
public function test_alter_table_drop_key_updates_postgresql_and_mysql_metadata(): void {
1269+
$driver = $this->create_driver();
1270+
1271+
$driver->query(
1272+
'CREATE TABLE wptests_alter_drop_key (
1273+
option_name varchar(191) NOT NULL
1274+
)'
1275+
);
1276+
$driver->store_mysql_schema_metadata(
1277+
'CREATE TABLE wptests_alter_drop_key (
1278+
option_name varchar(191) NOT NULL
1279+
)'
1280+
);
1281+
$driver->query( 'CREATE INDEX option_name ON wptests_alter_drop_key (option_name)' );
1282+
1283+
$this->assertSame( 0, $driver->query( 'ALTER TABLE wptests_alter_drop_key DROP KEY option_name' ) );
1284+
$this->assertSame(
1285+
array(
1286+
array(
1287+
'sql' => 'DROP INDEX "wptests_alter_drop_key__option_name"',
1288+
'params' => array(),
1289+
),
1290+
),
1291+
$driver->get_last_postgresql_queries()
1292+
);
1293+
1294+
$this->assertSame( array(), $this->get_mysql_index_metadata_rows( $driver, 'wptests_alter_drop_key' ) );
1295+
}
1296+
1297+
/**
1298+
* Tests ALTER TABLE primary-key drop forms fail before backend execution.
1299+
*/
1300+
public function test_alter_table_drop_primary_key_forms_do_not_reach_backend(): void {
1301+
$queries = array(
1302+
'ALTER TABLE wptests_alter_drop_primary DROP PRIMARY KEY',
1303+
'ALTER TABLE wptests_alter_drop_primary DROP INDEX PRIMARY',
1304+
'ALTER TABLE wptests_alter_drop_primary DROP KEY `PRIMARY`',
1305+
);
1306+
1307+
foreach ( $queries as $query ) {
1308+
$driver = $this->create_driver();
1309+
1310+
try {
1311+
$driver->query( $query );
1312+
$this->fail( 'Expected unsupported ALTER TABLE primary-key drop to throw.' );
1313+
} catch ( InvalidArgumentException $e ) {
1314+
$this->assertSame( 'Unsupported ALTER TABLE statement.', $e->getMessage(), $query );
1315+
$this->assertSame( array(), $driver->get_last_postgresql_queries(), $query );
1316+
}
1317+
}
1318+
}
1319+
11961320
/**
11971321
* Tests main database-qualified standalone index statements target public table metadata.
11981322
*/

0 commit comments

Comments
 (0)