Problem/Motivation

After upgrading Drupal core from 11.3.x to 11.4.x (tested on 11.4.2) with PHP 8.3 and sqlsrv 5.0.1, running drush updb or drush cr fails with errors in the database layer.

Errors observed:

1. TypeError:
Cannot access offset of type array in isset or empty in Connection::escapeField()

2. SQL Server error:
"The MERGE statement attempted to UPDATE or DELETE the same row more than once"

This occurs during key_value table writes, triggered during container rebuild or update operations.

Impact:
- drush cr fails
- drush updb fails
- System cannot bootstrap fully

This issue blocks usage of sqlsrv with Drupal 11.4.x.

Steps to reproduce

1. Install Drupal 11.3.x with sqlsrv module (5.0.1)
2. Upgrade Drupal to 11.4.x (e.g., 11.4.2)
3. Use PHP 8.3
4. Run:
drush updb
or
drush cr
5. Observe failure during key_value operations

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Issue fork sqlsrv-3610805

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

prathamesh.save created an issue. See original summary.

prathamesh.save’s picture

Thank you for identifying the root cause and linking the related Drupal core changes.

Since Drupal 11.4.x is now using composite-key Upsert queries, would it be possible for one of the SQLSRV module maintainers to make the necessary changes in the SQLSRV driver to support this new behavior?

Currently this issue blocks site load, drush cr and drush updb on Drupal 11.4.x installations using SQL Server, so any guidance, patch, or roadmap for compatibility would be greatly appreciated.

Thanks for your continued maintenance of the SQLSRV project.

benm2’s picture

Hi team. This issue has brought development on our site to a screeching halt. Would greatly appreciate somebody looking into this. I'm seriously considering switching my site over to MySQL.

solideogloria’s picture

Version: 5.0.1 » 5.0.x-dev
Assigned: Unassigned » solideogloria

I created a fix for this that I tested locally that works, with the assistance of AI. I had fatal errors, and with the changes it works again. I'll create a MR and patch.

solideogloria’s picture

Assigned: solideogloria » Unassigned
Status: Active » Needs review
StatusFileSize
new2.03 KB

Please make any changes to the MR. Patch is only uploaded for convenience for use with composer.patches.json.

    "drupal/sqlsrv": {
      "#3610805: Upsert fails in Drupal 11.4.x": "./patches/sqlsrv-3610805-m99.diff"
    },
solideogloria’s picture

I used the contact form for the maintainer, @code-poet.

code poet’s picture

Reviewing now - sorry for delay - don't check on DO much any more.

  • solideogloria committed 5981b738 on 5.0.x
    Fixes #3610805: Upsert fails in Drupal 11.4.x. Add support for composite...
code poet’s picture

Version: 5.0.x-dev » 5.0.2
Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

code poet’s picture

I'll leave this ticket open for a few weeks then close in case any issues are logged with the 5.0.2 release.

solideogloria’s picture

Version: 5.0.2 » 5.0.x-dev
Status: Fixed » Needs work

@code-poet This introduced a regression in Drupal 10.

Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42000]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Incorrect syntax near the keyword 'WHEN'.: MERGE [my_table] WITH (ROWLOCK) AS tgt USING(VALUES (:db_upsert_placeholder_0, :db_upsert_placeholder_1)) AS src ([field_1], [field_2]) ON WHEN MATCHED THEN UPDATE SET [field_2]=src.[field_2] WHEN NOT MATCHED THEN INSERT ([field_1], [field_2]) VALUES (src.[field_1], src.[field_2]);; Array ( [0] => Array ( [0] => value_1, [1] => value_2) ) in main() (line 19 of .../web/index.php).

#0 /var/www/u/web/modules/contrib/sqlsrv/src/Driver/Database/sqlsrv/Upsert.php(119): Drupal\sqlsrv\Driver\Database\sqlsrv\ExceptionHandler->handleExecutionException()

solideogloria’s picture

I have no idea what the cause is.

solideogloria’s picture

Warning: foreach() argument must be of type array|object, string given in Drupal\sqlsrv\Driver\Database\sqlsrv\Upsert->buildQuery() (line 159

#0 .../web/core/includes/bootstrap.inc(166): _drupal_error_handler_real()
#1 .../web/modules/contrib/sqlsrv/src/Driver/Database/sqlsrv/Upsert.php(159): _drupal_error_handler()
#2 .../web/modules/contrib/sqlsrv/src/Driver/Database/sqlsrv/Upsert.php(58): Drupal\sqlsrv\Driver\Database\sqlsrv\Upsert->buildQuery()

solideogloria’s picture

I think it's because $this->key isn't an iterable yet, in Drupal 10.

solideogloria’s picture

Priority: Major » Critical
Status: Needs work » Needs review
Issue tags: +Regression

I created a MR that fixes the issue on Drupal 10. I tested it successfully on a D10 site.

solideogloria’s picture

StatusFileSize
new935 bytes
    "drupal/sqlsrv": {
      "#3610805: [D10 regression] Upsert fails in Drupal 11.4.x with SQL Server.": "./patches/sqlsrv-regression-3610805-m101.diff"
    },
solideogloria’s picture

Issue tags: +Drupal 10
solideogloria’s picture

Title: Upsert fails in Drupal 11.4.x with SQL Server: TypeError in escapeField() and MERGE duplicate update error (composite keys not supported) » [D10 regression] Upsert fails in Drupal 11.4.x with SQL Server: TypeError in escapeField() and MERGE duplicate update error (composite keys not supported)