Problem/Motivation

Drupal core just introduced a feature to use the query portion of the database URI to pass in additional parameters to the database layer. Currently, the only parameter that is used in core is 'module'. the sqlsrv module would like to use 'schema' to pass in the name of the database schema, and use Connection:: createConnectionOptionsFromUrl() to manage this option. This strategy was working in development until the parent issue went live.

The database query sqlsrv://sa:Password12!@localhost/mydrupalsite?schema=dbo will currently cause Drupal to throw an error.

Proposed resolution

The file core/lib/Drupal/Core/Database/Database.php should change:

if ($query['module'])

to

if (isset($query['module'])) 

This will allow drivers to have query parameters without specifying the optional 'module' parameter. When other query parameters are officially added, this will have to be changed regardless.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Beakerboy created an issue. See original summary.

Beakerboy’s picture

Assigned: Beakerboy » Unassigned
Status: Active » Needs review
FileSize
723 bytes
daffie’s picture

Status: Needs review » Postponed (maintainer needs more info)
Issue tags: +Contrib database driver

Hi @Beakerboy: Could write up with more details what exactly you would like. Add examples with what should work according to you.

Beakerboy’s picture

I would like to use the database uri sqlsrv://sa:Password12!@localhost/mydrupalsite?schema=dbo

The new feature assumes that if there is any parameter in the query position, it must include ‘?module=something’. Changing if ($query['module']) to if (isset($query['module'])). Will allow a driver to specify a query parameter without a ‘module’.

daffie’s picture

Hi @Beakerboy: I think what you miss is that the query parameter can hold multiple variables. See: https://www.php.net/manual/en/function.parse-str.php. If you we to add the module parameter to your database connection URL it would become:
sqlsrv://sa:Password12!@localhost/mydrupalsite?schema=dbo&module=sqlsrv
or
sqlsrv://sa:Password12!@localhost/mydrupalsite?module=sqlsrv&schema=dbo
They work the same.

With the database connection URL that you gave as an example, the part within the if-statement (the one in your patch) will be skiped. Without your patch applied and with your patch applied.

As for your the code: if (isset($query['module'])) only checks the existens of the key "module" in the $query array. The code: if ($query['module']) does the same check as the previous code example and also checks that the value of $query['module'] is not an empty string, the number zero or NULL. In this case as the parse_str method returns only string values, the testing is only that it is not an empty string.

If my answer does not help you or you wanted to make a point that I missed, then please say so.

Beakerboy’s picture

Without my proposed change, my example URI will cause an error to be thrown because $query[‘module’] is not set. I can add an override to Connection:: createConnectionOptionsFromUrl() to ensure my module’s custom functionality is correct. Core does not need to know anything about what custom query parameters the sqlsrv module is implementing...but the lack of the isset($query[‘module’]) prevents sqlsrv (and any other driver) from implementing query parameters.

Good point on the empty string part. We could use short circuiting and do if(isset($query[‘module’]) && $query[‘module’]).

The first rule of PHP is to check user input. Core is not checking the query array and instead assuming that if it exists, there must be a ‘module’ index. I would like it to silently ignore cases where this index does not exist instead of throwing an error.

Beakerboy’s picture

Issue summary: View changes

I added a few more details to the issue. Should it be a bug instead of a feature request?

daffie’s picture

Category: Feature request » Bug report
Status: Postponed (maintainer needs more info) » Needs work

@Beakerboy: Yes, you are right. This is a bug. Do you want to make the automated test? Then I will review it.

Beakerboy’s picture

Should I add this to core/tests/Drupal/Tests/Core/Database/UrlConversionTest.php


'MySql with a custom query parameter' => [
        '',
        'mysql://test_user:test_pass@test_host:3306/test_database?extra=value',
        [
          'driver' => 'mysql',
          'username' => 'test_user',
          'password' => 'test_pass',
          'host' => 'test_host',
          'database' => 'test_database',
          'port' => 3306,
          'namespace' => 'Drupal\Core\Database\Driver\mysql',
        ],
      ],

This would test that adding some value to the query parameter will have no effect on the connection array; they will be silently ignored.

daffie’s picture

That looks about right. Make 2 patches: one with the test and the fix, the other patch only with the test. The first patch should pass the testbot and the second patch should fail.

Beakerboy’s picture

Status: Needs work » Needs review
FileSize
1.68 KB
980 bytes

including a failing test and a patch for the failure.

Status: Needs review » Needs work

The last submitted patch, 11: 3126940-11-expect-fail.patch, failed testing. View results

Beakerboy’s picture

Status: Needs work » Needs review

Testing demonstrated the failure and the fix. Needs review.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

The fix looks good.
The added testing looks good.
The testbot fails with the message; "Undefined index: module".
For me it is RTBC.

Good work @Beakerboy.

  • catch committed d6f9e2c on 9.1.x
    Issue #3126940 by Beakerboy, daffie: New DB URI breaks if an existing...

  • catch committed c2299b7 on 9.0.x
    Issue #3126940 by Beakerboy, daffie: New DB URI breaks if an existing...

  • catch committed 3c431ab on 8.9.x
    Issue #3126940 by Beakerboy, daffie: New DB URI breaks if an existing...
catch’s picture

Version: 9.0.x-dev » 8.9.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 9.1.x and cherry-picked back to 8.9.x, thanks!

Status: Fixed » Closed (fixed)

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