Drupal PHP Cross Reference Content Management Systems

Source: /includes/database/database.inc - 3010 lines - 94437 bytes - Summary - Text - Print

   1  <?php
   2  
   3  /**
   4   * @file
   5   * Core systems for the database layer.
   6   *
   7   * Classes required for basic functioning of the database system should be
   8   * placed in this file.  All utility functions should also be placed in this
   9   * file only, as they cannot auto-load the way classes can.
  10   */
  11  
  12  /**
  13   * @defgroup database Database abstraction layer
  14   * @{
  15   * Allow the use of different database servers using the same code base.
  16   *
  17   * Drupal provides a database abstraction layer to provide developers with
  18   * the ability to support multiple database servers easily. The intent of
  19   * this layer is to preserve the syntax and power of SQL as much as possible,
  20   * but also allow developers a way to leverage more complex functionality in
  21   * a unified way. It also provides a structured interface for dynamically
  22   * constructing queries when appropriate, and enforcing security checks and
  23   * similar good practices.
  24   *
  25   * The system is built atop PHP's PDO (PHP Data Objects) database API and
  26   * inherits much of its syntax and semantics.
  27   *
  28   * Most Drupal database SELECT queries are performed by a call to db_query() or
  29   * db_query_range(). Module authors should also consider using the PagerDefault
  30   * Extender for queries that return results that need to be presented on
  31   * multiple pages, and the Tablesort Extender for generating appropriate queries
  32   * for sortable tables.
  33   *
  34   * For example, one might wish to return a list of the most recent 10 nodes
  35   * authored by a given user. Instead of directly issuing the SQL query
  36   * @code
  37   * SELECT n.nid, n.title, n.created FROM node n WHERE n.uid = $uid LIMIT 0, 10;
  38   * @endcode
  39   * one would instead call the Drupal functions:
  40   * @code
  41   * $result = db_query_range('SELECT n.nid, n.title, n.created
  42   *   FROM {node} n WHERE n.uid = :uid', 0, 10, array(':uid' => $uid));
  43   * foreach ($result as $record) {
  44   *   // Perform operations on $record->title, etc. here.
  45   * }
  46   * @endcode
  47   * Curly braces are used around "node" to provide table prefixing via
  48   * DatabaseConnection::prefixTables(). The explicit use of a user ID is pulled
  49   * out into an argument passed to db_query() so that SQL injection attacks
  50   * from user input can be caught and nullified. The LIMIT syntax varies between
  51   * database servers, so that is abstracted into db_query_range() arguments.
  52   * Finally, note the PDO-based ability to iterate over the result set using
  53   * foreach ().
  54   *
  55   * All queries are passed as a prepared statement string. A
  56   * prepared statement is a "template" of a query that omits literal or variable
  57   * values in favor of placeholders. The values to place into those
  58   * placeholders are passed separately, and the database driver handles
  59   * inserting the values into the query in a secure fashion. That means you
  60   * should never quote or string-escape a value to be inserted into the query.
  61   *
  62   * There are two formats for placeholders: named and unnamed. Named placeholders
  63   * are strongly preferred in all cases as they are more flexible and
  64   * self-documenting. Named placeholders should start with a colon ":" and can be
  65   * followed by one or more letters, numbers or underscores.
  66   *
  67   * Named placeholders begin with a colon followed by a unique string. Example:
  68   * @code
  69   * SELECT nid, title FROM {node} WHERE uid=:uid;
  70   * @endcode
  71   *
  72   * ":uid" is a placeholder that will be replaced with a literal value when
  73   * the query is executed. A given placeholder label cannot be repeated in a
  74   * given query, even if the value should be the same. When using named
  75   * placeholders, the array of arguments to the query must be an associative
  76   * array where keys are a placeholder label (e.g., :uid) and the value is the
  77   * corresponding value to use. The array may be in any order.
  78   *
  79   * Unnamed placeholders are simply a question mark. Example:
  80   * @code
  81   * SELECT nid, title FROM {node} WHERE uid=?;
  82   * @endcode
  83   *
  84   * In this case, the array of arguments must be an indexed array of values to
  85   * use in the exact same order as the placeholders in the query.
  86   *
  87   * Note that placeholders should be a "complete" value. For example, when
  88   * running a LIKE query the SQL wildcard character, %, should be part of the
  89   * value, not the query itself. Thus, the following is incorrect:
  90   * @code
  91   * SELECT nid, title FROM {node} WHERE title LIKE :title%;
  92   * @endcode
  93   * It should instead read:
  94   * @code
  95   * SELECT nid, title FROM {node} WHERE title LIKE :title;
  96   * @endcode
  97   * and the value for :title should include a % as appropriate. Again, note the
  98   * lack of quotation marks around :title. Because the value is not inserted
  99   * into the query as one big string but as an explicitly separate value, the
 100   * database server knows where the query ends and a value begins. That is
 101   * considerably more secure against SQL injection than trying to remember
 102   * which values need quotation marks and string escaping and which don't.
 103   *
 104   * INSERT, UPDATE, and DELETE queries need special care in order to behave
 105   * consistently across all different databases. Therefore, they use a special
 106   * object-oriented API for defining a query structurally. For example, rather
 107   * than:
 108   * @code
 109   * INSERT INTO node (nid, title, body) VALUES (1, 'my title', 'my body');
 110   * @endcode
 111   * one would instead write:
 112   * @code
 113   * $fields = array('nid' => 1, 'title' => 'my title', 'body' => 'my body');
 114   * db_insert('node')->fields($fields)->execute();
 115   * @endcode
 116   * This method allows databases that need special data type handling to do so,
 117   * while also allowing optimizations such as multi-insert queries. UPDATE and
 118   * DELETE queries have a similar pattern.
 119   *
 120   * Drupal also supports transactions, including a transparent fallback for
 121   * databases that do not support transactions. To start a new transaction,
 122   * simply call $txn = db_transaction(); in your own code. The transaction will
 123   * remain open for as long as the variable $txn remains in scope.  When $txn is
 124   * destroyed, the transaction will be committed.  If your transaction is nested
 125   * inside of another then Drupal will track each transaction and only commit
 126   * the outer-most transaction when the last transaction object goes out out of
 127   * scope, that is, all relevant queries completed successfully.
 128   *
 129   * Example:
 130   * @code
 131   * function my_transaction_function() {
 132   *   // The transaction opens here.
 133   *   $txn = db_transaction();
 134   *
 135   *   try {
 136   *     $id = db_insert('example')
 137   *       ->fields(array(
 138   *         'field1' => 'mystring',
 139   *         'field2' => 5,
 140   *       ))
 141   *       ->execute();
 142   *
 143   *     my_other_function($id);
 144   *
 145   *     return $id;
 146   *   }
 147   *   catch (Exception $e) {
 148   *     // Something went wrong somewhere, so roll back now.
 149   *     $txn->rollback();
 150   *     // Log the exception to watchdog.
 151   *     watchdog_exception('type', $e);
 152   *   }
 153   *
 154   *   // $txn goes out of scope here.  Unless the transaction was rolled back, it
 155   *   // gets automatically committed here.
 156   * }
 157   *
 158   * function my_other_function($id) {
 159   *   // The transaction is still open here.
 160   *
 161   *   if ($id % 2 == 0) {
 162   *     db_update('example')
 163   *       ->condition('id', $id)
 164   *       ->fields(array('field2' => 10))
 165   *       ->execute();
 166   *   }
 167   * }
 168   * @endcode
 169   *
 170   * @link http://drupal.org/developing/api/database @endlink
 171   */
 172  
 173  
 174  /**
 175   * Base Database API class.
 176   *
 177   * This class provides a Drupal-specific extension of the PDO database
 178   * abstraction class in PHP. Every database driver implementation must provide a
 179   * concrete implementation of it to support special handling required by that
 180   * database.
 181   *
 182   * @see http://php.net/manual/en/book.pdo.php
 183   */
 184  abstract class DatabaseConnection extends PDO {
 185  
 186    /**
 187     * The database target this connection is for.
 188     *
 189     * We need this information for later auditing and logging.
 190     *
 191     * @var string
 192     */
 193    protected $target = NULL;
 194  
 195    /**
 196     * The key representing this connection.
 197     * 
 198     * The key is a unique string which identifies a database connection. A
 199     * connection can be a single server or a cluster of master and slaves (use
 200     * target to pick between master and slave).
 201     *
 202     * @var string
 203     */
 204    protected $key = NULL;
 205  
 206    /**
 207     * The current database logging object for this connection.
 208     *
 209     * @var DatabaseLog
 210     */
 211    protected $logger = NULL;
 212  
 213    /**
 214     * Tracks the number of "layers" of transactions currently active.
 215     *
 216     * On many databases transactions cannot nest.  Instead, we track
 217     * nested calls to transactions and collapse them into a single
 218     * transaction.
 219     *
 220     * @var array
 221     */
 222    protected $transactionLayers = array();
 223  
 224    /**
 225     * Index of what driver-specific class to use for various operations.
 226     *
 227     * @var array
 228     */
 229    protected $driverClasses = array();
 230  
 231    /**
 232     * The name of the Statement class for this connection.
 233     *
 234     * @var string
 235     */
 236    protected $statementClass = 'DatabaseStatementBase';
 237  
 238    /**
 239     * Whether this database connection supports transactions.
 240     *
 241     * @var bool
 242     */
 243    protected $transactionSupport = TRUE;
 244  
 245    /**
 246     * Whether this database connection supports transactional DDL.
 247     *
 248     * Set to FALSE by default because few databases support this feature.
 249     *
 250     * @var bool
 251     */
 252    protected $transactionalDDLSupport = FALSE;
 253  
 254    /**
 255     * An index used to generate unique temporary table names.
 256     *
 257     * @var integer
 258     */
 259    protected $temporaryNameIndex = 0;
 260  
 261    /**
 262     * The connection information for this connection object.
 263     *
 264     * @var array
 265     */
 266    protected $connectionOptions = array();
 267  
 268    /**
 269     * The schema object for this connection.
 270     *
 271     * @var object
 272     */
 273    protected $schema = NULL;
 274  
 275    /**
 276     * The prefixes used by this database connection.
 277     *
 278     * @var array
 279     */
 280    protected $prefixes = array();
 281  
 282    /**
 283     * List of search values for use in prefixTables().
 284     *
 285     * @var array
 286     */
 287    protected $prefixSearch = array();
 288  
 289    /**
 290     * List of replacement values for use in prefixTables().
 291     *
 292     * @var array
 293     */
 294    protected $prefixReplace = array();
 295  
 296    function __construct($dsn, $username, $password, $driver_options = array()) {
 297      // Initialize and prepare the connection prefix.
 298      $this->setPrefix(isset($this->connectionOptions['prefix']) ? $this->connectionOptions['prefix'] : '');
 299  
 300      // Because the other methods don't seem to work right.
 301      $driver_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
 302  
 303      // Call PDO::__construct and PDO::setAttribute.
 304      parent::__construct($dsn, $username, $password, $driver_options);
 305  
 306      // Set a specific PDOStatement class if the driver requires that.
 307      if (!empty($this->statementClass)) {
 308        $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($this->statementClass, array($this)));
 309      }
 310    }
 311  
 312    /**
 313     * Returns the default query options for any given query.
 314     *
 315     * A given query can be customized with a number of option flags in an
 316     * associative array:
 317     * - target: The database "target" against which to execute a query. Valid
 318     *   values are "default" or "slave". The system will first try to open a
 319     *   connection to a database specified with the user-supplied key. If one
 320     *   is not available, it will silently fall back to the "default" target.
 321     *   If multiple databases connections are specified with the same target,
 322     *   one will be selected at random for the duration of the request.
 323     * - fetch: This element controls how rows from a result set will be
 324     *   returned. Legal values include PDO::FETCH_ASSOC, PDO::FETCH_BOTH,
 325     *   PDO::FETCH_OBJ, PDO::FETCH_NUM, or a string representing the name of a
 326     *   class. If a string is specified, each record will be fetched into a new
 327     *   object of that class. The behavior of all other values is defined by PDO.
 328     *   See http://php.net/manual/pdostatement.fetch.php
 329     * - return: Depending on the type of query, different return values may be
 330     *   meaningful. This directive instructs the system which type of return
 331     *   value is desired. The system will generally set the correct value
 332     *   automatically, so it is extremely rare that a module developer will ever
 333     *   need to specify this value. Setting it incorrectly will likely lead to
 334     *   unpredictable results or fatal errors. Legal values include:
 335     *   - Database::RETURN_STATEMENT: Return the prepared statement object for
 336     *     the query. This is usually only meaningful for SELECT queries, where
 337     *     the statement object is how one accesses the result set returned by the
 338     *     query.
 339     *   - Database::RETURN_AFFECTED: Return the number of rows affected by an
 340     *     UPDATE or DELETE query. Be aware that means the number of rows actually
 341     *     changed, not the number of rows matched by the WHERE clause.
 342     *   - Database::RETURN_INSERT_ID: Return the sequence ID (primary key)
 343     *     created by an INSERT statement on a table that contains a serial
 344     *     column.
 345     *   - Database::RETURN_NULL: Do not return anything, as there is no
 346     *     meaningful value to return. That is the case for INSERT queries on
 347     *     tables that do not contain a serial column.
 348     * - throw_exception: By default, the database system will catch any errors
 349     *   on a query as an Exception, log it, and then rethrow it so that code
 350     *   further up the call chain can take an appropriate action. To suppress
 351     *   that behavior and simply return NULL on failure, set this option to
 352     *   FALSE.
 353     *
 354     * @return
 355     *   An array of default query options.
 356     */
 357    protected function defaultOptions() {
 358      return array(
 359        'target' => 'default',
 360        'fetch' => PDO::FETCH_OBJ,
 361        'return' => Database::RETURN_STATEMENT,
 362        'throw_exception' => TRUE,
 363      );
 364    }
 365  
 366    /**
 367     * Returns the connection information for this connection object.
 368     *
 369     * Note that Database::getConnectionInfo() is for requesting information
 370     * about an arbitrary database connection that is defined. This method
 371     * is for requesting the connection information of this specific
 372     * open connection object.
 373     *
 374     * @return
 375     *   An array of the connection information. The exact list of
 376     *   properties is driver-dependent.
 377     */
 378    public function getConnectionOptions() {
 379      return $this->connectionOptions;
 380    }
 381  
 382    /**
 383     * Set the list of prefixes used by this database connection.
 384     *
 385     * @param $prefix
 386     *   The prefixes, in any of the multiple forms documented in
 387     *   default.settings.php.
 388     */
 389    protected function setPrefix($prefix) {
 390      if (is_array($prefix)) {
 391        $this->prefixes = $prefix + array('default' => '');
 392      }
 393      else {
 394        $this->prefixes = array('default' => $prefix);
 395      }
 396  
 397      // Set up variables for use in prefixTables(). Replace table-specific
 398      // prefixes first.
 399      $this->prefixSearch = array();
 400      $this->prefixReplace = array();
 401      foreach ($this->prefixes as $key => $val) {
 402        if ($key != 'default') {
 403          $this->prefixSearch[] = '{' . $key . '}';
 404          $this->prefixReplace[] = $val . $key;
 405        }
 406      }
 407      // Then replace remaining tables with the default prefix.
 408      $this->prefixSearch[] = '{';
 409      $this->prefixReplace[] = $this->prefixes['default'];
 410      $this->prefixSearch[] = '}';
 411      $this->prefixReplace[] = '';
 412    }
 413  
 414    /**
 415     * Appends a database prefix to all tables in a query.
 416     *
 417     * Queries sent to Drupal should wrap all table names in curly brackets. This
 418     * function searches for this syntax and adds Drupal's table prefix to all
 419     * tables, allowing Drupal to coexist with other systems in the same database
 420     * and/or schema if necessary.
 421     *
 422     * @param $sql
 423     *   A string containing a partial or entire SQL query.
 424     *
 425     * @return
 426     *   The properly-prefixed string.
 427     */
 428    public function prefixTables($sql) {
 429      return str_replace($this->prefixSearch, $this->prefixReplace, $sql);
 430    }
 431  
 432    /**
 433     * Find the prefix for a table.
 434     *
 435     * This function is for when you want to know the prefix of a table. This
 436     * is not used in prefixTables due to performance reasons.
 437     */
 438    public function tablePrefix($table = 'default') {
 439      if (isset($this->prefixes[$table])) {
 440        return $this->prefixes[$table];
 441      }
 442      else {
 443        return $this->prefixes['default'];
 444      }
 445    }
 446  
 447    /**
 448     * Prepares a query string and returns the prepared statement.
 449     *
 450     * This method caches prepared statements, reusing them when
 451     * possible. It also prefixes tables names enclosed in curly-braces.
 452     *
 453     * @param $query
 454     *   The query string as SQL, with curly-braces surrounding the
 455     *   table names.
 456     *
 457     * @return DatabaseStatementInterface
 458     *   A PDO prepared statement ready for its execute() method.
 459     */
 460    public function prepareQuery($query) {
 461      $query = $this->prefixTables($query);
 462  
 463      // Call PDO::prepare.
 464      return parent::prepare($query);
 465    }
 466  
 467    /**
 468     * Tells this connection object what its target value is.
 469     *
 470     * This is needed for logging and auditing. It's sloppy to do in the
 471     * constructor because the constructor for child classes has a different
 472     * signature. We therefore also ensure that this function is only ever
 473     * called once.
 474     *
 475     * @param $target
 476     *   The target this connection is for. Set to NULL (default) to disable
 477     *   logging entirely.
 478     */
 479    public function setTarget($target = NULL) {
 480      if (!isset($this->target)) {
 481        $this->target = $target;
 482      }
 483    }
 484  
 485    /**
 486     * Returns the target this connection is associated with.
 487     *
 488     * @return
 489     *   The target string of this connection.
 490     */
 491    public function getTarget() {
 492      return $this->target;
 493    }
 494  
 495    /**
 496     * Tells this connection object what its key is.
 497     *
 498     * @param $target
 499     *   The key this connection is for.
 500     */
 501    public function setKey($key) {
 502      if (!isset($this->key)) {
 503        $this->key = $key;
 504      }
 505    }
 506  
 507    /**
 508     * Returns the key this connection is associated with.
 509     *
 510     * @return
 511     *   The key of this connection.
 512     */
 513    public function getKey() {
 514      return $this->key;
 515    }
 516  
 517    /**
 518     * Associates a logging object with this connection.
 519     *
 520     * @param $logger
 521     *   The logging object we want to use.
 522     */
 523    public function setLogger(DatabaseLog $logger) {
 524      $this->logger = $logger;
 525    }
 526  
 527    /**
 528     * Gets the current logging object for this connection.
 529     *
 530     * @return DatabaseLog
 531     *   The current logging object for this connection. If there isn't one,
 532     *   NULL is returned.
 533     */
 534    public function getLogger() {
 535      return $this->logger;
 536    }
 537  
 538    /**
 539     * Creates the appropriate sequence name for a given table and serial field.
 540     *
 541     * This information is exposed to all database drivers, although it is only
 542     * useful on some of them. This method is table prefix-aware.
 543     *
 544     * @param $table
 545     *   The table name to use for the sequence.
 546     * @param $field
 547     *   The field name to use for the sequence.
 548     *
 549     * @return
 550     *   A table prefix-parsed string for the sequence name.
 551     */
 552    public function makeSequenceName($table, $field) {
 553      return $this->prefixTables('{' . $table . '}_' . $field . '_seq');
 554    }
 555  
 556    /**
 557     * Flatten an array of query comments into a single comment string.
 558     *
 559     * The comment string will be sanitized to avoid SQL injection attacks.
 560     *
 561     * @param $comments
 562     *   An array of query comment strings.
 563     *
 564     * @return
 565     *   A sanitized comment string.
 566     */
 567    public function makeComment($comments) {
 568      if (empty($comments))
 569        return '';
 570  
 571      // Flatten the array of comments.
 572      $comment = implode('; ', $comments);
 573  
 574      // Sanitize the comment string so as to avoid SQL injection attacks.
 575      return '/* ' . $this->filterComment($comment) . ' */ ';
 576    }
 577  
 578    /**
 579     * Sanitize a query comment string.
 580     *
 581     * Ensure a query comment does not include strings such as "* /" that might
 582     * terminate the comment early. This avoids SQL injection attacks via the
 583     * query comment. The comment strings in this example are separated by a
 584     * space to avoid PHP parse errors.
 585     *
 586     * For example, the comment:
 587     * @code
 588     * db_update('example')
 589     *  ->condition('id', $id)
 590     *  ->fields(array('field2' => 10))
 591     *  ->comment('Exploit * / DROP TABLE node; --')
 592     *  ->execute()
 593     * @endcode
 594     *
 595     * Would result in the following SQL statement being generated:
 596     * @code
 597     * "/ * Exploit * / DROP TABLE node; -- * / UPDATE example SET field2=..."
 598     * @endcode
 599     *
 600     * Unless the comment is sanitised first, the SQL server would drop the
 601     * node table and ignore the rest of the SQL statement.
 602     *
 603     * @param $comment
 604     *   A query comment string.
 605     *
 606     * @return
 607     *   A sanitized version of the query comment string.
 608     */
 609    protected function filterComment($comment = '') {
 610      return preg_replace('/(\/\*\s*)|(\s*\*\/)/', '', $comment);
 611    }
 612  
 613    /**
 614     * Executes a query string against the database.
 615     *
 616     * This method provides a central handler for the actual execution of every
 617     * query. All queries executed by Drupal are executed as PDO prepared
 618     * statements.
 619     *
 620     * @param $query
 621     *   The query to execute. In most cases this will be a string containing
 622     *   an SQL query with placeholders. An already-prepared instance of
 623     *   DatabaseStatementInterface may also be passed in order to allow calling
 624     *   code to manually bind variables to a query. If a
 625     *   DatabaseStatementInterface is passed, the $args array will be ignored.
 626     *   It is extremely rare that module code will need to pass a statement
 627     *   object to this method. It is used primarily for database drivers for
 628     *   databases that require special LOB field handling.
 629     * @param $args
 630     *   An array of arguments for the prepared statement. If the prepared
 631     *   statement uses ? placeholders, this array must be an indexed array.
 632     *   If it contains named placeholders, it must be an associative array.
 633     * @param $options
 634     *   An associative array of options to control how the query is run. See
 635     *   the documentation for DatabaseConnection::defaultOptions() for details.
 636     *
 637     * @return DatabaseStatementInterface
 638     *   This method will return one of: the executed statement, the number of
 639     *   rows affected by the query (not the number matched), or the generated
 640     *   insert IT of the last query, depending on the value of
 641     *   $options['return']. Typically that value will be set by default or a
 642     *   query builder and should not be set by a user. If there is an error,
 643     *   this method will return NULL and may throw an exception if
 644     *   $options['throw_exception'] is TRUE.
 645     *
 646     * @throws PDOException
 647     */
 648    public function query($query, array $args = array(), $options = array()) {
 649  
 650      // Use default values if not already set.
 651      $options += $this->defaultOptions();
 652  
 653      try {
 654        // We allow either a pre-bound statement object or a literal string.
 655        // In either case, we want to end up with an executed statement object,
 656        // which we pass to PDOStatement::execute.
 657        if ($query instanceof DatabaseStatementInterface) {
 658          $stmt = $query;
 659          $stmt->execute(NULL, $options);
 660        }
 661        else {
 662          $this->expandArguments($query, $args);
 663          $stmt = $this->prepareQuery($query);
 664          $stmt->execute($args, $options);
 665        }
 666  
 667        // Depending on the type of query we may need to return a different value.
 668        // See DatabaseConnection::defaultOptions() for a description of each
 669        // value.
 670        switch ($options['return']) {
 671          case Database::RETURN_STATEMENT:
 672            return $stmt;
 673          case Database::RETURN_AFFECTED:
 674            return $stmt->rowCount();
 675          case Database::RETURN_INSERT_ID:
 676            return $this->lastInsertId();
 677          case Database::RETURN_NULL:
 678            return;
 679          default:
 680            throw new PDOException('Invalid return directive: ' . $options['return']);
 681        }
 682      }
 683      catch (PDOException $e) {
 684        if ($options['throw_exception']) {
 685          // Add additional debug information.
 686          if ($query instanceof DatabaseStatementInterface) {
 687            $e->query_string = $stmt->getQueryString();
 688          }
 689          else {
 690            $e->query_string = $query;
 691          }
 692          $e->args = $args;
 693          throw $e;
 694        }
 695        return NULL;
 696      }
 697    }
 698  
 699    /**
 700     * Expands out shorthand placeholders.
 701     *
 702     * Drupal supports an alternate syntax for doing arrays of values. We
 703     * therefore need to expand them out into a full, executable query string.
 704     *
 705     * @param $query
 706     *   The query string to modify.
 707     * @param $args
 708     *   The arguments for the query.
 709     *
 710     * @return
 711     *   TRUE if the query was modified, FALSE otherwise.
 712     */
 713    protected function expandArguments(&$query, &$args) {
 714      $modified = FALSE;
 715  
 716      // If the placeholder value to insert is an array, assume that we need
 717      // to expand it out into a comma-delimited set of placeholders.
 718      foreach (array_filter($args, 'is_array') as $key => $data) {
 719        $new_keys = array();
 720        foreach ($data as $i => $value) {
 721          // This assumes that there are no other placeholders that use the same
 722          // name.  For example, if the array placeholder is defined as :example
 723          // and there is already an :example_2 placeholder, this will generate
 724          // a duplicate key.  We do not account for that as the calling code
 725          // is already broken if that happens.
 726          $new_keys[$key . '_' . $i] = $value;
 727        }
 728  
 729        // Update the query with the new placeholders.
 730        // preg_replace is necessary to ensure the replacement does not affect
 731        // placeholders that start with the same exact text. For example, if the
 732        // query contains the placeholders :foo and :foobar, and :foo has an
 733        // array of values, using str_replace would affect both placeholders,
 734        // but using the following preg_replace would only affect :foo because
 735        // it is followed by a non-word character.
 736        $query = preg_replace('#' . $key . '\b#', implode(', ', array_keys($new_keys)), $query);
 737  
 738        // Update the args array with the new placeholders.
 739        unset($args[$key]);
 740        $args += $new_keys;
 741  
 742        $modified = TRUE;
 743      }
 744  
 745      return $modified;
 746    }
 747  
 748    /**
 749     * Gets the driver-specific override class if any for the specified class.
 750     *
 751     * @param string $class
 752     *   The class for which we want the potentially driver-specific class.
 753     * @param array $files
 754     *   The name of the files in which the driver-specific class can be.
 755     * @param $use_autoload
 756     *   If TRUE, attempt to load classes using PHP's autoload capability
 757     *   as well as the manual approach here.
 758     * @return string
 759     *   The name of the class that should be used for this driver.
 760     */
 761    public function getDriverClass($class, array $files = array(), $use_autoload = FALSE) {
 762      if (empty($this->driverClasses[$class])) {
 763        $driver = $this->driver();
 764        $this->driverClasses[$class] = $class . '_' . $driver;
 765        Database::loadDriverFile($driver, $files);
 766        if (!class_exists($this->driverClasses[$class], $use_autoload)) {
 767          $this->driverClasses[$class] = $class;
 768        }
 769      }
 770      return $this->driverClasses[$class];
 771    }
 772  
 773    /**
 774     * Prepares and returns a SELECT query object.
 775     *
 776     * @param $table
 777     *   The base table for this query, that is, the first table in the FROM
 778     *   clause. This table will also be used as the "base" table for query_alter
 779     *   hook implementations.
 780     * @param $alias
 781     *   The alias of the base table of this query.
 782     * @param $options
 783     *   An array of options on the query.
 784     *
 785     * @return SelectQueryInterface
 786     *   An appropriate SelectQuery object for this database connection. Note that
 787     *   it may be a driver-specific subclass of SelectQuery, depending on the
 788     *   driver.
 789     *
 790     * @see SelectQuery
 791     */
 792    public function select($table, $alias = NULL, array $options = array()) {
 793      $class = $this->getDriverClass('SelectQuery', array('query.inc', 'select.inc'));
 794      return new $class($table, $alias, $this, $options);
 795    }
 796  
 797    /**
 798     * Prepares and returns an INSERT query object.
 799     *
 800     * @param $options
 801     *   An array of options on the query.
 802     *
 803     * @return InsertQuery
 804     *   A new InsertQuery object.
 805     *
 806     * @see InsertQuery
 807     */
 808    public function insert($table, array $options = array()) {
 809      $class = $this->getDriverClass('InsertQuery', array('query.inc'));
 810      return new $class($this, $table, $options);
 811    }
 812  
 813    /**
 814     * Prepares and returns a MERGE query object.
 815     *
 816     * @param $options
 817     *   An array of options on the query.
 818     *
 819     * @return MergeQuery
 820     *   A new MergeQuery object.
 821     *
 822     * @see MergeQuery
 823     */
 824    public function merge($table, array $options = array()) {
 825      $class = $this->getDriverClass('MergeQuery', array('query.inc'));
 826      return new $class($this, $table, $options);
 827    }
 828  
 829  
 830    /**
 831     * Prepares and returns an UPDATE query object.
 832     *
 833     * @param $options
 834     *   An array of options on the query.
 835     *
 836     * @return UpdateQuery
 837     *   A new UpdateQuery object.
 838     *
 839     * @see UpdateQuery
 840     */
 841    public function update($table, array $options = array()) {
 842      $class = $this->getDriverClass('UpdateQuery', array('query.inc'));
 843      return new $class($this, $table, $options);
 844    }
 845  
 846    /**
 847     * Prepares and returns a DELETE query object.
 848     *
 849     * @param $options
 850     *   An array of options on the query.
 851     *
 852     * @return DeleteQuery
 853     *   A new DeleteQuery object.
 854     *
 855     * @see DeleteQuery
 856     */
 857    public function delete($table, array $options = array()) {
 858      $class = $this->getDriverClass('DeleteQuery', array('query.inc'));
 859      return new $class($this, $table, $options);
 860    }
 861  
 862    /**
 863     * Prepares and returns a TRUNCATE query object.
 864     *
 865     * @param $options
 866     *   An array of options on the query.
 867     *
 868     * @return TruncateQuery
 869     *   A new TruncateQuery object.
 870     *
 871     * @see TruncateQuery
 872     */
 873    public function truncate($table, array $options = array()) {
 874      $class = $this->getDriverClass('TruncateQuery', array('query.inc'));
 875      return new $class($this, $table, $options);
 876    }
 877  
 878    /**
 879     * Returns a DatabaseSchema object for manipulating the schema.
 880     *
 881     * This method will lazy-load the appropriate schema library file.
 882     *
 883     * @return DatabaseSchema
 884     *   The DatabaseSchema object for this connection.
 885     */
 886    public function schema() {
 887      if (empty($this->schema)) {
 888        $class = $this->getDriverClass('DatabaseSchema', array('schema.inc'));
 889        if (class_exists($class)) {
 890          $this->schema = new $class($this);
 891        }
 892      }
 893      return $this->schema;
 894    }
 895  
 896    /**
 897     * Escapes a table name string.
 898     *
 899     * Force all table names to be strictly alphanumeric-plus-underscore.
 900     * For some database drivers, it may also wrap the table name in
 901     * database-specific escape characters.
 902     *
 903     * @return
 904     *   The sanitized table name string.
 905     */
 906    public function escapeTable($table) {
 907      return preg_replace('/[^A-Za-z0-9_.]+/', '', $table);
 908    }
 909  
 910    /**
 911     * Escapes a field name string.
 912     *
 913     * Force all field names to be strictly alphanumeric-plus-underscore.
 914     * For some database drivers, it may also wrap the field name in
 915     * database-specific escape characters.
 916     *
 917     * @return
 918     *   The sanitized field name string.
 919     */
 920    public function escapeField($field) {
 921      return preg_replace('/[^A-Za-z0-9_.]+/', '', $field);
 922    }
 923  
 924    /**
 925     * Escapes an alias name string.
 926     *
 927     * Force all alias names to be strictly alphanumeric-plus-underscore. In
 928     * contrast to DatabaseConnection::escapeField() /
 929     * DatabaseConnection::escapeTable(), this doesn't allow the period (".")
 930     * because that is not allowed in aliases.
 931     *
 932     * @return
 933     *   The sanitized field name string.
 934     */
 935    public function escapeAlias($field) {
 936      return preg_replace('/[^A-Za-z0-9_]+/', '', $field);
 937    }
 938  
 939    /**
 940     * Escapes characters that work as wildcard characters in a LIKE pattern.
 941     *
 942     * The wildcard characters "%" and "_" as well as backslash are prefixed with
 943     * a backslash. Use this to do a search for a verbatim string without any
 944     * wildcard behavior.
 945     *
 946     * For example, the following does a case-insensitive query for all rows whose
 947     * name starts with $prefix:
 948     * @code
 949     * $result = db_query(
 950     *   'SELECT * FROM person WHERE name LIKE :pattern',
 951     *   array(':pattern' => db_like($prefix) . '%')
 952     * );
 953     * @endcode
 954     *
 955     * Backslash is defined as escape character for LIKE patterns in
 956     * DatabaseCondition::mapConditionOperator().
 957     *
 958     * @param $string
 959     *   The string to escape.
 960     *
 961     * @return
 962     *   The escaped string.
 963     */
 964    public function escapeLike($string) {
 965      return addcslashes($string, '\%_');
 966    }
 967  
 968    /**
 969     * Determines if there is an active transaction open.
 970     *
 971     * @return
 972     *   TRUE if we're currently in a transaction, FALSE otherwise.
 973     */
 974    public function inTransaction() {
 975      return ($this->transactionDepth() > 0);
 976    }
 977  
 978    /**
 979     * Determines current transaction depth.
 980     */
 981    public function transactionDepth() {
 982      return count($this->transactionLayers);
 983    }
 984  
 985    /**
 986     * Returns a new DatabaseTransaction object on this connection.
 987     *
 988     * @param $name
 989     *   Optional name of the savepoint.
 990     *
 991     * @return DatabaseTransaction
 992     *   A DatabaseTransaction object.
 993     *
 994     * @see DatabaseTransaction
 995     */
 996    public function startTransaction($name = '') {
 997      $class = $this->getDriverClass('DatabaseTransaction');
 998      return new $class($this, $name);
 999    }
1000  
1001    /**
1002     * Rolls back the transaction entirely or to a named savepoint.
1003     *
1004     * This method throws an exception if no transaction is active.
1005     *
1006     * @param $savepoint_name
1007     *   The name of the savepoint. The default, 'drupal_transaction', will roll
1008     *   the entire transaction back.
1009     *
1010     * @throws DatabaseTransactionNoActiveException
1011     *
1012     * @see DatabaseTransaction::rollback()
1013     */
1014    public function rollback($savepoint_name = 'drupal_transaction') {
1015      if (!$this->supportsTransactions()) {
1016        return;
1017      }
1018      if (!$this->inTransaction()) {
1019        throw new DatabaseTransactionNoActiveException();
1020      }
1021      // A previous rollback to an earlier savepoint may mean that the savepoint
1022      // in question has already been accidentally committed.
1023      if (!isset($this->transactionLayers[$savepoint_name])) {
1024        throw new DatabaseTransactionNoActiveException();
1025      }
1026  
1027      // We need to find the point we're rolling back to, all other savepoints
1028      // before are no longer needed. If we rolled back other active savepoints,
1029      // we need to throw an exception.
1030      $rolled_back_other_active_savepoints = FALSE;
1031      while ($savepoint = array_pop($this->transactionLayers)) {
1032        if ($savepoint == $savepoint_name) {
1033          // If it is the last the transaction in the stack, then it is not a
1034          // savepoint, it is the transaction itself so we will need to roll back
1035          // the transaction rather than a savepoint.
1036          if (empty($this->transactionLayers)) {
1037            break;
1038          }
1039          $this->query('ROLLBACK TO SAVEPOINT ' . $savepoint);
1040          $this->popCommittableTransactions();
1041          if ($rolled_back_other_active_savepoints) {
1042            throw new DatabaseTransactionOutOfOrderException();
1043          }
1044          return;
1045        }
1046        else {
1047          $rolled_back_other_active_savepoints = TRUE;
1048        }
1049      }
1050      parent::rollBack();
1051      if ($rolled_back_other_active_savepoints) {
1052        throw new DatabaseTransactionOutOfOrderException();
1053      }
1054    }
1055  
1056    /**
1057     * Increases the depth of transaction nesting.
1058     *
1059     * If no transaction is already active, we begin a new transaction.
1060     *
1061     * @throws DatabaseTransactionNameNonUniqueException
1062     *
1063     * @see DatabaseTransaction
1064     */
1065    public function pushTransaction($name) {
1066      if (!$this->supportsTransactions()) {
1067        return;
1068      }
1069      if (isset($this->transactionLayers[$name])) {
1070        throw new DatabaseTransactionNameNonUniqueException($name . " is already in use.");
1071      }
1072      // If we're already in a transaction then we want to create a savepoint
1073      // rather than try to create another transaction.
1074      if ($this->inTransaction()) {
1075        $this->query('SAVEPOINT ' . $name);
1076      }
1077      else {
1078        parent::beginTransaction();
1079      }
1080      $this->transactionLayers[$name] = $name;
1081    }
1082  
1083    /**
1084     * Decreases the depth of transaction nesting.
1085     *
1086     * If we pop off the last transaction layer, then we either commit or roll
1087     * back the transaction as necessary. If no transaction is active, we return
1088     * because the transaction may have manually been rolled back.
1089     *
1090     * @param $name
1091     *   The name of the savepoint
1092     *
1093     * @throws DatabaseTransactionNoActiveException
1094     * @throws DatabaseTransactionCommitFailedException
1095     *
1096     * @see DatabaseTransaction
1097     */
1098    public function popTransaction($name) {
1099      if (!$this->supportsTransactions()) {
1100        return;
1101      }
1102      // The transaction has already been committed earlier. There is nothing we
1103      // need to do. If this transaction was part of an earlier out-of-order
1104      // rollback, an exception would already have been thrown by
1105      // Database::rollback().
1106      if (!isset($this->transactionLayers[$name])) {
1107        return;
1108      }
1109  
1110      // Mark this layer as committable.
1111      $this->transactionLayers[$name] = FALSE;
1112      $this->popCommittableTransactions();
1113    }
1114  
1115    /**
1116     * Internal function: commit all the transaction layers that can commit.
1117     */
1118    protected function popCommittableTransactions() {
1119      // Commit all the committable layers.
1120      foreach (array_reverse($this->transactionLayers) as $name => $active) {
1121        // Stop once we found an active transaction.
1122        if ($active) {
1123          break;
1124        }
1125  
1126        // If there are no more layers left then we should commit.
1127        unset($this->transactionLayers[$name]);
1128        if (empty($this->transactionLayers)) {
1129          if (!parent::commit()) {
1130            throw new DatabaseTransactionCommitFailedException();
1131          }
1132        }
1133        else {
1134          $this->query('RELEASE SAVEPOINT ' . $name);
1135        }
1136      }
1137    }
1138  
1139    /**
1140     * Runs a limited-range query on this database object.
1141     *
1142     * Use this as a substitute for ->query() when a subset of the query is to be
1143     * returned. User-supplied arguments to the query should be passed in as
1144     * separate parameters so that they can be properly escaped to avoid SQL
1145     * injection attacks.
1146     *
1147     * @param $query
1148     *   A string containing an SQL query.
1149     * @param $args
1150     *   An array of values to substitute into the query at placeholder markers.
1151     * @param $from
1152     *   The first result row to return.
1153     * @param $count
1154     *   The maximum number of result rows to return.
1155     * @param $options
1156     *   An array of options on the query.
1157     *
1158     * @return DatabaseStatementInterface
1159     *   A database query result resource, or NULL if the query was not executed
1160     *   correctly.
1161     */
1162    abstract public function queryRange($query, $from, $count, array $args = array(), array $options = array());
1163  
1164    /**
1165     * Generates a temporary table name.
1166     *
1167     * @return
1168     *   A table name.
1169     */
1170    protected function generateTemporaryTableName() {
1171      return "db_temporary_" . $this->temporaryNameIndex++;
1172    }
1173  
1174    /**
1175     * Runs a SELECT query and stores its results in a temporary table.
1176     *
1177     * Use this as a substitute for ->query() when the results need to stored
1178     * in a temporary table. Temporary tables exist for the duration of the page
1179     * request. User-supplied arguments to the query should be passed in as
1180     * separate parameters so that they can be properly escaped to avoid SQL
1181     * injection attacks.
1182     *
1183     * Note that if you need to know how many results were returned, you should do
1184     * a SELECT COUNT(*) on the temporary table afterwards.
1185     *
1186     * @param $query
1187     *   A string containing a normal SELECT SQL query.
1188     * @param $args
1189     *   An array of values to substitute into the query at placeholder markers.
1190     * @param $options
1191     *   An associative array of options to control how the query is run. See
1192     *   the documentation for DatabaseConnection::defaultOptions() for details.
1193     *
1194     * @return
1195     *   The name of the temporary table.
1196     */
1197    abstract function queryTemporary($query, array $args = array(), array $options = array());
1198  
1199    /**
1200     * Returns the type of database driver.
1201     *
1202     * This is not necessarily the same as the type of the database itself. For
1203     * instance, there could be two MySQL drivers, mysql and mysql_mock. This
1204     * function would return different values for each, but both would return
1205     * "mysql" for databaseType().
1206     */
1207    abstract public function driver();
1208  
1209    /**
1210     * Returns the version of the database server.
1211     */
1212    public function version() {
1213      return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
1214    }
1215  
1216    /**
1217     * Determines if this driver supports transactions.
1218     *
1219     * @return
1220     *   TRUE if this connection supports transactions, FALSE otherwise.
1221     */
1222    public function supportsTransactions() {
1223      return $this->transactionSupport;
1224    }
1225  
1226    /**
1227     * Determines if this driver supports transactional DDL.
1228     *
1229     * DDL queries are those that change the schema, such as ALTER queries.
1230     *
1231     * @return
1232     *   TRUE if this connection supports transactions for DDL queries, FALSE
1233     *   otherwise.
1234     */
1235    public function supportsTransactionalDDL() {
1236      return $this->transactionalDDLSupport;
1237    }
1238  
1239    /**
1240     * Returns the name of the PDO driver for this connection.
1241     */
1242    abstract public function databaseType();
1243  
1244  
1245    /**
1246     * Gets any special processing requirements for the condition operator.
1247     *
1248     * Some condition types require special processing, such as IN, because
1249     * the value data they pass in is not a simple value. This is a simple
1250     * overridable lookup function. Database connections should define only
1251     * those operators they wish to be handled differently than the default.
1252     *
1253     * @param $operator
1254     *   The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
1255     *
1256     * @return
1257     *   The extra handling directives for the specified operator, or NULL.
1258     *
1259     * @see DatabaseCondition::compile()
1260     */
1261    abstract public function mapConditionOperator($operator);
1262  
1263    /**
1264     * Throws an exception to deny direct access to transaction commits.
1265     *
1266     * We do not want to allow users to commit transactions at any time, only
1267     * by destroying the transaction object or allowing it to go out of scope.
1268     * A direct commit bypasses all of the safety checks we've built on top of
1269     * PDO's transaction routines.
1270     *
1271     * @throws DatabaseTransactionExplicitCommitNotAllowedException
1272     *
1273     * @see DatabaseTransaction
1274     */
1275    public function commit() {
1276      throw new DatabaseTransactionExplicitCommitNotAllowedException();
1277    }
1278  
1279    /**
1280     * Retrieves an unique id from a given sequence.
1281     *
1282     * Use this function if for some reason you can't use a serial field. For
1283     * example, MySQL has no ways of reading of the current value of a sequence
1284     * and PostgreSQL can not advance the sequence to be larger than a given
1285     * value. Or sometimes you just need a unique integer.
1286     *
1287     * @param $existing_id
1288     *   After a database import, it might be that the sequences table is behind,
1289     *   so by passing in the maximum existing id, it can be assured that we
1290     *   never issue the same id.
1291     *
1292     * @return
1293     *   An integer number larger than any number returned by earlier calls and
1294     *   also larger than the $existing_id if one was passed in.
1295     */
1296    abstract public function nextId($existing_id = 0);
1297  }
1298  
1299  /**
1300   * Primary front-controller for the database system.
1301   *
1302   * This class is uninstantiatable and un-extendable. It acts to encapsulate
1303   * all control and shepherding of database connections into a single location
1304   * without the use of globals.
1305   */
1306  abstract class Database {
1307  
1308    /**
1309     * Flag to indicate a query call should simply return NULL.
1310     *
1311     * This is used for queries that have no reasonable return value anyway, such
1312     * as INSERT statements to a table without a serial primary key.
1313     */
1314    const RETURN_NULL = 0;
1315  
1316    /**
1317     * Flag to indicate a query call should return the prepared statement.
1318     */
1319    const RETURN_STATEMENT = 1;
1320  
1321    /**
1322     * Flag to indicate a query call should return the number of affected rows.
1323     */
1324    const RETURN_AFFECTED = 2;
1325  
1326    /**
1327     * Flag to indicate a query call should return the "last insert id".
1328     */
1329    const RETURN_INSERT_ID = 3;
1330  
1331    /**
1332     * An nested array of all active connections. It is keyed by database name
1333     * and target.
1334     *
1335     * @var array
1336     */
1337    static protected $connections = array();
1338  
1339    /**
1340     * A processed copy of the database connection information from settings.php.
1341     *
1342     * @var array
1343     */
1344    static protected $databaseInfo = NULL;
1345  
1346    /**
1347     * A list of key/target credentials to simply ignore.
1348     *
1349     * @var array
1350     */
1351    static protected $ignoreTargets = array();
1352  
1353    /**
1354     * The key of the currently active database connection.
1355     *
1356     * @var string
1357     */
1358    static protected $activeKey = 'default';
1359  
1360    /**
1361     * An array of active query log objects.
1362     *
1363     * Every connection has one and only one logger object for all targets and
1364     * logging keys.
1365     *
1366     * array(
1367     *   '$db_key' => DatabaseLog object.
1368     * );
1369     *
1370     * @var array
1371     */
1372    static protected $logs = array();
1373  
1374    /**
1375     * Starts logging a given logging key on the specified connection.
1376     *
1377     * @param $logging_key
1378     *   The logging key to log.
1379     * @param $key
1380     *   The database connection key for which we want to log.
1381     *
1382     * @return DatabaseLog
1383     *   The query log object. Note that the log object does support richer
1384     *   methods than the few exposed through the Database class, so in some
1385     *   cases it may be desirable to access it directly.
1386     *
1387     * @see DatabaseLog
1388     */
1389    final public static function startLog($logging_key, $key = 'default') {
1390      if (empty(self::$logs[$key])) {
1391        self::$logs[$key] = new DatabaseLog($key);
1392  
1393        // Every target already active for this connection key needs to have the
1394        // logging object associated with it.
1395        if (!empty(self::$connections[$key])) {
1396          foreach (self::$connections[$key] as $connection) {
1397            $connection->setLogger(self::$logs[$key]);
1398          }
1399        }
1400      }
1401  
1402      self::$logs[$key]->start($logging_key);
1403      return self::$logs[$key];
1404    }
1405  
1406    /**
1407     * Retrieves the queries logged on for given logging key.
1408     *
1409     * This method also ends logging for the specified key. To get the query log
1410     * to date without ending the logger request the logging object by starting
1411     * it again (which does nothing to an open log key) and call methods on it as
1412     * desired.
1413     *
1414     * @param $logging_key
1415     *   The logging key to log.
1416     * @param $key
1417     *   The database connection key for which we want to log.
1418     *
1419     * @return array
1420     *   The query log for the specified logging key and connection.
1421     *
1422     * @see DatabaseLog
1423     */
1424    final public static function getLog($logging_key, $key = 'default') {
1425      if (empty(self::$logs[$key])) {
1426        return NULL;
1427      }
1428      $queries = self::$logs[$key]->get($logging_key);
1429      self::$logs[$key]->end($logging_key);
1430      return $queries;
1431    }
1432  
1433    /**
1434     * Gets the connection object for the specified database key and target.
1435     *
1436     * @param $target
1437     *   The database target name.
1438     * @param $key
1439     *   The database connection key. Defaults to NULL which means the active key.
1440     *
1441     * @return DatabaseConnection
1442     *   The corresponding connection object.
1443     */
1444    final public static function getConnection($target = 'default', $key = NULL) {
1445      if (!isset($key)) {
1446        // By default, we want the active connection, set in setActiveConnection.
1447        $key = self::$activeKey;
1448      }
1449      // If the requested target does not exist, or if it is ignored, we fall back
1450      // to the default target. The target is typically either "default" or
1451      // "slave", indicating to use a slave SQL server if one is available. If
1452      // it's not available, then the default/master server is the correct server
1453      // to use.
1454      if (!empty(self::$ignoreTargets[$key][$target]) || !isset(self::$databaseInfo[$key][$target])) {
1455        $target = 'default';
1456      }
1457  
1458      if (!isset(self::$connections[$key][$target])) {
1459        // If necessary, a new connection is opened.
1460        self::$connections[$key][$target] = self::openConnection($key, $target);
1461      }
1462      return self::$connections[$key][$target];
1463    }
1464  
1465    /**
1466     * Determines if there is an active connection.
1467     *
1468     * Note that this method will return FALSE if no connection has been
1469     * established yet, even if one could be.
1470     *
1471     * @return
1472     *   TRUE if there is at least one database connection established, FALSE
1473     *   otherwise.
1474     */
1475    final public static function isActiveConnection() {
1476      return !empty(self::$activeKey) && !empty(self::$connections) && !empty(self::$connections[self::$activeKey]);
1477    }
1478  
1479    /**
1480     * Sets the active connection to the specified key.
1481     *
1482     * @return
1483     *   The previous database connection key.
1484     */
1485    final public static function setActiveConnection($key = 'default') {
1486      if (empty(self::$databaseInfo)) {
1487        self::parseConnectionInfo();
1488      }
1489  
1490      if (!empty(self::$databaseInfo[$key])) {
1491        $old_key = self::$activeKey;
1492        self::$activeKey = $key;
1493        return $old_key;
1494      }
1495    }
1496  
1497    /**
1498     * Process the configuration file for database information.
1499     */
1500    final public static function parseConnectionInfo() {
1501      global $databases;
1502  
1503      $database_info = is_array($databases) ? $databases : array();
1504      foreach ($database_info as $index => $info) {
1505        foreach ($database_info[$index] as $target => $value) {
1506          // If there is no "driver" property, then we assume it's an array of
1507          // possible connections for this target. Pick one at random. That allows
1508          //  us to have, for example, multiple slave servers.
1509          if (empty($value['driver'])) {
1510            $database_info[$index][$target] = $database_info[$index][$target][mt_rand(0, count($database_info[$index][$target]) - 1)];
1511          }
1512  
1513          // Parse the prefix information.
1514          if (!isset($database_info[$index][$target]['prefix'])) {
1515            // Default to an empty prefix.
1516            $database_info[$index][$target]['prefix'] = array(
1517              'default' => '',
1518            );
1519          }
1520          elseif (!is_array($database_info[$index][$target]['prefix'])) {
1521            // Transform the flat form into an array form.
1522            $database_info[$index][$target]['prefix'] = array(
1523              'default' => $database_info[$index][$target]['prefix'],
1524            );
1525          }
1526        }
1527      }
1528  
1529      if (!is_array(self::$databaseInfo)) {
1530        self::$databaseInfo = $database_info;
1531      }
1532  
1533      // Merge the new $database_info into the existing.
1534      // array_merge_recursive() cannot be used, as it would make multiple
1535      // database, user, and password keys in the same database array.
1536      else {
1537        foreach ($database_info as $database_key => $database_values) {
1538          foreach ($database_values as $target => $target_values) {
1539            self::$databaseInfo[$database_key][$target] = $target_values;
1540          }
1541        }
1542      }
1543    }
1544  
1545    /**
1546     * Adds database connection information for a given key/target.
1547     *
1548     * This method allows the addition of new connection credentials at runtime.
1549     * Under normal circumstances the preferred way to specify database
1550     * credentials is via settings.php. However, this method allows them to be
1551     * added at arbitrary times, such as during unit tests, when connecting to
1552     * admin-defined third party databases, etc.
1553     *
1554     * If the given key/target pair already exists, this method will be ignored.
1555     *
1556     * @param $key
1557     *   The database key.
1558     * @param $target
1559     *   The database target name.
1560     * @param $info
1561     *   The database connection information, as it would be defined in
1562     *   settings.php. Note that the structure of this array will depend on the
1563     *   database driver it is connecting to.
1564     */
1565    public static function addConnectionInfo($key, $target, $info) {
1566      if (empty(self::$databaseInfo[$key][$target])) {
1567        self::$databaseInfo[$key][$target] = $info;
1568      }
1569    }
1570  
1571    /**
1572     * Gets information on the specified database connection.
1573     *
1574     * @param $connection
1575     *   The connection key for which we want information.
1576     */
1577    final public static function getConnectionInfo($key = 'default') {
1578      if (empty(self::$databaseInfo)) {
1579        self::parseConnectionInfo();
1580      }
1581  
1582      if (!empty(self::$databaseInfo[$key])) {
1583        return self::$databaseInfo[$key];
1584      }
1585    }
1586  
1587    /**
1588     * Rename a connection and its corresponding connection information.
1589     *
1590     * @param $old_key
1591     *   The old connection key.
1592     * @param $new_key
1593     *   The new connection key.
1594     * @return
1595     *   TRUE in case of success, FALSE otherwise.
1596     */
1597    final public static function renameConnection($old_key, $new_key) {
1598      if (empty(self::$databaseInfo)) {
1599        self::parseConnectionInfo();
1600      }
1601  
1602      if (!empty(self::$databaseInfo[$old_key]) && empty(self::$databaseInfo[$new_key])) {
1603        // Migrate the database connection information.
1604        self::$databaseInfo[$new_key] = self::$databaseInfo[$old_key];
1605        unset(self::$databaseInfo[$old_key]);
1606  
1607        // Migrate over the DatabaseConnection object if it exists.
1608        if (isset(self::$connections[$old_key])) {
1609          self::$connections[$new_key] = self::$connections[$old_key];
1610          unset(self::$connections[$old_key]);
1611        }
1612  
1613        return TRUE;
1614      }
1615      else {
1616        return FALSE;
1617      }
1618    }
1619  
1620    /**
1621     * Remove a connection and its corresponding connection information.
1622     *
1623     * @param $key
1624     *   The connection key.
1625     * @return
1626     *   TRUE in case of success, FALSE otherwise.
1627     */
1628    final public static function removeConnection($key) {
1629      if (isset(self::$databaseInfo[$key])) {
1630        unset(self::$databaseInfo[$key]);
1631        unset(self::$connections[$key]);
1632        return TRUE;
1633      }
1634      else {
1635        return FALSE;
1636      }
1637    }
1638  
1639    /**
1640     * Opens a connection to the server specified by the given key and target.
1641     *
1642     * @param $key
1643     *   The database connection key, as specified in settings.php. The default is
1644     *   "default".
1645     * @param $target
1646     *   The database target to open.
1647     *
1648     * @throws DatabaseConnectionNotDefinedException
1649     * @throws DatabaseDriverNotSpecifiedException
1650     */
1651    final protected static function openConnection($key, $target) {
1652      if (empty(self::$databaseInfo)) {
1653        self::parseConnectionInfo();
1654      }
1655  
1656      // If the requested database does not exist then it is an unrecoverable
1657      // error.
1658      if (!isset(self::$databaseInfo[$key])) {
1659        throw new DatabaseConnectionNotDefinedException('The specified database connection is not defined: ' . $key);
1660      }
1661  
1662      if (!$driver = self::$databaseInfo[$key][$target]['driver']) {
1663        throw new DatabaseDriverNotSpecifiedException('Driver not specified for this database connection: ' . $key);
1664      }
1665  
1666      // We cannot rely on the registry yet, because the registry requires an
1667      // open database connection.
1668      $driver_class = 'DatabaseConnection_' . $driver;
1669      require_once  DRUPAL_ROOT . '/includes/database/' . $driver . '/database.inc';
1670      $new_connection = new $driver_class(self::$databaseInfo[$key][$target]);
1671      $new_connection->setTarget($target);
1672      $new_connection->setKey($key);
1673  
1674      // If we have any active logging objects for this connection key, we need
1675      // to associate them with the connection we just opened.
1676      if (!empty(self::$logs[$key])) {
1677        $new_connection->setLogger(self::$logs[$key]);
1678      }
1679  
1680      return $new_connection;
1681    }
1682  
1683    /**
1684     * Closes a connection to the server specified by the given key and target.
1685     *
1686     * @param $target
1687     *   The database target name.  Defaults to NULL meaning that all target
1688     *   connections will be closed.
1689     * @param $key
1690     *   The database connection key. Defaults to NULL which means the active key.
1691     */
1692    public static function closeConnection($target = NULL, $key = NULL) {
1693      // Gets the active connection by default.
1694      if (!isset($key)) {
1695        $key = self::$activeKey;
1696      }
1697      // To close the connection, we need to unset the static variable.
1698      if (isset($target)) {
1699        unset(self::$connections[$key][$target]);
1700      }
1701      else {
1702        unset(self::$connections[$key]);
1703      }
1704    }
1705  
1706    /**
1707     * Instructs the system to temporarily ignore a given key/target.
1708     *
1709     * At times we need to temporarily disable slave queries. To do so, call this
1710     * method with the database key and the target to disable. That database key
1711     * will then always fall back to 'default' for that key, even if it's defined.
1712     *
1713     * @param $key
1714     *   The database connection key.
1715     * @param $target
1716     *   The target of the specified key to ignore.
1717     */
1718    public static function ignoreTarget($key, $target) {
1719      self::$ignoreTargets[$key][$target] = TRUE;
1720    }
1721  
1722    /**
1723     * Load a file for the database that might hold a class.
1724     *
1725     * @param $driver
1726     *   The name of the driver.
1727     * @param array $files
1728     *   The name of the files the driver specific class can be.
1729     */
1730    public static function loadDriverFile($driver, array $files = array()) {
1731      static $base_path;
1732  
1733      if (empty($base_path)) {
1734        $base_path = dirname(realpath(__FILE__));
1735      }
1736  
1737      $driver_base_path = "$base_path/$driver";
1738      foreach ($files as $file) {
1739        // Load the base file first so that classes extending base classes will
1740        // have the base class loaded.
1741        foreach (array("$base_path/$file", "$driver_base_path/$file") as $filename) {
1742          // The OS caches file_exists() and PHP caches require_once(), so
1743          // we'll let both of those take care of performance here.
1744          if (file_exists($filename)) {
1745            require_once $filename;
1746          }
1747        }
1748      }
1749    }
1750  }
1751  
1752  /**
1753   * Exception for when popTransaction() is called with no active transaction.
1754   */
1755  class DatabaseTransactionNoActiveException extends Exception { }
1756  
1757  /**
1758   * Exception thrown when a savepoint or transaction name occurs twice.
1759   */
1760  class DatabaseTransactionNameNonUniqueException extends Exception { }
1761  
1762  /**
1763   * Exception thrown when a commit() function fails.
1764   */
1765  class DatabaseTransactionCommitFailedException extends Exception { }
1766  
1767  /**
1768   * Exception to deny attempts to explicitly manage transactions.
1769   *
1770   * This exception will be thrown when the PDO connection commit() is called.
1771   * Code should never call this method directly.
1772   */
1773  class DatabaseTransactionExplicitCommitNotAllowedException extends Exception { }
1774  
1775  /**
1776   * Exception thrown when a rollback() resulted in other active transactions being rolled-back.
1777   */
1778  class DatabaseTransactionOutOfOrderException extends Exception { }
1779  
1780  /**
1781   * Exception thrown for merge queries that do not make semantic sense.
1782   *
1783   * There are many ways that a merge query could be malformed.  They should all
1784   * throw this exception and set an appropriately descriptive message.
1785   */
1786  class InvalidMergeQueryException extends Exception {}
1787  
1788  /**
1789   * Exception thrown if an insert query specifies a field twice.
1790   *
1791   * It is not allowed to specify a field as default and insert field, this
1792   * exception is thrown if that is the case.
1793   */
1794  class FieldsOverlapException extends Exception {}
1795  
1796  /**
1797   * Exception thrown if an insert query doesn't specify insert or default fields.
1798   */
1799  class NoFieldsException extends Exception {}
1800  
1801  /**
1802   * Exception thrown if an undefined database connection is requested.
1803   */
1804  class DatabaseConnectionNotDefinedException extends Exception {}
1805  
1806  /**
1807   * Exception thrown if no driver is specified for a database connection.
1808   */
1809  class DatabaseDriverNotSpecifiedException extends Exception {}
1810  
1811  
1812  /**
1813   * A wrapper class for creating and managing database transactions.
1814   *
1815   * Not all databases or database configurations support transactions. For
1816   * example, MySQL MyISAM tables do not. It is also easy to begin a transaction
1817   * and then forget to commit it, which can lead to connection errors when
1818   * another transaction is started.
1819   *
1820   * This class acts as a wrapper for transactions. To begin a transaction,
1821   * simply instantiate it. When the object goes out of scope and is destroyed
1822   * it will automatically commit. It also will check to see if the specified
1823   * connection supports transactions. If not, it will simply skip any transaction
1824   * commands, allowing user-space code to proceed normally. The only difference
1825   * is that rollbacks won't actually do anything.
1826   *
1827   * In the vast majority of cases, you should not instantiate this class
1828   * directly. Instead, call ->startTransaction(), from the appropriate connection
1829   * object.
1830   */
1831  class DatabaseTransaction {
1832  
1833    /**
1834     * The connection object for this transaction.
1835     *
1836     * @var DatabaseConnection
1837     */
1838    protected $connection;
1839  
1840    /**
1841     * A boolean value to indicate whether this transaction has been rolled back.
1842     *
1843     * @var Boolean
1844     */
1845    protected $rolledBack = FALSE;
1846  
1847    /**
1848     * The name of the transaction.
1849     *
1850     * This is used to label the transaction savepoint. It will be overridden to
1851     * 'drupal_transaction' if there is no transaction depth.
1852     */
1853    protected $name;
1854  
1855    public function __construct(DatabaseConnection &$connection, $name = NULL) {
1856      $this->connection = &$connection;
1857      // If there is no transaction depth, then no transaction has started. Name
1858      // the transaction 'drupal_transaction'.
1859      if (!$depth = $connection->transactionDepth()) {
1860        $this->name = 'drupal_transaction';
1861      }
1862      // Within transactions, savepoints are used. Each savepoint requires a
1863      // name. So if no name is present we need to create one.
1864      elseif (!$name) {
1865        $this->name = 'savepoint_' . $depth;
1866      }
1867      else {
1868        $this->name = $name;
1869      }
1870      $this->connection->pushTransaction($this->name);
1871    }
1872  
1873    public function __destruct() {
1874      // If we rolled back then the transaction would have already been popped.
1875      if (!$this->rolledBack) {
1876        $this->connection->popTransaction($this->name);
1877      }
1878    }
1879  
1880    /**
1881     * Retrieves the name of the transaction or savepoint.
1882     */
1883    public function name() {
1884      return $this->name;
1885    }
1886  
1887    /**
1888     * Rolls back the current transaction.
1889     *
1890     * This is just a wrapper method to rollback whatever transaction stack we are
1891     * currently in, which is managed by the connection object itself. Note that
1892     * logging (preferable with watchdog_exception()) needs to happen after a
1893     * transaction has been rolled back or the log messages will be rolled back
1894     * too.
1895     *
1896     * @see DatabaseConnection::rollback()
1897     * @see watchdog_exception()
1898     */
1899    public function rollback() {
1900      $this->rolledBack = TRUE;
1901      $this->connection->rollback($this->name);
1902    }
1903  }
1904  
1905  /**
1906   * Represents a prepared statement.
1907   *
1908   * Some methods in that class are purposefully commented out. Due to a change in
1909   * how PHP defines PDOStatement, we can't define a signature for those methods
1910   * that will work the same way between versions older than 5.2.6 and later
1911   * versions.  See http://bugs.php.net/bug.php?id=42452 for more details.
1912   *
1913   * Child implementations should either extend PDOStatement:
1914   * @code
1915   * class DatabaseStatement_oracle extends PDOStatement implements DatabaseStatementInterface {}
1916   * @endcode
1917   * or define their own class. If defining their own class, they will also have
1918   * to implement either the Iterator or IteratorAggregate interface before
1919   * DatabaseStatementInterface:
1920   * @code
1921   * class DatabaseStatement_oracle implements Iterator, DatabaseStatementInterface {}
1922   * @endcode
1923   */
1924  interface DatabaseStatementInterface extends Traversable {
1925  
1926    /**
1927     * Executes a prepared statement
1928     *
1929     * @param $args
1930     *   An array of values with as many elements as there are bound parameters in
1931     *   the SQL statement being executed.
1932     * @param $options
1933     *   An array of options for this query.
1934     *
1935     * @return
1936     *   TRUE on success, or FALSE on failure.
1937     */
1938    public function execute($args = array(), $options = array());
1939  
1940    /**
1941     * Gets the query string of this statement.
1942     *
1943     * @return
1944     *   The query string, in its form with placeholders.
1945     */
1946    public function getQueryString();
1947  
1948    /**
1949     * Returns the number of rows affected by the last SQL statement.
1950     *
1951     * @return
1952     *   The number of rows affected by the last DELETE, INSERT, or UPDATE
1953     *   statement executed.
1954     */
1955    public function rowCount();
1956  
1957    /**
1958     * Sets the default fetch mode for this statement.
1959     *
1960     * See http://php.net/manual/en/pdo.constants.php for the definition of the
1961     * constants used.
1962     *
1963     * @param $mode
1964     *   One of the PDO::FETCH_* constants.
1965     * @param $a1
1966     *   An option depending of the fetch mode specified by $mode:
1967     *   - for PDO::FETCH_COLUMN, the index of the column to fetch
1968     *   - for PDO::FETCH_CLASS, the name of the class to create
1969     *   - for PDO::FETCH_INTO, the object to add the data to
1970     * @param $a2
1971     *   If $mode is PDO::FETCH_CLASS, the optional arguments to pass to the
1972     *   constructor.
1973     */
1974    // public function setFetchMode($mode, $a1 = NULL, $a2 = array());
1975  
1976    /**
1977     * Fetches the next row from a result set.
1978     *
1979     * See http://php.net/manual/en/pdo.constants.php for the definition of the
1980     * constants used.
1981     *
1982     * @param $mode
1983     *   One of the PDO::FETCH_* constants.
1984     *   Default to what was specified by setFetchMode().
1985     * @param $cursor_orientation
1986     *   Not implemented in all database drivers, don't use.
1987     * @param $cursor_offset
1988     *   Not implemented in all database drivers, don't use.
1989     *
1990     * @return
1991     *   A result, formatted according to $mode.
1992     */
1993    // public function fetch($mode = NULL, $cursor_orientation = NULL, $cursor_offset = NULL);
1994  
1995    /**
1996     * Returns a single field from the next record of a result set.
1997     *
1998     * @param $index
1999     *   The numeric index of the field to return. Defaults to the first field.
2000     *
2001     * @return
2002     *   A single field from the next record, or FALSE if there is no next record.
2003     */
2004    public function fetchField($index = 0);
2005  
2006    /**
2007     * Fetches the next row and returns it as an object.
2008     *
2009     * The object will be of the class specified by DatabaseStatementInterface::setFetchMode()
2010     * or stdClass if not specified.
2011     */
2012    // public function fetchObject();
2013  
2014    /**
2015     * Fetches the next row and returns it as an associative array.
2016     *
2017     * This method corresponds to PDOStatement::fetchObject(), but for associative
2018     * arrays. For some reason PDOStatement does not have a corresponding array
2019     * helper method, so one is added.
2020     *
2021     * @return
2022     *   An associative array, or FALSE if there is no next row.
2023     */
2024    public function fetchAssoc();
2025  
2026    /**
2027     * Returns an array containing all of the result set rows.
2028     *
2029     * @param $mode
2030     *   One of the PDO::FETCH_* constants.
2031     * @param $column_index
2032     *   If $mode is PDO::FETCH_COLUMN, the index of the column to fetch.
2033     * @param $constructor_arguments
2034     *   If $mode is PDO::FETCH_CLASS, the arguments to pass to the constructor.
2035     *
2036     * @return
2037     *   An array of results.
2038     */
2039    // function fetchAll($mode = NULL, $column_index = NULL, array $constructor_arguments);
2040  
2041    /**
2042     * Returns an entire single column of a result set as an indexed array.
2043     *
2044     * Note that this method will run the result set to the end.
2045     *
2046     * @param $index
2047     *   The index of the column number to fetch.
2048     *
2049     * @return
2050     *   An indexed array, or an empty array if there is no result set.
2051     */
2052    public function fetchCol($index = 0);
2053  
2054    /**
2055     * Returns the entire result set as a single associative array.
2056     *
2057     * This method is only useful for two-column result sets. It will return an
2058     * associative array where the key is one column from the result set and the
2059     * value is another field. In most cases, the default of the first two columns
2060     * is appropriate.
2061     *
2062     * Note that this method will run the result set to the end.
2063     *
2064     * @param $key_index
2065     *   The numeric index of the field to use as the array key.
2066     * @param $value_index
2067     *   The numeric index of the field to use as the array value.
2068     *
2069     * @return
2070     *   An associative array, or an empty array if there is no result set.
2071     */
2072    public function fetchAllKeyed($key_index = 0, $value_index = 1);
2073  
2074    /**
2075     * Returns the result set as an associative array keyed by the given field.
2076     *
2077     * If the given key appears multiple times, later records will overwrite
2078     * earlier ones.
2079     *
2080     * @param $key
2081     *   The name of the field on which to index the array.
2082     * @param $fetch
2083     *   The fetchmode to use. If set to PDO::FETCH_ASSOC, PDO::FETCH_NUM, or
2084     *   PDO::FETCH_BOTH the returned value with be an array of arrays. For any
2085     *   other value it will be an array of objects. By default, the fetch mode
2086     *   set for the query will be used.
2087     *
2088     * @return
2089     *   An associative array, or an empty array if there is no result set.
2090     */
2091    public function fetchAllAssoc($key, $fetch = NULL);
2092  }
2093  
2094  /**
2095   * Default implementation of DatabaseStatementInterface.
2096   *
2097   * PDO allows us to extend the PDOStatement class to provide additional
2098   * functionality beyond that offered by default. We do need extra
2099   * functionality. By default, this class is not driver-specific. If a given
2100   * driver needs to set a custom statement class, it may do so in its
2101   * constructor.
2102   *
2103   * @see http://us.php.net/pdostatement
2104   */
2105  class DatabaseStatementBase extends PDOStatement implements DatabaseStatementInterface {
2106  
2107    /**
2108     * Reference to the database connection object for this statement.
2109     *
2110     * The name $dbh is inherited from PDOStatement.
2111     *
2112     * @var DatabaseConnection
2113     */
2114    public $dbh;
2115  
2116    protected function __construct($dbh) {
2117      $this->dbh = $dbh;
2118      $this->setFetchMode(PDO::FETCH_OBJ);
2119    }
2120  
2121    public function execute($args = array(), $options = array()) {
2122      if (isset($options['fetch'])) {
2123        if (is_string($options['fetch'])) {
2124          // Default to an object. Note: db fields will be added to the object
2125          // before the constructor is run. If you need to assign fields after
2126          // the constructor is run, see http://drupal.org/node/315092.
2127          $this->setFetchMode(PDO::FETCH_CLASS, $options['fetch']);
2128        }
2129        else {
2130          $this->setFetchMode($options['fetch']);
2131        }
2132      }
2133  
2134      $logger = $this->dbh->getLogger();
2135      if (!empty($logger)) {
2136        $query_start = microtime(TRUE);
2137      }
2138  
2139      $return = parent::execute($args);
2140  
2141      if (!empty($logger)) {
2142        $query_end = microtime(TRUE);
2143        $logger->log($this, $args, $query_end - $query_start);
2144      }
2145  
2146      return $return;
2147    }
2148  
2149    public function getQueryString() {
2150      return $this->queryString;
2151    }
2152  
2153    public function fetchCol($index = 0) {
2154      return $this->fetchAll(PDO::FETCH_COLUMN, $index);
2155    }
2156  
2157    public function fetchAllAssoc($key, $fetch = NULL) {
2158      $return = array();
2159      if (isset($fetch)) {
2160        if (is_string($fetch)) {
2161          $this->setFetchMode(PDO::FETCH_CLASS, $fetch);
2162        }
2163        else {
2164          $this->setFetchMode($fetch);
2165        }
2166      }
2167  
2168      foreach ($this as $record) {
2169        $record_key = is_object($record) ? $record->$key : $record[$key];
2170        $return[$record_key] = $record;
2171      }
2172  
2173      return $return;
2174    }
2175  
2176    public function fetchAllKeyed($key_index = 0, $value_index = 1) {
2177      $return = array();
2178      $this->setFetchMode(PDO::FETCH_NUM);
2179      foreach ($this as $record) {
2180        $return[$record[$key_index]] = $record[$value_index];
2181      }
2182      return $return;
2183    }
2184  
2185    public function fetchField($index = 0) {
2186      // Call PDOStatement::fetchColumn to fetch the field.
2187      return $this->fetchColumn($index);
2188    }
2189  
2190    public function fetchAssoc() {
2191      // Call PDOStatement::fetch to fetch the row.
2192      return $this->fetch(PDO::FETCH_ASSOC);
2193    }
2194  }
2195  
2196  /**
2197   * Empty implementation of a database statement.
2198   *
2199   * This class satisfies the requirements of being a database statement/result
2200   * object, but does not actually contain data.  It is useful when developers
2201   * need to safely return an "empty" result set without connecting to an actual
2202   * database.  Calling code can then treat it the same as if it were an actual
2203   * result set that happens to contain no records.
2204   *
2205   * @see SearchQuery
2206   */
2207  class DatabaseStatementEmpty implements Iterator, DatabaseStatementInterface {
2208  
2209    public function execute($args = array(), $options = array()) {
2210      return FALSE;
2211    }
2212  
2213    public function getQueryString() {
2214      return '';
2215    }
2216  
2217    public function rowCount() {
2218      return 0;
2219    }
2220  
2221    public function setFetchMode($mode, $a1 = NULL, $a2 = array()) {
2222      return;
2223    }
2224  
2225    public function fetch($mode = NULL, $cursor_orientation = NULL, $cursor_offset = NULL) {
2226      return NULL;
2227    }
2228  
2229    public function fetchField($index = 0) {
2230      return NULL;
2231    }
2232  
2233    public function fetchObject() {
2234      return NULL;
2235    }
2236  
2237    public function fetchAssoc() {
2238      return NULL;
2239    }
2240  
2241    function fetchAll($mode = NULL, $column_index = NULL, array $constructor_arguments = array()) {
2242      return array();
2243    }
2244  
2245    public function fetchCol($index = 0) {
2246      return array();
2247    }
2248  
2249    public function fetchAllKeyed($key_index = 0, $value_index = 1) {
2250      return array();
2251    }
2252  
2253    public function fetchAllAssoc($key, $fetch = NULL) {
2254      return array();
2255    }
2256  
2257    /* Implementations of Iterator. */
2258  
2259    public function current() {
2260      return NULL;
2261    }
2262  
2263    public function key() {
2264      return NULL;
2265    }
2266  
2267    public function rewind() {
2268      // Nothing to do: our DatabaseStatement can't be rewound.
2269    }
2270  
2271    public function next() {
2272      // Do nothing, since this is an always-empty implementation.
2273    }
2274  
2275    public function valid() {
2276      return FALSE;
2277    }
2278  }
2279  
2280  /**
2281   * The following utility functions are simply convenience wrappers.
2282   *
2283   * They should never, ever have any database-specific code in them.
2284   */
2285  
2286  /**
2287   * Executes an arbitrary query string against the active database.
2288   *
2289   * Use this function for SELECT queries if it is just a simple query string.
2290   * If the caller or other modules need to change the query, use db_select()
2291   * instead.
2292   *
2293   * Do not use this function for INSERT, UPDATE, or DELETE queries. Those should
2294   * be handled via db_insert(), db_update() and db_delete() respectively.
2295   *
2296   * @param $query
2297   *   The prepared statement query to run. Although it will accept both named and
2298   *   unnamed placeholders, named placeholders are strongly preferred as they are
2299   *   more self-documenting.
2300   * @param $args
2301   *   An array of values to substitute into the query. If the query uses named
2302   *   placeholders, this is an associative array in any order. If the query uses
2303   *   unnamed placeholders (?), this is an indexed array and the order must match
2304   *   the order of placeholders in the query string.
2305   * @param $options
2306   *   An array of options to control how the query operates.
2307   *
2308   * @return DatabaseStatementInterface
2309   *   A prepared statement object, already executed.
2310   *
2311   * @see DatabaseConnection::defaultOptions()
2312   */
2313  function db_query($query, array $args = array(), array $options = array()) {
2314    if (empty($options['target'])) {
2315      $options['target'] = 'default';
2316    }
2317  
2318    return Database::getConnection($options['target'])->query($query, $args, $options);
2319  }
2320  
2321  /**
2322   * Executes a query against the active database, restricted to a range.
2323   *
2324   * @param $query
2325   *   The prepared statement query to run. Although it will accept both named and
2326   *   unnamed placeholders, named placeholders are strongly preferred as they are
2327   *   more self-documenting.
2328   * @param $from
2329   *   The first record from the result set to return.
2330   * @param $count
2331   *   The number of records to return from the result set.
2332   * @param $args
2333   *   An array of values to substitute into the query. If the query uses named
2334   *   placeholders, this is an associative array in any order. If the query uses
2335   *   unnamed placeholders (?), this is an indexed array and the order must match
2336   *   the order of placeholders in the query string.
2337   * @param $options
2338   *   An array of options to control how the query operates.
2339   *
2340   * @return DatabaseStatementInterface
2341   *   A prepared statement object, already executed.
2342   *
2343   * @see DatabaseConnection::defaultOptions()
2344   */
2345  function db_query_range($query, $from, $count, array $args = array(), array $options = array()) {
2346    if (empty($options['target'])) {
2347      $options['target'] = 'default';
2348    }
2349  
2350    return Database::getConnection($options['target'])->queryRange($query, $from, $count, $args, $options);
2351  }
2352  
2353  /**
2354   * Executes a query string and saves the result set to a temporary table.
2355   *
2356   * The execution of the query string happens against the active database.
2357   *
2358   * @param $query
2359   *   The prepared statement query to run. Although it will accept both named and
2360   *   unnamed placeholders, named placeholders are strongly preferred as they are
2361   *   more self-documenting.
2362   * @param $args
2363   *   An array of values to substitute into the query. If the query uses named
2364   *   placeholders, this is an associative array in any order. If the query uses
2365   *   unnamed placeholders (?), this is an indexed array and the order must match
2366   *   the order of placeholders in the query string.
2367   * @param $options
2368   *   An array of options to control how the query operates.
2369   *
2370   * @return
2371   *   The name of the temporary table.
2372   *
2373   * @see DatabaseConnection::defaultOptions()
2374   */
2375  function db_query_temporary($query, array $args = array(), array $options = array()) {
2376    if (empty($options['target'])) {
2377      $options['target'] = 'default';
2378    }
2379  
2380    return Database::getConnection($options['target'])->queryTemporary($query, $args, $options);
2381  }
2382  
2383  /**
2384   * Returns a new InsertQuery object for the active database.
2385   *
2386   * @param $table
2387   *   The table into which to insert.
2388   * @param $options
2389   *   An array of options to control how the query operates.
2390   *
2391   * @return InsertQuery
2392   *   A new InsertQuery object for this connection.
2393   */
2394  function db_insert($table, array $options = array()) {
2395    if (empty($options['target']) || $options['target'] == 'slave') {
2396      $options['target'] = 'default';
2397    }
2398    return Database::getConnection($options['target'])->insert($table, $options);
2399  }
2400  
2401  /**
2402   * Returns a new MergeQuery object for the active database.
2403   *
2404   * @param $table
2405   *   The table into which to merge.
2406   * @param $options
2407   *   An array of options to control how the query operates.
2408   *
2409   * @return MergeQuery
2410   *   A new MergeQuery object for this connection.
2411   */
2412  function db_merge($table, array $options = array()) {
2413    if (empty($options['target']) || $options['target'] == 'slave') {
2414      $options['target'] = 'default';
2415    }
2416    return Database::getConnection($options['target'])->merge($table, $options);
2417  }
2418  
2419  /**
2420   * Returns a new UpdateQuery object for the active database.
2421   *
2422   * @param $table
2423   *   The table to update.
2424   * @param $options
2425   *   An array of options to control how the query operates.
2426   *
2427   * @return UpdateQuery
2428   *   A new UpdateQuery object for this connection.
2429   */
2430  function db_update($table, array $options = array()) {
2431    if (empty($options['target']) || $options['target'] == 'slave') {
2432      $options['target'] = 'default';
2433    }
2434    return Database::getConnection($options['target'])->update($table, $options);
2435  }
2436  
2437  /**
2438   * Returns a new DeleteQuery object for the active database.
2439   *
2440   * @param $table
2441   *   The table from which to delete.
2442   * @param $options
2443   *   An array of options to control how the query operates.
2444   *
2445   * @return DeleteQuery
2446   *   A new DeleteQuery object for this connection.
2447   */
2448  function db_delete($table, array $options = array()) {
2449    if (empty($options['target']) || $options['target'] == 'slave') {
2450      $options['target'] = 'default';
2451    }
2452    return Database::getConnection($options['target'])->delete($table, $options);
2453  }
2454  
2455  /**
2456   * Returns a new TruncateQuery object for the active database.
2457   *
2458   * @param $table
2459   *   The table from which to delete.
2460   * @param $options
2461   *   An array of options to control how the query operates.
2462   *
2463   * @return TruncateQuery
2464   *   A new TruncateQuery object for this connection.
2465   */
2466  function db_truncate($table, array $options = array()) {
2467    if (empty($options['target']) || $options['target'] == 'slave') {
2468      $options['target'] = 'default';
2469    }
2470    return Database::getConnection($options['target'])->truncate($table, $options);
2471  }
2472  
2473  /**
2474   * Returns a new SelectQuery object for the active database.
2475   *
2476   * @param $table
2477   *   The base table for this query. May be a string or another SelectQuery
2478   *   object. If a query object is passed, it will be used as a subselect.
2479   * @param $alias
2480   *   The alias for the base table of this query.
2481   * @param $options
2482   *   An array of options to control how the query operates.
2483   *
2484   * @return SelectQuery
2485   *   A new SelectQuery object for this connection.
2486   */
2487  function db_select($table, $alias = NULL, array $options = array()) {
2488    if (empty($options['target'])) {
2489      $options['target'] = 'default';
2490    }
2491    return Database::getConnection($options['target'])->select($table, $alias, $options);
2492  }
2493  
2494  /**
2495   * Returns a new transaction object for the active database.
2496   *
2497   * @param string $name
2498   *   Optional name of the transaction.
2499   * @param array $options
2500   *   An array of options to control how the transaction operates:
2501   *   - target: The database target name.
2502   *
2503   * @return DatabaseTransaction
2504   *   A new DatabaseTransaction object for this connection.
2505   */
2506  function db_transaction($name = NULL, array $options = array()) {
2507    if (empty($options['target'])) {
2508      $options['target'] = 'default';
2509    }
2510    return Database::getConnection($options['target'])->startTransaction($name);
2511  }
2512  
2513  /**
2514   * Sets a new active database.
2515   *
2516   * @param $key
2517   *   The key in the $databases array to set as the default database.
2518   *
2519   * @return
2520   *   The key of the formerly active database.
2521   */
2522  function db_set_active($key = 'default') {
2523    return Database::setActiveConnection($key);
2524  }
2525  
2526  /**
2527   * Restricts a dynamic table name to safe characters.
2528   *
2529   * Only keeps alphanumeric and underscores.
2530   *
2531   * @param $table
2532   *   The table name to escape.
2533   *
2534   * @return
2535   *   The escaped table name as a string.
2536   */
2537  function db_escape_table($table) {
2538    return Database::getConnection()->escapeTable($table);
2539  }
2540  
2541  /**
2542   * Restricts a dynamic column or constraint name to safe characters.
2543   *
2544   * Only keeps alphanumeric and underscores.
2545   *
2546   * @param $field
2547   *   The field name to escape.
2548   *
2549   * @return
2550   *   The escaped field name as a string.
2551   */
2552  function db_escape_field($field) {
2553    return Database::getConnection()->escapeField($field);
2554  }
2555  
2556  /**
2557   * Escapes characters that work as wildcard characters in a LIKE pattern.
2558   *
2559   * The wildcard characters "%" and "_" as well as backslash are prefixed with
2560   * a backslash. Use this to do a search for a verbatim string without any
2561   * wildcard behavior.
2562   *
2563   * For example, the following does a case-insensitive query for all rows whose
2564   * name starts with $prefix:
2565   * @code
2566   * $result = db_query(
2567   *   'SELECT * FROM person WHERE name LIKE :pattern',
2568   *   array(':pattern' => db_like($prefix) . '%')
2569   * );
2570   * @endcode
2571   *
2572   * Backslash is defined as escape character for LIKE patterns in
2573   * DatabaseCondition::mapConditionOperator().
2574   *
2575   * @param $string
2576   *   The string to escape.
2577   *
2578   * @return
2579   *   The escaped string.
2580   */
2581  function db_like($string) {
2582    return Database::getConnection()->escapeLike($string);
2583  }
2584  
2585  /**
2586   * Retrieves the name of the currently active database driver.
2587   *
2588   * @return
2589   *   The name of the currently active database driver.
2590   */
2591  function db_driver() {
2592    return Database::getConnection()->driver();
2593  }
2594  
2595  /**
2596   * Closes the active database connection.
2597   *
2598   * @param $options
2599   *   An array of options to control which connection is closed. Only the target
2600   *   key has any meaning in this case.
2601   */
2602  function db_close(array $options = array()) {
2603    if (empty($options['target'])) {
2604      $options['target'] = NULL;
2605    }
2606    Database::closeConnection($options['target']);
2607  }
2608  
2609  /**
2610   * Retrieves a unique id.
2611   *
2612   * Use this function if for some reason you can't use a serial field. Using a
2613   * serial field is preferred, and InsertQuery::execute() returns the value of
2614   * the last ID inserted.
2615   *
2616   * @param $existing_id
2617   *   After a database import, it might be that the sequences table is behind, so
2618   *   by passing in a minimum ID, it can be assured that we never issue the same
2619   *   ID.
2620   *
2621   * @return
2622   *   An integer number larger than any number returned before for this sequence.
2623   */
2624  function db_next_id($existing_id = 0) {
2625    return Database::getConnection()->nextId($existing_id);
2626  }
2627  
2628  /**
2629   * Returns a new DatabaseCondition, set to "OR" all conditions together.
2630   *
2631   * @return DatabaseCondition
2632   */
2633  function db_or() {
2634    return new DatabaseCondition('OR');
2635  }
2636  
2637  /**
2638   * Returns a new DatabaseCondition, set to "AND" all conditions together.
2639   *
2640   * @return DatabaseCondition
2641   */
2642  function db_and() {
2643    return new DatabaseCondition('AND');
2644  }
2645  
2646  /**
2647   * Returns a new DatabaseCondition, set to "XOR" all conditions together.
2648   *
2649   * @return DatabaseCondition
2650   */
2651  function db_xor() {
2652    return new DatabaseCondition('XOR');
2653  }
2654  
2655  /**
2656   * Returns a new DatabaseCondition, set to the specified conjunction.
2657   *
2658   * Internal API function call.  The db_and(), db_or(), and db_xor()
2659   * functions are preferred.
2660   *
2661   * @param $conjunction
2662   *   The conjunction to use for query conditions (AND, OR or XOR).
2663   * @return DatabaseCondition
2664   */
2665  function db_condition($conjunction) {
2666    return new DatabaseCondition($conjunction);
2667  }
2668  
2669  /**
2670   * @} End of "defgroup database".
2671   */
2672  
2673  
2674  /**
2675   * @addtogroup schemaapi
2676   * @{
2677   */
2678  
2679  /**
2680   * Creates a new table from a Drupal table definition.
2681   *
2682   * @param $name
2683   *   The name of the table to create.
2684   * @param $table
2685   *   A Schema API table definition array.
2686   */
2687  function db_create_table($name, $table) {
2688    return Database::getConnection()->schema()->createTable($name, $table);
2689  }
2690  
2691  /**
2692   * Returns an array of field names from an array of key/index column specifiers.
2693   *
2694   * This is usually an identity function but if a key/index uses a column prefix
2695   * specification, this function extracts just the name.
2696   *
2697   * @param $fields
2698   *   An array of key/index column specifiers.
2699   *
2700   * @return
2701   *   An array of field names.
2702   */
2703  function db_field_names($fields) {
2704    return Database::getConnection()->schema()->fieldNames($fields);
2705  }
2706  
2707  /**
2708   * Checks if an index exists in the given table.
2709   *
2710   * @param $table
2711   *   The name of the table in drupal (no prefixing).
2712   * @param $name
2713   *   The name of the index in drupal (no prefixing).
2714   *
2715   * @return
2716   *   TRUE if the given index exists, otherwise FALSE.
2717   */
2718  function db_index_exists($table, $name) {
2719    return Database::getConnection()->schema()->indexExists($table, $name);
2720  }
2721  
2722  /**
2723   * Checks if a table exists.
2724   *
2725   * @param $table
2726   *   The name of the table in drupal (no prefixing).
2727   *
2728   * @return
2729   *   TRUE if the given table exists, otherwise FALSE.
2730   */
2731  function db_table_exists($table) {
2732    return Database::getConnection()->schema()->tableExists($table);
2733  }
2734  
2735  /**
2736   * Checks if a column exists in the given table.
2737   *
2738   * @param $table
2739   *   The name of the table in drupal (no prefixing).
2740   * @param $field
2741   *   The name of the field.
2742   *
2743   * @return
2744   *   TRUE if the given column exists, otherwise FALSE.
2745   */
2746  function db_field_exists($table, $field) {
2747    return Database::getConnection()->schema()->fieldExists($table, $field);
2748  }
2749  
2750  /**
2751   * Finds all tables that are like the specified base table name.
2752   *
2753   * @param $table_expression
2754   *   An SQL expression, for example "simpletest%" (without the quotes).
2755   *   BEWARE: this is not prefixed, the caller should take care of that.
2756   *
2757   * @return
2758   *   Array, both the keys and the values are the matching tables.
2759   */
2760  function db_find_tables($table_expression) {
2761    return Database::getConnection()->schema()->findTables($table_expression);
2762  }
2763  
2764  function _db_create_keys_sql($spec) {
2765    return Database::getConnection()->schema()->createKeysSql($spec);
2766  }
2767  
2768  /**
2769   * Renames a table.
2770   *
2771   * @param $table
2772   *   The current name of the table to be renamed.
2773   * @param $new_name
2774   *   The new name for the table.
2775   */
2776  function db_rename_table($table, $new_name) {
2777    return Database::getConnection()->schema()->renameTable($table, $new_name);
2778  }
2779  
2780  /**
2781   * Drops a table.
2782   *
2783   * @param $table
2784   *   The table to be dropped.
2785   */
2786  function db_drop_table($table) {
2787    return Database::getConnection()->schema()->dropTable($table);
2788  }
2789  
2790  /**
2791   * Adds a new field to a table.
2792   *
2793   * @param $table
2794   *   Name of the table to be altered.
2795   * @param $field
2796   *   Name of the field to be added.
2797   * @param $spec
2798   *   The field specification array, as taken from a schema definition. The
2799   *   specification may also contain the key 'initial'; the newly-created field
2800   *   will be set to the value of the key in all rows. This is most useful for
2801   *   creating NOT NULL columns with no default value in existing tables.
2802   * @param $keys_new
2803   *   Optional keys and indexes specification to be created on the table along
2804   *   with adding the field. The format is the same as a table specification, but
2805   *   without the 'fields' element. If you are adding a type 'serial' field, you
2806   *   MUST specify at least one key or index including it in this array. See
2807   *   db_change_field() for more explanation why.
2808   *
2809   * @see db_change_field()
2810   */
2811  function db_add_field($table, $field, $spec, $keys_new = array()) {
2812    return Database::getConnection()->schema()->addField($table, $field, $spec, $keys_new);
2813  }
2814  
2815  /**
2816   * Drops a field.
2817   *
2818   * @param $table
2819   *   The table to be altered.
2820   * @param $field
2821   *   The field to be dropped.
2822   */
2823  function db_drop_field($table, $field) {
2824    return Database::getConnection()->schema()->dropField($table, $field);
2825  }
2826  
2827  /**
2828   * Sets the default value for a field.
2829   *
2830   * @param $table
2831   *   The table to be altered.
2832   * @param $field
2833   *   The field to be altered.
2834   * @param $default
2835   *   Default value to be set. NULL for 'default NULL'.
2836   */
2837  function db_field_set_default($table, $field, $default) {
2838    return Database::getConnection()->schema()->fieldSetDefault($table, $field, $default);
2839  }
2840  
2841  /**
2842   * Sets a field to have no default value.
2843   *
2844   * @param $table
2845   *   The table to be altered.
2846   * @param $field
2847   *   The field to be altered.
2848   */
2849  function db_field_set_no_default($table, $field) {
2850    return Database::getConnection()->schema()->fieldSetNoDefault($table, $field);
2851  }
2852  
2853  /**
2854   * Adds a primary key to a database table.
2855   *
2856   * @param $table
2857   *   Name of the table to be altered.
2858   * @param $fields
2859   *   Array of fields for the primary key.
2860   */
2861  function db_add_primary_key($table, $fields) {
2862    return Database::getConnection()->schema()->addPrimaryKey($table, $fields);
2863  }
2864  
2865  /**
2866   * Drops the primary key of a database table.
2867   *
2868   * @param $table
2869   *   Name of the table to be altered.
2870   */
2871  function db_drop_primary_key($table) {
2872    return Database::getConnection()->schema()->dropPrimaryKey($table);
2873  }
2874  
2875  /**
2876   * Adds a unique key.
2877   *
2878   * @param $table
2879   *   The table to be altered.
2880   * @param $name
2881   *   The name of the key.
2882   * @param $fields
2883   *   An array of field names.
2884   */
2885  function db_add_unique_key($table, $name, $fields) {
2886    return Database::getConnection()->schema()->addUniqueKey($table, $name, $fields);
2887  }
2888  
2889  /**
2890   * Drops a unique key.
2891   *
2892   * @param $table
2893   *   The table to be altered.
2894   * @param $name
2895   *   The name of the key.
2896   */
2897  function db_drop_unique_key($table, $name) {
2898    return Database::getConnection()->schema()->dropUniqueKey($table, $name);
2899  }
2900  
2901  /**
2902   * Adds an index.
2903   *
2904   * @param $table
2905   *   The table to be altered.
2906   * @param $name
2907   *   The name of the index.
2908   * @param $fields
2909   *   An array of field names.
2910   */
2911  function db_add_index($table, $name, $fields) {
2912    return Database::getConnection()->schema()->addIndex($table, $name, $fields);
2913  }
2914  
2915  /**
2916   * Drops an index.
2917   *
2918   * @param $table
2919   *   The table to be altered.
2920   * @param $name
2921   *   The name of the index.
2922   */
2923  function db_drop_index($table, $name) {
2924    return Database::getConnection()->schema()->dropIndex($table, $name);
2925  }
2926  
2927  /**
2928   * Changes a field definition.
2929   *
2930   * IMPORTANT NOTE: To maintain database portability, you have to explicitly
2931   * recreate all indices and primary keys that are using the changed field.
2932   *
2933   * That means that you have to drop all affected keys and indexes with
2934   * db_drop_{primary_key,unique_key,index}() before calling db_change_field().
2935   * To recreate the keys and indices, pass the key definitions as the optional
2936   * $keys_new argument directly to db_change_field().
2937   *
2938   * For example, suppose you have:
2939   * @code
2940   * $schema['foo'] = array(
2941   *   'fields' => array(
2942   *     'bar' => array('type' => 'int', 'not null' => TRUE)
2943   *   ),
2944   *   'primary key' => array('bar')
2945   * );
2946   * @endcode
2947   * and you want to change foo.bar to be type serial, leaving it as the primary
2948   * key. The correct sequence is:
2949   * @code
2950   * db_drop_primary_key('foo');
2951   * db_change_field('foo', 'bar', 'bar',
2952   *   array('type' => 'serial', 'not null' => TRUE),
2953   *   array('primary key' => array('bar')));
2954   * @endcode
2955   *
2956   * The reasons for this are due to the different database engines:
2957   *
2958   * On PostgreSQL, changing a field definition involves adding a new field and
2959   * dropping an old one which causes any indices, primary keys and sequences
2960   * (from serial-type fields) that use the changed field to be dropped.
2961   *
2962   * On MySQL, all type 'serial' fields must be part of at least one key or index
2963   * as soon as they are created. You cannot use
2964   * db_add_{primary_key,unique_key,index}() for this purpose because the ALTER
2965   * TABLE command will fail to add the column without a key or index
2966   * specification. The solution is to use the optional $keys_new argument to
2967   * create the key or index at the same time as field.
2968   *
2969   * You could use db_add_{primary_key,unique_key,index}() in all cases unless you
2970   * are converting a field to be type serial. You can use the $keys_new argument
2971   * in all cases.
2972   *
2973   * @param $table
2974   *   Name of the table.
2975   * @param $field
2976   *   Name of the field to change.
2977   * @param $field_new
2978   *   New name for the field (set to the same as $field if you don't want to
2979   *   change the name).
2980   * @param $spec
2981   *   The field specification for the new field.
2982   * @param $keys_new
2983   *   Optional keys and indexes specification to be created on the table along
2984   *   with changing the field. The format is the same as a table specification
2985   *   but without the 'fields' element.
2986   */
2987  function db_change_field($table, $field, $field_new, $spec, $keys_new = array()) {
2988    return Database::getConnection()->schema()->changeField($table, $field, $field_new, $spec, $keys_new);
2989  }
2990  
2991  /**
2992   * @} End of "addtogroup schemaapi".
2993   */
2994  
2995  /**
2996   * Sets a session variable specifying the lag time for ignoring a slave server.
2997   */
2998  function db_ignore_slave() {
2999    $connection_info = Database::getConnectionInfo();
3000    // Only set ignore_slave_server if there are slave servers being used, which
3001    // is assumed if there are more than one.
3002    if (count($connection_info) > 1) {
3003      // Five minutes is long enough to allow the slave to break and resume
3004      // interrupted replication without causing problems on the Drupal site from
3005      // the old data.
3006      $duration = variable_get('maximum_replication_lag', 300);
3007      // Set session variable with amount of time to delay before using slave.
3008      $_SESSION['ignore_slave_server'] = REQUEST_TIME + $duration;
3009    }
3010  }

title

Description

title

Description

title

Description

title

title

Body