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.
36 protected $placeholder = 0;
38 public function __construct(SelectInterface $query, Connection $connection) {
39 $this->uniqueIdentifier = uniqid('', TRUE);
40 $this->query = $query;
41 $this->connection = $connection;
47 public function uniqueIdentifier() {
48 return $this->uniqueIdentifier;
54 public function nextPlaceholder() {
55 return $this->placeholder++;
61 public function addTag($tag) {
62 $this->query->addTag($tag);
69 public function hasTag($tag) {
70 return $this->query->hasTag($tag);
76 public function hasAllTags() {
77 return call_user_func_array([$this->query, 'hasAllTags'], func_get_args());
83 public function hasAnyTag() {
84 return call_user_func_array([$this->query, 'hasAnyTag'], func_get_args());
90 public function addMetaData($key, $object) {
91 $this->query->addMetaData($key, $object);
98 public function getMetaData($key) {
99 return $this->query->getMetaData($key);
105 public function condition($field, $value = NULL, $operator = '=') {
106 $this->query->condition($field, $value, $operator);
113 public function &conditions() {
114 return $this->query->conditions();
120 public function arguments() {
121 return $this->query->arguments();
127 public function where($snippet, $args = []) {
128 $this->query->where($snippet, $args);
135 public function compile(Connection $connection, PlaceholderInterface $queryPlaceholder) {
136 return $this->query->compile($connection, $queryPlaceholder);
142 public function compiled() {
143 return $this->query->compiled();
149 public function havingCondition($field, $value = NULL, $operator = '=') {
150 $this->query->havingCondition($field, $value, $operator);
157 public function &havingConditions() {
158 return $this->query->havingConditions();
164 public function havingArguments() {
165 return $this->query->havingArguments();
171 public function having($snippet, $args = []) {
172 $this->query->having($snippet, $args);
179 public function havingCompile(Connection $connection) {
180 return $this->query->havingCompile($connection);
186 public function havingIsNull($field) {
187 $this->query->havingIsNull($field);
194 public function havingIsNotNull($field) {
195 $this->query->havingIsNotNull($field);
202 public function havingExists(SelectInterface $select) {
203 $this->query->havingExists($select);
210 public function havingNotExists(SelectInterface $select) {
211 $this->query->havingNotExists($select);
218 public function extend($extender_name) {
219 $class = $this->connection->getDriverClass($extender_name);
220 return new $class($this, $this->connection);
223 /* Alter accessors to expose the query data to alter hooks. */
228 public function &getFields() {
229 return $this->query->getFields();
235 public function &getExpressions() {
236 return $this->query->getExpressions();
242 public function &getOrderBy() {
243 return $this->query->getOrderBy();
249 public function &getGroupBy() {
250 return $this->query->getGroupBy();
256 public function &getTables() {
257 return $this->query->getTables();
263 public function &getUnion() {
264 return $this->query->getUnion();
270 public function escapeLike($string) {
271 return $this->query->escapeLike($string);
277 public function escapeField($string) {
278 $this->query->escapeField($string);
285 public function getArguments(PlaceholderInterface $queryPlaceholder = NULL) {
286 return $this->query->getArguments($queryPlaceholder);
292 public function isPrepared() {
293 return $this->query->isPrepared();
299 public function preExecute(SelectInterface $query = NULL) {
300 // If no query object is passed in, use $this.
301 if (!isset($query)) {
305 return $this->query->preExecute($query);
311 public function execute() {
312 // By calling preExecute() here, we force it to preprocess the extender
313 // object rather than just the base query object. That means
314 // hook_query_alter() gets access to the extended object.
315 if (!$this->preExecute($this)) {
319 return $this->query->execute();
325 public function distinct($distinct = TRUE) {
326 $this->query->distinct($distinct);
333 public function addField($table_alias, $field, $alias = NULL) {
334 return $this->query->addField($table_alias, $field, $alias);
340 public function fields($table_alias, array $fields = []) {
341 $this->query->fields($table_alias, $fields);
348 public function addExpression($expression, $alias = NULL, $arguments = []) {
349 return $this->query->addExpression($expression, $alias, $arguments);
355 public function join($table, $alias = NULL, $condition = NULL, $arguments = []) {
356 return $this->query->join($table, $alias, $condition, $arguments);
362 public function innerJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
363 return $this->query->innerJoin($table, $alias, $condition, $arguments);
369 public function leftJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
370 return $this->query->leftJoin($table, $alias, $condition, $arguments);
376 public function rightJoin($table, $alias = NULL, $condition = NULL, $arguments = []) {
377 return $this->query->rightJoin($table, $alias, $condition, $arguments);
383 public function addJoin($type, $table, $alias = NULL, $condition = NULL, $arguments = []) {
384 return $this->query->addJoin($type, $table, $alias, $condition, $arguments);
390 public function orderBy($field, $direction = 'ASC') {
391 $this->query->orderBy($field, $direction);
398 public function orderRandom() {
399 $this->query->orderRandom();
406 public function range($start = NULL, $length = NULL) {
407 $this->query->range($start, $length);
414 public function union(SelectInterface $query, $type = '') {
415 $this->query->union($query, $type);
422 public function groupBy($field) {
423 $this->query->groupBy($field);
430 public function forUpdate($set = TRUE) {
431 $this->query->forUpdate($set);
438 public function countQuery() {
439 return $this->query->countQuery();
445 public function isNull($field) {
446 $this->query->isNull($field);
453 public function isNotNull($field) {
454 $this->query->isNotNull($field);
461 public function exists(SelectInterface $select) {
462 $this->query->exists($select);
469 public function notExists(SelectInterface $select) {
470 $this->query->notExists($select);
477 public function __toString() {
478 return (string) $this->query;
484 public function __clone() {
485 $this->uniqueIdentifier = uniqid('', TRUE);
487 // We need to deep-clone the query we're wrapping, which in turn may
488 // deep-clone other objects. Exciting!
489 $this->query = clone($this->query);
493 * Magic override for undefined methods.
495 * If one extender extends another extender, then methods in the inner extender
496 * will not be exposed on the outer extender. That's because we cannot know
497 * in advance what those methods will be, so we cannot provide wrapping
498 * implementations as we do above. Instead, we use this slower catch-all method
499 * to handle any additional methods.
501 public function __call($method, $args) {
502 $return = call_user_func_array([$this->query, $method], $args);
504 // Some methods will return the called object as part of a fluent interface.
505 // Others will return some useful value. If it's a value, then the caller
506 // probably wants that value. If it's the called object, then we instead
507 // return this object. That way we don't "lose" an extender layer when
508 // chaining methods together.
509 if ($return instanceof SelectInterface) {
520 public function conditionGroupFactory($conjunction = 'AND') {
521 return new Condition($conjunction);
527 public function andConditionGroup() {
528 return $this->conditionGroupFactory('AND');
534 public function orConditionGroup() {
535 return $this->conditionGroupFactory('OR');