Problem/Motivation
We've come across this issue in #2978575-152: Mysql 8 Support on Drupal 7 where we're working on back-porting the MySQL 8 support implemented in D8 in #2966523: MySQL 8 Support. It seems the problem still exists in 8.9.x
Given a table with a name that's a reserved keyword in MySQL 8, certain SELECT queries can fail as the table name is automatically added as an alias in the SQL and is not escaped / quoted.
In D7 this surfaces in \DatabaseTemporaryQueryTestCase::testTemporaryQuery
as that does a countQuery()
on the system
table (where "system" is reserved).
D8 doesn't have a system table, but the same query fails if we do create a table with a reserved name.
AFAICS this is no longer a problem in D9.x (perhaps because of #2986452: Database reserved keywords need to be quoted as per the ANSI standard ?).
I'll attach a patch with a very basic test that illustrates this in 8.9.x
It's also easy to reproduce manually:
mysql> CREATE TABLE `virtual` (`id` int);
$ drush ev "var_dump(db_select('virtual')->countQuery()->execute()->fetchField());"
PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'virtual [error]
virtual) subquery' at line 5 in /path/to/drupal-8.x/core/lib/Drupal/Core/Database/Statement.php:59
Stack trace:
#0 /path/to/drupal-8.x/core/lib/Drupal/Core/Database/Statement.php(59): PDOStatement->execute(Array)
#1 /path/to/drupal-8.x/core/lib/Drupal/Core/Database/Connection.php(640): Drupal\Core\Database\Statement->execute(Array, Array)
#2 /path/to/drupal-8.x/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php(357): Drupal\Core\Database\Connection->query('SELECT COUNT(*)...', Array, Array)
#3 /path/to/drupal-8.x/core/lib/Drupal/Core/Database/Query/Select.php(510): Drupal\Core\Database\Driver\mysql\Connection->query('SELECT COUNT(*)...', Array, Array)
#4 phar:///opt/drush/drush-8.3.5.phar/commands/core/core.drush.inc(1178) : eval()'d code(1): Drupal\Core\Database\Query\Select->execute()
[...snip...]
Next Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for
the right syntax to use near 'virtual virtual) subquery' at line 5: SELECT COUNT(*) AS expression
FROM
(SELECT 1 AS expression
FROM
{virtual} virtual) subquery; Array
(
)
in /path/to/drupal-8.x/core/lib/Drupal/Core/Database/Connection.php:701
I'm not sure why this alias is not automatically quoted as a reserved word; it may be because this particular way of constructing and executing a SelectQuery doesn't end up invoking \SelectQuery::__toString
and therefore escapeAlias
is not called. I'm not certain about that yet though.
Proposed resolution
Ensure that table aliases are escaped if they are reserved words (or perhaps ensure that reserved words are not used as aliases in the first place?).
Remaining tasks
Identify a solution, implement it, and backport it to D7.
User interface changes
n/a
API changes
n/a ?
Data model changes
n/a ?
Release notes snippet
tbc