cms/drupal/includes/database/query.inc
changeset 541 e756a8c72c3d
equal deleted inserted replaced
540:07239de796bb 541:e756a8c72c3d
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * @addtogroup database
       
     5  * @{
       
     6  */
       
     7 
       
     8 /**
       
     9  * @file
       
    10  * Non-specific Database query code. Used by all engines.
       
    11  */
       
    12 
       
    13 /**
       
    14  * Interface for a conditional clause in a query.
       
    15  */
       
    16 interface QueryConditionInterface {
       
    17 
       
    18   /**
       
    19    * Helper function: builds the most common conditional clauses.
       
    20    *
       
    21    * This method can take a variable number of parameters. If called with two
       
    22    * parameters, they are taken as $field and $value with $operator having a
       
    23    * value of IN if $value is an array and = otherwise.
       
    24    *
       
    25    * Do not use this method to test for NULL values. Instead, use
       
    26    * QueryConditionInterface::isNull() or QueryConditionInterface::isNotNull().
       
    27    *
       
    28    * @param $field
       
    29    *   The name of the field to check. If you would like to add a more complex
       
    30    *   condition involving operators or functions, use where().
       
    31    * @param $value
       
    32    *   The value to test the field against. In most cases, this is a scalar.
       
    33    *   For more complex options, it is an array. The meaning of each element in
       
    34    *   the array is dependent on the $operator.
       
    35    * @param $operator
       
    36    *   The comparison operator, such as =, <, or >=. It also accepts more
       
    37    *   complex options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is
       
    38    *   an array, and = otherwise.
       
    39    *
       
    40    * @return QueryConditionInterface
       
    41    *   The called object.
       
    42    *
       
    43    * @see QueryConditionInterface::isNull()
       
    44    * @see QueryConditionInterface::isNotNull()
       
    45    */
       
    46   public function condition($field, $value = NULL, $operator = NULL);
       
    47 
       
    48   /**
       
    49    * Adds an arbitrary WHERE clause to the query.
       
    50    *
       
    51    * @param $snippet
       
    52    *   A portion of a WHERE clause as a prepared statement. It must use named
       
    53    *   placeholders, not ? placeholders.
       
    54    * @param $args
       
    55    *   An associative array of arguments.
       
    56    *
       
    57    * @return QueryConditionInterface
       
    58    *   The called object.
       
    59    */
       
    60   public function where($snippet, $args = array());
       
    61 
       
    62   /**
       
    63    * Sets a condition that the specified field be NULL.
       
    64    *
       
    65    * @param $field
       
    66    *   The name of the field to check.
       
    67    *
       
    68    * @return QueryConditionInterface
       
    69    *   The called object.
       
    70    */
       
    71   public function isNull($field);
       
    72 
       
    73   /**
       
    74    * Sets a condition that the specified field be NOT NULL.
       
    75    *
       
    76    * @param $field
       
    77    *   The name of the field to check.
       
    78    *
       
    79    * @return QueryConditionInterface
       
    80    *   The called object.
       
    81    */
       
    82   public function isNotNull($field);
       
    83 
       
    84   /**
       
    85    * Sets a condition that the specified subquery returns values.
       
    86    *
       
    87    * @param SelectQueryInterface $select
       
    88    *   The subquery that must contain results.
       
    89    *
       
    90    * @return QueryConditionInterface
       
    91    *   The called object.
       
    92    */
       
    93   public function exists(SelectQueryInterface $select);
       
    94 
       
    95   /**
       
    96    * Sets a condition that the specified subquery returns no values.
       
    97    *
       
    98    * @param SelectQueryInterface $select
       
    99    *   The subquery that must not contain results.
       
   100    *
       
   101    * @return QueryConditionInterface
       
   102    *   The called object.
       
   103    */
       
   104   public function notExists(SelectQueryInterface $select);
       
   105 
       
   106   /**
       
   107    * Gets a complete list of all conditions in this conditional clause.
       
   108    *
       
   109    * This method returns by reference. That allows alter hooks to access the
       
   110    * data structure directly and manipulate it before it gets compiled.
       
   111    *
       
   112    * The data structure that is returned is an indexed array of entries, where
       
   113    * each entry looks like the following:
       
   114    * @code
       
   115    * array(
       
   116    *   'field' => $field,
       
   117    *   'value' => $value,
       
   118    *   'operator' => $operator,
       
   119    * );
       
   120    * @endcode
       
   121    *
       
   122    * In the special case that $operator is NULL, the $field is taken as a raw
       
   123    * SQL snippet (possibly containing a function) and $value is an associative
       
   124    * array of placeholders for the snippet.
       
   125    *
       
   126    * There will also be a single array entry of #conjunction, which is the
       
   127    * conjunction that will be applied to the array, such as AND.
       
   128    */
       
   129   public function &conditions();
       
   130 
       
   131   /**
       
   132    * Gets a complete list of all values to insert into the prepared statement.
       
   133    *
       
   134    * @return
       
   135    *   An associative array of placeholders and values.
       
   136    */
       
   137   public function arguments();
       
   138 
       
   139   /**
       
   140    * Compiles the saved conditions for later retrieval.
       
   141    *
       
   142    * This method does not return anything, but simply prepares data to be
       
   143    * retrieved via __toString() and arguments().
       
   144    *
       
   145    * @param $connection
       
   146    *   The database connection for which to compile the conditionals.
       
   147    * @param $queryPlaceholder
       
   148    *   The query this condition belongs to. If not given, the current query is
       
   149    *   used.
       
   150    */
       
   151   public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder);
       
   152 
       
   153   /**
       
   154    * Check whether a condition has been previously compiled.
       
   155    *
       
   156    * @return
       
   157    *   TRUE if the condition has been previously compiled.
       
   158    */
       
   159   public function compiled();
       
   160 }
       
   161 
       
   162 
       
   163 /**
       
   164  * Interface for a query that can be manipulated via an alter hook.
       
   165  */
       
   166 interface QueryAlterableInterface {
       
   167 
       
   168   /**
       
   169    * Adds a tag to a query.
       
   170    *
       
   171    * Tags are strings that identify a query. A query may have any number of
       
   172    * tags. Tags are used to mark a query so that alter hooks may decide if they
       
   173    * wish to take action. Tags should be all lower-case and contain only
       
   174    * letters, numbers, and underscore, and start with a letter. That is, they
       
   175    * should follow the same rules as PHP identifiers in general.
       
   176    *
       
   177    * @param $tag
       
   178    *   The tag to add.
       
   179    *
       
   180    * @return QueryAlterableInterface
       
   181    *   The called object.
       
   182    */
       
   183   public function addTag($tag);
       
   184 
       
   185   /**
       
   186    * Determines if a given query has a given tag.
       
   187    *
       
   188    * @param $tag
       
   189    *   The tag to check.
       
   190    *
       
   191    * @return
       
   192    *   TRUE if this query has been marked with this tag, FALSE otherwise.
       
   193    */
       
   194   public function hasTag($tag);
       
   195 
       
   196   /**
       
   197    * Determines if a given query has all specified tags.
       
   198    *
       
   199    * @param $tags
       
   200    *   A variable number of arguments, one for each tag to check.
       
   201    *
       
   202    * @return
       
   203    *   TRUE if this query has been marked with all specified tags, FALSE
       
   204    *   otherwise.
       
   205    */
       
   206   public function hasAllTags();
       
   207 
       
   208   /**
       
   209    * Determines if a given query has any specified tag.
       
   210    *
       
   211    * @param $tags
       
   212    *   A variable number of arguments, one for each tag to check.
       
   213    *
       
   214    * @return
       
   215    *   TRUE if this query has been marked with at least one of the specified
       
   216    *   tags, FALSE otherwise.
       
   217    */
       
   218   public function hasAnyTag();
       
   219 
       
   220   /**
       
   221    * Adds additional metadata to the query.
       
   222    *
       
   223    * Often, a query may need to provide additional contextual data to alter
       
   224    * hooks. Alter hooks may then use that information to decide if and how
       
   225    * to take action.
       
   226    *
       
   227    * @param $key
       
   228    *   The unique identifier for this piece of metadata. Must be a string that
       
   229    *   follows the same rules as any other PHP identifier.
       
   230    * @param $object
       
   231    *   The additional data to add to the query. May be any valid PHP variable.
       
   232    *
       
   233    * @return QueryAlterableInterface
       
   234    *   The called object.
       
   235    */
       
   236   public function addMetaData($key, $object);
       
   237 
       
   238   /**
       
   239    * Retrieves a given piece of metadata.
       
   240    *
       
   241    * @param $key
       
   242    *   The unique identifier for the piece of metadata to retrieve.
       
   243    *
       
   244    * @return
       
   245    *   The previously attached metadata object, or NULL if one doesn't exist.
       
   246    */
       
   247   public function getMetaData($key);
       
   248 }
       
   249 
       
   250 /**
       
   251  * Interface for a query that accepts placeholders.
       
   252  */
       
   253 interface QueryPlaceholderInterface {
       
   254 
       
   255   /**
       
   256    * Returns a unique identifier for this object.
       
   257    */
       
   258   public function uniqueIdentifier();
       
   259 
       
   260   /**
       
   261    * Returns the next placeholder ID for the query.
       
   262    *
       
   263    * @return
       
   264    *   The next available placeholder ID as an integer.
       
   265    */
       
   266   public function nextPlaceholder();
       
   267 }
       
   268 
       
   269 /**
       
   270  * Base class for query builders.
       
   271  *
       
   272  * Note that query builders use PHP's magic __toString() method to compile the
       
   273  * query object into a prepared statement.
       
   274  */
       
   275 abstract class Query implements QueryPlaceholderInterface {
       
   276 
       
   277   /**
       
   278    * The connection object on which to run this query.
       
   279    *
       
   280    * @var DatabaseConnection
       
   281    */
       
   282   protected $connection;
       
   283 
       
   284   /**
       
   285    * The target of the connection object.
       
   286    *
       
   287    * @var string
       
   288    */
       
   289   protected $connectionTarget;
       
   290 
       
   291   /**
       
   292    * The key of the connection object.
       
   293    *
       
   294    * @var string
       
   295    */
       
   296   protected $connectionKey;
       
   297 
       
   298   /**
       
   299    * The query options to pass on to the connection object.
       
   300    *
       
   301    * @var array
       
   302    */
       
   303   protected $queryOptions;
       
   304 
       
   305   /**
       
   306    * A unique identifier for this query object.
       
   307    */
       
   308   protected $uniqueIdentifier;
       
   309 
       
   310   /**
       
   311    * The placeholder counter.
       
   312    */
       
   313   protected $nextPlaceholder = 0;
       
   314 
       
   315   /**
       
   316    * An array of comments that can be prepended to a query.
       
   317    *
       
   318    * @var array
       
   319    */
       
   320   protected $comments = array();
       
   321 
       
   322   /**
       
   323    * Constructs a Query object.
       
   324    *
       
   325    * @param DatabaseConnection $connection
       
   326    *   Database connection object.
       
   327    * @param array $options
       
   328    *   Array of query options.
       
   329    */
       
   330   public function __construct(DatabaseConnection $connection, $options) {
       
   331     $this->uniqueIdentifier = uniqid('', TRUE);
       
   332 
       
   333     $this->connection = $connection;
       
   334     $this->connectionKey = $this->connection->getKey();
       
   335     $this->connectionTarget = $this->connection->getTarget();
       
   336 
       
   337     $this->queryOptions = $options;
       
   338   }
       
   339 
       
   340   /**
       
   341    * Implements the magic __sleep function to disconnect from the database.
       
   342    */
       
   343   public function __sleep() {
       
   344     $keys = get_object_vars($this);
       
   345     unset($keys['connection']);
       
   346     return array_keys($keys);
       
   347   }
       
   348 
       
   349   /**
       
   350    * Implements the magic __wakeup function to reconnect to the database.
       
   351    */
       
   352   public function __wakeup() {
       
   353     $this->connection = Database::getConnection($this->connectionTarget, $this->connectionKey);
       
   354   }
       
   355 
       
   356   /**
       
   357    * Implements the magic __clone function.
       
   358    */
       
   359   public function __clone() {
       
   360     $this->uniqueIdentifier = uniqid('', TRUE);
       
   361   }
       
   362 
       
   363   /**
       
   364    * Runs the query against the database.
       
   365    */
       
   366   abstract protected function execute();
       
   367 
       
   368   /**
       
   369    * Implements PHP magic __toString method to convert the query to a string.
       
   370    *
       
   371    * The toString operation is how we compile a query object to a prepared
       
   372    * statement.
       
   373    *
       
   374    * @return
       
   375    *   A prepared statement query string for this object.
       
   376    */
       
   377   abstract public function __toString();
       
   378 
       
   379   /**
       
   380    * Returns a unique identifier for this object.
       
   381    */
       
   382   public function uniqueIdentifier() {
       
   383     return $this->uniqueIdentifier;
       
   384   }
       
   385 
       
   386   /**
       
   387    * Gets the next placeholder value for this query object.
       
   388    *
       
   389    * @return int
       
   390    *   Next placeholder value.
       
   391    */
       
   392   public function nextPlaceholder() {
       
   393     return $this->nextPlaceholder++;
       
   394   }
       
   395 
       
   396   /**
       
   397    * Adds a comment to the query.
       
   398    *
       
   399    * By adding a comment to a query, you can more easily find it in your
       
   400    * query log or the list of active queries on an SQL server. This allows
       
   401    * for easier debugging and allows you to more easily find where a query
       
   402    * with a performance problem is being generated.
       
   403    *
       
   404    * The comment string will be sanitized to remove * / and other characters
       
   405    * that may terminate the string early so as to avoid SQL injection attacks.
       
   406    *
       
   407    * @param $comment
       
   408    *   The comment string to be inserted into the query.
       
   409    *
       
   410    * @return Query
       
   411    *   The called object.
       
   412    */
       
   413   public function comment($comment) {
       
   414     $this->comments[] = $comment;
       
   415     return $this;
       
   416   }
       
   417 
       
   418   /**
       
   419    * Returns a reference to the comments array for the query.
       
   420    *
       
   421    * Because this method returns by reference, alter hooks may edit the comments
       
   422    * array directly to make their changes. If just adding comments, however, the
       
   423    * use of comment() is preferred.
       
   424    *
       
   425    * Note that this method must be called by reference as well:
       
   426    * @code
       
   427    * $comments =& $query->getComments();
       
   428    * @endcode
       
   429    *
       
   430    * @return
       
   431    *   A reference to the comments array structure.
       
   432    */
       
   433   public function &getComments() {
       
   434     return $this->comments;
       
   435   }
       
   436 }
       
   437 
       
   438 /**
       
   439  * General class for an abstracted INSERT query.
       
   440  */
       
   441 class InsertQuery extends Query {
       
   442 
       
   443   /**
       
   444    * The table on which to insert.
       
   445    *
       
   446    * @var string
       
   447    */
       
   448   protected $table;
       
   449 
       
   450   /**
       
   451    * An array of fields on which to insert.
       
   452    *
       
   453    * @var array
       
   454    */
       
   455   protected $insertFields = array();
       
   456 
       
   457   /**
       
   458    * An array of fields that should be set to their database-defined defaults.
       
   459    *
       
   460    * @var array
       
   461    */
       
   462   protected $defaultFields = array();
       
   463 
       
   464   /**
       
   465    * A nested array of values to insert.
       
   466    *
       
   467    * $insertValues is an array of arrays. Each sub-array is either an
       
   468    * associative array whose keys are field names and whose values are field
       
   469    * values to insert, or a non-associative array of values in the same order
       
   470    * as $insertFields.
       
   471    *
       
   472    * Whether multiple insert sets will be run in a single query or multiple
       
   473    * queries is left to individual drivers to implement in whatever manner is
       
   474    * most appropriate. The order of values in each sub-array must match the
       
   475    * order of fields in $insertFields.
       
   476    *
       
   477    * @var array
       
   478    */
       
   479   protected $insertValues = array();
       
   480 
       
   481   /**
       
   482    * A SelectQuery object to fetch the rows that should be inserted.
       
   483    *
       
   484    * @var SelectQueryInterface
       
   485    */
       
   486   protected $fromQuery;
       
   487 
       
   488   /**
       
   489    * Constructs an InsertQuery object.
       
   490    *
       
   491    * @param DatabaseConnection $connection
       
   492    *   A DatabaseConnection object.
       
   493    * @param string $table
       
   494    *   Name of the table to associate with this query.
       
   495    * @param array $options
       
   496    *   Array of database options.
       
   497    */
       
   498   public function __construct($connection, $table, array $options = array()) {
       
   499     if (!isset($options['return'])) {
       
   500       $options['return'] = Database::RETURN_INSERT_ID;
       
   501     }
       
   502     parent::__construct($connection, $options);
       
   503     $this->table = $table;
       
   504   }
       
   505 
       
   506   /**
       
   507    * Adds a set of field->value pairs to be inserted.
       
   508    *
       
   509    * This method may only be called once. Calling it a second time will be
       
   510    * ignored. To queue up multiple sets of values to be inserted at once,
       
   511    * use the values() method.
       
   512    *
       
   513    * @param $fields
       
   514    *   An array of fields on which to insert. This array may be indexed or
       
   515    *   associative. If indexed, the array is taken to be the list of fields.
       
   516    *   If associative, the keys of the array are taken to be the fields and
       
   517    *   the values are taken to be corresponding values to insert. If a
       
   518    *   $values argument is provided, $fields must be indexed.
       
   519    * @param $values
       
   520    *   An array of fields to insert into the database. The values must be
       
   521    *   specified in the same order as the $fields array.
       
   522    *
       
   523    * @return InsertQuery
       
   524    *   The called object.
       
   525    */
       
   526   public function fields(array $fields, array $values = array()) {
       
   527     if (empty($this->insertFields)) {
       
   528       if (empty($values)) {
       
   529         if (!is_numeric(key($fields))) {
       
   530           $values = array_values($fields);
       
   531           $fields = array_keys($fields);
       
   532         }
       
   533       }
       
   534       $this->insertFields = $fields;
       
   535       if (!empty($values)) {
       
   536         $this->insertValues[] = $values;
       
   537       }
       
   538     }
       
   539 
       
   540     return $this;
       
   541   }
       
   542 
       
   543   /**
       
   544    * Adds another set of values to the query to be inserted.
       
   545    *
       
   546    * If $values is a numeric-keyed array, it will be assumed to be in the same
       
   547    * order as the original fields() call. If it is associative, it may be
       
   548    * in any order as long as the keys of the array match the names of the
       
   549    * fields.
       
   550    *
       
   551    * @param $values
       
   552    *   An array of values to add to the query.
       
   553    *
       
   554    * @return InsertQuery
       
   555    *   The called object.
       
   556    */
       
   557   public function values(array $values) {
       
   558     if (is_numeric(key($values))) {
       
   559       $this->insertValues[] = $values;
       
   560     }
       
   561     else {
       
   562       // Reorder the submitted values to match the fields array.
       
   563       foreach ($this->insertFields as $key) {
       
   564         $insert_values[$key] = $values[$key];
       
   565       }
       
   566       // For consistency, the values array is always numerically indexed.
       
   567       $this->insertValues[] = array_values($insert_values);
       
   568     }
       
   569     return $this;
       
   570   }
       
   571 
       
   572   /**
       
   573    * Specifies fields for which the database defaults should be used.
       
   574    *
       
   575    * If you want to force a given field to use the database-defined default,
       
   576    * not NULL or undefined, use this method to instruct the database to use
       
   577    * default values explicitly. In most cases this will not be necessary
       
   578    * unless you are inserting a row that is all default values, as you cannot
       
   579    * specify no values in an INSERT query.
       
   580    *
       
   581    * Specifying a field both in fields() and in useDefaults() is an error
       
   582    * and will not execute.
       
   583    *
       
   584    * @param $fields
       
   585    *   An array of values for which to use the default values
       
   586    *   specified in the table definition.
       
   587    *
       
   588    * @return InsertQuery
       
   589    *   The called object.
       
   590    */
       
   591   public function useDefaults(array $fields) {
       
   592     $this->defaultFields = $fields;
       
   593     return $this;
       
   594   }
       
   595 
       
   596   /**
       
   597    * Sets the fromQuery on this InsertQuery object.
       
   598    *
       
   599    * @param SelectQueryInterface $query
       
   600    *   The query to fetch the rows that should be inserted.
       
   601    *
       
   602    * @return InsertQuery
       
   603    *   The called object.
       
   604    */
       
   605   public function from(SelectQueryInterface $query) {
       
   606     $this->fromQuery = $query;
       
   607     return $this;
       
   608   }
       
   609 
       
   610   /**
       
   611    * Executes the insert query.
       
   612    *
       
   613    * @return
       
   614    *   The last insert ID of the query, if one exists. If the query
       
   615    *   was given multiple sets of values to insert, the return value is
       
   616    *   undefined. If no fields are specified, this method will do nothing and
       
   617    *   return NULL. That makes it safe to use in multi-insert loops.
       
   618    */
       
   619   public function execute() {
       
   620     // If validation fails, simply return NULL. Note that validation routines
       
   621     // in preExecute() may throw exceptions instead.
       
   622     if (!$this->preExecute()) {
       
   623       return NULL;
       
   624     }
       
   625 
       
   626     // If we're selecting from a SelectQuery, finish building the query and
       
   627     // pass it back, as any remaining options are irrelevant.
       
   628     if (!empty($this->fromQuery)) {
       
   629       $sql = (string) $this;
       
   630       // The SelectQuery may contain arguments, load and pass them through.
       
   631       return $this->connection->query($sql, $this->fromQuery->getArguments(), $this->queryOptions);
       
   632     }
       
   633 
       
   634     $last_insert_id = 0;
       
   635 
       
   636     // Each insert happens in its own query in the degenerate case. However,
       
   637     // we wrap it in a transaction so that it is atomic where possible. On many
       
   638     // databases, such as SQLite, this is also a notable performance boost.
       
   639     $transaction = $this->connection->startTransaction();
       
   640 
       
   641     try {
       
   642       $sql = (string) $this;
       
   643       foreach ($this->insertValues as $insert_values) {
       
   644         $last_insert_id = $this->connection->query($sql, $insert_values, $this->queryOptions);
       
   645       }
       
   646     }
       
   647     catch (Exception $e) {
       
   648       // One of the INSERTs failed, rollback the whole batch.
       
   649       $transaction->rollback();
       
   650       // Rethrow the exception for the calling code.
       
   651       throw $e;
       
   652     }
       
   653 
       
   654     // Re-initialize the values array so that we can re-use this query.
       
   655     $this->insertValues = array();
       
   656 
       
   657     // Transaction commits here where $transaction looses scope.
       
   658 
       
   659     return $last_insert_id;
       
   660   }
       
   661 
       
   662   /**
       
   663    * Implements PHP magic __toString method to convert the query to a string.
       
   664    *
       
   665    * @return string
       
   666    *   The prepared statement.
       
   667    */
       
   668   public function __toString() {
       
   669     // Create a sanitized comment string to prepend to the query.
       
   670     $comments = $this->connection->makeComment($this->comments);
       
   671 
       
   672     // Default fields are always placed first for consistency.
       
   673     $insert_fields = array_merge($this->defaultFields, $this->insertFields);
       
   674 
       
   675     if (!empty($this->fromQuery)) {
       
   676       return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
       
   677     }
       
   678 
       
   679     // For simplicity, we will use the $placeholders array to inject
       
   680     // default keywords even though they are not, strictly speaking,
       
   681     // placeholders for prepared statements.
       
   682     $placeholders = array();
       
   683     $placeholders = array_pad($placeholders, count($this->defaultFields), 'default');
       
   684     $placeholders = array_pad($placeholders, count($this->insertFields), '?');
       
   685 
       
   686     return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES (' . implode(', ', $placeholders) . ')';
       
   687   }
       
   688 
       
   689   /**
       
   690    * Preprocesses and validates the query.
       
   691    *
       
   692    * @return
       
   693    *   TRUE if the validation was successful, FALSE if not.
       
   694    *
       
   695    * @throws FieldsOverlapException
       
   696    * @throws NoFieldsException
       
   697    */
       
   698   public function preExecute() {
       
   699     // Confirm that the user did not try to specify an identical
       
   700     // field and default field.
       
   701     if (array_intersect($this->insertFields, $this->defaultFields)) {
       
   702       throw new FieldsOverlapException('You may not specify the same field to have a value and a schema-default value.');
       
   703     }
       
   704 
       
   705     if (!empty($this->fromQuery)) {
       
   706       // We have to assume that the used aliases match the insert fields.
       
   707       // Regular fields are added to the query before expressions, maintain the
       
   708       // same order for the insert fields.
       
   709       // This behavior can be overridden by calling fields() manually as only the
       
   710       // first call to fields() does have an effect.
       
   711       $this->fields(array_merge(array_keys($this->fromQuery->getFields()), array_keys($this->fromQuery->getExpressions())));
       
   712     }
       
   713     else {
       
   714       // Don't execute query without fields.
       
   715       if (count($this->insertFields) + count($this->defaultFields) == 0) {
       
   716         throw new NoFieldsException('There are no fields available to insert with.');
       
   717       }
       
   718     }
       
   719 
       
   720     // If no values have been added, silently ignore this query. This can happen
       
   721     // if values are added conditionally, so we don't want to throw an
       
   722     // exception.
       
   723     if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
       
   724       return FALSE;
       
   725     }
       
   726     return TRUE;
       
   727   }
       
   728 }
       
   729 
       
   730 /**
       
   731  * General class for an abstracted DELETE operation.
       
   732  */
       
   733 class DeleteQuery extends Query implements QueryConditionInterface {
       
   734 
       
   735   /**
       
   736    * The table from which to delete.
       
   737    *
       
   738    * @var string
       
   739    */
       
   740   protected $table;
       
   741 
       
   742   /**
       
   743    * The condition object for this query.
       
   744    *
       
   745    * Condition handling is handled via composition.
       
   746    *
       
   747    * @var DatabaseCondition
       
   748    */
       
   749   protected $condition;
       
   750 
       
   751   /**
       
   752    * Constructs a DeleteQuery object.
       
   753    *
       
   754    * @param DatabaseConnection $connection
       
   755    *   A DatabaseConnection object.
       
   756    * @param string $table
       
   757    *   Name of the table to associate with this query.
       
   758    * @param array $options
       
   759    *   Array of database options.
       
   760    */
       
   761   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
       
   762     $options['return'] = Database::RETURN_AFFECTED;
       
   763     parent::__construct($connection, $options);
       
   764     $this->table = $table;
       
   765 
       
   766     $this->condition = new DatabaseCondition('AND');
       
   767   }
       
   768 
       
   769   /**
       
   770    * Implements QueryConditionInterface::condition().
       
   771    */
       
   772   public function condition($field, $value = NULL, $operator = NULL) {
       
   773     $this->condition->condition($field, $value, $operator);
       
   774     return $this;
       
   775   }
       
   776 
       
   777   /**
       
   778    * Implements QueryConditionInterface::isNull().
       
   779    */
       
   780   public function isNull($field) {
       
   781     $this->condition->isNull($field);
       
   782     return $this;
       
   783   }
       
   784 
       
   785   /**
       
   786    * Implements QueryConditionInterface::isNotNull().
       
   787    */
       
   788   public function isNotNull($field) {
       
   789     $this->condition->isNotNull($field);
       
   790     return $this;
       
   791   }
       
   792 
       
   793   /**
       
   794    * Implements QueryConditionInterface::exists().
       
   795    */
       
   796   public function exists(SelectQueryInterface $select) {
       
   797     $this->condition->exists($select);
       
   798     return $this;
       
   799   }
       
   800 
       
   801   /**
       
   802    * Implements QueryConditionInterface::notExists().
       
   803    */
       
   804   public function notExists(SelectQueryInterface $select) {
       
   805     $this->condition->notExists($select);
       
   806     return $this;
       
   807   }
       
   808 
       
   809   /**
       
   810    * Implements QueryConditionInterface::conditions().
       
   811    */
       
   812   public function &conditions() {
       
   813     return $this->condition->conditions();
       
   814   }
       
   815 
       
   816   /**
       
   817    * Implements QueryConditionInterface::arguments().
       
   818    */
       
   819   public function arguments() {
       
   820     return $this->condition->arguments();
       
   821   }
       
   822 
       
   823   /**
       
   824    * Implements QueryConditionInterface::where().
       
   825    */
       
   826   public function where($snippet, $args = array()) {
       
   827     $this->condition->where($snippet, $args);
       
   828     return $this;
       
   829   }
       
   830 
       
   831   /**
       
   832    * Implements QueryConditionInterface::compile().
       
   833    */
       
   834   public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
       
   835     return $this->condition->compile($connection, $queryPlaceholder);
       
   836   }
       
   837 
       
   838   /**
       
   839    * Implements QueryConditionInterface::compiled().
       
   840    */
       
   841   public function compiled() {
       
   842     return $this->condition->compiled();
       
   843   }
       
   844 
       
   845   /**
       
   846    * Executes the DELETE query.
       
   847    *
       
   848    * @return int
       
   849    *   The number of rows affected by the delete query.
       
   850    */
       
   851   public function execute() {
       
   852     $values = array();
       
   853     if (count($this->condition)) {
       
   854       $this->condition->compile($this->connection, $this);
       
   855       $values = $this->condition->arguments();
       
   856     }
       
   857 
       
   858     return $this->connection->query((string) $this, $values, $this->queryOptions);
       
   859   }
       
   860 
       
   861   /**
       
   862    * Implements PHP magic __toString method to convert the query to a string.
       
   863    *
       
   864    * @return string
       
   865    *   The prepared statement.
       
   866    */
       
   867   public function __toString() {
       
   868     // Create a sanitized comment string to prepend to the query.
       
   869     $comments = $this->connection->makeComment($this->comments);
       
   870 
       
   871     $query = $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} ';
       
   872 
       
   873     if (count($this->condition)) {
       
   874 
       
   875       $this->condition->compile($this->connection, $this);
       
   876       $query .= "\nWHERE " . $this->condition;
       
   877     }
       
   878 
       
   879     return $query;
       
   880   }
       
   881 }
       
   882 
       
   883 
       
   884 /**
       
   885  * General class for an abstracted TRUNCATE operation.
       
   886  */
       
   887 class TruncateQuery extends Query {
       
   888 
       
   889   /**
       
   890    * The table to truncate.
       
   891    *
       
   892    * @var string
       
   893    */
       
   894   protected $table;
       
   895 
       
   896   /**
       
   897    * Constructs a TruncateQuery object.
       
   898    *
       
   899    * @param DatabaseConnection $connection
       
   900    *   A DatabaseConnection object.
       
   901    * @param string $table
       
   902    *   Name of the table to associate with this query.
       
   903    * @param array $options
       
   904    *   Array of database options.
       
   905    */
       
   906   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
       
   907     $options['return'] = Database::RETURN_AFFECTED;
       
   908     parent::__construct($connection, $options);
       
   909     $this->table = $table;
       
   910   }
       
   911 
       
   912   /**
       
   913    * Implements QueryConditionInterface::compile().
       
   914    */
       
   915   public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
       
   916     return $this->condition->compile($connection, $queryPlaceholder);
       
   917   }
       
   918 
       
   919   /**
       
   920    * Implements QueryConditionInterface::compiled().
       
   921    */
       
   922   public function compiled() {
       
   923     return $this->condition->compiled();
       
   924   }
       
   925 
       
   926   /**
       
   927    * Executes the TRUNCATE query.
       
   928    *
       
   929    * @return
       
   930    *   Return value is dependent on the database type.
       
   931    */
       
   932   public function execute() {
       
   933     return $this->connection->query((string) $this, array(), $this->queryOptions);
       
   934   }
       
   935 
       
   936   /**
       
   937    * Implements PHP magic __toString method to convert the query to a string.
       
   938    *
       
   939    * @return string
       
   940    *   The prepared statement.
       
   941    */
       
   942   public function __toString() {
       
   943     // Create a sanitized comment string to prepend to the query.
       
   944     $comments = $this->connection->makeComment($this->comments);
       
   945 
       
   946     // In most cases, TRUNCATE is not a transaction safe statement as it is a
       
   947     // DDL statement which results in an implicit COMMIT. When we are in a
       
   948     // transaction, fallback to the slower, but transactional, DELETE.
       
   949     // PostgreSQL also locks the entire table for a TRUNCATE strongly reducing
       
   950     // the concurrency with other transactions.
       
   951     if ($this->connection->inTransaction()) {
       
   952       return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
       
   953     }
       
   954     else {
       
   955       return $comments . 'TRUNCATE {' . $this->connection->escapeTable($this->table) . '} ';
       
   956     }
       
   957   }
       
   958 }
       
   959 
       
   960 /**
       
   961  * General class for an abstracted UPDATE operation.
       
   962  */
       
   963 class UpdateQuery extends Query implements QueryConditionInterface {
       
   964 
       
   965   /**
       
   966    * The table to update.
       
   967    *
       
   968    * @var string
       
   969    */
       
   970   protected $table;
       
   971 
       
   972   /**
       
   973    * An array of fields that will be updated.
       
   974    *
       
   975    * @var array
       
   976    */
       
   977   protected $fields = array();
       
   978 
       
   979   /**
       
   980    * An array of values to update to.
       
   981    *
       
   982    * @var array
       
   983    */
       
   984   protected $arguments = array();
       
   985 
       
   986   /**
       
   987    * The condition object for this query.
       
   988    *
       
   989    * Condition handling is handled via composition.
       
   990    *
       
   991    * @var DatabaseCondition
       
   992    */
       
   993   protected $condition;
       
   994 
       
   995   /**
       
   996    * Array of fields to update to an expression in case of a duplicate record.
       
   997    *
       
   998    * This variable is a nested array in the following format:
       
   999    * @code
       
  1000    * <some field> => array(
       
  1001    *  'condition' => <condition to execute, as a string>,
       
  1002    *  'arguments' => <array of arguments for condition, or NULL for none>,
       
  1003    * );
       
  1004    * @endcode
       
  1005    *
       
  1006    * @var array
       
  1007    */
       
  1008   protected $expressionFields = array();
       
  1009 
       
  1010   /**
       
  1011    * Constructs an UpdateQuery object.
       
  1012    *
       
  1013    * @param DatabaseConnection $connection
       
  1014    *   A DatabaseConnection object.
       
  1015    * @param string $table
       
  1016    *   Name of the table to associate with this query.
       
  1017    * @param array $options
       
  1018    *   Array of database options.
       
  1019    */
       
  1020   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
       
  1021     $options['return'] = Database::RETURN_AFFECTED;
       
  1022     parent::__construct($connection, $options);
       
  1023     $this->table = $table;
       
  1024 
       
  1025     $this->condition = new DatabaseCondition('AND');
       
  1026   }
       
  1027 
       
  1028   /**
       
  1029    * Implements QueryConditionInterface::condition().
       
  1030    */
       
  1031   public function condition($field, $value = NULL, $operator = NULL) {
       
  1032     $this->condition->condition($field, $value, $operator);
       
  1033     return $this;
       
  1034   }
       
  1035 
       
  1036   /**
       
  1037    * Implements QueryConditionInterface::isNull().
       
  1038    */
       
  1039   public function isNull($field) {
       
  1040     $this->condition->isNull($field);
       
  1041     return $this;
       
  1042   }
       
  1043 
       
  1044   /**
       
  1045    * Implements QueryConditionInterface::isNotNull().
       
  1046    */
       
  1047   public function isNotNull($field) {
       
  1048     $this->condition->isNotNull($field);
       
  1049     return $this;
       
  1050   }
       
  1051 
       
  1052   /**
       
  1053    * Implements QueryConditionInterface::exists().
       
  1054    */
       
  1055   public function exists(SelectQueryInterface $select) {
       
  1056     $this->condition->exists($select);
       
  1057     return $this;
       
  1058   }
       
  1059 
       
  1060   /**
       
  1061    * Implements QueryConditionInterface::notExists().
       
  1062    */
       
  1063   public function notExists(SelectQueryInterface $select) {
       
  1064     $this->condition->notExists($select);
       
  1065     return $this;
       
  1066   }
       
  1067 
       
  1068   /**
       
  1069    * Implements QueryConditionInterface::conditions().
       
  1070    */
       
  1071   public function &conditions() {
       
  1072     return $this->condition->conditions();
       
  1073   }
       
  1074 
       
  1075   /**
       
  1076    * Implements QueryConditionInterface::arguments().
       
  1077    */
       
  1078   public function arguments() {
       
  1079     return $this->condition->arguments();
       
  1080   }
       
  1081 
       
  1082   /**
       
  1083    * Implements QueryConditionInterface::where().
       
  1084    */
       
  1085   public function where($snippet, $args = array()) {
       
  1086     $this->condition->where($snippet, $args);
       
  1087     return $this;
       
  1088   }
       
  1089 
       
  1090   /**
       
  1091    * Implements QueryConditionInterface::compile().
       
  1092    */
       
  1093   public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
       
  1094     return $this->condition->compile($connection, $queryPlaceholder);
       
  1095   }
       
  1096 
       
  1097   /**
       
  1098    * Implements QueryConditionInterface::compiled().
       
  1099    */
       
  1100   public function compiled() {
       
  1101     return $this->condition->compiled();
       
  1102   }
       
  1103 
       
  1104   /**
       
  1105    * Adds a set of field->value pairs to be updated.
       
  1106    *
       
  1107    * @param $fields
       
  1108    *   An associative array of fields to write into the database. The array keys
       
  1109    *   are the field names and the values are the values to which to set them.
       
  1110    *
       
  1111    * @return UpdateQuery
       
  1112    *   The called object.
       
  1113    */
       
  1114   public function fields(array $fields) {
       
  1115     $this->fields = $fields;
       
  1116     return $this;
       
  1117   }
       
  1118 
       
  1119   /**
       
  1120    * Specifies fields to be updated as an expression.
       
  1121    *
       
  1122    * Expression fields are cases such as counter=counter+1. This method takes
       
  1123    * precedence over fields().
       
  1124    *
       
  1125    * @param $field
       
  1126    *   The field to set.
       
  1127    * @param $expression
       
  1128    *   The field will be set to the value of this expression. This parameter
       
  1129    *   may include named placeholders.
       
  1130    * @param $arguments
       
  1131    *   If specified, this is an array of key/value pairs for named placeholders
       
  1132    *   corresponding to the expression.
       
  1133    *
       
  1134    * @return UpdateQuery
       
  1135    *   The called object.
       
  1136    */
       
  1137   public function expression($field, $expression, array $arguments = NULL) {
       
  1138     $this->expressionFields[$field] = array(
       
  1139       'expression' => $expression,
       
  1140       'arguments' => $arguments,
       
  1141     );
       
  1142 
       
  1143     return $this;
       
  1144   }
       
  1145 
       
  1146   /**
       
  1147    * Executes the UPDATE query.
       
  1148    *
       
  1149    * @return
       
  1150    *   The number of rows affected by the update.
       
  1151    */
       
  1152   public function execute() {
       
  1153 
       
  1154     // Expressions take priority over literal fields, so we process those first
       
  1155     // and remove any literal fields that conflict.
       
  1156     $fields = $this->fields;
       
  1157     $update_values = array();
       
  1158     foreach ($this->expressionFields as $field => $data) {
       
  1159       if (!empty($data['arguments'])) {
       
  1160         $update_values += $data['arguments'];
       
  1161       }
       
  1162       unset($fields[$field]);
       
  1163     }
       
  1164 
       
  1165     // Because we filter $fields the same way here and in __toString(), the
       
  1166     // placeholders will all match up properly.
       
  1167     $max_placeholder = 0;
       
  1168     foreach ($fields as $field => $value) {
       
  1169       $update_values[':db_update_placeholder_' . ($max_placeholder++)] = $value;
       
  1170     }
       
  1171 
       
  1172     if (count($this->condition)) {
       
  1173       $this->condition->compile($this->connection, $this);
       
  1174       $update_values = array_merge($update_values, $this->condition->arguments());
       
  1175     }
       
  1176 
       
  1177     return $this->connection->query((string) $this, $update_values, $this->queryOptions);
       
  1178   }
       
  1179 
       
  1180   /**
       
  1181    * Implements PHP magic __toString method to convert the query to a string.
       
  1182    *
       
  1183    * @return string
       
  1184    *   The prepared statement.
       
  1185    */
       
  1186   public function __toString() {
       
  1187     // Create a sanitized comment string to prepend to the query.
       
  1188     $comments = $this->connection->makeComment($this->comments);
       
  1189 
       
  1190     // Expressions take priority over literal fields, so we process those first
       
  1191     // and remove any literal fields that conflict.
       
  1192     $fields = $this->fields;
       
  1193     $update_fields = array();
       
  1194     foreach ($this->expressionFields as $field => $data) {
       
  1195       $update_fields[] = $field . '=' . $data['expression'];
       
  1196       unset($fields[$field]);
       
  1197     }
       
  1198 
       
  1199     $max_placeholder = 0;
       
  1200     foreach ($fields as $field => $value) {
       
  1201       $update_fields[] = $field . '=:db_update_placeholder_' . ($max_placeholder++);
       
  1202     }
       
  1203 
       
  1204     $query = $comments . 'UPDATE {' . $this->connection->escapeTable($this->table) . '} SET ' . implode(', ', $update_fields);
       
  1205 
       
  1206     if (count($this->condition)) {
       
  1207       $this->condition->compile($this->connection, $this);
       
  1208       // There is an implicit string cast on $this->condition.
       
  1209       $query .= "\nWHERE " . $this->condition;
       
  1210     }
       
  1211 
       
  1212     return $query;
       
  1213   }
       
  1214 
       
  1215 }
       
  1216 
       
  1217 /**
       
  1218  * General class for an abstracted MERGE query operation.
       
  1219  *
       
  1220  * An ANSI SQL:2003 compatible database would run the following query:
       
  1221  *
       
  1222  * @code
       
  1223  * MERGE INTO table_name_1 USING table_name_2 ON (condition)
       
  1224  *   WHEN MATCHED THEN
       
  1225  *   UPDATE SET column1 = value1 [, column2 = value2 ...]
       
  1226  *   WHEN NOT MATCHED THEN
       
  1227  *   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
       
  1228  * @endcode
       
  1229  *
       
  1230  * Other databases (most notably MySQL, PostgreSQL and SQLite) will emulate
       
  1231  * this statement by running a SELECT and then INSERT or UPDATE.
       
  1232  *
       
  1233  * By default, the two table names are identical and they are passed into the
       
  1234  * the constructor. table_name_2 can be specified by the
       
  1235  * MergeQuery::conditionTable() method. It can be either a string or a
       
  1236  * subquery.
       
  1237  *
       
  1238  * The condition is built exactly like SelectQuery or UpdateQuery conditions,
       
  1239  * the UPDATE query part is built similarly like an UpdateQuery and finally the
       
  1240  * INSERT query part is built similarly like an InsertQuery. However, both
       
  1241  * UpdateQuery and InsertQuery has a fields method so
       
  1242  * MergeQuery::updateFields() and MergeQuery::insertFields() needs to be called
       
  1243  * instead. MergeQuery::fields() can also be called which calls both of these
       
  1244  * methods as the common case is to use the same column-value pairs for both
       
  1245  * INSERT and UPDATE. However, this is not mandatory. Another convenient
       
  1246  * wrapper is MergeQuery::key() which adds the same column-value pairs to the
       
  1247  * condition and the INSERT query part.
       
  1248  *
       
  1249  * Several methods (key(), fields(), insertFields()) can be called to set a
       
  1250  * key-value pair for the INSERT query part. Subsequent calls for the same
       
  1251  * fields override the earlier ones. The same is true for UPDATE and key(),
       
  1252  * fields() and updateFields().
       
  1253  */
       
  1254 class MergeQuery extends Query implements QueryConditionInterface {
       
  1255   /**
       
  1256    * Returned by execute() if an INSERT query has been executed.
       
  1257    */
       
  1258   const STATUS_INSERT = 1;
       
  1259 
       
  1260   /**
       
  1261    * Returned by execute() if an UPDATE query has been executed.
       
  1262    */
       
  1263   const STATUS_UPDATE = 2;
       
  1264 
       
  1265   /**
       
  1266    * The table to be used for INSERT and UPDATE.
       
  1267    *
       
  1268    * @var string
       
  1269    */
       
  1270   protected $table;
       
  1271 
       
  1272   /**
       
  1273    * The table or subquery to be used for the condition.
       
  1274    */
       
  1275   protected $conditionTable;
       
  1276 
       
  1277   /**
       
  1278    * An array of fields on which to insert.
       
  1279    *
       
  1280    * @var array
       
  1281    */
       
  1282   protected $insertFields = array();
       
  1283 
       
  1284   /**
       
  1285    * An array of fields which should be set to their database-defined defaults.
       
  1286    *
       
  1287    * Used on INSERT.
       
  1288    *
       
  1289    * @var array
       
  1290    */
       
  1291   protected $defaultFields = array();
       
  1292 
       
  1293   /**
       
  1294    * An array of values to be inserted.
       
  1295    *
       
  1296    * @var string
       
  1297    */
       
  1298   protected $insertValues = array();
       
  1299 
       
  1300   /**
       
  1301    * An array of fields that will be updated.
       
  1302    *
       
  1303    * @var array
       
  1304    */
       
  1305   protected $updateFields = array();
       
  1306 
       
  1307   /**
       
  1308    * Array of fields to update to an expression in case of a duplicate record.
       
  1309    *
       
  1310    * This variable is a nested array in the following format:
       
  1311    * @code
       
  1312    * <some field> => array(
       
  1313    *  'condition' => <condition to execute, as a string>,
       
  1314    *  'arguments' => <array of arguments for condition, or NULL for none>,
       
  1315    * );
       
  1316    * @endcode
       
  1317    *
       
  1318    * @var array
       
  1319    */
       
  1320   protected $expressionFields = array();
       
  1321 
       
  1322   /**
       
  1323    * Flag indicating whether an UPDATE is necessary.
       
  1324    *
       
  1325    * @var boolean
       
  1326    */
       
  1327   protected $needsUpdate = FALSE;
       
  1328 
       
  1329   /**
       
  1330   * Constructs a MergeQuery object.
       
  1331   *
       
  1332   * @param DatabaseConnection $connection
       
  1333   *   A DatabaseConnection object.
       
  1334   * @param string $table
       
  1335   *   Name of the table to associate with this query.
       
  1336   * @param array $options
       
  1337   *   Array of database options.
       
  1338   */
       
  1339   public function __construct(DatabaseConnection $connection, $table, array $options = array()) {
       
  1340     $options['return'] = Database::RETURN_AFFECTED;
       
  1341     parent::__construct($connection, $options);
       
  1342     $this->table = $table;
       
  1343     $this->conditionTable = $table;
       
  1344     $this->condition = new DatabaseCondition('AND');
       
  1345   }
       
  1346 
       
  1347   /**
       
  1348    * Sets the table or subquery to be used for the condition.
       
  1349    *
       
  1350    * @param $table
       
  1351    *   The table name or the subquery to be used. Use a SelectQuery object to
       
  1352    *   pass in a subquery.
       
  1353    *
       
  1354    * @return MergeQuery
       
  1355    *   The called object.
       
  1356    */
       
  1357   protected function conditionTable($table) {
       
  1358     $this->conditionTable = $table;
       
  1359     return $this;
       
  1360   }
       
  1361 
       
  1362   /**
       
  1363    * Adds a set of field->value pairs to be updated.
       
  1364    *
       
  1365    * @param $fields
       
  1366    *   An associative array of fields to write into the database. The array keys
       
  1367    *   are the field names and the values are the values to which to set them.
       
  1368    *
       
  1369    * @return MergeQuery
       
  1370    *   The called object.
       
  1371    */
       
  1372   public function updateFields(array $fields) {
       
  1373     $this->updateFields = $fields;
       
  1374     $this->needsUpdate = TRUE;
       
  1375     return $this;
       
  1376   }
       
  1377 
       
  1378   /**
       
  1379    * Specifies fields to be updated as an expression.
       
  1380    *
       
  1381    * Expression fields are cases such as counter = counter + 1. This method
       
  1382    * takes precedence over MergeQuery::updateFields() and it's wrappers,
       
  1383    * MergeQuery::key() and MergeQuery::fields().
       
  1384    *
       
  1385    * @param $field
       
  1386    *   The field to set.
       
  1387    * @param $expression
       
  1388    *   The field will be set to the value of this expression. This parameter
       
  1389    *   may include named placeholders.
       
  1390    * @param $arguments
       
  1391    *   If specified, this is an array of key/value pairs for named placeholders
       
  1392    *   corresponding to the expression.
       
  1393    *
       
  1394    * @return MergeQuery
       
  1395    *   The called object.
       
  1396    */
       
  1397   public function expression($field, $expression, array $arguments = NULL) {
       
  1398     $this->expressionFields[$field] = array(
       
  1399       'expression' => $expression,
       
  1400       'arguments' => $arguments,
       
  1401     );
       
  1402     $this->needsUpdate = TRUE;
       
  1403     return $this;
       
  1404   }
       
  1405 
       
  1406   /**
       
  1407    * Adds a set of field->value pairs to be inserted.
       
  1408    *
       
  1409    * @param $fields
       
  1410    *   An array of fields on which to insert. This array may be indexed or
       
  1411    *   associative. If indexed, the array is taken to be the list of fields.
       
  1412    *   If associative, the keys of the array are taken to be the fields and
       
  1413    *   the values are taken to be corresponding values to insert. If a
       
  1414    *   $values argument is provided, $fields must be indexed.
       
  1415    * @param $values
       
  1416    *   An array of fields to insert into the database. The values must be
       
  1417    *   specified in the same order as the $fields array.
       
  1418    *
       
  1419    * @return MergeQuery
       
  1420    *   The called object.
       
  1421    */
       
  1422   public function insertFields(array $fields, array $values = array()) {
       
  1423     if ($values) {
       
  1424       $fields = array_combine($fields, $values);
       
  1425     }
       
  1426     $this->insertFields = $fields;
       
  1427     return $this;
       
  1428   }
       
  1429 
       
  1430   /**
       
  1431    * Specifies fields for which the database-defaults should be used.
       
  1432    *
       
  1433    * If you want to force a given field to use the database-defined default,
       
  1434    * not NULL or undefined, use this method to instruct the database to use
       
  1435    * default values explicitly. In most cases this will not be necessary
       
  1436    * unless you are inserting a row that is all default values, as you cannot
       
  1437    * specify no values in an INSERT query.
       
  1438    *
       
  1439    * Specifying a field both in fields() and in useDefaults() is an error
       
  1440    * and will not execute.
       
  1441    *
       
  1442    * @param $fields
       
  1443    *   An array of values for which to use the default values
       
  1444    *   specified in the table definition.
       
  1445    *
       
  1446    * @return MergeQuery
       
  1447    *   The called object.
       
  1448    */
       
  1449   public function useDefaults(array $fields) {
       
  1450     $this->defaultFields = $fields;
       
  1451     return $this;
       
  1452   }
       
  1453 
       
  1454   /**
       
  1455    * Sets common field-value pairs in the INSERT and UPDATE query parts.
       
  1456    *
       
  1457    * This method should only be called once. It may be called either
       
  1458    * with a single associative array or two indexed arrays. If called
       
  1459    * with an associative array, the keys are taken to be the fields
       
  1460    * and the values are taken to be the corresponding values to set.
       
  1461    * If called with two arrays, the first array is taken as the fields
       
  1462    * and the second array is taken as the corresponding values.
       
  1463    *
       
  1464    * @param $fields
       
  1465    *   An array of fields to insert, or an associative array of fields and
       
  1466    *   values. The keys of the array are taken to be the fields and the values
       
  1467    *   are taken to be corresponding values to insert.
       
  1468    * @param $values
       
  1469    *   An array of values to set into the database. The values must be
       
  1470    *   specified in the same order as the $fields array.
       
  1471    *
       
  1472    * @return MergeQuery
       
  1473    *   The called object.
       
  1474    */
       
  1475   public function fields(array $fields, array $values = array()) {
       
  1476     if ($values) {
       
  1477       $fields = array_combine($fields, $values);
       
  1478     }
       
  1479     foreach ($fields as $key => $value) {
       
  1480       $this->insertFields[$key] = $value;
       
  1481       $this->updateFields[$key] = $value;
       
  1482     }
       
  1483     $this->needsUpdate = TRUE;
       
  1484     return $this;
       
  1485   }
       
  1486 
       
  1487   /**
       
  1488    * Sets the key field(s) to be used as conditions for this query.
       
  1489    *
       
  1490    * This method should only be called once. It may be called either
       
  1491    * with a single associative array or two indexed arrays. If called
       
  1492    * with an associative array, the keys are taken to be the fields
       
  1493    * and the values are taken to be the corresponding values to set.
       
  1494    * If called with two arrays, the first array is taken as the fields
       
  1495    * and the second array is taken as the corresponding values.
       
  1496    *
       
  1497    * The fields are copied to the condition of the query and the INSERT part.
       
  1498    * If no other method is called, the UPDATE will become a no-op.
       
  1499    *
       
  1500    * @param $fields
       
  1501    *   An array of fields to set, or an associative array of fields and values.
       
  1502    * @param $values
       
  1503    *   An array of values to set into the database. The values must be
       
  1504    *   specified in the same order as the $fields array.
       
  1505    *
       
  1506    * @return MergeQuery
       
  1507    *   The called object.
       
  1508    */
       
  1509   public function key(array $fields, array $values = array()) {
       
  1510     if ($values) {
       
  1511       $fields = array_combine($fields, $values);
       
  1512     }
       
  1513     foreach ($fields as $key => $value) {
       
  1514       $this->insertFields[$key] = $value;
       
  1515       $this->condition($key, $value);
       
  1516     }
       
  1517     return $this;
       
  1518   }
       
  1519 
       
  1520   /**
       
  1521    * Implements QueryConditionInterface::condition().
       
  1522    */
       
  1523   public function condition($field, $value = NULL, $operator = NULL) {
       
  1524     $this->condition->condition($field, $value, $operator);
       
  1525     return $this;
       
  1526   }
       
  1527 
       
  1528   /**
       
  1529    * Implements QueryConditionInterface::isNull().
       
  1530    */
       
  1531   public function isNull($field) {
       
  1532     $this->condition->isNull($field);
       
  1533     return $this;
       
  1534   }
       
  1535 
       
  1536   /**
       
  1537    * Implements QueryConditionInterface::isNotNull().
       
  1538    */
       
  1539   public function isNotNull($field) {
       
  1540     $this->condition->isNotNull($field);
       
  1541     return $this;
       
  1542   }
       
  1543 
       
  1544   /**
       
  1545    * Implements QueryConditionInterface::exists().
       
  1546    */
       
  1547   public function exists(SelectQueryInterface $select) {
       
  1548     $this->condition->exists($select);
       
  1549     return $this;
       
  1550   }
       
  1551 
       
  1552   /**
       
  1553    * Implements QueryConditionInterface::notExists().
       
  1554    */
       
  1555   public function notExists(SelectQueryInterface $select) {
       
  1556     $this->condition->notExists($select);
       
  1557     return $this;
       
  1558   }
       
  1559 
       
  1560   /**
       
  1561    * Implements QueryConditionInterface::conditions().
       
  1562    */
       
  1563   public function &conditions() {
       
  1564     return $this->condition->conditions();
       
  1565   }
       
  1566 
       
  1567   /**
       
  1568    * Implements QueryConditionInterface::arguments().
       
  1569    */
       
  1570   public function arguments() {
       
  1571     return $this->condition->arguments();
       
  1572   }
       
  1573 
       
  1574   /**
       
  1575    * Implements QueryConditionInterface::where().
       
  1576    */
       
  1577   public function where($snippet, $args = array()) {
       
  1578     $this->condition->where($snippet, $args);
       
  1579     return $this;
       
  1580   }
       
  1581 
       
  1582   /**
       
  1583    * Implements QueryConditionInterface::compile().
       
  1584    */
       
  1585   public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
       
  1586     return $this->condition->compile($connection, $queryPlaceholder);
       
  1587   }
       
  1588 
       
  1589   /**
       
  1590    * Implements QueryConditionInterface::compiled().
       
  1591    */
       
  1592   public function compiled() {
       
  1593     return $this->condition->compiled();
       
  1594   }
       
  1595 
       
  1596   /**
       
  1597    * Implements PHP magic __toString method to convert the query to a string.
       
  1598    *
       
  1599    * In the degenerate case, there is no string-able query as this operation
       
  1600    * is potentially two queries.
       
  1601    *
       
  1602    * @return string
       
  1603    *   The prepared query statement.
       
  1604    */
       
  1605   public function __toString() {
       
  1606   }
       
  1607 
       
  1608   public function execute() {
       
  1609     if (!count($this->condition)) {
       
  1610       throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
       
  1611     }
       
  1612     $select = $this->connection->select($this->conditionTable)
       
  1613       ->condition($this->condition);
       
  1614     $select->addExpression('1');
       
  1615     if (!$select->execute()->fetchField()) {
       
  1616       try {
       
  1617         $insert = $this->connection->insert($this->table)->fields($this->insertFields);
       
  1618         if ($this->defaultFields) {
       
  1619           $insert->useDefaults($this->defaultFields);
       
  1620         }
       
  1621         $insert->execute();
       
  1622         return self::STATUS_INSERT;
       
  1623       }
       
  1624       catch (Exception $e) {
       
  1625         // The insert query failed, maybe it's because a racing insert query
       
  1626         // beat us in inserting the same row. Retry the select query, if it
       
  1627         // returns a row, ignore the error and continue with the update
       
  1628         // query below.
       
  1629         if (!$select->execute()->fetchField()) {
       
  1630           throw $e;
       
  1631         }
       
  1632       }
       
  1633     }
       
  1634     if ($this->needsUpdate) {
       
  1635       $update = $this->connection->update($this->table)
       
  1636         ->fields($this->updateFields)
       
  1637         ->condition($this->condition);
       
  1638       if ($this->expressionFields) {
       
  1639         foreach ($this->expressionFields as $field => $data) {
       
  1640           $update->expression($field, $data['expression'], $data['arguments']);
       
  1641         }
       
  1642       }
       
  1643       $update->execute();
       
  1644       return self::STATUS_UPDATE;
       
  1645      }
       
  1646   }
       
  1647 }
       
  1648 
       
  1649 /**
       
  1650  * Generic class for a series of conditions in a query.
       
  1651  */
       
  1652 class DatabaseCondition implements QueryConditionInterface, Countable {
       
  1653 
       
  1654   /**
       
  1655    * Array of conditions.
       
  1656    *
       
  1657    * @var array
       
  1658    */
       
  1659   protected $conditions = array();
       
  1660 
       
  1661   /**
       
  1662    * Array of arguments.
       
  1663    *
       
  1664    * @var array
       
  1665    */
       
  1666   protected $arguments = array();
       
  1667 
       
  1668   /**
       
  1669    * Whether the conditions have been changed.
       
  1670    *
       
  1671    * TRUE if the condition has been changed since the last compile.
       
  1672    * FALSE if the condition has been compiled and not changed.
       
  1673    *
       
  1674    * @var bool
       
  1675    */
       
  1676   protected $changed = TRUE;
       
  1677 
       
  1678   /**
       
  1679    * The identifier of the query placeholder this condition has been compiled against.
       
  1680    */
       
  1681   protected $queryPlaceholderIdentifier;
       
  1682 
       
  1683   /**
       
  1684    * Constructs a DataBaseCondition object.
       
  1685    *
       
  1686    * @param string $conjunction
       
  1687    *   The operator to use to combine conditions: 'AND' or 'OR'.
       
  1688    */
       
  1689   public function __construct($conjunction) {
       
  1690     $this->conditions['#conjunction'] = $conjunction;
       
  1691   }
       
  1692 
       
  1693   /**
       
  1694    * Implements Countable::count().
       
  1695    *
       
  1696    * Returns the size of this conditional. The size of the conditional is the
       
  1697    * size of its conditional array minus one, because one element is the
       
  1698    * conjunction.
       
  1699    */
       
  1700   public function count() {
       
  1701     return count($this->conditions) - 1;
       
  1702   }
       
  1703 
       
  1704   /**
       
  1705    * Implements QueryConditionInterface::condition().
       
  1706    */
       
  1707   public function condition($field, $value = NULL, $operator = NULL) {
       
  1708     if (!isset($operator)) {
       
  1709       if (is_array($value)) {
       
  1710         $operator = 'IN';
       
  1711       }
       
  1712       elseif (!isset($value)) {
       
  1713         $operator = 'IS NULL';
       
  1714       }
       
  1715       else {
       
  1716         $operator = '=';
       
  1717       }
       
  1718     }
       
  1719     $this->conditions[] = array(
       
  1720       'field' => $field,
       
  1721       'value' => $value,
       
  1722       'operator' => $operator,
       
  1723     );
       
  1724 
       
  1725     $this->changed = TRUE;
       
  1726 
       
  1727     return $this;
       
  1728   }
       
  1729 
       
  1730   /**
       
  1731    * Implements QueryConditionInterface::where().
       
  1732    */
       
  1733   public function where($snippet, $args = array()) {
       
  1734     $this->conditions[] = array(
       
  1735       'field' => $snippet,
       
  1736       'value' => $args,
       
  1737       'operator' => NULL,
       
  1738     );
       
  1739     $this->changed = TRUE;
       
  1740 
       
  1741     return $this;
       
  1742   }
       
  1743 
       
  1744   /**
       
  1745    * Implements QueryConditionInterface::isNull().
       
  1746    */
       
  1747   public function isNull($field) {
       
  1748     return $this->condition($field);
       
  1749   }
       
  1750 
       
  1751   /**
       
  1752    * Implements QueryConditionInterface::isNotNull().
       
  1753    */
       
  1754   public function isNotNull($field) {
       
  1755     return $this->condition($field, NULL, 'IS NOT NULL');
       
  1756   }
       
  1757 
       
  1758   /**
       
  1759    * Implements QueryConditionInterface::exists().
       
  1760    */
       
  1761   public function exists(SelectQueryInterface $select) {
       
  1762     return $this->condition('', $select, 'EXISTS');
       
  1763   }
       
  1764 
       
  1765   /**
       
  1766    * Implements QueryConditionInterface::notExists().
       
  1767    */
       
  1768   public function notExists(SelectQueryInterface $select) {
       
  1769     return $this->condition('', $select, 'NOT EXISTS');
       
  1770   }
       
  1771 
       
  1772   /**
       
  1773    * Implements QueryConditionInterface::conditions().
       
  1774    */
       
  1775   public function &conditions() {
       
  1776     return $this->conditions;
       
  1777   }
       
  1778 
       
  1779   /**
       
  1780    * Implements QueryConditionInterface::arguments().
       
  1781    */
       
  1782   public function arguments() {
       
  1783     // If the caller forgot to call compile() first, refuse to run.
       
  1784     if ($this->changed) {
       
  1785       return NULL;
       
  1786     }
       
  1787     return $this->arguments;
       
  1788   }
       
  1789 
       
  1790   /**
       
  1791    * Implements QueryConditionInterface::compile().
       
  1792    */
       
  1793   public function compile(DatabaseConnection $connection, QueryPlaceholderInterface $queryPlaceholder) {
       
  1794     // Re-compile if this condition changed or if we are compiled against a
       
  1795     // different query placeholder object.
       
  1796     if ($this->changed || isset($this->queryPlaceholderIdentifier) && ($this->queryPlaceholderIdentifier != $queryPlaceholder->uniqueIdentifier())) {
       
  1797       $this->queryPlaceholderIdentifier = $queryPlaceholder->uniqueIdentifier();
       
  1798 
       
  1799       $condition_fragments = array();
       
  1800       $arguments = array();
       
  1801 
       
  1802       $conditions = $this->conditions;
       
  1803       $conjunction = $conditions['#conjunction'];
       
  1804       unset($conditions['#conjunction']);
       
  1805       foreach ($conditions as $condition) {
       
  1806         if (empty($condition['operator'])) {
       
  1807           // This condition is a literal string, so let it through as is.
       
  1808           $condition_fragments[] = ' (' . $condition['field'] . ') ';
       
  1809           $arguments += $condition['value'];
       
  1810         }
       
  1811         else {
       
  1812           // It's a structured condition, so parse it out accordingly.
       
  1813           // Note that $condition['field'] will only be an object for a dependent
       
  1814           // DatabaseCondition object, not for a dependent subquery.
       
  1815           if ($condition['field'] instanceof QueryConditionInterface) {
       
  1816             // Compile the sub-condition recursively and add it to the list.
       
  1817             $condition['field']->compile($connection, $queryPlaceholder);
       
  1818             $condition_fragments[] = '(' . (string) $condition['field'] . ')';
       
  1819             $arguments += $condition['field']->arguments();
       
  1820           }
       
  1821           else {
       
  1822             // For simplicity, we treat all operators as the same data structure.
       
  1823             // In the typical degenerate case, this won't get changed.
       
  1824             $operator_defaults = array(
       
  1825               'prefix' => '',
       
  1826               'postfix' => '',
       
  1827               'delimiter' => '',
       
  1828               'operator' => $condition['operator'],
       
  1829               'use_value' => TRUE,
       
  1830             );
       
  1831             $operator = $connection->mapConditionOperator($condition['operator']);
       
  1832             if (!isset($operator)) {
       
  1833               $operator = $this->mapConditionOperator($condition['operator']);
       
  1834             }
       
  1835             $operator += $operator_defaults;
       
  1836 
       
  1837             $placeholders = array();
       
  1838             if ($condition['value'] instanceof SelectQueryInterface) {
       
  1839               $condition['value']->compile($connection, $queryPlaceholder);
       
  1840               $placeholders[] = (string) $condition['value'];
       
  1841               $arguments += $condition['value']->arguments();
       
  1842               // Subqueries are the actual value of the operator, we don't
       
  1843               // need to add another below.
       
  1844               $operator['use_value'] = FALSE;
       
  1845             }
       
  1846             // We assume that if there is a delimiter, then the value is an
       
  1847             // array. If not, it is a scalar. For simplicity, we first convert
       
  1848             // up to an array so that we can build the placeholders in the same way.
       
  1849             elseif (!$operator['delimiter']) {
       
  1850               $condition['value'] = array($condition['value']);
       
  1851             }
       
  1852             if ($operator['use_value']) {
       
  1853               foreach ($condition['value'] as $value) {
       
  1854                 $placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
       
  1855                 $arguments[$placeholder] = $value;
       
  1856                 $placeholders[] = $placeholder;
       
  1857               }
       
  1858             }
       
  1859             $condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
       
  1860           }
       
  1861         }
       
  1862       }
       
  1863 
       
  1864       $this->changed = FALSE;
       
  1865       $this->stringVersion = implode($conjunction, $condition_fragments);
       
  1866       $this->arguments = $arguments;
       
  1867     }
       
  1868   }
       
  1869 
       
  1870   /**
       
  1871    * Implements QueryConditionInterface::compiled().
       
  1872    */
       
  1873   public function compiled() {
       
  1874     return !$this->changed;
       
  1875   }
       
  1876 
       
  1877   /**
       
  1878    * Implements PHP magic __toString method to convert the conditions to string.
       
  1879    *
       
  1880    * @return string
       
  1881    *   A string version of the conditions.
       
  1882    */
       
  1883   public function __toString() {
       
  1884     // If the caller forgot to call compile() first, refuse to run.
       
  1885     if ($this->changed) {
       
  1886       return NULL;
       
  1887     }
       
  1888     return $this->stringVersion;
       
  1889   }
       
  1890 
       
  1891   /**
       
  1892    * PHP magic __clone() method.
       
  1893    *
       
  1894    * Only copies fields that implement QueryConditionInterface. Also sets
       
  1895    * $this->changed to TRUE.
       
  1896    */
       
  1897   function __clone() {
       
  1898     $this->changed = TRUE;
       
  1899     foreach ($this->conditions as $key => $condition) {
       
  1900       if ($key !== '#conjunction') {
       
  1901         if ($condition['field'] instanceOf QueryConditionInterface) {
       
  1902           $this->conditions[$key]['field'] = clone($condition['field']);
       
  1903         }
       
  1904         if ($condition['value'] instanceOf SelectQueryInterface) {
       
  1905           $this->conditions[$key]['value'] = clone($condition['value']);
       
  1906         }
       
  1907       }
       
  1908     }
       
  1909   }
       
  1910 
       
  1911   /**
       
  1912    * Gets any special processing requirements for the condition operator.
       
  1913    *
       
  1914    * Some condition types require special processing, such as IN, because
       
  1915    * the value data they pass in is not a simple value. This is a simple
       
  1916    * overridable lookup function.
       
  1917    *
       
  1918    * @param $operator
       
  1919    *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
       
  1920    *
       
  1921    * @return
       
  1922    *   The extra handling directives for the specified operator, or NULL.
       
  1923    */
       
  1924   protected function mapConditionOperator($operator) {
       
  1925     // $specials does not use drupal_static as its value never changes.
       
  1926     static $specials = array(
       
  1927       'BETWEEN' => array('delimiter' => ' AND '),
       
  1928       'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
       
  1929       'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
       
  1930       'EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
       
  1931       'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
       
  1932       'IS NULL' => array('use_value' => FALSE),
       
  1933       'IS NOT NULL' => array('use_value' => FALSE),
       
  1934       // Use backslash for escaping wildcard characters.
       
  1935       'LIKE' => array('postfix' => " ESCAPE '\\\\'"),
       
  1936       'NOT LIKE' => array('postfix' => " ESCAPE '\\\\'"),
       
  1937       // These ones are here for performance reasons.
       
  1938       '=' => array(),
       
  1939       '<' => array(),
       
  1940       '>' => array(),
       
  1941       '>=' => array(),
       
  1942       '<=' => array(),
       
  1943     );
       
  1944     if (isset($specials[$operator])) {
       
  1945       $return = $specials[$operator];
       
  1946     }
       
  1947     else {
       
  1948       // We need to upper case because PHP index matches are case sensitive but
       
  1949       // do not need the more expensive drupal_strtoupper because SQL statements are ASCII.
       
  1950       $operator = strtoupper($operator);
       
  1951       $return = isset($specials[$operator]) ? $specials[$operator] : array();
       
  1952     }
       
  1953 
       
  1954     $return += array('operator' => $operator);
       
  1955 
       
  1956     return $return;
       
  1957   }
       
  1958 
       
  1959 }
       
  1960 
       
  1961 /**
       
  1962  * @} End of "addtogroup database".
       
  1963  */