/** * Implements PHP magic __toString method to convert the query to a string. * * @return string * The prepared statement. */ public function __toString() { // Create a sanitized comment string to prepend to the query. $comments = $this->connection->makeComment($this->comments); // Expressions take priority over literal fields, so we process those first // and remove any literal fields that conflict. $fields = $this->fields; $update_fields = array(); foreach ($this->expressionFields as $field => $data) { $update_fields[] = $field . '=' . $data['expression']; unset($fields[$field]); } $max_placeholder = 0; foreach ($fields as $field => $value) { $update_fields[] = $field . '=:db_update_placeholder_' . $max_placeholder++; } $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields); if (count($this->condition)) { $this->condition->compile($this->connection, $this); // There is an implicit string cast on $this->condition. $query .= "\nWHERE " . $this->condition; } return $query; }
public function __toString() { // Create a comments string to prepend to the query. $comments = !empty($this->comments) ? '/* ' . implode('; ', $this->comments) . ' */ ' : ''; // SELECT $query = $comments . 'SELECT '; if ($this->distinct) { $query .= 'DISTINCT '; } // FIELDS and EXPRESSIONS $fields = array(); foreach ($this->tables as $alias => $table) { if (!empty($table['all_fields'])) { $fields[] = $this->connection->escapeTable($alias) . '.*'; } } foreach ($this->fields as $alias => $field) { // Always use the AS keyword for field aliases, as some // databases require it (e.g., PostgreSQL). $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeAlias($field['alias']); } foreach ($this->expressions as $alias => $expression) { $fields[] = $expression['expression'] . ' AS ' . $this->connection->escapeAlias($expression['alias']); } $query .= implode(', ', $fields); // FROM - We presume all queries have a FROM, as any query that doesn't won't need the query builder anyway. $query .= "\nFROM "; foreach ($this->tables as $alias => $table) { $query .= "\n"; if (isset($table['join type'])) { $query .= $table['join type'] . ' JOIN '; } // If the table is a subquery, compile it and integrate it into this query. if ($table['table'] instanceof SelectQueryInterface) { // Run preparation steps on this sub-query before converting to string. $subquery = $table['table']; $subquery->preExecute(); $table_string = '(' . (string) $subquery . ')'; } else { $table_string = '{' . $this->connection->escapeTable($table['table']) . '}'; } // Don't use the AS keyword for table aliases, as some // databases don't support it (e.g., Oracle). $query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']); if (!empty($table['condition'])) { $query .= ' ON ' . $table['condition']; } } // WHERE if (count($this->where)) { // The following line will not generate placeholders correctly if there // is a subquery. Fortunately, it is also called from getArguments() first // so it's not a problem in practice... unless you try to call __toString() // before calling getArguments(). That is a problem that we will have to // fix in Drupal 8, because it requires more refactoring than we are // able to do in Drupal 7. // @todo Move away from __toString() For SelectQuery compilation at least. $this->where->compile($this->connection, $this); // There is an implicit string cast on $this->condition. $query .= "\nWHERE " . $this->where; } // GROUP BY if ($this->group) { $query .= "\nGROUP BY " . implode(', ', $this->group); } // HAVING if (count($this->having)) { $this->having->compile($this->connection, $this); // There is an implicit string cast on $this->having. $query .= "\nHAVING " . $this->having; } // ORDER BY if ($this->order) { $query .= "\nORDER BY "; $fields = array(); foreach ($this->order as $field => $direction) { $fields[] = $field . ' ' . $direction; } $query .= implode(', ', $fields); } // RANGE // There is no universal SQL standard for handling range or limit clauses. // Fortunately, all core-supported databases use the same range syntax. // Databases that need a different syntax can override this method and // do whatever alternate logic they need to. if (!empty($this->range)) { $query .= "\nLIMIT " . (int) $this->range['length'] . " OFFSET " . (int) $this->range['start']; } // UNION is a little odd, as the select queries to combine are passed into // this query, but syntactically they all end up on the same level. if ($this->union) { foreach ($this->union as $union) { $query .= ' ' . $union['type'] . ' ' . (string) $union['query']; } } if ($this->forUpdate) { $query .= ' FOR UPDATE'; } return $query; }