Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2308,6 +2308,38 @@ private function execute_delete_statement( WP_Parser_Node $node ): void {
throw $this->new_access_denied_to_information_schema_exception();
}

/*
* SQLite doesn't support DELETE with ORDER BY/LIMIT.
* We need to use a subquery to emulate this behavior.
*
* For instance, the following query:
* DELETE FROM t WHERE c = 2 LIMIT 1;
* Will be rewritten to:
* DELETE FROM t WHERE rowid IN ( SELECT rowid FROM t WHERE c = 2 LIMIT 1 );
*/
$has_order = $node->has_child_node( 'orderClause' );
$has_limit = $node->has_child_node( 'simpleLimitClause' );
if ( $has_order || $has_limit ) {
$where_subquery = 'SELECT rowid FROM ' . $this->translate_sequence(
array(
$table_ref,
$node->get_first_child_node( 'tableAlias' ),
$node->get_first_child_node( 'whereClause' ),
$node->get_first_child_node( 'orderClause' ),
$node->get_first_child_node( 'simpleLimitClause' ),
)
);

$query = sprintf(
'DELETE FROM %s WHERE rowid IN ( %s )',
$this->translate( $table_ref ),
$where_subquery
);

$this->last_result_statement = $this->execute_sqlite_query( $query );
return;
}

$query = $this->translate( $node );
$this->last_result_statement = $this->execute_sqlite_query( $query );
}
Expand Down
58 changes: 58 additions & 0 deletions packages/mysql-on-sqlite/tests/WP_SQLite_Driver_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,64 @@ public function testUpdateWithoutWhereButWithLimit() {
$this->assertEquals( '2003-05-27 10:08:48', $result2[0]->option_value );
}

public function testDeleteWithLimit() {
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('first', '2003-05-27 00:00:45')"
);
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('second', '2003-05-28 00:00:45')"
);
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('third', '2003-05-29 00:00:45')"
);

// LIMIT only: only one row is removed even though WHERE matches every row.
$result = $this->assertQuery( "DELETE FROM _dates WHERE option_name LIKE '%' LIMIT 1" );
$this->assertSame( 1, $result );

$rows = $this->engine->query( 'SELECT option_name FROM _dates ORDER BY option_name' );
$this->assertCount( 2, $rows );

// ORDER BY + LIMIT: deletes the lexicographically-first remaining row.
$result = $this->assertQuery( 'DELETE FROM _dates ORDER BY option_name ASC LIMIT 1' );
$this->assertSame( 1, $result );

$rows = $this->engine->query( 'SELECT option_name FROM _dates' );
$this->assertCount( 1, $rows );
$this->assertSame( 'third', $rows[0]->option_name );
}

public function testDeleteWithoutWhereButWithLimit() {
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('first', '2003-05-27 10:08:48')"
);
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('second', '2003-05-27 10:08:48')"
);

$result = $this->assertQuery( 'DELETE FROM _dates LIMIT 1' );
$this->assertSame( 1, $result );

$rows = $this->engine->query( 'SELECT option_name FROM _dates' );
$this->assertCount( 1, $rows );
}

public function testDeleteWithAliasAndLimit() {
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('a', '2003-05-27 00:00:45')"
);
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('b', '2003-05-28 00:00:45')"
);

$result = $this->assertQuery( "DELETE FROM _dates AS d WHERE d.option_name = 'a' LIMIT 1" );
$this->assertSame( 1, $result );

$rows = $this->engine->query( 'SELECT option_name FROM _dates' );
$this->assertCount( 1, $rows );
$this->assertSame( 'b', $rows[0]->option_name );
}

public function testCastAsBinary() {
$this->assertQuery(
// Use a confusing alias to make sure it replaces only the correct token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,36 @@ public function testDelete(): void {
'DELETE FROM `t` WHERE `c` = 1',
'DELETE FROM t WHERE c = 1'
);

// DELETE with LIMIT.
$this->assertQuery(
'DELETE FROM `t` WHERE rowid IN ( SELECT rowid FROM `t` LIMIT 1 )',
'DELETE FROM t LIMIT 1'
);

// DELETE with WHERE and LIMIT.
$this->assertQuery(
'DELETE FROM `t` WHERE rowid IN ( SELECT rowid FROM `t` WHERE `c` = 1 LIMIT 5 )',
'DELETE FROM t WHERE c = 1 LIMIT 5'
);

// DELETE with ORDER BY and LIMIT.
$this->assertQuery(
'DELETE FROM `t` WHERE rowid IN ( SELECT rowid FROM `t` ORDER BY `c` ASC LIMIT 1 )',
'DELETE FROM t ORDER BY c ASC LIMIT 1'
);

// DELETE with WHERE, ORDER BY, and LIMIT.
$this->assertQuery(
'DELETE FROM `t` WHERE rowid IN ( SELECT rowid FROM `t` WHERE `c` = 1 ORDER BY `c` ASC LIMIT 1 )',
'DELETE FROM t WHERE c = 1 ORDER BY c ASC LIMIT 1'
);

// DELETE with a table alias and LIMIT.
$this->assertQuery(
'DELETE FROM `t` WHERE rowid IN ( SELECT rowid FROM `t` AS `a` WHERE `a`.`c` = 1 LIMIT 1 )',
'DELETE FROM t AS a WHERE a.c = 1 LIMIT 1'
);
}

public function testCreateTable(): void {
Expand Down
Loading