ATTR_STRINGIFY_FETCHES no longer working since PHP 8.1.22 / 8.2.9

Created on 8 August 2023, 11 months ago
Updated 12 September 2023, 10 months ago

Problem/Motivation

We have updated our PHP container from 8.1.21 to 8.1.22 and ever since, the command $connection->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, TRUE); throws an exception PDOException SQLSTATE[IMSSP]: An invalid attribute was designated on the PDO object. in \Drupal\sqlsrv\Driver\Database\sqlsrv\Connection::__construct

When I remove that command, everything seems to be working fine. I couldn't find any reference on what has really changed on the PHP side. The included sqlsrv and pdo_sqlsrv drivers haven't changed, they are at version 5.11.0

Anyone else seeing that issue?

🐛 Bug report
Status

Fixed

Version

4.3

Component

Code

Created by

🇩🇪Germany jurgenhaas Gottmadingen

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @jurgenhaas
  • @jurgenhaas opened merge request.
  • 🇬🇧United Kingdom pstewart

    I'm seeing the same error message on my production site, with errors starting at 6:22am. Am currently investigating whether an automated os packages upgrade has triggered.

  • 🇬🇧United Kingdom pstewart

    I've confirmed that the issue for me was triggered this morning by OS package updates, which involved php 8.1 (8.1.21 to 8.1.22) and msodbcsql17 (17.10.2 to 17.10.4). I was able to bring my site back online by commenting out the setAttribute call on line 208 of src/Driver/Database/sqlsrv/Connection.php as per @jurgenhaas 's issue fork. For the benefit of anyone unfamiliar with patching looking to bring their site back online in a hurry:

      /**
       * {@inheritdoc}
       */
      public function __construct(\PDO $connection, array $connection_options) {
        // COMMENT OUT THIS LINE --> $connection->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, TRUE);
        parent::__construct($connection, $connection_options);
    
        // This driver defaults to transaction support, except if explicitly passed
        // FALSE.
        $this->transactionalDDLSupport = !isset($connection_options['transactions']) || $connection_options['transactions'] !== FALSE;
    
        // Store connection options for future reference.
        $this->connectionOptions = $connection_options;
      }
    
    

    It's possible there might be some very specific side-effects form disabling this attribute on some site (most likely around truthiness of numeric 0 vs stringified '0'), however I suspect the impact of any such side-effects is likely to be low (particularly when compared to a broken website).

  • 🇬🇧United Kingdom pstewart

    It looks like there was a bug fix in php 8.1.22 relating to this pdo attribute that might be responsible - I've not dug into it yet but have added a note on the relevant issue: After php8.1, when PDO::ATTR_EMULATE_PREPARES is true and PDO::ATTR_STRINGIFY_FETCHES is true, decimal zeros are no longer filled #11587.

    For anyone affected by this and concerned about any potential side-effects of not setting the attribute, downgrading back to php 8.1.21 is an alternative option to try.

  • 🇬🇧United Kingdom pstewart

    Update: it turns out this was picked up in the Laravel community last week. The change introduced in php 8.1.22 / 8.2.9 was that PDO has now started passing though the stringify attribute to the driver's set attribute method, which has exposed a bug in the Microsoft PHP pdo_sqlsrv driver whereby this attribute isn't being handled by it's set attribute method implementation. More discussion can be found on laravel issue #47937.

    There is a pull request to fix the issue on the pdo_sqlsrv driver, which is awaiting review: Fixed error when using PDO::ATTR_STRINGIFY_FETCHES #1468

    Ultimately this whole thing should resolve when the PR is accepted and Microsoft release a new version of the pdo_sqlsrv ext with
    the fix, however that could take a while so we'll workaround in the meantime.

    It's unclear to me what PDO::ATTR_STRINGIFY_FETCHES defaults to, so I'd rather not risk unintended side effects by removing it altogether. The exception occurs after the database handle's internal stringify attribute is set, so my preference is to continue to set the attribute from our code but put a try/catch around it to disregard the exception.

  • Status changed to Fixed 11 months ago
  • 🇬🇧United Kingdom pstewart

    Committed try / catch approach. Will now make a new 4.3 release and merge to 4.4 branch.

  • 🇬🇧United Kingdom pstewart

    Tagged and released 4.3.4 and 4.4.0-beta2

  • 🇬🇧United Kingdom pstewart

    Noting that in my haste I made the try / catch here catch the exception but didn't include a variable for the exception object. This works OK in newer PHP versions (e.g. 8.0+), but causes a parse error on older php versions where the exception variable is required (e.g. 7.4 and below). As current Drupal 9 versions only officially support 8.0+ and 7.4 is EOL this is unlikely to be causing many people problems, but if anyone is running into this then my recommendation is to downgrade sqlsrv back to the previous version as php 7.4 shouldn't be affected by the ATRR_STRINGIFY_FETCHES issue in any case. I'll open a follow-up for fixing the php 7.4 parse error.

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

  • Status changed to Fixed 10 months ago
  • 🇦🇺Australia genebobmiller

    I am still seeing the message:

    ```
    Warning: SQLSTATE: IMSSP
    Error Code: -33
    Error Message: An invalid attribute was designated on the PDO object.
    in Drupal\sqlsrv\Driver\Database\sqlsrv\Connection->__construct()
    (line 209
    ```
    Is that expected?
    sqlsrv:4.3.4

Production build 0.69.0 2024