Example #1
0
 /**
  * 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 = db_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')
 {
     // Call parent function to order on this.
     $return = parent::orderBy($field, $direction);
     if ($this->hasTag('entity_query')) {
         return $return;
     }
     // If there is a table alias specified, split it up.
     if (strpos($field, '.') !== FALSE) {
         list($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 $return;
             }
         } 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 $return;
             }
         }
     }
     // Also check expression aliases.
     foreach ($this->expressions as $expression) {
         if ($expression['alias'] == $field) {
             return $return;
         }
     }
     // If a table loads all fields, it can not be added again. It would
     // result in an ambigious 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 $return;
         }
     }
     // If $field contains an characters which are not allowed in a field name
     // it is considered an expression, these can't be handeld automatically
     // either.
     if ($this->connection->escapeField($field) != $field) {
         return $return;
     }
     // This is a case that can be handled automatically, add the field.
     $this->addField(NULL, $field);
     return $return;
 }
Example #2
0
 /**
  * {@inheritdoc}
  */
 public function fields($table_alias, array $fields = array())
 {
     if (!$fields) {
         $table = $this->tables[$table_alias]['table'];
         if (!empty($this->databaseContents[$table])) {
             $fields = array_keys(reset($this->databaseContents[$table]));
         } else {
             throw new \Exception(SafeMarkup::format('All fields on empty table @table is not supported.', array('@table' => $table)));
         }
     }
     return parent::fields($table_alias, $fields);
 }
 /**
  * Tests that fields passed for ordering get escaped properly.
  */
 public function testFieldEscaping()
 {
     $this->query->orderBy('x; DROP table node; --');
     $sql = $this->query->__toString();
     $this->assertStringEndsWith('ORDER BY xDROPtablenode ASC', $sql, 'Order by field is escaped correctly.');
 }
Example #4
0
 /**
  * {@inheritdoc}
  */
 public function execute()
 {
     $this->connection->addSavepoint();
     try {
         $result = parent::execute();
     } catch (\Exception $e) {
         $this->connection->rollbackSavepoint();
         throw $e;
     }
     $this->connection->releaseSavepoint();
     return $result;
 }
Example #5
0
 /**
  * Override for SelectQuery::compile().
  *
  * Detect when this query is prepared for use in a sub-query.
  */
 public function compile(DatabaseConnection $connection, DatabasePlaceholderInterface $queryPlaceholder) {
   $this->inSubQuery = $queryPlaceholder != $this;
   return parent::compile($connection, $queryPlaceholder);
 }