2008-08-21 19:36:39 +00:00
< ? php
/**
* @ file
* Generic Database schema code .
*/
2011-08-07 16:39:05 +00:00
require_once dirname ( __FILE__ ) . '/query.inc' ;
2010-11-29 04:45:11 +00:00
2008-08-21 19:36:39 +00:00
/**
* @ defgroup schemaapi Schema API
* @ {
2011-01-03 18:03:54 +00:00
* API to handle database schemas .
2008-08-21 19:36:39 +00:00
*
* A Drupal schema definition is an array structure representing one or
* more tables and their related keys and indexes . A schema is defined by
* hook_schema (), which usually lives in a modulename . install file .
*
* By implementing hook_schema () and specifying the tables your module
* declares , you can easily create and drop these tables on all
* supported database engines . You don ' t have to deal with the
* different SQL dialects for table creation and alteration of the
* supported database engines .
*
* hook_schema () should return an array with a key for each table that
* the module defines .
*
* The following keys are defined :
2009-08-02 08:16:16 +00:00
* - 'description' : A string in non - markup plain text describing this table
* and its purpose . References to other tables should be enclosed in
2008-12-20 18:24:41 +00:00
* curly - brackets . For example , the node_revisions table
2008-08-21 19:36:39 +00:00
* description field might contain " Stores per-revision title and
* body data for each { node } . "
* - 'fields' : An associative array ( 'fieldname' => specification )
2008-12-20 18:24:41 +00:00
* that describes the table ' s database columns . The specification
* is also an array . The following specification parameters are defined :
2009-08-02 08:16:16 +00:00
* - 'description' : A string in non - markup plain text describing this field
* and its purpose . References to other tables should be enclosed in
2008-12-20 18:24:41 +00:00
* curly - brackets . For example , the node table vid field
2008-08-21 19:36:39 +00:00
* description might contain " Always holds the largest (most
2008-12-03 16:32:22 +00:00
* recent ) { node_revision } . vid value for this nid . "
2009-10-08 02:44:54 +00:00
* - 'type' : The generic datatype : 'char' , 'varchar' , 'text' , 'blob' , 'int' ,
2010-12-28 19:38:39 +00:00
* 'float' , 'numeric' , or 'serial' . Most types just map to the according
* database engine specific datatypes . Use 'serial' for auto incrementing
* fields . This will expand to 'INT auto_increment' on MySQL .
* - 'mysql_type' , 'pgsql_type' , 'sqlite_type' , etc .: If you need to
* use a record type not included in the officially supported list
* of types above , you can specify a type for each database
* backend . In this case , you can leave out the type parameter ,
* but be advised that your schema will fail to load on backends that
* do not have a type specified . A possible solution can be to
* use the " text " type as a fallback .
2009-08-02 08:16:16 +00:00
* - 'serialize' : A boolean indicating whether the field will be stored as
* a serialized string .
2008-08-21 19:36:39 +00:00
* - 'size' : The data size : 'tiny' , 'small' , 'medium' , 'normal' ,
2008-12-20 18:24:41 +00:00
* 'big' . This is a hint about the largest value the field will
2008-08-21 19:36:39 +00:00
* store and determines which of the database engine specific
* datatypes will be used ( e . g . on MySQL , TINYINT vs . INT vs . BIGINT ) .
* 'normal' , the default , selects the base type ( e . g . on MySQL ,
* INT , VARCHAR , BLOB , etc . ) .
* Not all sizes are available for all data types . See
2010-03-09 11:39:07 +00:00
* DatabaseSchema :: getFieldTypeMap () for possible combinations .
2008-08-21 19:36:39 +00:00
* - 'not null' : If true , no NULL values will be allowed in this
2008-12-20 18:24:41 +00:00
* database column . Defaults to false .
* - 'default' : The field ' s default value . The PHP type of the
* value matters : '' , '0' , and 0 are all different . If you
2008-08-21 19:36:39 +00:00
* specify '0' as the default value for a type 'int' field it
* will not work because '0' is a string containing the
* character " zero " , not an integer .
2009-07-09 10:12:14 +00:00
* - 'length' : The maximal length of a type 'char' , 'varchar' or 'text'
2008-12-20 18:24:41 +00:00
* field . Ignored for other field types .
2008-08-21 19:36:39 +00:00
* - 'unsigned' : A boolean indicating whether a type 'int' , 'float'
2008-12-20 18:24:41 +00:00
* and 'numeric' only is signed or unsigned . Defaults to
* FALSE . Ignored for other field types .
2008-08-21 19:36:39 +00:00
* - 'precision' , 'scale' : For type 'numeric' fields , indicates
* the precision ( total number of significant digits ) and scale
2008-12-20 18:24:41 +00:00
* ( decimal digits right of the decimal point ) . Both values are
* mandatory . Ignored for other field types .
2012-04-23 01:57:18 +00:00
* - 'binary' : A boolean indicating that MySQL should force 'char' ,
* 'varchar' or 'text' fields to use case - sensitive binary collation .
* This has no effect on other database types for which case sensitivity
* is already the default behavior .
2008-08-21 19:36:39 +00:00
* All parameters apart from 'type' are optional except that type
2012-03-01 00:54:06 +00:00
* 'numeric' columns must specify 'precision' and 'scale' , and type
* 'varchar' must specify the 'length' parameter .
2008-08-21 19:36:39 +00:00
* - 'primary key' : An array of one or more key column specifiers ( see below )
* that form the primary key .
2009-01-18 06:47:58 +00:00
* - 'unique keys' : An associative array of unique keys ( 'keyname' =>
2008-12-20 18:24:41 +00:00
* specification ) . Each specification is an array of one or more
2008-08-21 19:36:39 +00:00
* key column specifiers ( see below ) that form a unique key on the table .
2010-08-22 13:55:53 +00:00
* - 'foreign keys' : An associative array of relations ( 'my_relation' =>
* specification ) . Each specification is an array containing the name of
* the referenced table ( 'table' ), and an array of column mappings
* ( 'columns' ) . Column mappings are defined by key pairs ( 'source_column' =>
2015-10-14 22:29:54 +00:00
* 'referenced_column' ) . This key is for documentation purposes only ; foreign
* keys are not created in the database , nor are they enforced by Drupal .
2010-01-25 10:38:35 +00:00
* - 'indexes' : An associative array of indexes ( 'indexname' =>
2008-12-20 18:24:41 +00:00
* specification ) . Each specification is an array of one or more
2008-08-21 19:36:39 +00:00
* key column specifiers ( see below ) that form an index on the
* table .
*
* A key column specifier is either a string naming a column or an
* array of two elements , column name and length , specifying a prefix
* of the named column .
*
* As an example , here is a SUBSET of the schema definition for
2008-12-20 18:24:41 +00:00
* Drupal 's ' node ' table . It show four fields ( nid , vid , type , and
2008-08-21 19:36:39 +00:00
* title ), the primary key on field 'nid' , a unique key named 'vid' on
* field 'vid' , and two indexes , one named 'nid' on field 'nid' and
* one named 'node_title_type' on the field 'title' and the first four
* bytes of the field 'type' :
*
* @ code
* $schema [ 'node' ] = array (
2009-06-01 22:07:10 +00:00
* 'description' => 'The base table for nodes.' ,
2008-08-21 19:36:39 +00:00
* 'fields' => array (
2009-06-01 22:07:10 +00:00
* 'nid' => array ( 'type' => 'serial' , 'unsigned' => TRUE , 'not null' => TRUE ),
* 'vid' => array ( 'type' => 'int' , 'unsigned' => TRUE , 'not null' => TRUE , 'default' => 0 ),
* 'type' => array ( 'type' => 'varchar' , 'length' => 32 , 'not null' => TRUE , 'default' => '' ),
* 'language' => array ( 'type' => 'varchar' , 'length' => 12 , 'not null' => TRUE , 'default' => '' ),
* 'title' => array ( 'type' => 'varchar' , 'length' => 255 , 'not null' => TRUE , 'default' => '' ),
* 'uid' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'status' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 1 ),
* 'created' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'changed' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'comment' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'promote' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'moderate' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'sticky' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
* 'tnid' => array ( 'type' => 'int' , 'unsigned' => TRUE , 'not null' => TRUE , 'default' => 0 ),
* 'translate' => array ( 'type' => 'int' , 'not null' => TRUE , 'default' => 0 ),
2008-08-21 19:36:39 +00:00
* ),
* 'indexes' => array (
2009-06-01 22:07:10 +00:00
* 'node_changed' => array ( 'changed' ),
* 'node_created' => array ( 'created' ),
* 'node_moderate' => array ( 'moderate' ),
* 'node_frontpage' => array ( 'promote' , 'status' , 'sticky' , 'created' ),
* 'node_status_type' => array ( 'status' , 'type' , 'nid' ),
2008-08-21 19:36:39 +00:00
* 'node_title_type' => array ( 'title' , array ( 'type' , 4 )),
2009-06-01 22:07:10 +00:00
* 'node_type' => array ( array ( 'type' , 4 )),
* 'uid' => array ( 'uid' ),
* 'tnid' => array ( 'tnid' ),
* 'translate' => array ( 'translate' ),
2008-08-21 19:36:39 +00:00
* ),
2009-06-01 22:07:10 +00:00
* 'unique keys' => array (
* 'vid' => array ( 'vid' ),
* ),
2015-10-14 22:29:54 +00:00
* // For documentation purposes only; foreign keys are not created in the
* // database.
2009-06-01 22:07:10 +00:00
* 'foreign keys' => array (
2010-08-22 13:55:53 +00:00
* 'node_revision' => array (
* 'table' => 'node_revision' ,
* 'columns' => array ( 'vid' => 'vid' ),
* ),
* 'node_author' => array (
* 'table' => 'users' ,
* 'columns' => array ( 'uid' => 'uid' ),
* ),
2009-06-01 22:07:10 +00:00
* ),
* 'primary key' => array ( 'nid' ),
2008-08-21 19:36:39 +00:00
* );
* @ endcode
*
* @ see drupal_install_schema ()
*/
2017-06-02 21:33:13 +00:00
/**
* Base class for database schema definitions .
*/
2009-08-29 05:43:35 +00:00
abstract class DatabaseSchema implements QueryPlaceholderInterface {
2008-09-03 12:04:49 +00:00
2008-08-21 19:36:39 +00:00
protected $connection ;
2008-09-03 12:04:49 +00:00
2009-08-29 05:43:35 +00:00
/**
* The placeholder counter .
*/
protected $placeholder = 0 ;
2010-04-07 15:07:59 +00:00
/**
* Definition of prefixInfo array structure .
*
* Rather than redefining DatabaseSchema :: getPrefixInfo () for each driver ,
* by defining the defaultSchema variable only MySQL has to re - write the
* method .
*
* @ see DatabaseSchema :: getPrefixInfo ()
*/
protected $defaultSchema = 'public' ;
2009-08-29 05:43:35 +00:00
2011-08-22 02:27:31 +00:00
/**
* A unique identifier for this query object .
*/
protected $uniqueIdentifier ;
2008-08-21 19:36:39 +00:00
public function __construct ( $connection ) {
2011-08-22 02:27:31 +00:00
$this -> uniqueIdentifier = uniqid ( '' , TRUE );
2008-08-21 19:36:39 +00:00
$this -> connection = $connection ;
}
2008-09-03 12:04:49 +00:00
2011-08-22 02:27:31 +00:00
/**
* Implements the magic __clone function .
*/
public function __clone () {
$this -> uniqueIdentifier = uniqid ( '' , TRUE );
}
/**
* Implements QueryPlaceHolderInterface :: uniqueIdentifier () .
*/
public function uniqueIdentifier () {
return $this -> uniqueIdentifier ;
}
/**
* Implements QueryPlaceHolderInterface :: nextPlaceholder () .
*/
2009-08-29 05:43:35 +00:00
public function nextPlaceholder () {
return $this -> placeholder ++ ;
}
2010-04-07 15:07:59 +00:00
/**
2010-06-28 19:57:34 +00:00
* Get information about the table name and schema from the prefix .
2010-04-07 15:07:59 +00:00
*
* @ param
* Name of table to look prefix up for . Defaults to 'default' because thats
2010-06-28 19:57:34 +00:00
* default key for prefix .
2010-08-02 18:55:17 +00:00
* @ param $add_prefix
* Boolean that indicates whether the given table name should be prefixed .
*
2010-04-07 15:07:59 +00:00
* @ return
* A keyed array with information about the schema , table name and prefix .
*/
2010-08-02 18:55:17 +00:00
protected function getPrefixInfo ( $table = 'default' , $add_prefix = TRUE ) {
2010-04-07 15:07:59 +00:00
$info = array (
'schema' => $this -> defaultSchema ,
'prefix' => $this -> connection -> tablePrefix ( $table ),
);
2010-08-02 18:55:17 +00:00
if ( $add_prefix ) {
$table = $info [ 'prefix' ] . $table ;
}
2010-04-07 15:07:59 +00:00
// If the prefix contains a period in it, then that means the prefix also
// contains a schema reference in which case we will change the schema key
// to the value before the period in the prefix. Everything after the dot
// will be prefixed onto the front of the table.
2010-08-02 18:55:17 +00:00
if (( $pos = strpos ( $table , '.' )) !== FALSE ) {
2010-04-07 15:07:59 +00:00
// Grab everything before the period.
2010-08-02 18:55:17 +00:00
$info [ 'schema' ] = substr ( $table , 0 , $pos );
// Grab everything after the dot.
$info [ 'table' ] = substr ( $table , ++ $pos );
2010-04-07 15:07:59 +00:00
}
else {
2010-08-02 18:55:17 +00:00
$info [ 'table' ] = $table ;
2010-04-07 15:07:59 +00:00
}
return $info ;
}
/**
* Create names for indexes , primary keys and constraints .
*
* This prevents using {} around non - table names like indexes and keys .
*/
function prefixNonTable ( $table ) {
$args = func_get_args ();
$info = $this -> getPrefixInfo ( $table );
$args [ 0 ] = $info [ 'table' ];
return implode ( '_' , $args );
}
2009-01-08 09:52:12 +00:00
/**
* Build a condition to match a table name against a standard information_schema .
*
* The information_schema is a SQL standard that provides information about the
* database server and the databases , schemas , tables , columns and users within
2009-01-26 14:08:44 +00:00
* it . This makes information_schema a useful tool to use across the drupal
2009-01-08 09:52:12 +00:00
* database drivers and is used by a few different functions . The function below
* describes the conditions to be meet when querying information_schema . tables
* for drupal tables or information associated with drupal tables . Even though
* this is the standard method , not all databases follow standards and so this
* method should be overwritten by a database driver if the database provider
* uses alternate methods . Because information_schema . tables is used in a few
* different functions , a database driver will only need to override this function
* to make all the others work . For example see includes / databases / mysql / schema . inc .
*
* @ param $table_name
2010-04-07 15:07:59 +00:00
* The name of the table in question .
2009-01-08 09:52:12 +00:00
* @ param $operator
* The operator to apply on the 'table' part of the condition .
2010-08-02 18:55:17 +00:00
* @ param $add_prefix
* Boolean to indicate whether the table name needs to be prefixed .
2010-03-21 20:49:01 +00:00
*
2009-12-04 16:31:04 +00:00
* @ return QueryConditionInterface
2009-01-08 09:52:12 +00:00
* A DatabaseCondition object .
*/
2010-08-02 18:55:17 +00:00
protected function buildTableNameCondition ( $table_name , $operator = '=' , $add_prefix = TRUE ) {
2010-03-07 08:03:45 +00:00
$info = $this -> connection -> getConnectionOptions ();
2009-01-08 09:52:12 +00:00
2010-04-07 15:07:59 +00:00
// Retrive the table name and schema
2010-08-02 18:55:17 +00:00
$table_info = $this -> getPrefixInfo ( $table_name , $add_prefix );
2009-01-08 09:52:12 +00:00
2009-01-19 01:28:28 +00:00
$condition = new DatabaseCondition ( 'AND' );
2010-03-07 08:03:45 +00:00
$condition -> condition ( 'table_catalog' , $info [ 'database' ]);
2010-04-07 15:07:59 +00:00
$condition -> condition ( 'table_schema' , $table_info [ 'schema' ]);
$condition -> condition ( 'table_name' , $table_info [ 'table' ], $operator );
2009-01-08 09:52:12 +00:00
return $condition ;
}
2008-08-21 19:36:39 +00:00
/**
* Check if a table exists .
2009-01-26 14:08:44 +00:00
*
2009-01-08 09:52:12 +00:00
* @ param $table
* The name of the table in drupal ( no prefixing ) .
2010-03-21 20:49:01 +00:00
*
2009-01-08 09:52:12 +00:00
* @ return
2010-03-01 11:30:37 +00:00
* TRUE if the given table exists , otherwise FALSE .
2008-08-21 19:36:39 +00:00
*/
2009-01-08 09:52:12 +00:00
public function tableExists ( $table ) {
2010-04-07 15:07:59 +00:00
$condition = $this -> buildTableNameCondition ( $table );
2009-08-29 05:43:35 +00:00
$condition -> compile ( $this -> connection , $this );
2009-01-08 09:52:12 +00:00
// Normally, we would heartily discourage the use of string
2010-01-25 10:38:35 +00:00
// concatenation for conditionals like this however, we
2009-01-08 09:52:12 +00:00
// couldn't use db_select() here because it would prefix
// information_schema.tables and the query would fail.
2009-05-29 01:51:46 +00:00
// Don't use {} around information_schema.tables table.
2010-03-01 11:30:37 +00:00
return ( bool ) $this -> connection -> query ( " SELECT 1 FROM information_schema.tables WHERE " . ( string ) $condition , $condition -> arguments ()) -> fetchField ();
2009-01-08 09:52:12 +00:00
}
/**
* Find all tables that are like the specified base table name .
*
* @ param $table_expression
* An SQL expression , for example " simpletest% " ( without the quotes ) .
* BEWARE : this is not prefixed , the caller should take care of that .
2010-03-21 20:49:01 +00:00
*
2009-01-08 09:52:12 +00:00
* @ return
* Array , both the keys and the values are the matching tables .
*/
public function findTables ( $table_expression ) {
2010-08-02 18:55:17 +00:00
$condition = $this -> buildTableNameCondition ( $table_expression , 'LIKE' , FALSE );
2009-08-29 05:43:35 +00:00
$condition -> compile ( $this -> connection , $this );
2009-01-08 09:52:12 +00:00
// Normally, we would heartily discourage the use of string
2010-01-25 10:38:35 +00:00
// concatenation for conditionals like this however, we
2009-01-08 09:52:12 +00:00
// couldn't use db_select() here because it would prefix
// information_schema.tables and the query would fail.
2009-05-29 01:51:46 +00:00
// Don't use {} around information_schema.tables table.
2010-03-01 11:30:37 +00:00
return $this -> connection -> query ( " SELECT table_name FROM information_schema.tables WHERE " . ( string ) $condition , $condition -> arguments ()) -> fetchAllKeyed ( 0 , 0 );
2009-01-08 09:52:12 +00:00
}
2008-09-03 12:04:49 +00:00
2008-08-21 19:36:39 +00:00
/**
* Check if a column exists in the given table .
2010-03-01 11:30:37 +00:00
*
* @ param $table
* The name of the table in drupal ( no prefixing ) .
* @ param $name
* The name of the column .
2010-03-21 20:49:01 +00:00
*
2010-03-01 11:30:37 +00:00
* @ return
* TRUE if the given column exists , otherwise FALSE .
2008-08-21 19:36:39 +00:00
*/
2010-03-28 11:45:11 +00:00
public function fieldExists ( $table , $column ) {
2010-04-07 15:07:59 +00:00
$condition = $this -> buildTableNameCondition ( $table );
2009-01-08 09:52:12 +00:00
$condition -> condition ( 'column_name' , $column );
2009-08-29 05:43:35 +00:00
$condition -> compile ( $this -> connection , $this );
2009-01-08 09:52:12 +00:00
// Normally, we would heartily discourage the use of string
2010-01-25 10:38:35 +00:00
// concatenation for conditionals like this however, we
2009-01-08 09:52:12 +00:00
// couldn't use db_select() here because it would prefix
// information_schema.tables and the query would fail.
2009-05-29 01:51:46 +00:00
// Don't use {} around information_schema.columns table.
2010-03-01 11:30:37 +00:00
return ( bool ) $this -> connection -> query ( " SELECT 1 FROM information_schema.columns WHERE " . ( string ) $condition , $condition -> arguments ()) -> fetchField ();
2009-01-08 09:52:12 +00:00
}
2008-09-03 12:04:49 +00:00
2008-08-21 19:36:39 +00:00
/**
2010-03-21 20:49:01 +00:00
* Returns a mapping of Drupal schema field names to DB - native field types .
*
* Because different field types do not map 1 : 1 between databases , Drupal has
* its own normalized field type names . This function returns a driver - specific
* mapping table from Drupal names to the native names for each database .
*
* @ return array
* An array of Schema API field types to driver - specific field types .
*/
2008-08-21 19:36:39 +00:00
abstract public function getFieldTypeMap ();
2008-09-03 12:04:49 +00:00
2008-08-21 19:36:39 +00:00
/**
* Rename a table .
*
* @ param $table
* The table to be renamed .
* @ param $new_name
* The new name for the table .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table doesn ' t exist .
* @ throws DatabaseSchemaObjectExistsException
2010-03-01 06:27:58 +00:00
* If a table with the specified new name already exists .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function renameTable ( $table , $new_name );
2008-08-21 19:36:39 +00:00
/**
* Drop a table .
*
* @ param $table
* The table to be dropped .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ return
* TRUE if the table was successfully dropped , FALSE if there was no table
* by that name to begin with .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function dropTable ( $table );
2008-09-03 12:04:49 +00:00
2008-08-21 19:36:39 +00:00
/**
* Add a new field to a table .
*
* @ param $table
* Name of the table to be altered .
* @ param $field
* Name of the field to be added .
* @ param $spec
* The field specification array , as taken from a schema definition .
* The specification may also contain the key 'initial' , the newly
* created field will be set to the value of the key in all rows .
* This is most useful for creating NOT NULL columns with no default
* value in existing tables .
* @ param $keys_new
2014-06-06 18:54:24 +00:00
* ( optional ) Keys and indexes specification to be created on the
2008-08-21 19:36:39 +00:00
* table along with adding the field . The format is the same as a
2008-12-20 18:24:41 +00:00
* table specification but without the 'fields' element . If you are
2008-08-21 19:36:39 +00:00
* adding a type 'serial' field , you MUST specify at least one key
2010-01-30 07:54:01 +00:00
* or index including it in this array . See db_change_field () for more
2008-08-21 19:36:39 +00:00
* explanation why .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table doesn ' t exist .
* @ throws DatabaseSchemaObjectExistsException
* If the specified table already has a field by that name .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function addField ( $table , $field , $spec , $keys_new = array ());
2008-08-21 19:36:39 +00:00
/**
* Drop a field .
*
* @ param $table
* The table to be altered .
* @ param $field
* The field to be dropped .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ return
* TRUE if the field was successfully dropped , FALSE if there was no field
* by that name to begin with .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function dropField ( $table , $field );
2008-08-21 19:36:39 +00:00
/**
* Set the default value for a field .
*
* @ param $table
* The table to be altered .
* @ param $field
* The field to be altered .
* @ param $default
* Default value to be set . NULL for 'default NULL' .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table or field doesn ' t exist .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function fieldSetDefault ( $table , $field , $default );
2008-08-21 19:36:39 +00:00
/**
* Set a field to have no default value .
*
* @ param $table
* The table to be altered .
* @ param $field
* The field to be altered .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table or field doesn ' t exist .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function fieldSetNoDefault ( $table , $field );
2008-08-21 19:36:39 +00:00
2009-12-15 08:30:53 +00:00
/**
2010-03-01 11:30:37 +00:00
* Checks if an index exists in the given table .
2009-12-15 08:30:53 +00:00
*
* @ param $table
2010-03-01 11:30:37 +00:00
* The name of the table in drupal ( no prefixing ) .
2009-12-15 08:30:53 +00:00
* @ param $name
2010-03-01 11:30:37 +00:00
* The name of the index in drupal ( no prefixing ) .
2010-03-21 20:49:01 +00:00
*
2009-12-15 08:30:53 +00:00
* @ return
2010-03-01 11:30:37 +00:00
* TRUE if the given index exists , otherwise FALSE .
2009-12-15 08:30:53 +00:00
*/
abstract public function indexExists ( $table , $name );
2008-08-21 19:36:39 +00:00
/**
* Add a primary key .
*
* @ param $table
* The table to be altered .
* @ param $fields
* Fields for the primary key .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table doesn ' t exist .
* @ throws DatabaseSchemaObjectExistsException
* If the specified table already has a primary key .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function addPrimaryKey ( $table , $fields );
2008-08-21 19:36:39 +00:00
/**
* Drop the primary key .
*
* @ param $table
* The table to be altered .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ return
* TRUE if the primary key was successfully dropped , FALSE if there was no
* primary key on this table to begin with .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function dropPrimaryKey ( $table );
2008-08-21 19:36:39 +00:00
/**
* Add a unique key .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the key .
* @ param $fields
* An array of field names .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table doesn ' t exist .
* @ throws DatabaseSchemaObjectExistsException
* If the specified table already has a key by that name .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function addUniqueKey ( $table , $name , $fields );
2008-08-21 19:36:39 +00:00
/**
* Drop a unique key .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the key .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ return
* TRUE if the key was successfully dropped , FALSE if there was no key by
* that name to begin with .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function dropUniqueKey ( $table , $name );
2008-08-21 19:36:39 +00:00
/**
* Add an index .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the index .
* @ param $fields
* An array of field names .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table doesn ' t exist .
* @ throws DatabaseSchemaObjectExistsException
* If the specified table already has an index by that name .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function addIndex ( $table , $name , $fields );
2008-08-21 19:36:39 +00:00
/**
* Drop an index .
*
* @ param $table
* The table to be altered .
* @ param $name
* The name of the index .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ return
* TRUE if the index was successfully dropped , FALSE if there was no index
* by that name to begin with .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function dropIndex ( $table , $name );
2008-08-21 19:36:39 +00:00
/**
* Change a field definition .
*
* IMPORTANT NOTE : To maintain database portability , you have to explicitly
* recreate all indices and primary keys that are using the changed field .
*
* That means that you have to drop all affected keys and indexes with
* db_drop_ { primary_key , unique_key , index }() before calling db_change_field () .
* To recreate the keys and indices , pass the key definitions as the
* optional $keys_new argument directly to db_change_field () .
*
* For example , suppose you have :
* @ code
* $schema [ 'foo' ] = array (
* 'fields' => array (
* 'bar' => array ( 'type' => 'int' , 'not null' => TRUE )
* ),
* 'primary key' => array ( 'bar' )
* );
* @ endcode
* and you want to change foo . bar to be type serial , leaving it as the
2008-12-20 18:24:41 +00:00
* primary key . The correct sequence is :
2008-08-21 19:36:39 +00:00
* @ code
2009-09-29 15:13:57 +00:00
* db_drop_primary_key ( 'foo' );
* db_change_field ( 'foo' , 'bar' , 'bar' ,
2008-08-21 19:36:39 +00:00
* array ( 'type' => 'serial' , 'not null' => TRUE ),
* array ( 'primary key' => array ( 'bar' )));
* @ endcode
*
* The reasons for this are due to the different database engines :
*
* On PostgreSQL , changing a field definition involves adding a new field
* and dropping an old one which * causes any indices , primary keys and
* sequences ( from serial - type fields ) that use the changed field to be dropped .
*
* On MySQL , all type 'serial' fields must be part of at least one key
2008-12-20 18:24:41 +00:00
* or index as soon as they are created . You cannot use
2008-08-21 19:36:39 +00:00
* db_add_ { primary_key , unique_key , index }() for this purpose because
* the ALTER TABLE command will fail to add the column without a key
2008-12-20 18:24:41 +00:00
* or index specification . The solution is to use the optional
2008-08-21 19:36:39 +00:00
* $keys_new argument to create the key or index at the same time as
* field .
*
* You could use db_add_ { primary_key , unique_key , index }() in all cases
* unless you are converting a field to be type serial . You can use
* the $keys_new argument in all cases .
*
* @ param $table
* Name of the table .
* @ param $field
* Name of the field to change .
* @ param $field_new
* New name for the field ( set to the same as $field if you don ' t want to change the name ) .
* @ param $spec
* The field specification for the new field .
* @ param $keys_new
2014-06-06 18:54:24 +00:00
* ( optional ) Keys and indexes specification to be created on the
2008-08-21 19:36:39 +00:00
* table along with changing the field . The format is the same as a
* table specification but without the 'fields' element .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectDoesNotExistException
* If the specified table or source field doesn ' t exist .
* @ throws DatabaseSchemaObjectExistsException
* If the specified destination field already exists .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
abstract public function changeField ( $table , $field , $field_new , $spec , $keys_new = array ());
2008-08-21 19:36:39 +00:00
/**
* Create a new table from a Drupal table definition .
*
* @ param $name
* The name of the table to create .
* @ param $table
* A Schema API table definition array .
2010-03-21 20:49:01 +00:00
*
2010-02-28 20:03:05 +00:00
* @ throws DatabaseSchemaObjectExistsException
* If the specified table already exists .
2008-08-21 19:36:39 +00:00
*/
2009-09-29 15:13:57 +00:00
public function createTable ( $name , $table ) {
2010-02-28 20:03:05 +00:00
if ( $this -> tableExists ( $name )) {
2014-11-02 00:39:29 +00:00
throw new DatabaseSchemaObjectExistsException ( t ( 'Table @name already exists.' , array ( '@name' => $name )));
2010-02-28 20:03:05 +00:00
}
2010-04-28 20:25:22 +00:00
$statements = $this -> createTableSql ( $name , $table );
2008-08-21 19:36:39 +00:00
foreach ( $statements as $statement ) {
2010-04-28 20:25:22 +00:00
$this -> connection -> query ( $statement );
2008-08-21 19:36:39 +00:00
}
}
2008-09-03 12:04:49 +00:00
2008-08-21 19:36:39 +00:00
/**
* Return an array of field names from an array of key / index column specifiers .
*
* This is usually an identity function but if a key / index uses a column prefix
* specification , this function extracts just the name .
*
* @ param $fields
* An array of key / index column specifiers .
2010-03-21 20:49:01 +00:00
*
2008-08-21 19:36:39 +00:00
* @ return
* An array of field names .
*/
public function fieldNames ( $fields ) {
2009-09-29 15:13:57 +00:00
$return = array ();
2008-08-21 19:36:39 +00:00
foreach ( $fields as $field ) {
if ( is_array ( $field )) {
2009-09-29 15:13:57 +00:00
$return [] = $field [ 0 ];
2008-08-21 19:36:39 +00:00
}
else {
2009-09-29 15:13:57 +00:00
$return [] = $field ;
2008-08-21 19:36:39 +00:00
}
}
2009-09-29 15:13:57 +00:00
return $return ;
2008-08-21 19:36:39 +00:00
}
2009-03-14 20:34:17 +00:00
/**
* Prepare a table or column comment for database query .
2009-05-24 17:39:35 +00:00
*
2009-03-14 20:34:17 +00:00
* @ param $comment
* The comment string to prepare .
* @ param $length
* Optional upper limit on the returned string length .
2010-03-21 20:49:01 +00:00
*
2009-03-14 20:34:17 +00:00
* @ return
* The prepared comment .
*/
public function prepareComment ( $comment , $length = NULL ) {
return $this -> connection -> quote ( $comment );
}
2008-08-21 19:36:39 +00:00
}
2010-02-28 20:03:05 +00:00
/**
2010-03-01 06:27:58 +00:00
* Exception thrown if an object being created already exists .
*
* For example , this exception should be thrown whenever there is an attempt to
* create a new database table , field , or index that already exists in the
* database schema .
2010-02-28 20:03:05 +00:00
*/
class DatabaseSchemaObjectExistsException extends Exception {}
/**
2010-03-01 06:27:58 +00:00
* Exception thrown if an object being modified doesn ' t exist yet .
*
* For example , this exception should be thrown whenever there is an attempt to
* modify a database table , field , or index that does not currently exist in
* the database schema .
2010-02-28 20:03:05 +00:00
*/
class DatabaseSchemaObjectDoesNotExistException extends Exception {}
2008-08-21 19:36:39 +00:00
/**
* @ } End of " defgroup schemaapi " .
*/