From e910d7f6f05502e00bbd8ae9ca70b30c86ebc8d3 Mon Sep 17 00:00:00 2001 From: Jan Jakes Date: Sat, 10 Aug 2024 20:15:02 +0200 Subject: [PATCH] Fix detection whether a query contains the GROUP BY clause There is a logic for translating WHERE ... HAVING without GROUP BY to WHERE ... AND, and this bug was causing that every HAVING was rewritten to AND, which resulted in GROUP BY ... HAVING queries like the following one failing: SELECT name, COUNT(*) as count FROM _tmp_table GROUP BY name HAVING COUNT(*) > 1; --- tests/WP_SQLite_Translator_Tests.php | 29 +++++++++++++++++++ .../sqlite/class-wp-sqlite-translator.php | 6 +--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php index 4192740..188be93 100644 --- a/tests/WP_SQLite_Translator_Tests.php +++ b/tests/WP_SQLite_Translator_Tests.php @@ -3048,6 +3048,35 @@ public function testCurrentTimestamp() { $this->assertQuery( 'DELETE FROM _dates WHERE option_value = CURRENT_TIMESTAMP()' ); } + public function testGroupByHaving() { + $this->assertQuery( + 'CREATE TABLE _tmp_table ( + name varchar(20) + );' + ); + + $this->assertQuery( + "INSERT INTO _tmp_table VALUES ('a'), ('b'), ('b'), ('c'), ('c'), ('c')" + ); + + $result = $this->assertQuery( + 'SELECT name, COUNT(*) as count FROM _tmp_table GROUP BY name HAVING COUNT(*) > 1' + ); + $this->assertEquals( + array( + (object) array( + 'name' => 'b', + 'count' => '2', + ), + (object) array( + 'name' => 'c', + 'count' => '3', + ), + ), + $result + ); + } + /** * @dataProvider mysqlVariablesToTest */ diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php index 06fd052..8329513 100644 --- a/wp-includes/sqlite/class-wp-sqlite-translator.php +++ b/wp-includes/sqlite/class-wp-sqlite-translator.php @@ -2607,15 +2607,11 @@ private function capture_group_by( $token ) { ! $token->matches( WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED, - array( 'GROUP' ) + array( 'GROUP BY' ) ) ) { return false; } - $next = $this->rewriter->peek_nth( 2 )->value; - if ( 'BY' !== strtoupper( $next ?? '' ) ) { - return false; - } $this->has_group_by = true;