Simpletest Coverage - includes/database/database.inc

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

Legend

Missed
lines code that were not excersized during program execution.
Covered
lines code were excersized during program execution.
Comment/non executable
Comment or non-executable line of code.
Dead
lines of code that according to xdebug could not be executed. This is counted as coverage code because in almost all cases it is code that runnable.