3 namespace Drupal\Core\Database\Query;
5 use Drupal\Core\Database\Connection;
8 * The base extender class for Select queries.
10 class SelectExtender implements SelectInterface {
13 * The Select query object we are extending/decorating.
15 * @var \Drupal\Core\Database\Query\SelectInterface
20 * The connection object on which to run this query.
22 * @var \Drupal\Core\Database\Connection
24 protected $connection;
27 * A unique identifier for this query object.
29 protected $uniqueIdentifier;
32 * The placeholder counter.
34 protected $placeholder = 0;
36 public function __construct(SelectInterface $query, Connection $connection) {
37 $this->uniqueIdentifier = uniqid('', TRUE);
38 $this->query = $query;
39 $this->connection = $connection;
45 public function uniqueIdentifier() {
46 return $this->uniqueIdentifier;
52 public function nextPlaceholder() {
53 return $this->placeholder++;
59 public function addTag($tag) {
60 $this->query->addTag($tag);
67 public function hasTag($tag) {
68 return $this->query->hasTag($tag);
74 public function hasAllTags() {
75 return call_user_func_array([$this->query, 'hasAllTags'], func_get_args());
81 public function hasAnyTag() {
82 return call_user_func_array([$this->query, 'hasAnyTag'], func_get_args());
88 public function addMetaData($key, $object) {
89 $this->query->addMetaData($key, $object);
96 public function getMetaData($key) {
97 return $this->query->getMetaData($key);
103 public function condition($field, $value = NULL, $operator = '=') {
104 $this->query->condition($field, $value, $operator);
111 public function &conditions() {
112 return $this->query->conditions();
118 public function arguments() {
119 return $this->query->arguments();
125 public function where($snippet, $args = []) {
126 $this->query->where($snippet, $args);
133 public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
134 return $this->query->compile($connection, $queryPlaceholder);
140 public function compiled() {
141 return $this->query->compiled();
147 public function havingCondition($field, $value = NULL, $operator = '=') {
148 $this->query->havingCondition($field, $value, $operator);
155 public function &havingConditions() {
156 return $this->query->havingConditions();
162 public function havingArguments() {
163 return $this->query->havingArguments();
169 public function having($snippet, $args = []) {
170 $this->query->having($snippet, $args);
177 public function havingCompile(Connection $connection) {
178 return $this->query->havingCompile($connection);
184 public function havingIsNull($field) {
185 $this->query->havingIsNull($field);
192 public function havingIsNotNull($field) {
193 $this->query->havingIsNotNull($field);
200 public function havingExists(SelectInterface $select) {
201 $this->query->havingExists($select);
208 public function havingNotExists(SelectInterface $select) {
209 $this->query->havingNotExists($select);
216 public function extend($extender_name) {
217 $class = $this->connection->getDriverClass($extender_name);
218 return new $class($this, $this->connection);
221 /* Alter accessors to expose the query data to alter hooks. */
226 public function &getFields() {
227 return $this->query->getFields();
233 public function &getExpressions() {
234 return $this->query->getExpressions();
240 public function &getOrderBy() {
241 return $this->query->getOrderBy();
247 public function &getGroupBy() {
248 return $this->query->getGroupBy();
254 public function &getTables() {
255 return $this->query->getTables();
261 public function &getUnion() {
262 return $this->query->getUnion();
268 public function escapeLike($string) {
269 return $this->query->escapeLike($string);
275 public function escapeField($string) {
276 $this->query->escapeField($string);
283 public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) {
284 return $this->query->getArguments($queryPlaceholder);
290 public function isPrepared() {
291 return $this->query->isPrepared();
297 public function preExecute(SelectInterface $query = NULL) {
298 // If no query object is passed in, use $this.
299 if (!isset($query)) {
303 return $this->query->preExecute($query);
309 public function execute() {
310 // By calling preExecute() here, we force it to preprocess the extender
311 // object rather than just the base query object. That means
312 // hook_query_alter() gets access to the extended object.
313 if (!$this->preExecute($this)) {
317 return $this->query->execute();
323 public function distinct($distinct = TRUE) {
324 $this->query->distinct($distinct);
331 public function addField($table_alias, $field, $alias = NULL) {
332 return $this->query->addField($table_alias, $field, $alias);
338 public function fields($table_alias, array $fields = []) {
339 $this->query->fields($table_alias, $fields);
346 public function addExpression($expression, $alias = NULL, $arguments = []) {
347 return $this->query->addExpression($expression, $alias, $arguments);
353 public function join($table, $alias = NULL, $condition = NULL, $arguments = []) {
354 return $this->query->join($table, $alias, $condition, $arguments);
360 public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
361 return $this->query->innerJoin($table, $alias, $condition, $arguments);
367 public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
368 return $this->query->leftJoin($table, $alias, $condition, $arguments);
374 public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
375 return $this->query->rightJoin($table, $alias, $condition, $arguments);
381 public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = []) {
382 return $this->query->addJoin($type, $table, $alias, $condition, $arguments);
388 public function orderBy($field, $direction = 'ASC') {
389 $this->query->orderBy($field, $direction);
396 public function orderRandom() {
397 $this->query->orderRandom();
404 public function range($start = NULL, $length = NULL) {
405 $this->query->range($start, $length);
412 public function union(SelectInterface $query, $type = '') {
413 $this->query->union($query, $type);
420 public function groupBy($field) {
421 $this->query->groupBy($field);
428 public function forUpdate($set = TRUE) {
429 $this->query->forUpdate($set);
436 public function countQuery() {
437 return $this->query->countQuery();
443 public function isNull($field) {
444 $this->query->isNull($field);
451 public function isNotNull($field) {
452 $this->query->isNotNull($field);
459 public function exists(SelectInterface $select) {
460 $this->query->exists($select);
467 public function notExists(SelectInterface $select) {
468 $this->query->notExists($select);
475 public function __toString() {
476 return (string) $this->query;
482 public function __clone() {
483 $this->uniqueIdentifier = uniqid('', TRUE);
485 // We need to deep-clone the query we're wrapping, which in turn may
486 // deep-clone other objects. Exciting!
487 $this->query = clone($this->query);
491 * Magic override for undefined methods.
493 * If one extender extends another extender, then methods in the inner extender
494 * will not be exposed on the outer extender. That's because we cannot know
495 * in advance what those methods will be, so we cannot provide wrapping
496 * implementations as we do above. Instead, we use this slower catch-all method
497 * to handle any additional methods.
499 public function __call($method, $args) {
500 $return = call_user_func_array([$this->query, $method], $args);
502 // Some methods will return the called object as part of a fluent interface.
503 // Others will return some useful value. If it's a value, then the caller
504 // probably wants that value. If it's the called object, then we instead
505 // return this object. That way we don't "lose" an extender layer when
506 // chaining methods together.
507 if ($return instanceof SelectInterface) {
518 public function conditionGroupFactory($conjunction = 'AND') {
519 return new Condition($conjunction);
525 public function andConditionGroup() {
526 return $this->conditionGroupFactory('AND');
532 public function orConditionGroup() {
533 return $this->conditionGroupFactory('OR');