Problem/Motivation

Drupal 9 recently added the Connection::identifierQuote(). SQL Server does not use a single character to enclose reserved words. It uses square brackets. We need to be able to handle situations where the opening and closing character are different.

Proposed resolution

Instead of having a method to return a string use a class property which is an array with two string values - the start and end quote character.

Remaining tasks

None

User interface changes

None

API changes

Remove \Drupal\Core\Database\Connection::identifierQuote() and replace with \Drupal\Core\Database\Connection::$identifierQuotes

Data model changes

None

Release notes snippet

Custom or contrib database drivers updated for the recent identifier quote change will need to remove \Drupal\Core\Database\Connection::identifierQuote() and replace with \Drupal\Core\Database\Connection::$identifierQuotes. Read https://www.drupal.org/node/2986894 for more information about both changes.

Comments

Beakerboy created an issue. See original summary.

alexpott’s picture

@Beakerboy thanks for testing Drupal 9 prior to release. It's great to get real world testing of #2986452: Database reserved keywords need to be quoted as per the ANSI standard prior to it landing. Especially real world testing that reveals a flaw in the design where this was supposed to make things much easier for contrib drivers like sqlsrv. I'll work on this this weekend if no-one beats me to it.

catch’s picture

Issue summary: View changes
alexpott’s picture

Status: Active » Needs review
StatusFileSize
new4.73 KB
new12.82 KB

Here are two ways to fix this. One is less of an API change than the other. Personally I prefer the -alt patch which changes the protected function \Drupal\Core\Database\Connection::identifierQuote() return value to be an array. This function only exists within 9.0.x and is in a very low level part of the system and is protected.

alexpott’s picture

StatusFileSize
new13 KB
new19.82 KB

After sleeping on this I've realised that using a method to contain the identifier quotes is more than a little bit awkward. You should do something functional is that method - so we can make it a property but still keep the deprecation and means no one is wondering about \Drupal\Core\Database\Connection::quoteIdentifiers() vs \Drupal\Core\Database\Connection::identifierQuote()/\Drupal\Core\Database\Connection::identifierQuotes().

alexpott’s picture

StatusFileSize
new2.55 KB
new20.39 KB

More assert() magic for enforcing the contract.

daffie’s picture

StatusFileSize
new20.13 KB

Straight reroll no changes.

daffie’s picture

Patch looks good. My preference is the alternative solution.
My review for the patch from comment #6.

  1. Instead of doing an array of $identifierQuotes, can we do 2 variables: $identifierStartingQuote and $identifierEndingQuote. Less confusion. We do not have to, just an idea.
  2. +++ b/core/lib/Drupal/Core/Database/Connection.php
    @@ -413,7 +416,7 @@ public function prefixTables($sql) {
    -    return str_replace(['[', ']'], $this->identifierQuote(), $sql);
    +    return str_replace(['[', ']'], $this->identifierQuotes, $sql);
    

    So for SQL Server, they will be replacing the blockquotes with blockquotes. :)

  3. In Drupal\Tests\Core\Database\ConnectionTest can we also add bracket testing in providerEscapeAlias().
daffie’s picture

What ever solution it will be we shall have to update the CR in https://www.drupal.org/node/3123251.

alexpott’s picture

StatusFileSize
new641 bytes
new20.24 KB
new20.44 KB

@daffie good call on the additional test. Personally I prefer a single class property for this.

re $identifierStartingQuote and $identifierEndingQuote I think 1 class property is better in this instance than two. Easier to keep consistent.

I've pondered several times whether we should allow a single element array if the quotes are the same or whether a string of 1 or 2 characters for the same thing.

Seems like we need 9.1.x and 9.0.x patches. Oh yay.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

All the code changes look good to me.
Removed the method Drupal\Core\Database\Connection::identifierQuote().
Added the class variable Drupal\Core\Database\Connection::$identifierQuotes.
The change record must be changed for this. The problem is that this can only be done after this issue has landed, because the CR is already published.
For me the patch is RTBC.

  • catch committed 396a950 on 9.1.x
    Issue #3126658 by alexpott, daffie, Beakerboy: Support enclosing...

  • catch committed 81b4b3a on 9.0.x
    Issue #3126658 by alexpott, daffie, Beakerboy: Support enclosing...
catch’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs release manager review

Agreed we should just get this in since it's not been in for long in its current state.

Committed/pushed to 9.1.x and 9.0.x, thanks!

edit: CR still needs updating.

catch’s picture

Status: Fixed » Needs work
Issue tags: +Needs release note

Arghh also needs a release notes snippet.

daffie’s picture

Updated the CR https://www.drupal.org/node/2986894 for this issue.

alexpott’s picture

Issue summary: View changes
Status: Needs work » Fixed
Issue tags: -Needs release note

@daffie the changes to the CR look good.

Added a release note and filled out the issue summary.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.