Commit 9fb5187d authored by alexpott's avatar alexpott

Issue #2443679 followup by chx: PostgreSQL: Fix taxonomy\Tests\TermTest

parent 554f9a46
......@@ -763,6 +763,9 @@ services:
arguments: ['@database']
tags:
- { name: backend_overridable }
pgsql.entity.query.sql:
class: Drupal\Core\Entity\Query\Sql\pgsql\QueryFactory
arguments: ['@database']
entity.query.null:
class: Drupal\Core\Entity\Query\Null\QueryFactory
entity.query.keyvalue:
......
<?php
/**
* @file
* Contains Drupal\Core\Database\Driver\mysql\EntityQuery\Condition
*/
namespace Drupal\Core\Database\Driver\mysql\EntityQuery;
use Drupal\Core\Database\EntityQuery\ConditionInterface as EntityQueryConditionInterface;
/**
* Implements entity query conditions for SQL databases.
*/
class Condition implements EntityQueryConditionInterface {
/**
* {@inheritdoc}
*/
public static function translateCondition(array &$condition, $case_sensitive) { }
}
<?php
/**
* @file
* Contains Drupal\Core\Database\Driver\sqlite\EntityQuery\Condition
*/
namespace Drupal\Core\Database\Driver\sqlite\EntityQuery;
use Drupal\Core\Database\EntityQuery\ConditionInterface as EntityQueryConditionInterface;
/**
* Implements entity query conditions for SQL databases.
*/
class Condition implements EntityQueryConditionInterface {
/**
* {@inheritdoc}
*/
public static function translateCondition(array &$condition, $case_sensitive) { }
}
<?php
/**
* @file
* Contains \Drupal\Core\Database\EntityQuery\ConditionInterface.
*/
namespace Drupal\Core\Database\EntityQuery;
/**
* Provides an interface for entity query conditions for SQL databases.
*/
interface ConditionInterface {
/**
* Translates the string operators to SQL equivalents. This is a no-op method
* for MySQL and SQLite databases but allows override if needed, e.g. for
* PostgreSQL to support case insensitive queries.
*
* @param array $condition
* The condition array.
* @param bool|null $case_sensitive
* If the condition should be case sensitive or not, NULL if the field does
* not define it.
*
* @see \Drupal\Core\Entity\Query\Sql\Condition::$entityQueryCondition
*/
public static function translateCondition(array &$condition, $case_sensitive);
}
......@@ -463,6 +463,13 @@ public function escapeLike($string) {
return $this->connection->escapeLike($string);
}
/**
* {@inheritdoc}
*/
public function escapeField($string) {
return $this->connection->escapeField($string);
}
/**
* {@inheritdoc}
*/
......
......@@ -210,6 +210,14 @@ public function escapeLike($string) {
return $this->query->escapeLike($string);
}
/**
* {@inheritdoc}
*/
public function escapeField($string) {
$this->query->escapeField($string);
return $this;
}
public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) {
return $this->query->getArguments($queryPlaceholder);
}
......
......@@ -140,6 +140,18 @@ public function &getUnion();
*/
public function escapeLike($string);
/**
* Escapes a field name string.
*
* Force all field names to be strictly alphanumeric-plus-underscore.
* For some database drivers, it may also wrap the field name in
* database-specific escape characters.
*
* @return
* The sanitized field name string.
*/
public function escapeField($string);
/**
* Compiles and returns an associative array of the arguments for this prepared statement.
*
......@@ -632,4 +644,5 @@ public function __clone();
* The called object.
*/
public function forUpdate($set = TRUE);
}
......@@ -36,15 +36,27 @@ abstract class ConditionFundamentals {
*/
protected $query;
/**
* List of potential namespaces of the classes belonging to this condition.
*
* @var array
*/
protected $namespaces = array();
/**
* Constructs a Condition object.
*
* @param string $conjunction
* The operator to use to combine conditions: 'AND' or 'OR'.
* @param QueryInterface $query
* The entity query this condition belongs to.
* @param array $namespaces
* List of potential namespaces of the classes belonging to this condition.
*/
public function __construct($conjunction, QueryInterface $query) {
public function __construct($conjunction, QueryInterface $query, $namespaces = []) {
$this->conjunction = $conjunction;
$this->query = $query;
$this->namespaces = $namespaces;
}
/**
......
......@@ -7,7 +7,6 @@
namespace Drupal\Core\Entity\Query\Sql;
use Drupal\Core\Database\Database;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Database\Query\Condition as SqlCondition;
use Drupal\Core\Entity\Query\ConditionBase;
......@@ -90,13 +89,8 @@ public function notExists($field, $langcode = NULL) {
* @see \Drupal\Core\Database\Query\ConditionInterface::condition()
*/
public static function translateCondition(&$condition, SelectInterface $sql_query, $case_sensitive) {
// There is nothing to do for IN () queries except for PostgreSQL for which
// the condition arguments need to have case lowered to support not case
// sensitive fields.
// // There is nothing we can do for IN ().
if (is_array($condition['value'])) {
$entityQueryCondition = Database::getConnection()->getDriverClass('EntityQuery\\Condition');
$entityQueryCondition::translateCondition($condition, $case_sensitive);
return;
}
......
......@@ -11,6 +11,7 @@
use Drupal\Core\Entity\Query\ConditionAggregateBase;
use Drupal\Core\Entity\Query\ConditionAggregateInterface;
use Drupal\Core\Database\Query\Condition as SqlCondition;
use Drupal\Core\Entity\Query\QueryBase;
/**
* Defines the aggregate condition for sql based storage.
......@@ -39,7 +40,8 @@ public function compile($conditionContainer) {
else {
$type = ((strtoupper($this->conjunction) == 'OR') || ($condition['operator'] == 'IS NULL')) ? 'LEFT' : 'INNER';
$field = $tables->addField($condition['field'], $type, $condition['langcode']);
Condition::translateCondition($condition, $sql_query, $tables->isFieldCaseSensitive($condition['field']));
$condition_class = QueryBase::getClass($this->namespaces, 'Condition');
$condition_class::translateCondition($condition, $sql_query, $tables->isFieldCaseSensitive($condition['field']));
$function = $condition['function'];
$placeholder = ':db_placeholder_' . $conditionContainer->nextPlaceholder();
$conditionContainer->having("$function($field) {$condition['operator']} $placeholder", array($placeholder => $condition['value']));
......
......@@ -52,7 +52,8 @@ public function prepare() {
* Implements \Drupal\Core\Entity\Query\QueryAggregateInterface::conditionAggregateGroupFactory().
*/
public function conditionAggregateGroupFactory($conjunction = 'AND') {
return new ConditionAggregate($conjunction, $this);
$class = static::getClass($this->namespaces, 'ConditionAggregate');
return new $class($conjunction, $this, $this->namespaces);
}
/**
......
......@@ -2,29 +2,25 @@
/**
* @file
* Contains Drupal\Core\Database\Driver\pgsql\EntityQuery\Condition
* Contains \Drupal\Core\Entity\Query\Sql\pgsql\Condition.
*/
namespace Drupal\Core\Database\Driver\pgsql\EntityQuery;
namespace Drupal\Core\Entity\Query\Sql\pgsql;
use Drupal\Core\Database\Database;
use Drupal\Core\Database\EntityQuery\ConditionInterface as EntityQueryConditionInterface;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\Query\Sql\Condition as BaseCondition;
/**
* Implements entity query conditions for SQL databases.
* Implements entity query conditions for PostgreSQL databases.
*/
class Condition implements EntityQueryConditionInterface {
class Condition extends BaseCondition {
/**
* {@inheritdoc}
*/
public static function translateCondition(array &$condition, $case_sensitive) {
$connection = Database::getConnection();
// For PostgreSQL all the condition arguments need to have case
// lowered to support not case sensitive fields.
public static function translateCondition(&$condition, SelectInterface $sql_query, $case_sensitive) {
if (is_array($condition['value']) && $case_sensitive === FALSE) {
$condition['where'] = 'LOWER(' . $connection->escapeField($condition['real_field']) . ') ' . $condition['operator'] . ' (';
$condition['where'] = 'LOWER(' . $sql_query->escapeField($condition['real_field']) . ') ' . $condition['operator'] . ' (';
$condition['where_args'] = [];
$n = 1;
......@@ -38,7 +34,8 @@ public static function translateCondition(array &$condition, $case_sensitive) {
}
$condition['where'] = trim($condition['where'], ',');
$condition['where'] .= ')';
return;
}
parent::translateCondition($condition, $sql_query, $case_sensitive);
}
}
<?php
/**
* @file
* Contains \Drupal\Core\Entity\Query\Sql\pgsql\QueryFactory.
*/
namespace Drupal\Core\Entity\Query\Sql\pgsql;
use Drupal\Core\Entity\Query\Sql\QueryFactory as BaseQueryFactory;
/**
* PostgreSQL specific entity query implementation.
*
* To add a new query implementation extending the default SQL one, add
* a service definition like pgsql.entity.query.sql and a factory class like
* this. The system will automatically find the relevant Query, QueryAggregate,
* Condition, ConditionAggregate, Tables classes in this namespace, in the
* namespace of the parent class and so on. So after creating an empty query
* factory class like this, it is possible to just drop in a class extending
* the base class in this namespace and it will be used automatically but it
* is optional: if a class is not extended the relevant default is used.
*
* @see \Drupal\Core\Entity\Query\QueryBase::getNamespaces()
* @see \Drupal\Core\Entity\Query\QueryBase::getClass()
*/
class QueryFactory extends BaseQueryFactory {
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment