Skip to content

Commit 4043e6d

Browse files
committed
Add support for CURRENT_TIMESTAMP() with parentheses
While SQLite does support CURRENT_TIMESTAMP function calls natively, it doesn't support calling the function with parentheses in the form of CURRENT_TIMESTAMP(), so we need to remove them.
1 parent 4c63355 commit 4043e6d

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

tests/WP_SQLite_Translator_Tests.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2859,6 +2859,46 @@ public function testDefaultNullValue() {
28592859
);
28602860
}
28612861

2862+
public function testCurrentTimestamp() {
2863+
// SELECT
2864+
$results = $this->assertQuery(
2865+
'SELECT
2866+
current_timestamp AS t1,
2867+
CURRENT_TIMESTAMP AS t2,
2868+
current_timestamp() AS t3,
2869+
CURRENT_TIMESTAMP() AS t4'
2870+
);
2871+
$this->assertIsArray( $results );
2872+
$this->assertCount( 1, $results );
2873+
$this->assertRegExp( '/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/', $results[0]->t1 );
2874+
$this->assertRegExp( '/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/', $results[0]->t2 );
2875+
$this->assertRegExp( '/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/', $results[0]->t3 );
2876+
2877+
// INSERT
2878+
$this->assertQuery(
2879+
"INSERT INTO _dates (option_name, option_value) VALUES ('first', current_timestamp())"
2880+
);
2881+
$results = $this->assertQuery( 'SELECT option_value AS t FROM _dates' );
2882+
$this->assertCount( 1, $results );
2883+
$this->assertRegExp( '/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/', $results[0]->t );
2884+
2885+
// UPDATE
2886+
$this->assertQuery( 'UPDATE _dates SET option_value = NULL' );
2887+
$results = $this->assertQuery( 'SELECT option_value AS t FROM _dates' );
2888+
$this->assertCount( 1, $results );
2889+
$this->assertEmpty( $results[0]->t );
2890+
2891+
$this->assertQuery( 'UPDATE _dates SET option_value = CURRENT_TIMESTAMP()' );
2892+
$results = $this->assertQuery( 'SELECT option_value AS t FROM _dates' );
2893+
$this->assertCount( 1, $results );
2894+
$this->assertRegExp( '/\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d/', $results[0]->t );
2895+
2896+
// DELETE
2897+
// We can only assert that the query passes. It is not guaranteed that we'll actually
2898+
// delete the existing record, as the delete query could fall into a different second.
2899+
$this->assertQuery( 'DELETE FROM _dates WHERE option_value = CURRENT_TIMESTAMP()' );
2900+
}
2901+
28622902
/**
28632903
* @dataProvider mysqlVariablesToTest
28642904
*/

wp-includes/sqlite/class-wp-sqlite-translator.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,23 @@ public function get_return_value() {
772772
* @throws Exception If the query is not supported.
773773
*/
774774
private function execute_mysql_query( $query ) {
775-
$tokens = ( new WP_SQLite_Lexer( $query ) )->tokens;
775+
$tokens = ( new WP_SQLite_Lexer( $query ) )->tokens;
776+
777+
// SQLite does not support CURRENT_TIMESTAMP() calls with parentheses.
778+
// Since CURRENT_TIMESTAMP() can appear in most types of SQL queries,
779+
// let's remove the parentheses globally before further processing.
780+
foreach ( $tokens as $i => $token ) {
781+
if ( WP_SQLite_Token::TYPE_KEYWORD === $token->type && 'CURRENT_TIMESTAMP' === $token->keyword ) {
782+
$paren_open = $tokens[ $i + 1 ] ?? null;
783+
$paren_close = $tokens[ $i + 2 ] ?? null;
784+
if ( WP_SQLite_Token::TYPE_OPERATOR === $paren_open->type && '(' === $paren_open->value
785+
&& WP_SQLite_Token::TYPE_OPERATOR === $paren_close->type && ')' === $paren_close->value ) {
786+
unset( $tokens[ $i + 1 ], $tokens[ $i + 2 ] );
787+
}
788+
}
789+
}
790+
$tokens = array_values( $tokens );
791+
776792
$this->rewriter = new WP_SQLite_Query_Rewriter( $tokens );
777793
$this->query_type = $this->rewriter->peek()->value;
778794

0 commit comments

Comments
 (0)