annotate core/lib/Drupal/Core/Database/database.api.php @ 19:fa3358dc1485 tip

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