diff --git a/core/lib/Drupal/Core/Database/Query/Condition.php b/core/lib/Drupal/Core/Database/Query/Condition.php
index ad7397ef8c72e57aa00007d8bfa0aa60c411d22b..400384dca00946a8e4d1ff4210f539f759574237 100644
--- a/core/lib/Drupal/Core/Database/Query/Condition.php
+++ b/core/lib/Drupal/Core/Database/Query/Condition.php
@@ -39,6 +39,13 @@ class Condition implements ConditionInterface, \Countable {
    */
   protected $queryPlaceholderIdentifier;
 
+  /**
+   * Contains the string version of the Condition.
+   *
+   * @var string
+   */
+  protected $stringVersion;
+
   /**
    * Constructs a Condition object.
    *
@@ -158,86 +165,127 @@ public function compile(Connection $connection, PlaceholderInterface $queryPlace
       $conjunction = $conditions['#conjunction'];
       unset($conditions['#conjunction']);
       foreach ($conditions as $condition) {
-        if (empty($condition['operator'])) {
-          // This condition is a literal string, so let it through as is.
-          $condition_fragments[] = ' (' . $condition['field'] . ') ';
+        // Process field.
+        if ($condition['field'] instanceof ConditionInterface) {
+          // Left hand part is a structured condition or a subquery. Compile,
+          // put brackets around it (if it is a query), and collect any
+          // arguments.
+          $condition['field']->compile($connection, $queryPlaceholder);
+          $field_fragment = (string) $condition['field'];
+          if ($condition['field'] instanceof SelectInterface) {
+            $field_fragment = '(' . $field_fragment . ')';
+          }
+          $arguments += $condition['field']->arguments();
+          // If the operator and value were not passed in to the
+          // @see ConditionInterface::condition() method (and thus have the
+          // default value as defined over there) it is assumed to be a valid
+          // condition on its own: ignore the operator and value parts.
+          $ignore_operator = $condition['operator'] === '=' && $condition['value'] === NULL;
+        }
+        elseif (!isset($condition['operator'])) {
+          // Left hand part is a literal string added with the
+          // @see ConditionInterface::where() method. Put brackets around
+          // the snippet and collect the arguments from the value part.
+          // Also ignore the operator and value parts.
+          $field_fragment = '(' . $condition['field'] . ')';
           $arguments += $condition['value'];
+          $ignore_operator = TRUE;
+        }
+        else {
+          // Left hand part is a normal field. Add it as is.
+          $field_fragment = $connection->escapeField($condition['field']);
+          $ignore_operator = FALSE;
+        }
+
+        // Process operator.
+        if ($ignore_operator) {
+          $operator = array('operator' => '', 'use_value' => FALSE);
         }
         else {
-          // It's a structured condition, so parse it out accordingly.
-          // Note that $condition['field'] will only be an object for a dependent
-          // DatabaseCondition object, not for a dependent subquery.
-          if ($condition['field'] instanceof ConditionInterface) {
-            // Compile the sub-condition recursively and add it to the list.
-            $condition['field']->compile($connection, $queryPlaceholder);
-            $condition_fragments[] = '(' . (string) $condition['field'] . ')';
-            $arguments += $condition['field']->arguments();
+          // Remove potentially dangerous characters.
+          // If something passed in an invalid character stop early, so we
+          // don't rely on a broken SQL statement when we would just replace
+          // those characters.
+          if (stripos($condition['operator'], 'UNION') !== FALSE || strpbrk($condition['operator'], '[-\'"();') !== FALSE) {
+            $this->changed = TRUE;
+            $this->arguments = [];
+            // Provide a string which will result into an empty query result.
+            $this->stringVersion = '( AND 1 = 0 )';
+
+            // Conceptually throwing an exception caused by user input is bad
+            // as you result into a WSOD, which depending on your webserver
+            // configuration can result into the assumption that your site is
+            // broken.
+            // On top of that the database API relies on __toString() which
+            // does not allow to throw exceptions.
+            trigger_error('Invalid characters in query operator: ' . $condition['operator'], E_USER_ERROR);
+            return;
           }
-          else {
-            // For simplicity, we treat all operators as the same data structure.
-            // In the typical degenerate case, this won't get changed.
-            $operator_defaults = array(
-              'prefix' => '',
-              'postfix' => '',
-              'delimiter' => '',
-              'operator' => $condition['operator'],
-              'use_value' => TRUE,
-            );
-            // Remove potentially dangerous characters.
-            // If something passed in an invalid character stop early, so we
-            // don't rely on a broken SQL statement when we would just replace
-            // those characters.
-            if (stripos($condition['operator'], 'UNION') !== FALSE || strpbrk($condition['operator'], '[-\'"();') !== FALSE) {
-              $this->changed = TRUE;
-              $this->arguments = [];
-              // Provide a string which will result into an empty query result.
-              $this->stringVersion = '( AND 1 = 0 )';
-
-              // Conceptually throwing an exception caused by user input is bad
-              // as you result into a WSOD, which depending on your webserver
-              // configuration can result into the assumption that your site is
-              // broken.
-              // On top of that the database API relies on __toString() which
-              // does not allow to throw exceptions.
-              trigger_error('Invalid characters in query operator: ' . $condition['operator'], E_USER_ERROR);
-              return;
-            }
-            $operator = $connection->mapConditionOperator($condition['operator']);
-            if (!isset($operator)) {
-              $operator = $this->mapConditionOperator($condition['operator']);
-            }
-            $operator += $operator_defaults;
-
-            $placeholders = array();
-            if ($condition['value'] instanceof SelectInterface) {
-              $condition['value']->compile($connection, $queryPlaceholder);
-              $placeholders[] = (string) $condition['value'];
-              $arguments += $condition['value']->arguments();
-              // Subqueries are the actual value of the operator, we don't
-              // need to add another below.
-              $operator['use_value'] = FALSE;
+
+          // For simplicity, we convert all operators to a data structure to
+          // allow to specify a prefix, a delimiter and such. Find the
+          // associated data structure by first doing a database specific
+          // lookup, followed by a specification according to the SQL standard.
+          $operator = $connection->mapConditionOperator($condition['operator']);
+          if (!isset($operator)) {
+            $operator = $this->mapConditionOperator($condition['operator']);
+          }
+          $operator += array('operator' => $condition['operator']);
+        }
+        // Add defaults.
+        $operator += array(
+          'prefix' => '',
+          'postfix' => '',
+          'delimiter' => '',
+          'use_value' => TRUE,
+        );
+        $operator_fragment = $operator['operator'];
+
+        // Process value.
+        $value_fragment = '';
+        if ($operator['use_value']) {
+          // For simplicity, we first convert to an array, so that we can handle
+          // the single and multi value cases the same.
+          if (!is_array($condition['value'])) {
+            if ($condition['value'] instanceof SelectInterface && ($operator['operator'] === 'IN' || $operator['operator'] === 'NOT IN')) {
+              // Special case: IN is followed by a single select query instead
+              // of a set of values: unset prefix and postfix to prevent double
+              // brackets.
+              $operator['prefix'] = '';
+              $operator['postfix'] = '';
             }
-            // We assume that if there is a delimiter, then the value is an
-            // array. If not, it is a scalar. For simplicity, we first convert
-            // up to an array so that we can build the placeholders in the same way.
-            elseif (!$operator['delimiter'] && !is_array($condition['value'])) {
-              $condition['value'] = array($condition['value']);
+            $condition['value'] = array($condition['value']);
+          }
+          // Process all individual values.
+          $value_fragment = array();
+          foreach ($condition['value'] as $value) {
+            if ($value instanceof SelectInterface) {
+              // Right hand part is a subquery. Compile, put brackets around it
+              // and collect any arguments.
+              $value->compile($connection, $queryPlaceholder);
+              $value_fragment[] = '(' . (string) $value . ')';
+              $arguments += $value->arguments();
             }
-            if ($operator['use_value']) {
-              foreach ($condition['value'] as $value) {
-                $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
-                $arguments[$placeholder] = $value;
-                $placeholders[] = $placeholder;
-              }
+            else {
+              // Right hand part is a normal value. Replace the value with a
+              // placeholder and add the value as an argument.
+              $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
+              $value_fragment[] = $placeholder;
+              $arguments[$placeholder] = $value;
             }
-            $condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
           }
+          $value_fragment = $operator['prefix'] . implode($operator['delimiter'], $value_fragment) . $operator['postfix'];
         }
+
+        // Concatenate the left hand part, operator and right hand part.
+        $condition_fragments[] = trim(implode(' ', array($field_fragment, $operator_fragment, $value_fragment)));
       }
 
-      $this->changed = FALSE;
-      $this->stringVersion = implode($conjunction, $condition_fragments);
+      // Concatenate all conditions using the conjunction and brackets around
+      // the individual conditions to assure the proper evaluation order.
+      $this->stringVersion = count($condition_fragments) > 1 ? '(' . implode(") $conjunction (", $condition_fragments) . ')' : implode($condition_fragments);
       $this->arguments = $arguments;
+      $this->changed = FALSE;
     }
   }
 
@@ -289,7 +337,7 @@ function __clone() {
    * the value data they pass in is not a simple value. This is a simple
    * overridable lookup function.
    *
-   * @param $operator
+   * @param string $operator
    *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
    *
    * @return array
@@ -301,15 +349,17 @@ protected function mapConditionOperator($operator) {
     static $specials = array(
       'BETWEEN' => array('delimiter' => ' AND '),
       'NOT BETWEEN' => array('delimiter' => ' AND '),
-      'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
-      'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
-      'EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
-      'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
+      'IN' => array('delimiter' => ', ', 'prefix' => '(', 'postfix' => ')'),
+      'NOT IN' => array('delimiter' => ', ', 'prefix' => '(', 'postfix' => ')'),
       'IS NULL' => array('use_value' => FALSE),
       'IS NOT NULL' => array('use_value' => FALSE),
       // Use backslash for escaping wildcard characters.
       'LIKE' => array('postfix' => " ESCAPE '\\\\'"),
       'NOT LIKE' => array('postfix' => " ESCAPE '\\\\'"),
+      // Exists expects an already bracketed subquery as right hand part. Do
+      // not define additional brackets.
+      'EXISTS' => array(),
+      'NOT EXISTS' => array(),
       // These ones are here for performance reasons.
       '=' => array(),
       '<' => array(),
diff --git a/core/lib/Drupal/Core/Database/Query/ConditionInterface.php b/core/lib/Drupal/Core/Database/Query/ConditionInterface.php
index bd0b52bd2cce48b41da719b07c8eb4497b8f1f25..a881cdddbcf9f00aecf809fea9e8c808384016c6 100644
--- a/core/lib/Drupal/Core/Database/Query/ConditionInterface.php
+++ b/core/lib/Drupal/Core/Database/Query/ConditionInterface.php
@@ -12,13 +12,21 @@ interface ConditionInterface {
   /**
    * Helper function: builds the most common conditional clauses.
    *
-   * This method can take a variable number of parameters. If called with two
-   * parameters, they are taken as $field and $value with $operator having a
-   * value of =.
+   * This method takes 1 to 3 parameters.
+   *
+   * If called with 1 parameter, it should be a ConditionInterface that in
+   * itself forms a valid where clause. Use e.g. to build clauses with nested
+   * AND's and OR's.
+   *
+   * If called with 2 parameters, they are taken as $field and $value with
+   * $operator having a value of =.
    *
    * Do not use this method to test for NULL values. Instead, use
    * QueryConditionInterface::isNull() or QueryConditionInterface::isNotNull().
    *
+   * To improve readability, the operators EXISTS and NOT EXISTS have their own
+   * utility method defined.
+   *
    * Drupal considers LIKE case insensitive and the following is often used
    * to tell the database that case insensitive equivalence is desired:
    * @code
@@ -32,33 +40,43 @@ interface ConditionInterface {
    * be case sensitive and when a case insensitive collation is used, the =
    * operator will also be case insensitive.
    *
-   * @param $field
-   *   The name of the field to check. If you would like to add a more complex
-   *   condition involving operators or functions, use where().
-   * @param $value
-   *   The value to test the field against. In most cases, this is a scalar.
-   *   For more complex options, it is an array. The meaning of each element in
-   *   the array is dependent on the $operator.
-   * @param $operator
-   *   The comparison operator, such as =, <, or >=. It also accepts more
-   *   complex options such as IN, LIKE, LIKE BINARY, or BETWEEN. Defaults to =.
+   * @param string|\Drupal\Core\Database\Query\ConditionInterface $field
+   *   The name of the field to check. This can also be QueryConditionInterface
+   *   in itself. Use where(), if you would like to add a more complex condition
+   *   involving operators or functions, or an already compiled condition.
+   * @param string|array|\Drupal\Core\Database\Query\SelectInterface|null $value
+   *   The value to test the field against. In most cases, and depending on the
+   *   operator, this will be a scalar or an array. As SQL accepts select
+   *   queries on any place where a scalar value or set is expected, $value may
+   *   also be a(n array of) SelectInterface(s). If $operator is a unary
+   *   operator, e.g. EXISTS, $value will be ignored and should be null.
+   * @param string|null $operator
+   *   The operator to use. Supported for all supported databases are at least:
+   *   - The comparison operators =, <>, <, <=, >, >=.
+   *   - The operators (NOT) BETWEEN, (NOT) IN, (NOT) EXISTS, (NOT) LIKE.
+   *   Other operators (e.g. LIKE, BINARY) may or may not work. Defaults to =.
    *
    * @return \Drupal\Core\Database\Query\ConditionInterface
    *   The called object.
    *
    * @see \Drupal\Core\Database\Query\ConditionInterface::isNull()
    * @see \Drupal\Core\Database\Query\ConditionInterface::isNotNull()
+   * @see \Drupal\Core\Database\Query\ConditionInterface::exists()
+   * @see \Drupal\Core\Database\Query\ConditionInterface::notExist()
+   * @see \Drupal\Core\Database\Query\ConditionInterface::where()
    */
   public function condition($field, $value = NULL, $operator = '=');
 
   /**
    * Adds an arbitrary WHERE clause to the query.
    *
-   * @param $snippet
+   * @param string $snippet
    *   A portion of a WHERE clause as a prepared statement. It must use named
-   *   placeholders, not ? placeholders.
-   * @param $args
-   *   An associative array of arguments.
+   *   placeholders, not ? placeholders. The caller is responsible for providing
+   *   unique placeholders that do not interfere with the placeholders generated
+   *   by this QueryConditionInterface object.
+   * @param array $args
+   *   An associative array of arguments keyed by the named placeholders.
    *
    * @return \Drupal\Core\Database\Query\ConditionInterface
    *   The called object.
@@ -68,8 +86,8 @@ public function where($snippet, $args = array());
   /**
    * Sets a condition that the specified field be NULL.
    *
-   * @param $field
-   *   The name of the field to check.
+   * @param string|\Drupal\Core\Database\Query\SelectInterface $field
+   *   The name of the field or a subquery to check.
    *
    * @return \Drupal\Core\Database\Query\ConditionInterface
    *   The called object.
@@ -79,8 +97,8 @@ public function isNull($field);
   /**
    * Sets a condition that the specified field be NOT NULL.
    *
-   * @param $field
-   *   The name of the field to check.
+   * @param string|\Drupal\Core\Database\Query\SelectInterface $field
+   *   The name of the field or a subquery to check.
    *
    * @return \Drupal\Core\Database\Query\ConditionInterface
    *   The called object.
@@ -110,7 +128,7 @@ public function exists(SelectInterface $select);
   public function notExists(SelectInterface $select);
 
   /**
-   * Gets a complete list of all conditions in this conditional clause.
+   * Gets the, possibly nested, list of conditions in this conditional clause.
    *
    * This method returns by reference. That allows alter hooks to access the
    * data structure directly and manipulate it before it gets compiled.
@@ -131,6 +149,9 @@ public function notExists(SelectInterface $select);
    *
    * There will also be a single array entry of #conjunction, which is the
    * conjunction that will be applied to the array, such as AND.
+   *
+   * @return array
+   *   The, possibly nested, list of all conditions (by reference).
    */
   public function &conditions();
 
diff --git a/core/modules/views_ui/src/Tests/PreviewTest.php b/core/modules/views_ui/src/Tests/PreviewTest.php
index 3b4dd9bf830cdd5b02c2d208a7e831834687d3b2..d2dcd121936649cc36bc755e8dfe64b1ec643ba6 100644
--- a/core/modules/views_ui/src/Tests/PreviewTest.php
+++ b/core/modules/views_ui/src/Tests/PreviewTest.php
@@ -105,7 +105,7 @@ function testPreviewUI() {
     $this->assertText(t('Query execute time'));
     $this->assertText(t('View render time'));
     $this->assertRaw('<strong>Query</strong>');
-    $this->assertText("SELECT views_test_data.name AS views_test_data_name\nFROM \n{views_test_data} views_test_data\nWHERE (( (views_test_data.id = &#039;100&#039; ) ))");
+    $this->assertText("SELECT views_test_data.name AS views_test_data_name\nFROM \n{views_test_data} views_test_data\nWHERE (views_test_data.id = &#039;100&#039; )");
 
     // Test that the statistics and query are rendered above the preview.
     $this->assertTrue(strpos($this->getRawContent(), 'views-query-info') < strpos($this->getRawContent(), 'view-test-preview'), 'Statistics shown above the preview.');
diff --git a/core/tests/Drupal/KernelTests/Core/Database/SelectSubqueryTest.php b/core/tests/Drupal/KernelTests/Core/Database/SelectSubqueryTest.php
index 4877ca2f73dc93eacaf6b4628f57a0d78bb0c224..98849bbaaab3cba1f7600b1133dd4517fdf6337e 100644
--- a/core/tests/Drupal/KernelTests/Core/Database/SelectSubqueryTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Database/SelectSubqueryTest.php
@@ -39,7 +39,7 @@ function testFromSubquerySelect() {
       // WHERE tt.task = 'code'
       $people = $select->execute()->fetchCol();
 
-      $this->assertEqual(count($people), 1, 'Returned the correct number of rows.');
+      $this->assertCount(1, $people, 'Returned the correct number of rows.');
     }
   }
 
@@ -66,11 +66,11 @@ function testFromSubquerySelectWithLimit() {
     //   INNER JOIN test t ON t.id=tt.pid
     $people = $select->execute()->fetchCol();
 
-    $this->assertEqual(count($people), 1, 'Returned the correct number of rows.');
+    $this->assertCount(1, $people, 'Returned the correct number of rows.');
   }
 
   /**
-   * Tests that we can use a subquery in a WHERE clause.
+   * Tests that we can use a subquery with an IN operator in a WHERE clause.
    */
   function testConditionSubquerySelect() {
     // Create a subquery, which is just a normal query object.
@@ -89,7 +89,92 @@ function testConditionSubquerySelect() {
     // FROM test tt2
     // WHERE tt2.pid IN (SELECT tt.pid AS pid FROM test_task tt WHERE tt.priority=1)
     $people = $select->execute()->fetchCol();
-    $this->assertEqual(count($people), 5, 'Returned the correct number of rows.');
+    $this->assertCount(5, $people, 'Returned the correct number of rows.');
+  }
+
+  /**
+   * Test that we can use a subquery with a relational operator in a WHERE clause.
+   */
+  function testConditionSubquerySelect2() {
+    // Create a subquery, which is just a normal query object.
+    $subquery = db_select('test', 't2');
+    $subquery->addExpression('AVG(t2.age)');
+
+    // Create another query that adds a clause using the subquery.
+    $select = db_select('test', 't');
+    $select->addField('t', 'name');
+    $select->condition('t.age', $subquery, '<');
+
+    // The resulting query should be equivalent to:
+    // SELECT t.name
+    // FROM test t
+    // WHERE t.age < (SELECT AVG(t2.age) FROM test t2)
+    $people = $select->execute()->fetchCol();
+    $this->assertEquals(['John', 'Paul'], $people, 'Returned Paul and John.', 0.0, 10, TRUE);
+  }
+
+  /**
+   * Test that we can use 2 subqueries with a relational operator in a WHERE clause.
+   */
+  function testConditionSubquerySelect3() {
+    // Create subquery 1, which is just a normal query object.
+    $subquery1 = db_select('test_task', 'tt');
+    $subquery1->addExpression('AVG(tt.priority)');
+    $subquery1->where('tt.pid = t.id');
+
+    // Create subquery 2, which is just a normal query object.
+    $subquery2 = db_select('test_task', 'tt2');
+    $subquery2->addExpression('AVG(tt2.priority)');
+
+    // Create another query that adds a clause using the subqueries.
+    $select = db_select('test', 't');
+    $select->addField('t', 'name');
+    $select->condition($subquery1, $subquery2, '>');
+
+    // The resulting query should be equivalent to:
+    // SELECT t.name
+    // FROM test t
+    // WHERE (SELECT AVG(tt.priority) FROM test_task tt WHERE tt.pid = t.id) > (SELECT AVG(tt2.priority) FROM test_task tt2)
+    $people = $select->execute()->fetchCol();
+    $this->assertEquals(['John'], $people, 'Returned John.', 0.0, 10, TRUE);
+  }
+
+  /**
+   * Test that we can use multiple subqueries.
+   *
+   * This test uses a subquery at the left hand side and multiple subqueries at
+   * the right hand side. The test query may not be that logical but that's due
+   * to the limited amount of data and tables. 'Valid' use cases do exist :)
+   */
+  function testConditionSubquerySelect4() {
+    // Create subquery 1, which is just a normal query object.
+    $subquery1 = db_select('test_task', 'tt');
+    $subquery1->addExpression('AVG(tt.priority)');
+    $subquery1->where('tt.pid = t.id');
+
+    // Create subquery 2, which is just a normal query object.
+    $subquery2 = db_select('test_task', 'tt2');
+    $subquery2->addExpression('MIN(tt2.priority)');
+    $subquery2->where('tt2.pid <> t.id');
+
+    // Create subquery 3, which is just a normal query object.
+    $subquery3 = db_select('test_task', 'tt3');
+    $subquery3->addExpression('AVG(tt3.priority)');
+    $subquery3->where('tt3.pid <> t.id');
+
+    // Create another query that adds a clause using the subqueries.
+    $select = db_select('test', 't');
+    $select->addField('t', 'name');
+    $select->condition($subquery1, [$subquery2, $subquery3], 'BETWEEN');
+
+    // The resulting query should be equivalent to:
+    // SELECT t.name AS name
+    // FROM {test} t
+    // WHERE (SELECT AVG(tt.priority) AS expression FROM {test_task} tt WHERE (tt.pid = t.id))
+    //   BETWEEN (SELECT MIN(tt2.priority) AS expression FROM {test_task} tt2 WHERE (tt2.pid <> t.id))
+    //       AND (SELECT AVG(tt3.priority) AS expression FROM {test_task} tt3 WHERE (tt3.pid <> t.id));
+    $people = $select->execute()->fetchCol();
+    $this->assertEquals(['George', 'Paul'], $people, 'Returned George and Paul.', 0.0, 10, TRUE);
   }
 
   /**
@@ -113,7 +198,7 @@ function testJoinSubquerySelect() {
     //   INNER JOIN (SELECT tt.pid AS pid FROM test_task tt WHERE priority=1) tt ON t.id=tt.pid
     $people = $select->execute()->fetchCol();
 
-    $this->assertEqual(count($people), 2, 'Returned the correct number of rows.');
+    $this->assertCount(2, $people, 'Returned the correct number of rows.');
   }
 
   /**
@@ -143,7 +228,7 @@ function testExistsSubquerySelect() {
 
     // Ensure that we got the right record.
     $record = $result->fetch();
-    $this->assertEqual($record->name, 'George', 'Fetched name is correct using EXISTS query.');
+    $this->assertEquals('George', $record->name, 'Fetched name is correct using EXISTS query.');
   }
 
   /**
@@ -173,7 +258,7 @@ function testNotExistsSubquerySelect() {
 
     // Ensure that we got the right number of records.
     $people = $query->execute()->fetchCol();
-    $this->assertEqual(count($people), 3, 'NOT EXISTS query returned the correct results.');
+    $this->assertCount(3, $people, 'NOT EXISTS query returned the correct results.');
   }
 
 }
diff --git a/core/tests/Drupal/Tests/Core/Database/ConditionTest.php b/core/tests/Drupal/Tests/Core/Database/ConditionTest.php
index fde028b9b5e0aad1a789842211120da9907dbc10..f33e3c331bfbcd2467bac11bc3b9908b7e917f4e 100644
--- a/core/tests/Drupal/Tests/Core/Database/ConditionTest.php
+++ b/core/tests/Drupal/Tests/Core/Database/ConditionTest.php
@@ -15,12 +15,27 @@
  */
 class ConditionTest extends UnitTestCase {
 
+  /**
+   * Provides a list of known operations and the expected output.
+   *
+   * @return array
+   *   - Expected result for the string version of the condition.
+   *   - The field name to input in the condition.
+   */
+  public function providerSimpleCondition() {
+    return [
+      ['name = :db_condition_placeholder_0', 'name'],
+      ['name123 = :db_condition_placeholder_0', 'name-123'],
+    ];
+  }
+
   /**
    * @covers ::compile
+   * @dataProvider providerSimpleCondition()
    */
-  public function testSimpleCondition() {
+  public function testSimpleCondition($expected, $field_name) {
     $connection = $this->prophesize(Connection::class);
-    $connection->escapeField('name')->will(function ($args) {
+    $connection->escapeField($field_name)->will(function ($args) {
       return preg_replace('/[^A-Za-z0-9_.]+/', '', $args[0]);
     });
     $connection->mapConditionOperator('=')->willReturn(['operator' => '=']);
@@ -36,10 +51,10 @@ public function testSimpleCondition() {
     $query_placeholder = $query_placeholder->reveal();
 
     $condition = new Condition('AND');
-    $condition->condition('name', ['value']);
+    $condition->condition($field_name, ['value']);
     $condition->compile($connection, $query_placeholder);
 
-    $this->assertEquals(' (name = :db_condition_placeholder_0) ', $condition->__toString());
+    $this->assertEquals($expected, $condition->__toString());
     $this->assertEquals([':db_condition_placeholder_0' => 'value'], $condition->arguments());
   }
 
@@ -96,28 +111,28 @@ public function dataProviderTestCompileWithKnownOperators() {
     // aren't directly supported by core, but instead need manual handling with
     // prefix/suffix at the moment.
     $data = [];
-    $data[] = [' (name = :db_condition_placeholder_0) ', 'name', 'value', '='];
-    $data[] = [' (name != :db_condition_placeholder_0) ', 'name', 'value', '!='];
-    $data[] = [' (name <> :db_condition_placeholder_0) ', 'name', 'value', '<>'];
-    $data[] = [' (name >= :db_condition_placeholder_0) ', 'name', 'value', '>='];
-    $data[] = [' (name > :db_condition_placeholder_0) ', 'name', 'value', '>'];
-    $data[] = [' (name <= :db_condition_placeholder_0) ', 'name', 'value', '<='];
-    $data[] = [' (name < :db_condition_placeholder_0) ', 'name', 'value', '<'];
-    // $data[] = [' ( GREATEST (1, 2, 3) ) ', '', [1, 2, 3], 'GREATEST'];
-    $data[] = [' (name IN  (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)) ', 'name', ['1', '2', '3'], 'IN'];
-    $data[] = [' (name NOT IN  (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)) ', 'name', ['1', '2', '3'], 'NOT IN'];
-    // $data[] = [' ( INTERVAL (1, 2, 3) ) ', '', [1, 2, 3], 'INTERVAL'];
-    $data[] = [' (name IS NULL ) ', 'name', NULL, 'IS NULL'];
-    $data[] = [' (name IS NOT NULL ) ', 'name', NULL, 'IS NOT NULL'];
-    $data[] = [' (name IS :db_condition_placeholder_0) ', 'name', 'TRUE', 'IS'];
-    // $data[] = [' ( LEAST (1, 2, 3) ) ', '', [1, 2, 3], 'LEAST'];
-    $data[] = [" (name LIKE :db_condition_placeholder_0 ESCAPE '\\\\') ", 'name', '%muh%', 'LIKE', [':db_condition_placeholder_0' => '%muh%']];
-    $data[] = [" (name NOT LIKE :db_condition_placeholder_0 ESCAPE '\\\\') ", 'name', '%muh%', 'NOT LIKE', [':db_condition_placeholder_0' => '%muh%']];
-    $data[] = [" (name BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1) ", 'name', [1, 2], 'BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
-    $data[] = [" (name NOT BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1) ", 'name', [1, 2], 'NOT BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
-    // $data[] = [' ( STRCMP (name, :db_condition_placeholder_0) ) ', '', ['test-string'], 'STRCMP', [':db_condition_placeholder_0' => 'test-string']];
-    // $data[] = [' (EXISTS ) ', '', NULL, 'EXISTS'];
-    // $data[] = [' (name NOT EXISTS ) ', 'name', NULL, 'NOT EXISTS'];
+    $data[] = ['name = :db_condition_placeholder_0', 'name', 'value', '='];
+    $data[] = ['name != :db_condition_placeholder_0', 'name', 'value', '!='];
+    $data[] = ['name <> :db_condition_placeholder_0', 'name', 'value', '<>'];
+    $data[] = ['name >= :db_condition_placeholder_0', 'name', 'value', '>='];
+    $data[] = ['name > :db_condition_placeholder_0', 'name', 'value', '>'];
+    $data[] = ['name <= :db_condition_placeholder_0', 'name', 'value', '<='];
+    $data[] = ['name < :db_condition_placeholder_0', 'name', 'value', '<'];
+    // $data[] = ['GREATEST (1, 2, 3)', '', [1, 2, 3], 'GREATEST'];
+    $data[] = ['name IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)', 'name', ['1', '2', '3'], 'IN'];
+    $data[] = ['name NOT IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)', 'name', ['1', '2', '3'], 'NOT IN'];
+    // $data[] = ['INTERVAL (1, 2, 3)', '', [1, 2, 3], 'INTERVAL'];
+    $data[] = ['name IS NULL', 'name', NULL, 'IS NULL'];
+    $data[] = ['name IS NOT NULL', 'name', NULL, 'IS NOT NULL'];
+    $data[] = ['name IS :db_condition_placeholder_0', 'name', 'TRUE', 'IS'];
+    // $data[] = ['LEAST (1, 2, 3)', '', [1, 2, 3], 'LEAST'];
+    $data[] = ["name LIKE :db_condition_placeholder_0 ESCAPE '\\\\'", 'name', '%muh%', 'LIKE', [':db_condition_placeholder_0' => '%muh%']];
+    $data[] = ["name NOT LIKE :db_condition_placeholder_0 ESCAPE '\\\\'", 'name', '%muh%', 'NOT LIKE', [':db_condition_placeholder_0' => '%muh%']];
+    $data[] = ["name BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1", 'name', [1, 2], 'BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
+    $data[] = ["name NOT BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1", 'name', [1, 2], 'NOT BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
+    // $data[] = ['STRCMP (name, :db_condition_placeholder_0)', '', ['test-string'], 'STRCMP', [':db_condition_placeholder_0' => 'test-string']];
+    // $data[] = ['EXISTS', '', NULL, 'EXISTS'];
+    // $data[] = ['name NOT EXISTS', 'name', NULL, 'NOT EXISTS'];
 
     return $data;
   }