Problem/Motivation

Entity query has a use case for "disabling" a db query condition (i.e. a kill switch on the condition). The current implementation does not work if we decide to escape all identifiers/fields of a condition by default, as discussed in #2966523: MySQL 8 Support.

Contrib also has this use case, for example in the Tree module.

Proposed resolution

Add a alwaysFalse() method to \Drupal\Core\Database\Query\ConditionInterface and implement it in \Drupal\Core\Database\Query\QueryConditionTrait.

Remaining tasks

Review, etc.

User interface changes

Nope.

API changes

API addition, a new method on ConditionInterface.

Data model changes

Nope.

Comments

amateescu created an issue. See original summary.

amateescu’s picture

Status: Active » Needs review
StatusFileSize
new1.91 KB

This should do it.

Status: Needs review » Needs work

The last submitted patch, 2: 2986334.patch, failed testing. View results

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new3.02 KB
new1.11 KB

This should be better.

jibran’s picture

Issue tags: +Needs tests
alexpott’s picture

Status: Needs review » Needs work
+++ b/core/lib/Drupal/Core/Database/Query/QueryConditionTrait.php
@@ -63,6 +63,14 @@ public function notExists(SelectInterface $select) {
+    $this->condition->where('1 = 0');

I think this can be $this->condition->alwaysFalse()?

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new3.02 KB
new533 bytes

Right you are.

amateescu’s picture

Issue tags: -Needs tests
StatusFileSize
new4.07 KB
new1.05 KB

Here's the test coverage needed. No test-only patch because it's a new feature.

jibran’s picture

Issue tags: +Needs change record

This looks good to me. We do need a change record for this.

alexpott’s picture

Status: Needs review » Needs work
+++ b/core/tests/Drupal/KernelTests/Core/Database/SelectTest.php
@@ -252,6 +252,27 @@ public function testIsNotNullCondition() {
+    $names = db_select('test', 'test')
...
+    $names = db_select('test', 'test')

db_select() is deprecated. Let's not add new usages - especially when $this->connection is available. Don't update the rest of the test though - thats not in scope.

+1 to the change record.

daffie’s picture

Should we not add a deprecation notice with the condition method that ->condition('1 <> 1') will not longer work after the release of Drupal 9.0.

amateescu’s picture

Title: Add a way to "disable" a database query condition » Add a way to enforce an empty result set for a database condition query
Status: Needs work » Needs review
Issue tags: -Needs change record
StatusFileSize
new4.1 KB
new999 bytes

Added a CR (https://www.drupal.org/node/2986827) with explicit wording about the incorrect usage of ->condition('1 <> 1') and fixed #10.

alexpott’s picture

One thing to note is that ->condition('1 <> 1') only works by complete and utter accident!

Checkout the output for

$query = db_select('node');
$query->condition('1 <> 1');
var_dump((string) $query);

it's

string(64) "SELECT
FROM
{node} node
WHERE 11 = :db_condition_placeholder_0"]

And the value for :db_condition_placeholder_0 is an empty string. So by complete fluke it works.

I think we should consider deprecating the ability to pass a string for $field and NULL for $value and $operator is equal to = (its default value) in \Drupal\Core\Database\Query\ConditionInterface::condition(). The only time a NULL for $value makes sense is if $field is a \Drupal\Core\Database\Query\ConditionInterface or $operation is a unary operator.

alexpott’s picture

StatusFileSize
new814 bytes
new4.5 KB

Here's probably the best way to deprecate this... let's see what falls out the trees.

amateescu’s picture

That's an interesting proposal but I think it needs its own dedicated issue in order to be discussed properly. This one (including the CR) is just about adding the helper and make people aware to not shoot themselves in the foot :)

amateescu’s picture

StatusFileSize
new4.1 KB

Re-uploading #12 to be clear about which patch is ready for review/rtbc.

The last submitted patch, 14: 2986334-14.patch, failed testing. View results

alexpott’s picture

The change record looks good. The new method is documented correctly and there is test coverage of nearly everything. The only thing missing coverage afaics is:

+++ b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
@@ -474,6 +474,14 @@ public function notExists(SelectInterface $select) {
+  public function alwaysFalse() {
+    $this->query->alwaysFalse();
+    return $this;
+  }

There is no test coverage of this. We should add some by repeating the test added and doing ->extend('Drupal\Core\Database\Query\SelectExtender')

amateescu’s picture

StatusFileSize
new4.81 KB
new1.22 KB

Very good point, added test coverage for the extender as well.

alexpott’s picture

Status: Needs review » Reviewed & tested by the community

Thanks @amateescu - as per #18 - now everything is addressed.

bojanz’s picture

This is a good idea. +1 for RTBC

I initially expected the method to be falsify(), so that it's a verb and not an adjective, but maybe that makes the method less obvious.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 19: 2986334-19.patch, failed testing. View results

jibran’s picture

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

Status: Reviewed & tested by the community » Fixed

Committed 8f1228f and pushed to 8.7.x. Thanks!

  • catch committed 2ddb398 on 8.7.x
    Issue #2986334 by amateescu, alexpott: Add a way to enforce an empty...

Status: Fixed » Closed (fixed)

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