Unverified Commit 9b9e1f08 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3155563 by mcdruid, mrinalini9, Hardik_Patel_12, mondrake, daffie:...

Issue #3155563 by mcdruid, mrinalini9, Hardik_Patel_12, mondrake, daffie: select query should quote aliases which are reserved words in MySQL
parent 7727f4f9
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -814,13 +814,16 @@ 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']) ? $this->connection->escapeAlias($field['table']) . '.' : '';
      // Always use the AS keyword for field aliases, as some
      // databases require it (e.g., PostgreSQL).
      $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
      $fields[] = $table . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']);
    }
    foreach ($this->expressions as $expression) {
      $fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']);
@@ -852,7 +855,7 @@ public function __toString() {

      // Don't use the AS keyword for table aliases, as some
      // databases don't support it (e.g., Oracle).
      $query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']);
      $query .= $table_string . ' ' . $this->connection->escapeAlias($table['alias']);

      if (!empty($table['condition'])) {
        $query .= ' ON ' . (string) $table['condition'];
+16 −0
Original line number Diff line number Diff line
@@ -333,6 +333,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;
+8 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ protected function setUp() {
      'test_serialized',
      'test_special_columns',
      'TEST_UPPERCASE',
      'virtual',
    ]);
    self::addSampleData();
  }
@@ -164,6 +165,13 @@ public static function addSampleData() {
        'function' => 'Function value 1',
      ])
      ->execute();

    $connection->insert('virtual')
      ->fields([
        'id' => 1,
        'function' => 'Function value 1',
      ])
      ->execute();
  }

}
+83 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\KernelTests\Core\Database;

/**
 * Tests queries that include reserved words.
 *
 * @group Database
 */
class ReservedWordTest extends DatabaseTestBase {

  /**
   * Tests SELECT count query from a table with a reserved name.
   */
  public function testSelectReservedWordTableCount() {
    $query = $this->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);
  }

}