diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php index 78462d0b638f9a1edb1a387e4b4ae5efc93d1abe..86aa642ade5d26557fb3679f76627f110063bef2 100644 --- a/core/lib/Drupal/Core/Database/Query/Select.php +++ b/core/lib/Drupal/Core/Database/Query/Select.php @@ -807,13 +807,15 @@ public function __toString() { $fields = []; foreach ($this->tables as $alias => $table) { if (!empty($table['all_fields'])) { - $fields[] = $this->connection->escapeTable($alias) . '.*'; + $fields[] = $this->connection->escapeAlias($alias) . '.*'; } } foreach ($this->fields as $field) { + // Note that $field['table'] holds the table_alias. + // @see \Drupal\Core\Database\Query\Select::addField + $table = isset($field['table']) ? $field['table'] . '.' : ''; // Always use the AS keyword for field aliases, as some // databases require it (e.g., PostgreSQL). - $table = isset($field['table']) ? $field['table'] . '.' : ''; $fields[] = $this->connection->escapeField($table . $field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']); } foreach ($this->expressions as $expression) { diff --git a/core/modules/system/tests/modules/database_test/database_test.install b/core/modules/system/tests/modules/database_test/database_test.install index a2b4da4a17db34795637eedee3b5680f9ad7261c..effd261994db612edc7dcb2e96b7d8fb9e064036 100644 --- a/core/modules/system/tests/modules/database_test/database_test.install +++ b/core/modules/system/tests/modules/database_test/database_test.install @@ -331,6 +331,22 @@ function database_test_schema() { 'primary key' => ['id'], ]; + $schema['virtual'] = [ + 'description' => 'A simple table with reserved name in MySQL 8.', + 'fields' => [ + 'id' => [ + 'description' => 'Simple unique ID.', + 'type' => 'int', + 'not null' => TRUE, + ], + 'function' => [ + 'description' => 'A column with reserved name in MySQL 8.', + 'type' => 'text', + ], + ], + 'primary key' => ['id'], + ]; + $schema['TEST_UPPERCASE'] = $schema['test']; return $schema; diff --git a/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php b/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php index 9ac9c6beded983eea5c28efb2e789cb5902003a8..ce73c29bf3c7a894fd6aaec1e70b1df183b66a7a 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/Database/DatabaseTestBase.php @@ -37,6 +37,7 @@ protected function setUp() { 'test_serialized', 'TEST_UPPERCASE', 'select', + 'virtual', ]); self::addSampleData(); } @@ -163,6 +164,13 @@ public static function addSampleData() { 'update' => 'Update value 1', ]) ->execute(); + + $connection->insert('virtual') + ->fields([ + 'id' => 1, + 'function' => 'Function value 1', + ]) + ->execute(); } } diff --git a/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php b/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9bc296c8e67c96b32ced46fc373658fdc930856f --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Database/ReservedWordTest.php @@ -0,0 +1,83 @@ +connection->select('virtual'); + $num_records = $query->countQuery()->execute()->fetchField(); + + $this->assertSame('1', $num_records); + } + + /** + * Tests SELECT query with a specific field from a table with a reserved name. + */ + public function testSelectReservedWordTableSpecificField() { + $query = $this->connection->select('virtual'); + $query->addField('virtual', 'function'); + $rows = $query->execute()->fetchCol(); + + $this->assertSame('Function value 1', $rows[0]); + } + + /** + * Tests SELECT query with all fields from a table with a reserved name. + */ + public function testSelectReservedWordTableAllFields() { + $query = $this->connection->select('virtual'); + $query->fields('virtual'); + $result = $query->execute()->fetchObject(); + + $this->assertSame('Function value 1', $result->function); + } + + /** + * Tests SELECT count query from a table with a reserved alias. + */ + public function testSelectReservedWordAliasCount() { + $query = $this->connection->select('test', 'character'); + $num_records = $query->countQuery()->execute()->fetchField(); + + $this->assertSame('4', $num_records); + } + + /** + * Tests SELECT query with specific fields from a table with a reserved alias. + */ + public function testSelectReservedWordAliasSpecificFields() { + $query = $this->connection->select('test', 'high_priority'); + $query->addField('high_priority', 'name'); + $query->addField('high_priority', 'age', 'age'); + $query->condition('age', 27); + $record = $query->execute()->fetchObject(); + + // Ensure that we got the right record. + $this->assertSame('George', $record->name); + $this->assertSame('27', $record->age); + } + + /** + * Tests SELECT query with all fields from a table with a reserved alias. + */ + public function testSelectReservedWordAliasAllFields() { + $record = $this->connection->select('test', 'signal') + ->fields('signal') + ->condition('age', 27) + ->execute()->fetchObject(); + + // Ensure that we got the right record. + $this->assertSame('George', $record->name); + $this->assertSame('27', $record->age); + } + +}