Select.php

Same filename in this branch
  1. 11.x core/modules/sqlite/src/Driver/Database/sqlite/Select.php
  2. 11.x core/modules/mysql/src/Driver/Database/mysql/Select.php
  3. 11.x core/tests/Drupal/Tests/Core/Database/Stub/Select.php
  4. 11.x core/tests/fixtures/database_drivers/module/core_fake/src/Driver/Database/CoreFakeWithAllCustomClasses/Select.php
  5. 11.x core/lib/Drupal/Core/Render/Element/Select.php
  6. 11.x core/lib/Drupal/Core/Database/Query/Select.php
Same filename in other branches
  1. 9 core/modules/sqlite/src/Driver/Database/sqlite/Select.php
  2. 9 core/modules/mysql/src/Driver/Database/mysql/Select.php
  3. 9 core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/Select.php
  4. 9 core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysqlDeprecatedVersion/Select.php
  5. 9 core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestPgsql/Select.php
  6. 9 core/modules/pgsql/src/Driver/Database/pgsql/Select.php
  7. 9 core/tests/Drupal/Tests/Core/Database/Stub/Select.php
  8. 9 core/tests/fixtures/database_drivers/module/corefake/src/Driver/Database/corefakeWithAllCustomClasses/Select.php
  9. 9 core/lib/Drupal/Core/Render/Element/Select.php
  10. 9 core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
  11. 9 core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
  12. 9 core/lib/Drupal/Core/Database/Query/Select.php
  13. 8.9.x core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestMysql/Select.php
  14. 8.9.x core/modules/system/tests/modules/driver_test/src/Driver/Database/DrivertestPgsql/Select.php
  15. 8.9.x core/tests/Drupal/Tests/Core/Database/Stub/Select.php
  16. 8.9.x core/lib/Drupal/Core/Render/Element/Select.php
  17. 8.9.x core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
  18. 8.9.x core/lib/Drupal/Core/Database/Driver/mysql/Select.php
  19. 8.9.x core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
  20. 8.9.x core/lib/Drupal/Core/Database/Query/Select.php
  21. 10 core/modules/sqlite/src/Driver/Database/sqlite/Select.php
  22. 10 core/modules/mysql/src/Driver/Database/mysql/Select.php
  23. 10 core/modules/pgsql/src/Driver/Database/pgsql/Select.php
  24. 10 core/tests/Drupal/Tests/Core/Database/Stub/Select.php
  25. 10 core/tests/fixtures/database_drivers/module/core_fake/src/Driver/Database/CoreFakeWithAllCustomClasses/Select.php
  26. 10 core/lib/Drupal/Core/Render/Element/Select.php
  27. 10 core/lib/Drupal/Core/Database/Driver/sqlite/Select.php
  28. 10 core/lib/Drupal/Core/Database/Driver/pgsql/Select.php
  29. 10 core/lib/Drupal/Core/Database/Query/Select.php

Namespace

Drupal\pgsql\Driver\Database\pgsql

File

core/modules/pgsql/src/Driver/Database/pgsql/Select.php

View source
<?php

namespace Drupal\pgsql\Driver\Database\pgsql;

use Drupal\Core\Database\Query\Select as QuerySelect;

/**
 * @addtogroup database
 * @{
 */

/**
 * PostgreSQL implementation of \Drupal\Core\Database\Query\Select.
 */
class Select extends QuerySelect {
    public function orderRandom() {
        $alias = $this->addExpression('RANDOM()', 'random_field');
        $this->orderBy($alias);
        return $this;
    }
    
    /**
     * Overrides SelectQuery::orderBy().
     *
     * PostgreSQL adheres strictly to the SQL-92 standard and requires that when
     * using DISTINCT or GROUP BY conditions, fields and expressions that are
     * ordered on also need to be selected. This is a best effort implementation
     * to handle the cases that can be automated by adding the field if it is not
     * yet selected.
     *
     * @code
     *   $query = \Drupal::database()->select('example', 'e');
     *   $query->join('example_revision', 'er', '[e].[vid] = [er].[vid]');
     *   $query
     *     ->distinct()
     *     ->fields('e')
     *     ->orderBy('timestamp');
     * @endcode
     *
     * In this query, it is not possible (without relying on the schema) to know
     * whether timestamp belongs to example_revision and needs to be added or
     * belongs to node and is already selected. Queries like this will need to be
     * corrected in the original query by adding an explicit call to
     * SelectQuery::addField() or SelectQuery::fields().
     *
     * Since this has a small performance impact, both by the additional
     * processing in this function and in the database that needs to return the
     * additional fields, this is done as an override instead of implementing it
     * directly in SelectQuery::orderBy().
     */
    public function orderBy($field, $direction = 'ASC') {
        // Only allow ASC and DESC, default to ASC.
        // Emulate MySQL default behavior to sort NULL values first for ascending,
        // and last for descending.
        // @see http://www.postgresql.org/docs/9.3/static/queries-order.html
        $direction = strtoupper($direction) == 'DESC' ? 'DESC NULLS LAST' : 'ASC NULLS FIRST';
        $this->order[$field] = $direction;
        if ($this->hasTag('entity_query')) {
            return $this;
        }
        // If there is a table alias specified, split it up.
        if (str_contains($field, '.')) {
            [
                $table,
                $table_field,
            ] = explode('.', $field);
        }
        // Figure out if the field has already been added.
        foreach ($this->fields as $existing_field) {
            if (!empty($table)) {
                // If table alias is given, check if field and table exists.
                if ($existing_field['table'] == $table && $existing_field['field'] == $table_field) {
                    return $this;
                }
            }
            else {
                // If there is no table, simply check if the field exists as a field or
                // an aliased field.
                if ($existing_field['alias'] == $field) {
                    return $this;
                }
            }
        }
        // Also check expression aliases.
        foreach ($this->expressions as $expression) {
            if ($expression['alias'] == $this->connection
                ->escapeAlias($field)) {
                return $this;
            }
        }
        // If a table loads all fields, it can not be added again. It would
        // result in an ambiguous alias error because that field would be loaded
        // twice: Once through table_alias.* and once directly. If the field
        // actually belongs to a different table, it must be added manually.
        foreach ($this->tables as $table) {
            if (!empty($table['all_fields'])) {
                return $this;
            }
        }
        // If $field contains characters which are not allowed in a field name
        // it is considered an expression, these can't be handled automatically
        // either.
        if ($this->connection
            ->escapeField($field) != $field) {
            return $this;
        }
        // This is a case that can be handled automatically, add the field.
        $this->addField(NULL, $field);
        return $this;
    }
    
    /**
     * {@inheritdoc}
     */
    public function addExpression($expression, $alias = NULL, $arguments = []) {
        if (empty($alias)) {
            $alias = 'expression';
        }
        // This implements counting in the same manner as the parent method.
        $alias_candidate = $alias;
        $count = 2;
        while (!empty($this->expressions[$alias_candidate])) {
            $alias_candidate = $alias . '_' . $count++;
        }
        $alias = $alias_candidate;
        $this->expressions[$alias] = [
            'expression' => $expression,
            'alias' => $this->connection
                ->escapeAlias($alias_candidate),
            'arguments' => $arguments,
        ];
        return $alias;
    }
    
    /**
     * {@inheritdoc}
     */
    public function execute() {
        $this->connection
            ->addSavepoint();
        try {
            $result = parent::execute();
        } catch (\Exception $e) {
            $this->connection
                ->rollbackSavepoint();
            throw $e;
        }
        $this->connection
            ->releaseSavepoint();
        return $result;
    }

}

/**
 * @} End of "addtogroup database".
 */

Classes

Title Deprecated Summary
Select PostgreSQL implementation of \Drupal\Core\Database\Query\Select.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.