Version 1
[yaffs-website] / web / core / lib / Drupal / Core / Database / database.api.php
1 <?php
2
3 /**
4  * @file
5  * Hooks related to the Database system and the Schema API.
6  */
7
8 /**
9  * @defgroup database Database abstraction layer
10  * @{
11  * Allow the use of different database servers using the same code base.
12  *
13  * @section sec_intro Overview
14  * Drupal's database abstraction layer provides a unified database query API
15  * that can query different underlying databases. It is built upon PHP's
16  * PDO (PHP Data Objects) database API, and inherits much of its syntax and
17  * semantics. Besides providing a unified API for database queries, the
18  * database abstraction layer also provides a structured way to construct
19  * complex queries, and it protects the database by using good security
20  * practices.
21  *
22  * For more detailed information on the database abstraction layer, see
23  * https://www.drupal.org/developing/api/database.
24  *
25  * @section sec_entity Querying entities
26  * Any query on Drupal entities or fields should use the Entity Query API. See
27  * the @link entity_api entity API topic @endlink for more information.
28  *
29  * @section sec_simple Simple SELECT database queries
30  * For simple SELECT queries that do not involve entities, the Drupal database
31  * abstraction layer provides the functions db_query() and db_query_range(),
32  * which execute SELECT queries (optionally with range limits) and return result
33  * sets that you can iterate over using foreach loops. (The result sets are
34  * objects implementing the \Drupal\Core\Database\StatementInterface interface.)
35  * You can use the simple query functions for query strings that are not
36  * dynamic (except for placeholders, see below), and that you are certain will
37  * work in any database engine. See @ref sec_dynamic below if you have a more
38  * complex query, or a query whose syntax would be different in some databases.
39  *
40  * As a note, db_query() and similar functions are wrappers on connection object
41  * methods. In most classes, you should use dependency injection and the
42  * database connection object instead of these wrappers; See @ref sec_connection
43  * below for details.
44  *
45  * To use the simple database query functions, you will need to make a couple of
46  * modifications to your bare SQL query:
47  * - Enclose your table name in {}. Drupal allows site builders to use
48  *   database table name prefixes, so you cannot be sure what the actual
49  *   name of the table will be. So, use the name that is in the hook_schema(),
50  *   enclosed in {}, and Drupal will calculate the right name.
51  * - Instead of putting values for conditions into the query, use placeholders.
52  *   The placeholders are named and start with :, and they take the place of
53  *   putting variables directly into the query, to protect against SQL
54  *   injection attacks.
55  * - LIMIT syntax differs between databases, so if you have a ranged query,
56  *   use db_query_range() instead of db_query().
57  *
58  * For example, if the query you want to run is:
59  * @code
60  * SELECT e.id, e.title, e.created FROM example e WHERE e.uid = $uid
61  *   ORDER BY e.created DESC LIMIT 0, 10;
62  * @endcode
63  * you would do it like this:
64  * @code
65  * $result = db_query_range('SELECT e.id, e.title, e.created
66  *   FROM {example} e
67  *   WHERE e.uid = :uid
68  *   ORDER BY e.created DESC',
69  *   0, 10, array(':uid' => $uid));
70  * foreach ($result as $record) {
71  *   // Perform operations on $record->title, etc. here.
72  * }
73  * @endcode
74  *
75  * Note that if your query has a string condition, like:
76  * @code
77  * WHERE e.my_field = 'foo'
78  * @endcode
79  * when you convert it to placeholders, omit the quotes:
80  * @code
81  * WHERE e.my_field = :my_field
82  * ... array(':my_field' => 'foo') ...
83  * @endcode
84  *
85  * @section sec_dynamic Dynamic SELECT queries
86  * For SELECT queries where the simple query API described in @ref sec_simple
87  * will not work well, you need to use the dynamic query API. However, you
88  * should still use the Entity Query API if your query involves entities or
89  * fields (see the @link entity_api Entity API topic @endlink for more on
90  * entity queries).
91  *
92  * As a note, db_select() and similar functions are wrappers on connection
93  * object methods. In most classes, you should use dependency injection and the
94  * database connection object instead of these wrappers; See @ref sec_connection
95  * below for details.
96  *
97  * The dynamic query API lets you build up a query dynamically using method
98  * calls. As an illustration, the query example from @ref sec_simple above
99  * would be:
100  * @code
101  * $result = db_select('example', 'e')
102  *   ->fields('e', array('id', 'title', 'created'))
103  *   ->condition('e.uid', $uid)
104  *   ->orderBy('e.created', 'DESC')
105  *   ->range(0, 10)
106  *   ->execute();
107  * @endcode
108  *
109  * There are also methods to join to other tables, add fields with aliases,
110  * isNull() to have a @code WHERE e.foo IS NULL @endcode condition, etc. See
111  * https://www.drupal.org/developing/api/database for many more details.
112  *
113  * One note on chaining: It is common in the dynamic database API to chain
114  * method calls (as illustrated here), because most of the query methods modify
115  * the query object and then return the modified query as their return
116  * value. However, there are some important exceptions; these methods (and some
117  * others) do not support chaining:
118  * - join(), innerJoin(), etc.: These methods return the joined table alias.
119  * - addField(): This method returns the field alias.
120  * Check the documentation for the query method you are using to see if it
121  * returns the query or something else, and only chain methods that return the
122  * query.
123  *
124  * @section_insert INSERT, UPDATE, and DELETE queries
125  * INSERT, UPDATE, and DELETE queries need special care in order to behave
126  * consistently across databases; you should never use db_query() to run
127  * an INSERT, UPDATE, or DELETE query. Instead, use functions db_insert(),
128  * db_update(), and db_delete() to obtain a base query on your table, and then
129  * add dynamic conditions (as illustrated in @ref sec_dynamic above).
130  *
131  * As a note, db_insert() and similar functions are wrappers on connection
132  * object methods. In most classes, you should use dependency injection and the
133  * database connection object instead of these wrappers; See @ref sec_connection
134  * below for details.
135  *
136  * For example, if your query is:
137  * @code
138  * INSERT INTO example (id, uid, path, name) VALUES (1, 2, 'path', 'Name');
139  * @endcode
140  * You can execute it via:
141  * @code
142  * $fields = array('id' => 1, 'uid' => 2, 'path' => 'path', 'name' => 'Name');
143  * db_insert('example')
144  *   ->fields($fields)
145  *   ->execute();
146  * @endcode
147  *
148  * @section sec_transaction Transactions
149  * Drupal supports transactions, including a transparent fallback for
150  * databases that do not support transactions. To start a new transaction,
151  * call @code $txn = db_transaction(); @endcode The transaction will
152  * remain open for as long as the variable $txn remains in scope; when $txn is
153  * destroyed, the transaction will be committed. If your transaction is nested
154  * inside of another then Drupal will track each transaction and only commit
155  * the outer-most transaction when the last transaction object goes out out of
156  * scope (when all relevant queries have completed successfully).
157  *
158  * Example:
159  * @code
160  * function my_transaction_function() {
161  *   // The transaction opens here.
162  *   $txn = db_transaction();
163  *
164  *   try {
165  *     $id = db_insert('example')
166  *       ->fields(array(
167  *         'field1' => 'mystring',
168  *         'field2' => 5,
169  *       ))
170  *       ->execute();
171  *
172  *     my_other_function($id);
173  *
174  *     return $id;
175  *   }
176  *   catch (Exception $e) {
177  *     // Something went wrong somewhere, so roll back now.
178  *     $txn->rollBack();
179  *     // Log the exception to watchdog.
180  *     watchdog_exception('type', $e);
181  *   }
182  *
183  *   // $txn goes out of scope here.  Unless the transaction was rolled back, it
184  *   // gets automatically committed here.
185  * }
186  *
187  * function my_other_function($id) {
188  *   // The transaction is still open here.
189  *
190  *   if ($id % 2 == 0) {
191  *     db_update('example')
192  *       ->condition('id', $id)
193  *       ->fields(array('field2' => 10))
194  *       ->execute();
195  *   }
196  * }
197  * @endcode
198  *
199  * @section sec_connection Database connection objects
200  * The examples here all use functions like db_select() and db_query(), which
201  * can be called from any Drupal method or function code. In some classes, you
202  * may already have a database connection object in a member variable, or it may
203  * be passed into a class constructor via dependency injection. If that is the
204  * case, you can look at the code for db_select() and the other functions to see
205  * how to get a query object from your connection variable. For example:
206  * @code
207  * $query = $connection->select('example', 'e');
208  * @endcode
209  * would be the equivalent of
210  * @code
211  * $query = db_select('example', 'e');
212  * @endcode
213  * if you had a connection object variable $connection available to use. See
214  * also the @link container Services and Dependency Injection topic. @endlink
215  *
216  * @see https://www.drupal.org/developing/api/database
217  * @see entity_api
218  * @see schemaapi
219  *
220  * @}
221  */
222
223 /**
224  * @defgroup schemaapi Schema API
225  * @{
226  * API to handle database schemas.
227  *
228  * A Drupal schema definition is an array structure representing one or
229  * more tables and their related keys and indexes. A schema is defined by
230  * hook_schema(), which usually lives in a modulename.install file.
231  *
232  * By implementing hook_schema() and specifying the tables your module
233  * declares, you can easily create and drop these tables on all
234  * supported database engines. You don't have to deal with the
235  * different SQL dialects for table creation and alteration of the
236  * supported database engines.
237  *
238  * hook_schema() should return an array with a key for each table that
239  * the module defines.
240  *
241  * The following keys are defined:
242  *   - 'description': A string in non-markup plain text describing this table
243  *     and its purpose. References to other tables should be enclosed in
244  *     curly-brackets. For example, the node_field_revision table
245  *     description field might contain "Stores per-revision title and
246  *     body data for each {node}."
247  *   - 'fields': An associative array ('fieldname' => specification)
248  *     that describes the table's database columns. The specification
249  *     is also an array. The following specification parameters are defined:
250  *     - 'description': A string in non-markup plain text describing this field
251  *       and its purpose. References to other tables should be enclosed in
252  *       curly-brackets. For example, the node table vid field
253  *       description might contain "Always holds the largest (most
254  *       recent) {node_field_revision}.vid value for this nid."
255  *     - 'type': The generic datatype: 'char', 'varchar', 'text', 'blob', 'int',
256  *       'float', 'numeric', or 'serial'. Most types just map to the according
257  *       database engine specific datatypes. Use 'serial' for auto incrementing
258  *       fields. This will expand to 'INT auto_increment' on MySQL.
259  *       A special 'varchar_ascii' type is also available for limiting machine
260  *       name field to US ASCII characters.
261  *     - 'mysql_type', 'pgsql_type', 'sqlite_type', etc.: If you need to
262  *       use a record type not included in the officially supported list
263  *       of types above, you can specify a type for each database
264  *       backend. In this case, you can leave out the type parameter,
265  *       but be advised that your schema will fail to load on backends that
266  *       do not have a type specified. A possible solution can be to
267  *       use the "text" type as a fallback.
268  *     - 'serialize': A boolean indicating whether the field will be stored as
269  *       a serialized string.
270  *     - 'size': The data size: 'tiny', 'small', 'medium', 'normal',
271  *       'big'. This is a hint about the largest value the field will
272  *       store and determines which of the database engine specific
273  *       datatypes will be used (e.g. on MySQL, TINYINT vs. INT vs. BIGINT).
274  *       'normal', the default, selects the base type (e.g. on MySQL,
275  *       INT, VARCHAR, BLOB, etc.).
276  *       Not all sizes are available for all data types. See
277  *       DatabaseSchema::getFieldTypeMap() for possible combinations.
278  *     - 'not null': If true, no NULL values will be allowed in this
279  *       database column. Defaults to false.
280  *     - 'default': The field's default value. The PHP type of the
281  *       value matters: '', '0', and 0 are all different. If you
282  *       specify '0' as the default value for a type 'int' field it
283  *       will not work because '0' is a string containing the
284  *       character "zero", not an integer.
285  *     - 'length': The maximal length of a type 'char', 'varchar' or 'text'
286  *       field. Ignored for other field types.
287  *     - 'unsigned': A boolean indicating whether a type 'int', 'float'
288  *       and 'numeric' only is signed or unsigned. Defaults to
289  *       FALSE. Ignored for other field types.
290  *     - 'precision', 'scale': For type 'numeric' fields, indicates
291  *       the precision (total number of significant digits) and scale
292  *       (decimal digits right of the decimal point). Both values are
293  *       mandatory. Ignored for other field types.
294  *     - 'binary': A boolean indicating that MySQL should force 'char',
295  *       'varchar' or 'text' fields to use case-sensitive binary collation.
296  *       This has no effect on other database types for which case sensitivity
297  *       is already the default behavior.
298  *     All parameters apart from 'type' are optional except that type
299  *     'numeric' columns must specify 'precision' and 'scale', and type
300  *     'varchar' must specify the 'length' parameter.
301  *  - 'primary key': An array of one or more key column specifiers (see below)
302  *    that form the primary key.
303  *  - 'unique keys': An associative array of unique keys ('keyname' =>
304  *    specification). Each specification is an array of one or more
305  *    key column specifiers (see below) that form a unique key on the table.
306  *  - 'foreign keys': An associative array of relations ('my_relation' =>
307  *    specification). Each specification is an array containing the name of
308  *    the referenced table ('table'), and an array of column mappings
309  *    ('columns'). Column mappings are defined by key pairs ('source_column' =>
310  *    'referenced_column'). This key is for documentation purposes only; foreign
311  *    keys are not created in the database, nor are they enforced by Drupal.
312  *  - 'indexes':  An associative array of indexes ('indexname' =>
313  *    specification). Each specification is an array of one or more
314  *    key column specifiers (see below) that form an index on the
315  *    table.
316  *
317  * A key column specifier is either a string naming a column or an
318  * array of two elements, column name and length, specifying a prefix
319  * of the named column.
320  *
321  * As an example, here is a SUBSET of the schema definition for
322  * Drupal's 'node' table. It show four fields (nid, vid, type, and
323  * title), the primary key on field 'nid', a unique key named 'vid' on
324  * field 'vid', and two indexes, one named 'nid' on field 'nid' and
325  * one named 'node_title_type' on the field 'title' and the first four
326  * bytes of the field 'type':
327  *
328  * @code
329  * $schema['node'] = array(
330  *   'description' => 'The base table for nodes.',
331  *   'fields' => array(
332  *     'nid'       => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE),
333  *     'vid'       => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE,'default' => 0),
334  *     'type'      => array('type' => 'varchar','length' => 32,'not null' => TRUE, 'default' => ''),
335  *     'language'  => array('type' => 'varchar','length' => 12,'not null' => TRUE,'default' => ''),
336  *     'title'     => array('type' => 'varchar','length' => 255,'not null' => TRUE, 'default' => ''),
337  *     'uid'       => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
338  *     'status'    => array('type' => 'int', 'not null' => TRUE, 'default' => 1),
339  *     'created'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
340  *     'changed'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
341  *     'comment'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
342  *     'promote'   => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
343  *     'moderate'  => array('type' => 'int', 'not null' => TRUE,'default' => 0),
344  *     'sticky'    => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
345  *     'translate' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
346  *   ),
347  *   'indexes' => array(
348  *     'node_changed'        => array('changed'),
349  *     'node_created'        => array('created'),
350  *     'node_moderate'       => array('moderate'),
351  *     'node_frontpage'      => array('promote', 'status', 'sticky', 'created'),
352  *     'node_status_type'    => array('status', 'type', 'nid'),
353  *     'node_title_type'     => array('title', array('type', 4)),
354  *     'node_type'           => array(array('type', 4)),
355  *     'uid'                 => array('uid'),
356  *     'translate'           => array('translate'),
357  *   ),
358  *   'unique keys' => array(
359  *     'vid' => array('vid'),
360  *   ),
361  *   // For documentation purposes only; foreign keys are not created in the
362  *   // database.
363  *   'foreign keys' => array(
364  *     'node_revision' => array(
365  *       'table' => 'node_field_revision',
366  *       'columns' => array('vid' => 'vid'),
367  *      ),
368  *     'node_author' => array(
369  *       'table' => 'users',
370  *       'columns' => array('uid' => 'uid'),
371  *      ),
372  *    ),
373  *   'primary key' => array('nid'),
374  * );
375  * @endcode
376  *
377  * @see drupal_install_schema()
378  *
379  * @}
380  */
381
382 /**
383  * @addtogroup hooks
384  * @{
385  */
386
387 /**
388  * Perform alterations to a structured query.
389  *
390  * Structured (aka dynamic) queries that have tags associated may be altered by any module
391  * before the query is executed.
392  *
393  * @param $query
394  *   A Query object describing the composite parts of a SQL query.
395  *
396  * @see hook_query_TAG_alter()
397  * @see node_query_node_access_alter()
398  * @see AlterableInterface
399  * @see SelectInterface
400  *
401  * @ingroup database
402  */
403 function hook_query_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
404   if ($query->hasTag('micro_limit')) {
405     $query->range(0, 2);
406   }
407 }
408
409 /**
410  * Perform alterations to a structured query for a given tag.
411  *
412  * @param $query
413  *   An Query object describing the composite parts of a SQL query.
414  *
415  * @see hook_query_alter()
416  * @see node_query_node_access_alter()
417  * @see AlterableInterface
418  * @see SelectInterface
419  *
420  * @ingroup database
421  */
422 function hook_query_TAG_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
423   // Skip the extra expensive alterations if site has no node access control modules.
424   if (!node_access_view_all_nodes()) {
425     // Prevent duplicates records.
426     $query->distinct();
427     // The recognized operations are 'view', 'update', 'delete'.
428     if (!$op = $query->getMetaData('op')) {
429       $op = 'view';
430     }
431     // Skip the extra joins and conditions for node admins.
432     if (!\Drupal::currentUser()->hasPermission('bypass node access')) {
433       // The node_access table has the access grants for any given node.
434       $access_alias = $query->join('node_access', 'na', '%alias.nid = n.nid');
435       $or = db_or();
436       // If any grant exists for the specified user, then user has access to the node for the specified operation.
437       foreach (node_access_grants($op, $query->getMetaData('account')) as $realm => $gids) {
438         foreach ($gids as $gid) {
439           $or->condition(db_and()
440             ->condition($access_alias . '.gid', $gid)
441             ->condition($access_alias . '.realm', $realm)
442           );
443         }
444       }
445
446       if (count($or->conditions())) {
447         $query->condition($or);
448       }
449
450       $query->condition($access_alias . 'grant_' . $op, 1, '>=');
451     }
452   }
453 }
454
455 /**
456  * Define the current version of the database schema.
457  *
458  * A Drupal schema definition is an array structure representing one or more
459  * tables and their related keys and indexes. A schema is defined by
460  * hook_schema() which must live in your module's .install file.
461  *
462  * The tables declared by this hook will be automatically created when the
463  * module is installed, and removed when the module is uninstalled. This happens
464  * before hook_install() is invoked, and after hook_uninstall() is invoked,
465  * respectively.
466  *
467  * By declaring the tables used by your module via an implementation of
468  * hook_schema(), these tables will be available on all supported database
469  * engines. You don't have to deal with the different SQL dialects for table
470  * creation and alteration of the supported database engines.
471  *
472  * See the Schema API Handbook at https://www.drupal.org/node/146843 for details
473  * on schema definition structures. Note that foreign key definitions are for
474  * documentation purposes only; foreign keys are not created in the database,
475  * nor are they enforced by Drupal.
476  *
477  * @return array
478  *   A schema definition structure array. For each element of the
479  *   array, the key is a table name and the value is a table structure
480  *   definition.
481  *
482  * @ingroup schemaapi
483  */
484 function hook_schema() {
485   $schema['node'] = [
486     // Example (partial) specification for table "node".
487     'description' => 'The base table for nodes.',
488     'fields' => [
489       'nid' => [
490         'description' => 'The primary identifier for a node.',
491         'type' => 'serial',
492         'unsigned' => TRUE,
493         'not null' => TRUE,
494       ],
495       'vid' => [
496         'description' => 'The current {node_field_revision}.vid version identifier.',
497         'type' => 'int',
498         'unsigned' => TRUE,
499         'not null' => TRUE,
500         'default' => 0,
501       ],
502       'type' => [
503         'description' => 'The type of this node.',
504         'type' => 'varchar',
505         'length' => 32,
506         'not null' => TRUE,
507         'default' => '',
508       ],
509       'title' => [
510         'description' => 'The node title.',
511         'type' => 'varchar',
512         'length' => 255,
513         'not null' => TRUE,
514         'default' => '',
515       ],
516     ],
517     'indexes' => [
518       'node_changed'        => ['changed'],
519       'node_created'        => ['created'],
520     ],
521     'unique keys' => [
522       'nid_vid' => ['nid', 'vid'],
523       'vid'     => ['vid'],
524     ],
525     // For documentation purposes only; foreign keys are not created in the
526     // database.
527     'foreign keys' => [
528       'node_revision' => [
529         'table' => 'node_field_revision',
530         'columns' => ['vid' => 'vid'],
531       ],
532       'node_author' => [
533         'table' => 'users',
534         'columns' => ['uid' => 'uid'],
535       ],
536     ],
537     'primary key' => ['nid'],
538   ];
539   return $schema;
540 }
541
542 /**
543  * @} End of "addtogroup hooks".
544  */