Skip to content

Commit f2ad6dd

Browse files
committed
Implement ALTER TABLE ... DROP FOREIGN KEY
1 parent 916708d commit f2ad6dd

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

tests/WP_SQLite_Driver_Metadata_Tests.php

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ public function testUseStatement() {
108108
}
109109

110110
private function assertQuery( $sql ) {
111-
$retval = $this->engine->query( $sql );
111+
try {
112+
$retval = $this->engine->query( $sql );
113+
} catch ( Exception $e ) {
114+
var_dump( $this->engine->get_last_sqlite_queries() );
115+
throw $e;
116+
}
112117
$this->assertNotFalse( $retval );
113118
return $retval;
114119
}
@@ -1567,4 +1572,56 @@ public function testInformationSchemaAlterTableAddForeignKeys(): void {
15671572
$result
15681573
);
15691574
}
1575+
1576+
public function testInformationSchemaAlterTableDropForeignKeys(): void {
1577+
$this->assertQuery( 'CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(255))' );
1578+
$this->assertQuery(
1579+
'CREATE TABLE t2 (
1580+
id INT,
1581+
t1_id INT REFERENCES t1 (id),
1582+
FOREIGN KEY (t1_id) REFERENCES t1 (id),
1583+
CONSTRAINT fk1 FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
1584+
)'
1585+
);
1586+
1587+
// INFORMATION_SCHEMA.TABLE_CONSTRAINTS
1588+
$result = $this->assertQuery( "SELECT * FROM information_schema.table_constraints WHERE table_name = 't2'" );
1589+
$this->assertCount( 3, $result );
1590+
1591+
// INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
1592+
$result = $this->assertQuery( "SELECT * FROM information_schema.referential_constraints WHERE table_name = 't2'" );
1593+
$this->assertCount( 3, $result );
1594+
1595+
// INFORMATION_SCHEMA.KEY_COLUMN_USAGE
1596+
$result = $this->assertQuery( "SELECT * FROM information_schema.key_column_usage WHERE table_name = 't2'" );
1597+
$this->assertCount( 3, $result );
1598+
1599+
// SHOW CREATE TABLE
1600+
$result = $this->assertQuery( 'SHOW CREATE TABLE t2' );
1601+
$this->assertEquals(
1602+
array(
1603+
(object) array(
1604+
'Create Table' => implode(
1605+
"\n",
1606+
array(
1607+
'CREATE TABLE `t2` (',
1608+
' `id` int DEFAULT NULL,',
1609+
' `t1_id` int DEFAULT NULL,',
1610+
' CONSTRAINT `fk1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`) ON DELETE CASCADE,',
1611+
' CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`),',
1612+
' CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`)',
1613+
') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci',
1614+
)
1615+
),
1616+
),
1617+
),
1618+
$result
1619+
);
1620+
1621+
// DROP FOREIGN KEY
1622+
$this->assertQuery( 'ALTER TABLE t2 DROP FOREIGN KEY fk1' );
1623+
1624+
$result = $this->assertQuery( "SELECT * FROM information_schema.table_constraints WHERE table_name = 't2'" );
1625+
$this->assertCount( 2, $result );
1626+
}
15701627
}

wp-includes/sqlite-ast/class-wp-sqlite-information-schema-builder.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,15 @@ public function record_alter_table( WP_Parser_Node $node ): void {
640640

641641
// DROP
642642
if ( WP_MySQL_Lexer::DROP_SYMBOL === $first_token->id ) {
643+
// DROP FOREIGN KEY
644+
if ( $action->has_child_token( WP_MySQL_Lexer::FOREIGN_SYMBOL ) ) {
645+
$field_identifier = $action->get_first_child_node( 'fieldIdentifier' );
646+
$identifiers = $field_identifier->get_descendant_nodes( 'identifier' );
647+
$name = $this->get_value( end( $identifiers ) );
648+
$this->record_drop_foreign_key( $table_is_temporary, $table_name, $name );
649+
continue;
650+
}
651+
643652
// DROP [COLUMN]
644653
$column_ref = $action->get_first_child_node( 'fieldIdentifier' );
645654
if ( null !== $column_ref ) {
@@ -1209,6 +1218,46 @@ private function record_add_constraint(
12091218
}
12101219
}
12111220

1221+
/**
1222+
* Analyze DROP FOREIGN KEY statement and record data in the information schema.
1223+
*
1224+
* @param bool $table_is_temporary Whether the table is temporary.
1225+
* @param string $table_name The table name.
1226+
* @param string $name The foreign key name.
1227+
*/
1228+
private function record_drop_foreign_key(
1229+
bool $table_is_temporary,
1230+
string $table_name,
1231+
string $name
1232+
): void {
1233+
$this->delete_values(
1234+
$this->get_table_name( $table_is_temporary, 'table_constraints' ),
1235+
array(
1236+
'TABLE_SCHEMA' => $this->db_name,
1237+
'TABLE_NAME' => $table_name,
1238+
'CONSTRAINT_NAME' => $name,
1239+
)
1240+
);
1241+
1242+
$this->delete_values(
1243+
$this->get_table_name( $table_is_temporary, 'referential_constraints' ),
1244+
array(
1245+
'CONSTRAINT_SCHEMA' => $this->db_name,
1246+
'TABLE_NAME' => $table_name,
1247+
'CONSTRAINT_NAME' => $name,
1248+
)
1249+
);
1250+
1251+
$this->delete_values(
1252+
$this->get_table_name( $table_is_temporary, 'key_column_usage' ),
1253+
array(
1254+
'TABLE_SCHEMA' => $this->db_name,
1255+
'TABLE_NAME' => $table_name,
1256+
'CONSTRAINT_NAME' => $name,
1257+
)
1258+
);
1259+
}
1260+
12121261
/**
12131262
* Analyze "columnDefinition" or "fieldDefinition" AST node and extract column data.
12141263
*

0 commit comments

Comments
 (0)