Problem/Motivation

At the moment all 3 by core supported driver can work with the same implementation of Drupal\Core\Database\Query\Condition.
The MSSQL database driver has to for #3113203: Kernel Test testDbLike mandates specific escape behavior. override the default implementation of the Condition class. Also there is for the SQLite driver an override necessary (see: #2031261: Make SQLite faster by combining multiple inserts and updates in a single query). The way in which the override is implemented for the SQLite driver is very different to the other query operators. We should database driver override the default implementation of the Condition class in the same way as is done for: select, delete, insert, merge, schema, truncate, update and upsert.
If there are other examples of custom implementations of the class Drupal\Core\Database\Query\Condition, please add them here.

Proposed resolution

Change the calling of the Drupal\Core\Database\Query\Condition to the same way as is done for: select, delete, insert, merge, schema, truncate, update and upsert.

User interface changes

none

API changes

Add the method Drupal\Core\Database\Connection::condition().
All code like: new Condition('AND') must change to: Database::getConnection()->condition('AND').

Data model changes

none

CommentFileSizeAuthor
#96 3113403-8.9.x-95.patch11.24 KBalexpott
#96 3113403-9.0.x-95.patch11.45 KBalexpott
#96 90-95-interdiff.txt891 bytesalexpott
#90 3113403-90.patch12.32 KBbeakerboy
#88 3113403-89.patch12.33 KBbeakerboy
#85 3113403-86.patch12.34 KBbeakerboy
#82 3113403-82.patch11.24 KBbeakerboy
#80 interdiff_77-80.txt1.43 KBneelam_wadhwani
#80 3113403-80.patch11.45 KBneelam_wadhwani
#77 3113403-77.patch10.39 KBneelam_wadhwani
#74 3113403-74.patch11.26 KBneelam_wadhwani
#74 interdiff_72-74.txt1.35 KBneelam_wadhwani
#72 3113403-72.patch10.39 KBneelam_wadhwani
#72 interdiff_69-72.txt1.95 KBneelam_wadhwani
#69 interdiff_65-69.txt800 bytesneelam_wadhwani
#69 3113403-69.patch10.23 KBneelam_wadhwani
#65 3113403-65.patch9.3 KBbeakerboy
#63 3113403-63.patch9.5 KBbeakerboy
#62 3113403-62.patch9.15 KBbeakerboy
#59 3113403-59.patch8.19 KBbeakerboy
#58 3113403-56.patch8.17 KBbeakerboy
#56 3113403-56.patch0 bytesbeakerboy
#55 3113403-54.patch7.79 KBbeakerboy
#53 3113403-53.patch13.98 KBbeakerboy
#41 3113403-8.9-41.patch14.87 KBalexpott
#36 3113403-30.patch14.87 KBdaffie
#35 2031261-91-combined-with-3113403-30.patch26.26 KBdaffie
#33 3113403-33.patch15.3 KBbeakerboy
#30 3113403-30.patch14.87 KBbeakerboy
#27 3113403-27.patch13.36 KBbeakerboy
#26 3113403-26.patch13.37 KBbeakerboy
#16 partial-interdiff-3113403-14-16.txt3.51 KBdaffie
#16 3113403-16.patch14.81 KBdaffie
#14 drupal-3113403-Make_condition_driver_overridable-14.patch5.64 KBbeakerboy
#8 example-do-not-test.patch933 bytesdaffie
#11 drupal-3113403-Make_condition_driver_overridable-11.patch4.75 KBbeakerboy
#2 3113403-2.patch2.33 KBdaffie

Comments

daffie created an issue. See original summary.

daffie’s picture

Issue tags: +Needs tests
StatusFileSize
new2.33 KB
beakerboy’s picture

I was able to use a custom Condition by overriding the Select constructor. My new constructor first called the parent, then replaced $this->condition with my custom condition class.

daffie’s picture

@beakerboy: I think that your solution does not work with nested conditions like (from Drupal\KernelTests\Core\Database\SelectComplexTest):

  /**
   * Confirms that we can properly nest conditional clauses.
   */
  public function testNestedConditions() {
    // This query should translate to:
    // "SELECT job FROM {test} WHERE name = 'Paul' AND (age = 26 OR age = 27)"
    // That should find only one record. Yes it's a non-optimal way of writing
    // that query but that's not the point!
    $query = $this->connection->select('test');
    $query->addField('test', 'job');
    $query->condition('name', 'Paul');
    $query->condition((new Condition('OR'))->condition('age', 26)->condition('age', 27));

    $job = $query->execute()->fetchField();
    $this->assertEqual($job, 'Songwriter', 'Correct data retrieved.');
  }
beakerboy’s picture

You might be right. I’ll have to make a custom test case that uses a regular expression within a nested Condition.

beakerboy’s picture

It looks like Select, Delete, Update, and Merge need to call $connection->condition() inside their constructors.

beakerboy’s picture

Status: Needs review » Needs work
daffie’s picture

Assigned: Unassigned » daffie
StatusFileSize
new933 bytes

You might be right. I’ll have to make a custom test case that uses a regular expression within a nested Condition.

Here is an example for you.

beakerboy’s picture

I already made one:
https://github.com/Beakerboy/sqlsrv/blob/Custom-condition/tests/src/Kern...

This test passes with your patch in #2, but after removing my custom constructor, all the core REGEXP tests fail, which led me to marking this issue as “needs work”.

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new4.75 KB

Updated Patch. I was making this against 8.8.x, but it'll probably work as-is on 9.x

beakerboy’s picture

It looks like the Unit Test OrderBy::setUp() needs to be able to get a Condition stub from the mocked connection.

beakerboy’s picture

Status: Needs review » Needs work
beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new5.64 KB

Updated Patch

beakerboy’s picture

daffie’s picture

Assigned: daffie » Unassigned
Issue tags: -Needs tests
StatusFileSize
new14.81 KB
new3.51 KB

I have tried to make an interdiff.txt file, but that was not possible because #2799911: Make the Connection parameter the first parameter in Select Query Builder. has landed. A partial interdiff.txt was the most I could get.

I added some extra code so that whole database subsystem uses the driver overridable conditions.
Also added testing for all of that.

daffie’s picture

Priority: Normal » Major

The issue #2031261: Make SQLite faster by combining multiple inserts and updates in a single query has been postponed on this issue. That issue has a priority of major, so upgrading this issue priority to also major.

effulgentsia’s picture

Version: 9.1.x-dev » 9.0.x-dev
Category: Feature request » Task

Thanks for opening this and for the patch! Since this is necessary to fix #2031261: Make SQLite faster by combining multiple inserts and updates in a single query, recategorizing it as a task, and in-scope for 9.0.x (and 8.9.x, but it needs to get into 9.0.x first).

beakerboy’s picture

Has anybody reviewed the 8.8.x patch (#14)? It would be great to have it moved to RTBC.

daffie’s picture

@Beakerboy: You can review the patch. Here is an howto: https://www.drupal.org/patch/review. You can do it. I have faith in you!

beakerboy’s picture

You can review the patch.

@daffie...That is my patch, I can't review my own patch. Feel free to move this issue forward. I have faith in you!

daffie’s picture

That is my patch

@Beakerboy: Forgot about that. About the reviewing: the whole idea is that there are at least 2 people who think that the current patch good enough is for the core committer to let him/her review it. For me is your patch with my changes good enough to be RTBC. If you think the same, then say so. You can then set the status to RTBC or let me do it.

beakerboy’s picture

@daffie, yes, I know about the review process...we've both been working with drupal for nearly the same length of time. I don't have a good test set-up for D9, so I've been working off D8.8. Your patch appears fine, but I have not actually tested it myself. In reviewing the code it looks like I missed the ConditionGroupFactory, so I can add that to my patch, test it, consider it the same as yours, but re-rolled to D8 and give it RTBC.

beakerboy’s picture

@daffie would if make sense to change Query/Connection.php to


public function conditionGroupFactory($conjunction = 'AND') {
  return new static($conjunction);
}

Wouldn’t this prevent each class having to implement this function.

daffie’s picture

@Beakerboy: I do not think that what you are suggesting in comment #24 will work. But you could create a patch and we will see what the testbot thinks of it.

beakerboy’s picture

StatusFileSize
new13.37 KB

Patch, #16 rolled back to 8.8 and using late static binding.

beakerboy’s picture

StatusFileSize
new13.36 KB

Try late static binding.

beakerboy’s picture

Status: Needs review » Needs work

@daffie I reviewed your #16 patch, and I thought it looked good. I made my suggested changes and that patch has several failures. However, I retested yours and it also has many failures.

beakerboy’s picture

Status: Needs work » Needs review

MySQL 5.5 is not supported by D9, moving back to Needs Review.

beakerboy’s picture

StatusFileSize
new14.87 KB

I made the patch wrong. I needed to run `git diff HEAD`. This is with late static binding.

daffie’s picture

+++ b/core/lib/Drupal/Core/Database/Query/Condition.php
@@ -399,7 +399,7 @@ protected function mapConditionOperator($operator) {
+    return new static($conjunction);

@Beakerboy: I think you forgot to remove one static.

beakerboy’s picture

@daffie I didn’t forget it. Calling `new static()` is the whole point of this. By taking advantage of late static binding, the parent will always return an instance of the child class, and we do not have to implement Condition::conditionGroupFactory() in every driver. If every child must do new self(), you can instead have the parent do new static(). As an extra safety precaution, should the Query\Condition class be marked abstract(Also Delete, Merge, Select, Transaction, Truncate, Update, and Upsert)?

beakerboy’s picture

StatusFileSize
new15.3 KB

Here's the same concept as #30 on 8.8.x-dev

beakerboy’s picture

Status: Needs review » Reviewed & tested by the community

I tested #16 with SQL Server and it passes my custom condition tests along with the core kernel test suite. I feel #30 is an improvement though. @daffie, could you offer your opinion?

daffie’s picture

StatusFileSize
new26.26 KB

Testing to make sure that the patch combined with the patch from #2031261-91: Make SQLite faster by combining multiple inserts and updates in a single query works.

daffie’s picture

StatusFileSize
new14.87 KB

I am re-uploading the patch from comment #30. As it the patch that should be committed. @Beakerboy worked on the changes that I have made in the patch from comment #16. Therefor I feel that I can do a review and give this issue an RTBC.
The switch to using late static binding looks good to me. The combination patch with the patch from #2031261-91: Make SQLite faster by combining multiple inserts and updates in a single query shows that the solution with the late static binding works.
For me is the patch RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record

This needs a change record.

beakerboy’s picture

Status: Needs work » Needs review

Draft change record has been created. The only people I can imagine this would impact are database driver developers. It should be invisible to everybody else.

@alexpott if the Condition class is now a required component of each database driver, should it be an abstract class? What about Delete, Select, Update, etc? Marking them abstract would make it clear to developers that it must be implemented at the driver level, but would require the unit testing suite to stub each of them.

beakerboy’s picture

Issue tags: -Needs change record
daffie’s picture

Status: Needs review » Reviewed & tested by the community

@Beakerboy: The rule is that an issue that was RTBC and only needs a change record, you can put it back to RTBC after you created the change record. BTW thank you for creating the change record.

alexpott’s picture

StatusFileSize
new14.87 KB

We also need to put this in D8.9. Here's a patch that fixes the conflicts in core/tests/Drupal/Tests/Core/Database/OrderByTest.php

alexpott’s picture

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

Committed 7a943a3 and pushed to 9.0.x. Thanks!
Committed 9397737 and pushed to 8.9.x. Thanks!

diff --git a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
index eb4b24dbef..d909f7c50b 100644
--- a/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Schema.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Core\Database\Driver\mysql;
 
-use Drupal\Core\Database\Query\Condition;
 use Drupal\Core\Database\SchemaException;
 use Drupal\Core\Database\SchemaObjectExistsException;
 use Drupal\Core\Database\SchemaObjectDoesNotExistException;
diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 56317af7e1..1987177a3e 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -2,7 +2,6 @@
 
 namespace Drupal\Core\Database;
 
-use Drupal\Core\Database\Query\Condition;
 use Drupal\Core\Database\Query\PlaceholderInterface;
 
 /**

Fixed unused uses on commit.

  • alexpott committed 9397737 on 8.9.x
    Issue #3113403 by Beakerboy, daffie: Make Drupal\Core\Database\Query\...

  • alexpott committed 7a943a3 on 9.0.x
    Issue #3113403 by Beakerboy, daffie: Make Drupal\Core\Database\Query\...

  • alexpott committed 7d8eb55 on 8.9.x
    Revert "Issue #3113403 by Beakerboy, daffie: Make Drupal\Core\Database\...

  • alexpott committed 6139217 on 9.0.x
    Revert "Issue #3113403 by Beakerboy, daffie: Make Drupal\Core\Database\...
alexpott’s picture

Status: Fixed » Needs work

Had to revert this to get a bit more discussion on BC layers.

So \Drupal\Core\Database\Connection::getDriverClass() is not helping us like it should. Unfortunately decisions were taken in #2461239: Database driver class fallback is broken and stubbed instead to require code to duplicated rather than to have it resolve to the base class. This was in an effort to keep thing simple. However that means this change will break every contrib driver because it is missing a condition class. Given that the condition class is just going to be

+++ b/core/lib/Drupal/Core/Database/Driver/mysql/Condition.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Drupal\Core\Database\Driver\mysql;
+
+use Drupal\Core\Database\Query\Condition as QueryCondition;
+
+/**
+ * MySQL implementation of \Drupal\Core\Database\Query\Condition.
+ */
+class Condition extends QueryCondition {}

That feels really really wrong.

alexpott’s picture

So the simplest thing in order to maintain BC and comply with policy is to so something like:

diff --git a/core/lib/Drupal/Core/Database/Connection.php b/core/lib/Drupal/Core/Database/Connection.php
index 691a6ae84c..874037da71 100644
--- a/core/lib/Drupal/Core/Database/Connection.php
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Core\Database;
 
+use Drupal\Core\Database\Query\Condition;
+
 /**
  * Base Database API class.
  *
@@ -781,6 +783,10 @@ public function getDriverClass($class) {
       }
       $driver_class = $this->connectionOptions['namespace'] . '\\' . $class;
       $this->driverClasses[$class] = class_exists($driver_class) ? $driver_class : $class;
+      if ($this->driverClasses[$class] === 'Condition') {
+        @trigger_error('blah di blah. See change record.', E_USER_DEPRECATED);
+        $this->driverClasses[$class] = Condition::class;
+      }
     }
     return $this->driverClasses[$class];
   }

That way if we can't resolve the Condition class we trigger a deprecation error (only once) and contrib db drivers get to continue. We can even add the @trigger_error in a follow-up for 9.1 so we can commit this to 8.9.x - we would need a test of the fallback though.

beakerboy’s picture

@alexpott Most of the classes in the MySQL driver namespace are stubs. The new condition class will just be following precedent.

daffie’s picture

@Beakerboy: You know that this patch is coming. It should also work for contrib driver who does not know that this is coming and do nothing. See: https://www.drupal.org/core/d8-bc-policy.

beakerboy’s picture

Is there a way getDriverClass() can be changed which would be backwards compatible, while also not creating a special exception for the Condition class? It would be nice to allow all drivers to drop any unextended Query classes.

alexpott’s picture

@Beakerboy I totally think we should do that I disagree with the reasoning giving in the other issue about not doing that. But that's a follow-up. If we want to get this in D9 (and D8) then the path suggested above is the quickest and scoped correctly for this issue.

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new13.98 KB

New patch with changes suggested by @alexpott

Status: Needs review » Needs work

The last submitted patch, 53: 3113403-53.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

beakerboy’s picture

StatusFileSize
new7.79 KB
  • update getDriverClass
  • removed tests for driver Condition classes
  • No deprecation warning if the long-term goal is to remove all driver stubs

Edit:
I have no idea why this patch is not applying. It looks right...

OrderByTest.php changed a couple hours before I uploaded, but after I tested. Need to reroll.

beakerboy’s picture

StatusFileSize
new0 bytes

Updated patch against latest 9.0 branch

daffie’s picture

@beakerboy: Your patch file is empty.

beakerboy’s picture

StatusFileSize
new8.17 KB

odd...try uploading again.

beakerboy’s picture

StatusFileSize
new8.19 KB

My use statement was above my namespace declaration.

Edit:
If anyone knows why this is failing, post below. I can’t figure it out. As far as I can see, Condition::class can only refer to one namespace, the Query\Condition from the use statement. Any other case requires that the class actually exists, so there should never be a “Class 'Condition' not found” error.

alexpott’s picture

We need to put the same BC layer in \Drupal\database_statement_monitoring_test\LoggedStatementsTrait::getDriverClass(). We're going to be able to get rid of that in #3115388: PP-1: Deprecate \Drupal\Core\Database\Database::getDatabaseDriverNamespace as it is no longer needed but for now we need to duplicate :( but at least it is only test code.

alexpott’s picture

+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -865,6 +867,9 @@ public function getDriverClass($class) {
+      if ($this->driverClasses[$class] === 'Condition') {
+        $this->driverClasses[$class] = Condition::class;
+      }

Need a @todo pointing to a 9.1.x followup to add an @trigger_error.

beakerboy’s picture

StatusFileSize
new9.15 KB

updating \Drupal\database_statement_monitoring_test\LoggedStatementsTrait::getDriverClass()

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new9.5 KB

Added @todo

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Database/Connection.php
@@ -852,6 +854,8 @@ protected function expandArguments(&$query, &$args) {
+   * @todo https://www.drupal.org/project/drupal/issues/3120036
+   *

@@ -865,6 +869,9 @@ public function getDriverClass($class) {
+      if ($this->driverClasses[$class] === 'Condition') {
+        $this->driverClasses[$class] = Condition::class;
+      }
     }

Here i'd inline the @todo... something like

      if ($this->driverClasses[$class] === 'Condition') {
        // @todo Deprecate the fallback for contrib and custom drivers in 9.1.x
        //   in  https://www.drupal.org/project/drupal/issues/3120036.
        $this->driverClasses[$class] = Condition::class;
      }
beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new9.3 KB

Changed with suggestions from @alexpott

daffie’s picture

Status: Needs review » Needs work

@Beakerboy: The added @todo looks good. Only one space too many between "in" and the link. An other problem with the current patch is that I am missing the added tests. Can you put them back in the patch. Thank you for working on this patch. We are almost there.

beakerboy’s picture

@daffie, the tests are missing because this latest version no longer requires all drivers to have a stubbed Connection class. I’ve moved the tests to my driver code to ensure that it returns its custom Condition. I’m sure there’s a way to mock a custom driver with a custom Condition to prove that it is returned when appropriate, but I do not know how to do that.

daffie’s picture

the tests are missing because this latest version no longer requires all drivers to have a stubbed Connection class

You are right @Beakerboy. All the previous added tests now fail for that reason. We can/should test that the added method exists and what is returns. Could we add the test to Drupal\KernelTests\Core\Database\ConnectionTest for that reason.

  /**
   * Test that the method ::condition() returns an Condition object.
   */
  public function testCondition() {
    $db = Database::getConnection('default', 'default');
    $namespace = (new \ReflectionObject($db))->getNamespaceName() . "\\Condition";
    if (!class_exists($namespace)) {
      $namespace = 'Drupal\Core\Database\Query\Condition';
    }
    $condition = $db->condition('AND');
    $this->assertIdentical($namespace, get_class($condition));
  }

If you add that and fix the nitpick from comment #66, I will set the status back to RTBC.

neelam_wadhwani’s picture

StatusFileSize
new10.23 KB
new800 bytes

Hello @daffie
I have added the test.
Please review the patch.

neelam_wadhwani’s picture

Status: Needs work » Needs review
beakerboy’s picture

@neelam_wadhwani thank you for your swift assistance. This patch still needs the fix for the whitespace issue referred to in #66. There is also 2 coding standards issues with your patch (https://www.drupal.org/pift-ci-job/1617547)

Also @daffie,
This just tests that the default Condition will be returned. Since the point of this issue is to allow a contrib driver to override the Condition, shouldn’t we test THAT. Maybe something like this:

  /**
   * Test that the core Condition can be overridden.
   */
  public function testContribCondition() {
    $this->mockCondition = $this->getMockBuilder('Drupal\Core\Database\Query\Condition')
      ->setMockClassName('MockCondition')
      ->setConstructorArgs([NULL])
      ->disableOriginalConstructor()
      ->getMock();
    $contrib_namespace = 'Drupal\Driver\Database\mock';
    $mocked_namespace = $contrib_namespace . '\\Condition';
    class_alias('MockCondition', $mocked_namespace);

    $this->options['namespace'] = $mocked_namespace;
    $this->options['prefix']['default'] = '';

    $this->mockPdo = $this->createMock('Drupal\Tests\Core\Database\Stub\StubPDO');

    $connection = new Connection($this->mockPdo, $this->options);
    $condition = $connection->condition();
    $this->assertIdentical($mocked_namespace, get_class($condition));
  }
neelam_wadhwani’s picture

StatusFileSize
new1.95 KB
new10.39 KB

Hello @Beakerboy
Updated the coding standard.
Please review patch.

daffie’s picture

Status: Needs review » Needs work

My test from comment #68 test that the added method exists and that it now will return. If driver overrides the default condition implementation the test will still pass. The test from @Beakerboy tests with a mock that when there is an override for the condition then the added method will return the override. My suggestion is to add both tests.

@neelam_wadhwani: There is still a coding standard violation in your patch.

neelam_wadhwani’s picture

StatusFileSize
new1.35 KB
new11.26 KB

Hello @daffie
I have fixed the coding standard issue and attach the other test of @Beakerboy.

KIndly review patch.

neelam_wadhwani’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 74: 3113403-74.patch, failed testing. View results

neelam_wadhwani’s picture

StatusFileSize
new10.39 KB

Hello @daffie
After adding that test in ConnectionTest.php, it got failed.
So i removed that test and updated the patch.

neelam_wadhwani’s picture

Status: Needs work » Needs review
beakerboy’s picture

@neelam_wadhwani My test was just written off the top of my head and typed in on my phone, so I know there would be a couple problems. The error you received can be resolved with an appropriate use statement to the core Connection object. I think it also needs:

-   $this->options['namespace'] = $mocked_namespace;
+   $this->options['namespace'] = $contrib_namespace;
neelam_wadhwani’s picture

StatusFileSize
new11.45 KB
new1.43 KB

Hello @Beakerboy
I have updated changes.
Kindly review patch.

Status: Needs review » Needs work

The last submitted patch, 80: 3113403-80.patch, failed testing. View results

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new11.24 KB

We cannot instantiate an abstract class (Core\Connection). Mocking it instead. Should this be in Unit Tests instead of Kernel Tests? This new test passes the namespace in with the options parameter. The whole situation would be more realistic if, instead, the connection and the Condition shared the same namespace and the options array did not have a namespace set. Opinions anyone?

Status: Needs review » Needs work

The last submitted patch, 82: 3113403-82.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

daffie’s picture

@Beakerboy: Thank you for adding the test. Some minor stuff and we are done.

  1. +++ b/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php
    @@ -155,4 +155,42 @@ public function testMultipleStatements() {
    +      ->getMock();
    

    You need to use getMockForAbstractClass() instead of getMock().

  2. +++ b/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php
    @@ -155,4 +155,42 @@ public function testMultipleStatements() {
    +    $contrib_namespace = 'Drupal\Driver\Database\mock';
    +    $mocked_namespace = $contrib_namespace . '\\Condition';
    

    You do not use the variable $contrib_namespace anywhere else, it can be removed.

  3. +++ b/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php
    @@ -155,4 +155,42 @@ public function testMultipleStatements() {
    +  public function testContribCondition() {
    

    This belong with the other unit tests. Drupal\Tests\Core\Database\ConditionTest is a good location.

  4. +++ b/core/tests/Drupal/KernelTests/Core/Database/ConnectionTest.php
    @@ -155,4 +155,42 @@ public function testMultipleStatements() {
    +    $mockCondition = $this->getMockBuilder('Drupal\Core\Database\Query\Condition')
    

    For PHPUnit it is better to use:
    $mockCondition = $this->getMockBuilder(Condition::class)

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new12.34 KB
  • Moved testContribCondition() to unit tests.
  • Removed leading slash on namespace in LoggedStatementsTrait.
  • Using Class::class instead of hardcoding strings.
  • Using getMockForAbstractClass()
  • Prevent deprecation warning by stubbing Connection::identifierQuote()

$contrib_namespace is assigned to $options['namespace'], so it is used in two places.

Status: Needs review » Needs work

The last submitted patch, 85: 3113403-86.patch, failed testing. View results

beakerboy’s picture

This error is saying that the assertIdentical() method is undefined. I fail to see the problem. There must be a typo somewhere that my brain just is not picking up.

Edit: Unit tests have migrated away from the legacy assertions. All of these should be changed to assertSame().

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new12.33 KB

Using assertSame().

Status: Needs review » Needs work

The last submitted patch, 88: 3113403-89.patch, failed testing. View results

beakerboy’s picture

Status: Needs work » Needs review
StatusFileSize
new12.32 KB

Using the correct class name.

daffie’s picture

Status: Needs review » Needs work

I have cleaned up your test a bit. I did not actually test the code. As I told you on Slack, your test is good. Great work.

  /**
   * Test that the core Condition can be overridden.
   */
  public function testContribCondition() {
    $mockCondition = $this->getMockBuilder(Condition::class)
      ->setMockClassName('MockCondition')
      ->setConstructorArgs([NULL])
      ->disableOriginalConstructor()
      ->getMock();

    $options['namespace'] = 'Drupal\Driver\Database\mock';
    $options['prefix']['default'] = '';
    $mockPdo = $this->createMock(StubPDO::class);

    $connection = $this->getMockBuilder(Connection::class)
      ->setConstructorArgs([$mockPdo, $options])
      ->setMethods(['identifierQuote'])
      ->getMockForAbstractClass();

    // @todo In drupal:10.0.0 this function will be abstract and the mock
    // builder will automatically create it. This can be can be removed at that
    // time.
    $connection->expects($this->once())
      ->method('identifierQuote')
      ->willReturn(NULL);

    $this->assertSame('Drupal\Driver\Database\mock\Condition', get_class($connection->condition('AND')));
  }
beakerboy’s picture

Status: Needs work » Needs review

Class alias is necessary.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

The code looks good. All changes I asked for a done.
All the testing is in order.
For me it is RTBC.

@Beakerboy: Thank you for all your hard work!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 90: 3113403-90.patch, failed testing. View results

beakerboy’s picture

Status: Needs work » Reviewed & tested by the community
alexpott’s picture

StatusFileSize
new891 bytes
new11.45 KB
new11.24 KB

We need a 8.9.x patch and \Drupal\Tests\Core\Database\OrderByTest no longer needs to change because we fallback now. We might need to change it when we deprecate the fallback but that's okay we handle it then.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed f156b5c6b1 to 9.1.x and e02296ec61 to 9.0.x. Thanks!

Committed 6f339f2 and pushed to 8.9.x. Thanks!

daffie’s picture

Status: Fixed » Needs work

In #2031261: Make SQLite faster by combining multiple inserts and updates in a single query returns the testbot the following error when used with MySQL:

Drupal\KernelTests\Core\Database\SelectTest

exception: [Other] Line 0 of sites/default/files/simpletest/phpunit-235.xml:
PHPunit Test failed to complete; Error: PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

Testing Drupal\KernelTests\Core\Database\SelectTest
..................................E                               35 / 35 (100%)

Time: 39.55 seconds, Memory: 4.00 MB

There was 1 error:

1) Drupal\KernelTests\Core\Database\SelectTest::testLargeInCondition
Error: Call to undefined method Drupal\Core\Database\Driver\mysql\Connection::condition()

/var/www/html/core/tests/Drupal/KernelTests/Core/Database/SelectTest.php:655
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestResult.php:691

ERRORS!
Tests: 35, Assertions: 89, Errors: 1.
beakerboy’s picture

The commit hashes in the comment above lead to 404 pages. Is there a staging area where commits sit before being pushed to GitLab? Maybe the testbot also pulls from GitLab and they are not fully public yet.

alexpott’s picture

Status: Needs work » Reviewed & tested by the community

@beakerboy @daffie I forgot to push so we're back to rtbc.

  • alexpott committed f156b5c on 9.1.x
    Issue #3113403 by Beakerboy, neelam_wadhwani, daffie, alexpott: Make...
alexpott’s picture

Okay I've committed this to 9.1.x. We need a release manager +1 to backport this to 8.9.x and 9.0.x

daffie’s picture

Issue tags: +Needs release manager review

@alexpott wants a release manager go for backporting this issue back to 9.0.x and 8.9.x. This issue is a prerequisite for #2031261: Make SQLite faster by combining multiple inserts and updates in a single query.

catch’s picture

This looks safe to backport and enables fixing a bug. Removing tag.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Thanks @catch. Committed and pushed e02296ec61 to 9.0.x and 6f339f2 and pushed to 8.9.x. Thanks!

  • alexpott committed 6f339f2 on 8.9.x
    Issue #3113403 by Beakerboy, neelam_wadhwani, daffie, alexpott: Make...

  • alexpott committed e02296e on 9.0.x
    Issue #3113403 by Beakerboy, neelam_wadhwani, daffie, alexpott: Make...

Status: Fixed » Closed (fixed)

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