123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- <?php
- namespace Drupal\Core\Database\Query;
- use Drupal\Core\Database\Database;
- use Drupal\Core\Database\Connection;
- /**
- * General class for an abstracted UPDATE operation.
- *
- * @ingroup database
- */
- class Update extends Query implements ConditionInterface {
- use QueryConditionTrait;
- /**
- * The table to update.
- *
- * @var string
- */
- protected $table;
- /**
- * An array of fields that will be updated.
- *
- * @var array
- */
- protected $fields = [];
- /**
- * An array of values to update to.
- *
- * @var array
- */
- protected $arguments = [];
- /**
- * Array of fields to update to an expression in case of a duplicate record.
- *
- * This variable is a nested array in the following format:
- * @code
- * <some field> => array(
- * 'condition' => <condition to execute, as a string>,
- * 'arguments' => <array of arguments for condition, or NULL for none>,
- * );
- * @endcode
- *
- * @var array
- */
- protected $expressionFields = [];
- /**
- * Constructs an Update query object.
- *
- * @param \Drupal\Core\Database\Connection $connection
- * A Connection object.
- * @param string $table
- * Name of the table to associate with this query.
- * @param array $options
- * Array of database options.
- */
- public function __construct(Connection $connection, $table, array $options = []) {
- $options['return'] = Database::RETURN_AFFECTED;
- parent::__construct($connection, $options);
- $this->table = $table;
- $this->condition = new Condition('AND');
- }
- /**
- * Adds a set of field->value pairs to be updated.
- *
- * @param $fields
- * An associative array of fields to write into the database. The array keys
- * are the field names and the values are the values to which to set them.
- *
- * @return \Drupal\Core\Database\Query\Update
- * The called object.
- */
- public function fields(array $fields) {
- $this->fields = $fields;
- return $this;
- }
- /**
- * Specifies fields to be updated as an expression.
- *
- * Expression fields are cases such as counter=counter+1. This method takes
- * precedence over fields().
- *
- * @param $field
- * The field to set.
- * @param $expression
- * The field will be set to the value of this expression. This parameter
- * may include named placeholders.
- * @param $arguments
- * If specified, this is an array of key/value pairs for named placeholders
- * corresponding to the expression.
- *
- * @return \Drupal\Core\Database\Query\Update
- * The called object.
- */
- public function expression($field, $expression, array $arguments = NULL) {
- $this->expressionFields[$field] = [
- 'expression' => $expression,
- 'arguments' => $arguments,
- ];
- return $this;
- }
- /**
- * Executes the UPDATE query.
- *
- * @return
- * The number of rows matched by the update query. This includes rows that
- * actually didn't have to be updated because the values didn't change.
- */
- public function execute() {
- // Expressions take priority over literal fields, so we process those first
- // and remove any literal fields that conflict.
- $fields = $this->fields;
- $update_values = [];
- foreach ($this->expressionFields as $field => $data) {
- if (!empty($data['arguments'])) {
- $update_values += $data['arguments'];
- }
- if ($data['expression'] instanceof SelectInterface) {
- $data['expression']->compile($this->connection, $this);
- $update_values += $data['expression']->arguments();
- }
- unset($fields[$field]);
- }
- // Because we filter $fields the same way here and in __toString(), the
- // placeholders will all match up properly.
- $max_placeholder = 0;
- foreach ($fields as $value) {
- $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value;
- }
- if (count($this->condition)) {
- $this->condition->compile($this->connection, $this);
- $update_values = array_merge($update_values, $this->condition->arguments());
- }
- return $this->connection->query((string) $this, $update_values, $this->queryOptions);
- }
- /**
- * 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 = [];
- foreach ($this->expressionFields as $field => $data) {
- if ($data['expression'] instanceof SelectInterface) {
- // Compile and cast expression subquery to a string.
- $data['expression']->compile($this->connection, $this);
- $data['expression'] = ' (' . $data['expression'] . ')';
- }
- $update_fields[] = $this->connection->escapeField($field) . '=' . $data['expression'];
- unset($fields[$field]);
- }
- $max_placeholder = 0;
- foreach ($fields as $field => $value) {
- $update_fields[] = $this->connection->escapeField($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;
- }
- }
|