diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php index 93ffa081a6fb5ee27930282ba6aa3c33905018fc..c4fd8535f4504d10abb8c9da935d5e779891eec9 100644 --- a/core/lib/Drupal/Core/Database/Query/Select.php +++ b/core/lib/Drupal/Core/Database/Query/Select.php @@ -878,7 +878,10 @@ public function __toString() { // GROUP BY if ($this->group) { - $query .= "\nGROUP BY " . implode(', ', $this->group); + $group_by_fields = array_map(function (string $field): string { + return $this->connection->escapeField($field); + }, $this->group); + $query .= "\nGROUP BY " . implode(', ', $group_by_fields); } // HAVING diff --git a/core/modules/views/tests/src/Kernel/QueryGroupByTest.php b/core/modules/views/tests/src/Kernel/QueryGroupByTest.php index 171688321e4ea53d6238bc96f17d8bacccec755a..20a55769fbd540b6bc4d9809fd024d2a30b787d1 100644 --- a/core/modules/views/tests/src/Kernel/QueryGroupByTest.php +++ b/core/modules/views/tests/src/Kernel/QueryGroupByTest.php @@ -230,7 +230,7 @@ public function testGroupByBaseField() { $view->displayHandlers->get('default')->options['fields']['name']['group_type'] = 'min'; unset($view->displayHandlers->get('default')->options['fields']['id']['group_type']); $this->executeView($view); - $this->assertStringContainsString('GROUP BY entity_test.id', (string) $view->build_info['query'], 'GROUP BY field includes the base table name when grouping on the base field.'); + $this->assertMatchesRegularExpression('/GROUP BY .*[^\w\s]entity_test[^\w\s]\.[^\w\s]id[^\w\s]/', (string) $view->build_info['query'], 'GROUP BY field includes the base table name when grouping on the base field.'); } /** diff --git a/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php b/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php index 9bc296c8e67c96b32ced46fc373658fdc930856f..c541f466d46d5933b796e7b9b3dc4ba4a1f1f677 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php @@ -80,4 +80,30 @@ public function testSelectReservedWordAliasAllFields() { $this->assertSame('27', $record->age); } + /** + * Tests SELECT query with GROUP BY clauses on fields with reserved names. + */ + public function testGroupBy() { + $this->connection->insert('select') + ->fields([ + 'id' => 2, + 'update' => 'Update value 1', + ]) + ->execute(); + + // Using aliases. + $query = $this->connection->select('select', 's'); + $query->addExpression('COUNT([id])', 'num'); + $query->addField('s', 'update'); + $query->groupBy('s.update'); + $this->assertSame('2', $query->execute()->fetchAssoc()['num']); + + // Not using aliases. + $query = $this->connection->select('select'); + $query->addExpression('COUNT([id])', 'num'); + $query->addField('select', 'update'); + $query->groupBy('update'); + $this->assertSame('2', $query->execute()->fetchAssoc()['num']); + } + } diff --git a/core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php b/core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php index 281f3d4d57c96d589cc05c3b3920f24e3df5acf3..e7df5c4386b18c79db56fe913dca3f8f6542bc5c 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/SelectComplexTest.php @@ -82,6 +82,10 @@ public function testGroupBy() { $task_field = $query->addField('t', 'task'); $query->orderBy($count_field); $query->groupBy($task_field); + + $this->assertMatchesRegularExpression("/ORDER BY .*[^\w\s]num[^\w\s]/", (string) $query); + $this->assertMatchesRegularExpression("/GROUP BY .*[^\w\s]task[^\w\s]/", (string) $query); + $result = $query->execute(); $num_records = 0;