Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support UPDATE LIMIT #93

Merged
merged 13 commits into from
Apr 16, 2024
30 changes: 30 additions & 0 deletions tests/WP_SQLite_Translator_Tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,36 @@ public function testInsertDateNow() {
$this->assertEquals( gmdate( 'Y' ), $results[0]->y );
}

public function testUpdateWithLimit() {
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('first', '2003-05-27 00:00:45');"
kozer marked this conversation as resolved.
Show resolved Hide resolved
);

$this->assertQuery(
"UPDATE _dates SET option_value = '2001-05-27 10:08:48' WHERE option_name = 'first' ORDER BY option_name LIMIT 1;"
);
$results = $this->engine->get_query_results();

$result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first';" );

$this->assertEquals( '2001-05-27 10:08:48', $result1[0]->option_value );
}

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

$this->assertQuery(
"UPDATE _dates SET option_value = '2001-05-27 10:08:48' WHERE option_name = 'first' ORDER BY option_name LIMIT 1"
);
$results = $this->engine->get_query_results();

$result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" );

$this->assertEquals( '2001-05-27 10:08:48', $result1[0]->option_value );
}

public function testCastAsBinary() {
$this->assertQuery(
// Use a confusing alias to make sure it replaces only the correct token
Expand Down
53 changes: 51 additions & 2 deletions wp-includes/sqlite/class-wp-sqlite-translator.php
Original file line number Diff line number Diff line change
Expand Up @@ -1550,14 +1550,41 @@ private function execute_describe() {
*/
kozer marked this conversation as resolved.
Show resolved Hide resolved
private function execute_update() {
$this->rewriter->consume(); // Update.

$params = array();
$limit = $this->rewriter->peek(
adamziel marked this conversation as resolved.
Show resolved Hide resolved
array(
'type' => WP_SQLite_Token::TYPE_KEYWORD,
'value' => 'LIMIT',
)
);
$order_by = $this->rewriter->peek(
array(
'type' => WP_SQLite_Token::TYPE_KEYWORD,
'value' => 'ORDER BY',
)
);
$where = $this->rewriter->peek(
array(
'type' => WP_SQLite_Token::TYPE_KEYWORD,
'value' => 'WHERE',
)
);
$params = array();
while ( true ) {
$token = $this->rewriter->peek();
if ( ! $token ) {
break;
}

if ( $token->value === 'WHERE' && ( $limit || $order_by ) ) {
kozer marked this conversation as resolved.
Show resolved Hide resolved
$this->remember_last_reserved_keyword( $token );
$this->rewriter->consume();
$this->prepare_update_for_limit_or_order();
}

if ( $token->value === ';' && $token->type === WP_SQLite_Token::TYPE_DELIMITER && ( $limit || $order_by ) ) {
adamziel marked this conversation as resolved.
Show resolved Hide resolved
$this->rewriter->skip();
}

// Record the table name.
if (
! $this->table_name &&
Expand All @@ -1580,13 +1607,35 @@ private function execute_update() {

$this->rewriter->consume();
}

if ( $where && ( $limit || $order_by ) ) {
$this->rewriter->add( new WP_SQLite_Token( ')', WP_SQLite_Token::TYPE_OPERATOR ) );
}

$this->rewriter->consume_all();

$updated_query = $this->rewriter->get_updated_query();
$this->execute_sqlite_query( $updated_query, $params );
$this->set_result_from_affected_rows();
}

private function prepare_update_for_limit_or_order() {
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
kozer marked this conversation as resolved.
Show resolved Hide resolved
$this->rewriter->add( new WP_SQLite_Token( 'rowid', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_KEY ) );
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
$this->rewriter->add( new WP_SQLite_Token( 'IN', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) );
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
$this->rewriter->add( new WP_SQLite_Token( '(', WP_SQLite_Token::TYPE_OPERATOR ) );
$this->rewriter->add( new WP_SQLite_Token( 'SELECT', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) );
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
$this->rewriter->add( new WP_SQLite_Token( 'rowid', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_KEY ) );
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
$this->rewriter->add( new WP_SQLite_Token( 'FROM', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) );
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
$this->rewriter->add( new WP_SQLite_Token( $this->table_name, WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) );
$this->rewriter->add( new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ) );
$this->rewriter->add( new WP_SQLite_Token( 'WHERE', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED ) );
}
/**
* Executes a INSERT or REPLACE statement.
*/
Expand Down