2008-08-21 19:36:39 +00:00
< ? php
// $Id$
/**
* @ file
* Database schema code for MySQL database servers .
*/
/**
* @ ingroup schemaapi
* @ {
*/
class DatabaseSchema_mysql extends DatabaseSchema {
public function tableExists ( $table ) {
return ( bool ) $this -> connection -> query ( " SHOW TABLES LIKE ' { " . $table . " }' " , array (), array ()) -> fetchField ();
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
public function columnExists ( $table , $column ) {
2008-09-19 20:30:32 +00:00
return ( bool ) $this -> connection -> query ( " SHOW COLUMNS FROM { " . $this -> connection -> escapeTable ( $table ) . " } LIKE ' " . $this -> connection -> escapeTable ( $column ) . " ' " , array (), array ()) -> fetchField ();
2008-08-21 19:36:39 +00:00
}
/**
* Generate SQL to create a new table from a Drupal schema definition .
*
* @ param $name
* The name of the table to create .
* @ param $table
* A Schema API table definition array .
* @ return
* An array of SQL statements to create the table .
*/
protected function createTableSql ( $name , $table ) {
if ( empty ( $table [ 'mysql_suffix' ])) {
$table [ 'mysql_suffix' ] = " /*!40100 DEFAULT CHARACTER SET UTF8 */ " ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
$sql = " CREATE TABLE { " . $name . " } ( \n " ;
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
// Add the SQL statement for each field.
foreach ( $table [ 'fields' ] as $field_name => $field ) {
$sql .= $this -> createFieldSql ( $field_name , $this -> processField ( $field )) . " , \n " ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
// Process keys & indexes.
$keys = $this -> createKeysSql ( $table );
if ( count ( $keys )) {
$sql .= implode ( " , \n " , $keys ) . " , \n " ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
// Remove the last comma and space.
$sql = substr ( $sql , 0 , - 3 ) . " \n ) " ;
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
$sql .= $table [ 'mysql_suffix' ];
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
return array ( $sql );
}
/**
* Create an SQL string for a field to be used in table creation or alteration .
*
* Before passing a field out of a schema definition into this function it has
* to be processed by _db_process_field () .
*
* @ param $name
* Name of the field .
* @ param $spec
* The field specification , as per the schema data structure format .
*/
protected function createFieldSql ( $name , $spec ) {
$sql = " ` " . $name . " ` " . $spec [ 'mysql_type' ];
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( isset ( $spec [ 'length' ])) {
$sql .= '(' . $spec [ 'length' ] . ')' ;
}
elseif ( isset ( $spec [ 'precision' ]) && isset ( $spec [ 'scale' ])) {
$sql .= '(' . $spec [ 'precision' ] . ', ' . $spec [ 'scale' ] . ')' ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( ! empty ( $spec [ 'unsigned' ])) {
$sql .= ' unsigned' ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( ! empty ( $spec [ 'not null' ])) {
$sql .= ' NOT NULL' ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( ! empty ( $spec [ 'auto_increment' ])) {
$sql .= ' auto_increment' ;
}
2008-09-15 20:48:10 +00:00
2008-12-02 19:45:01 +00:00
// $spec['default'] can be NULL, so we explicitly check for the key here.
2008-11-13 20:52:13 +00:00
if ( array_key_exists ( 'default' , $spec )) {
2008-08-21 19:36:39 +00:00
if ( is_string ( $spec [ 'default' ])) {
$spec [ 'default' ] = " ' " . $spec [ 'default' ] . " ' " ;
}
2008-11-13 20:52:13 +00:00
elseif ( is_null ( $spec [ 'default' ])) {
$spec [ 'default' ] = 'NULL' ;
}
2008-08-21 19:36:39 +00:00
$sql .= ' DEFAULT ' . $spec [ 'default' ];
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( empty ( $spec [ 'not null' ]) && ! isset ( $spec [ 'default' ])) {
$sql .= ' DEFAULT NULL' ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
return $sql ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
/**
* Set database - engine specific properties for a field .
*
* @ param $field
* A field description array , as specified in the schema documentation .
*/
protected function processField ( $field ) {
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( ! isset ( $field [ 'size' ])) {
$field [ 'size' ] = 'normal' ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
// Set the correct database-engine specific datatype.
if ( ! isset ( $field [ 'mysql_type' ])) {
$map = db_type_map ();
$field [ 'mysql_type' ] = $map [ $field [ 'type' ] . ':' . $field [ 'size' ]];
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
if ( $field [ 'type' ] == 'serial' ) {
$field [ 'auto_increment' ] = TRUE ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
return $field ;
}
public function getFieldTypeMap () {
// Put :normal last so it gets preserved by array_flip. This makes
// it much easier for modules (such as schema.module) to map
// database types back into schema types.
static $map = array (
'varchar:normal' => 'VARCHAR' ,
'char:normal' => 'CHAR' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'text:tiny' => 'TINYTEXT' ,
'text:small' => 'TINYTEXT' ,
'text:medium' => 'MEDIUMTEXT' ,
'text:big' => 'LONGTEXT' ,
'text:normal' => 'TEXT' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'serial:tiny' => 'TINYINT' ,
'serial:small' => 'SMALLINT' ,
'serial:medium' => 'MEDIUMINT' ,
'serial:big' => 'BIGINT' ,
'serial:normal' => 'INT' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'int:tiny' => 'TINYINT' ,
'int:small' => 'SMALLINT' ,
'int:medium' => 'MEDIUMINT' ,
'int:big' => 'BIGINT' ,
'int:normal' => 'INT' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'float:tiny' => 'FLOAT' ,
'float:small' => 'FLOAT' ,
'float:medium' => 'FLOAT' ,
'float:big' => 'DOUBLE' ,
'float:normal' => 'FLOAT' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'numeric:normal' => 'DECIMAL' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'blob:big' => 'LONGBLOB' ,
'blob:normal' => 'BLOB' ,
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
'datetime:normal' => 'DATETIME' ,
);
return $map ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
protected function createKeysSql ( $spec ) {
$keys = array ();
if ( ! empty ( $spec [ 'primary key' ])) {
$keys [] = 'PRIMARY KEY (' . $this -> createKeysSqlHelper ( $spec [ 'primary key' ]) . ')' ;
}
if ( ! empty ( $spec [ 'unique keys' ])) {
foreach ( $spec [ 'unique keys' ] as $key => $fields ) {
$keys [] = 'UNIQUE KEY ' . $key . ' (' . $this -> createKeysSqlHelper ( $fields ) . ')' ;
}
}
if ( ! empty ( $spec [ 'indexes' ])) {
foreach ( $spec [ 'indexes' ] as $index => $fields ) {
$keys [] = 'INDEX ' . $index . ' (' . $this -> createKeysSqlHelper ( $fields ) . ')' ;
}
}
return $keys ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
protected function createKeySql ( $fields ) {
$ret = array ();
foreach ( $fields as $field ) {
if ( is_array ( $field )) {
$ret [] = $field [ 0 ] . '(' . $field [ 1 ] . ')' ;
}
else {
$ret [] = $field ;
}
}
return implode ( ', ' , $ret );
}
protected function createKeysSqlHelper ( $fields ) {
$ret = array ();
foreach ( $fields as $field ) {
if ( is_array ( $field )) {
$ret [] = $field [ 0 ] . '(' . $field [ 1 ] . ')' ;
}
else {
$ret [] = $field ;
}
}
return implode ( ', ' , $ret );
}
public function renameTable ( & $ret , $table , $new_name ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} RENAME TO {' . $new_name . '}' );
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
public function dropTable ( & $ret , $table ) {
$ret [] = update_sql ( 'DROP TABLE {' . $table . '}' );
}
public function addField ( & $ret , $table , $field , $spec , $keys_new = array ()) {
$fixnull = FALSE ;
if ( ! empty ( $spec [ 'not null' ]) && ! isset ( $spec [ 'default' ])) {
$fixnull = TRUE ;
$spec [ 'not null' ] = FALSE ;
}
$query = 'ALTER TABLE {' . $table . '} ADD ' ;
$query .= $this -> createFieldSql ( $field , $this -> processField ( $spec ));
if ( count ( $keys_new )) {
$query .= ', ADD ' . implode ( ', ADD ' , $this -> createKeysSql ( $keys_new ));
}
$ret [] = update_sql ( $query );
if ( isset ( $spec [ 'initial' ])) {
// All this because update_sql does not support %-placeholders.
$sql = 'UPDATE {' . $table . '} SET ' . $field . ' = ' . db_type_placeholder ( $spec [ 'type' ]);
$result = db_query ( $sql , $spec [ 'initial' ]);
$ret [] = array ( 'success' => $result !== FALSE , 'query' => check_plain ( $sql . ' (' . $spec [ 'initial' ] . ')' ));
}
if ( $fixnull ) {
$spec [ 'not null' ] = TRUE ;
$this -> changeField ( $ret , $table , $field , $field , $spec );
}
}
public function dropField ( & $ret , $table , $field ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} DROP ' . $field );
}
public function fieldSetDefault ( & $ret , $table , $field , $default ) {
2008-11-13 20:52:13 +00:00
if ( is_null ( $default )) {
2008-08-21 19:36:39 +00:00
$default = 'NULL' ;
}
else {
$default = is_string ( $default ) ? " ' $default ' " : $default ;
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} ALTER COLUMN ' . $field . ' SET DEFAULT ' . $default );
}
public function fieldSetNoDefault ( & $ret , $table , $field ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} ALTER COLUMN ' . $field . ' DROP DEFAULT' );
}
public function addPrimaryKey ( & $ret , $table , $fields ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} ADD PRIMARY KEY (' . $this -> createKeySql ( $fields ) . ')' );
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
public function dropPrimaryKey ( & $ret , $table ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} DROP PRIMARY KEY' );
}
public function addUniqueKey ( & $ret , $table , $name , $fields ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} ADD UNIQUE KEY ' . $name . ' (' . $this -> createKeySql ( $fields ) . ')' );
}
public function dropUniqueKey ( & $ret , $table , $name ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} DROP KEY ' . $name );
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
public function addIndex ( & $ret , $table , $name , $fields ) {
$query = 'ALTER TABLE {' . $table . '} ADD INDEX ' . $name . ' (' . $this -> createKeySql ( $fields ) . ')' ;
$ret [] = update_sql ( $query );
}
public function dropIndex ( & $ret , $table , $name ) {
$ret [] = update_sql ( 'ALTER TABLE {' . $table . '} DROP INDEX ' . $name );
}
2008-09-15 20:48:10 +00:00
2008-08-21 19:36:39 +00:00
public function changeField ( & $ret , $table , $field , $field_new , $spec , $keys_new = array ()) {
2008-11-11 16:49:38 +00:00
$sql = 'ALTER TABLE {' . $table . '} CHANGE `' . $field . '` ' . $this -> createFieldSql ( $field_new , $this -> processField ( $spec ));
2008-08-21 19:36:39 +00:00
if ( count ( $keys_new )) {
$sql .= ', ADD ' . implode ( ', ADD ' , $this -> createKeysSql ( $keys_new ));
}
$ret [] = update_sql ( $sql );
}
}
/**
* @ } End of " ingroup schemaapi " .
*/