2006-09-25 21:16:08 +00:00
< ? php
/*
* $Id $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL . For more information , see
* < http :// www . phpdoctrine . com >.
*/
2006-11-19 12:06:42 +00:00
Doctrine :: autoload ( 'Doctrine_DataDict' );
2006-09-25 21:16:08 +00:00
/**
2006-11-19 12:06:42 +00:00
* @ package Doctrine
* @ license http :// www . opensource . org / licenses / lgpl - license . php LGPL
* @ author Konsta Vesterinen < kvesteri @ cc . hut . fi >
2006-10-19 20:56:59 +00:00
* @ author Lukas Smith < smith @ pooteeweet . org > ( PEAR MDB2 library )
2006-11-19 12:06:42 +00:00
* @ version $Revision $
* @ category Object Relational Mapping
* @ link www . phpdoctrine . com
* @ since 1.0
*/
2006-12-02 22:44:53 +00:00
class Doctrine_DataDict_Mysql extends Doctrine_DataDict {
2006-12-14 12:25:34 +00:00
protected $keywords = array (
'ADD' , 'ALL' , 'ALTER' ,
'ANALYZE' , 'AND' , 'AS' ,
'ASC' , 'ASENSITIVE' , 'BEFORE' ,
'BETWEEN' , 'BIGINT' , 'BINARY' ,
'BLOB' , 'BOTH' , 'BY' ,
'CALL' , 'CASCADE' , 'CASE' ,
'CHANGE' , 'CHAR' , 'CHARACTER' ,
'CHECK' , 'COLLATE' , 'COLUMN' ,
'CONDITION' , 'CONNECTION' , 'CONSTRAINT' ,
'CONTINUE' , 'CONVERT' , 'CREATE' ,
'CROSS' , 'CURRENT_DATE' , 'CURRENT_TIME' ,
'CURRENT_TIMESTAMP' , 'CURRENT_USER' , 'CURSOR' ,
'DATABASE' , 'DATABASES' , 'DAY_HOUR' ,
'DAY_MICROSECOND' , 'DAY_MINUTE' , 'DAY_SECOND' ,
'DEC' , 'DECIMAL' , 'DECLARE' ,
'DEFAULT' , 'DELAYED' , 'DELETE' ,
'DESC' , 'DESCRIBE' , 'DETERMINISTIC' ,
'DISTINCT' , 'DISTINCTROW' , 'DIV' ,
'DOUBLE' , 'DROP' , 'DUAL' ,
'EACH' , 'ELSE' , 'ELSEIF' ,
'ENCLOSED' , 'ESCAPED' , 'EXISTS' ,
'EXIT' , 'EXPLAIN' , 'FALSE' ,
'FETCH' , 'FLOAT' , 'FLOAT4' ,
'FLOAT8' , 'FOR' , 'FORCE' ,
'FOREIGN' , 'FROM' , 'FULLTEXT' ,
'GRANT' , 'GROUP' , 'HAVING' ,
'HIGH_PRIORITY' , 'HOUR_MICROSECOND' , 'HOUR_MINUTE' ,
'HOUR_SECOND' , 'IF' , 'IGNORE' ,
'IN' , 'INDEX' , 'INFILE' ,
'INNER' , 'INOUT' , 'INSENSITIVE' ,
'INSERT' , 'INT' , 'INT1' ,
'INT2' , 'INT3' , 'INT4' ,
'INT8' , 'INTEGER' , 'INTERVAL' ,
'INTO' , 'IS' , 'ITERATE' ,
'JOIN' , 'KEY' , 'KEYS' ,
'KILL' , 'LEADING' , 'LEAVE' ,
'LEFT' , 'LIKE' , 'LIMIT' ,
'LINES' , 'LOAD' , 'LOCALTIME' ,
'LOCALTIMESTAMP' , 'LOCK' , 'LONG' ,
'LONGBLOB' , 'LONGTEXT' , 'LOOP' ,
'LOW_PRIORITY' , 'MATCH' , 'MEDIUMBLOB' ,
'MEDIUMINT' , 'MEDIUMTEXT' , 'MIDDLEINT' ,
'MINUTE_MICROSECOND' , 'MINUTE_SECOND' , 'MOD' ,
'MODIFIES' , 'NATURAL' , 'NOT' ,
'NO_WRITE_TO_BINLOG' , 'NULL' , 'NUMERIC' ,
'ON' , 'OPTIMIZE' , 'OPTION' ,
'OPTIONALLY' , 'OR' , 'ORDER' ,
'OUT' , 'OUTER' , 'OUTFILE' ,
'PRECISION' , 'PRIMARY' , 'PROCEDURE' ,
'PURGE' , 'RAID0' , 'READ' ,
'READS' , 'REAL' , 'REFERENCES' ,
'REGEXP' , 'RELEASE' , 'RENAME' ,
'REPEAT' , 'REPLACE' , 'REQUIRE' ,
'RESTRICT' , 'RETURN' , 'REVOKE' ,
'RIGHT' , 'RLIKE' , 'SCHEMA' ,
'SCHEMAS' , 'SECOND_MICROSECOND' , 'SELECT' ,
'SENSITIVE' , 'SEPARATOR' , 'SET' ,
'SHOW' , 'SMALLINT' , 'SONAME' ,
'SPATIAL' , 'SPECIFIC' , 'SQL' ,
'SQLEXCEPTION' , 'SQLSTATE' , 'SQLWARNING' ,
'SQL_BIG_RESULT' , 'SQL_CALC_FOUND_ROWS' , 'SQL_SMALL_RESULT' ,
'SSL' , 'STARTING' , 'STRAIGHT_JOIN' ,
'TABLE' , 'TERMINATED' , 'THEN' ,
'TINYBLOB' , 'TINYINT' , 'TINYTEXT' ,
'TO' , 'TRAILING' , 'TRIGGER' ,
'TRUE' , 'UNDO' , 'UNION' ,
'UNIQUE' , 'UNLOCK' , 'UNSIGNED' ,
'UPDATE' , 'USAGE' , 'USE' ,
'USING' , 'UTC_DATE' , 'UTC_TIME' ,
'UTC_TIMESTAMP' , 'VALUES' , 'VARBINARY' ,
'VARCHAR' , 'VARCHARACTER' , 'VARYING' ,
'WHEN' , 'WHERE' , 'WHILE' ,
'WITH' , 'WRITE' , 'X509' ,
'XOR' , 'YEAR_MONTH' , 'ZEROFILL'
);
2006-10-19 20:56:59 +00:00
/**
* Obtain DBMS specific SQL code portion needed to declare an text type
* field to be used in statements like CREATE TABLE .
*
* @ param array $field associative array with the name of the properties
* of the field being declared as array indexes . Currently , the types
* of supported field properties are as follows :
*
* length
* Integer value that determines the maximum length of the text
* field . If this argument is missing the field should be
* declared to have the longest length allowed by the DBMS .
*
* default
* Text value to be used as default for this field .
*
* notnull
* Boolean flag that indicates whether this field is constrained
* to not be set to null .
2006-11-19 12:06:42 +00:00
*
2006-10-19 20:56:59 +00:00
* @ return string DBMS specific SQL code portion that should be used to
* declare the specified field .
*/
2006-11-26 19:48:55 +00:00
public function getNativeDeclaration ( $field ) {
2006-10-19 20:56:59 +00:00
switch ( $field [ 'type' ]) {
2006-11-27 22:22:31 +00:00
case 'char' :
$length = ( ! empty ( $field [ 'length' ])) ? $field [ 'length' ] : false ;
return $length ? 'CHAR(' . $length . ')' : 'CHAR(255)' ;
case 'varchar' :
2006-10-19 20:56:59 +00:00
case 'array' :
case 'object' :
case 'string' :
if ( empty ( $field [ 'length' ]) && array_key_exists ( 'default' , $field )) {
2006-11-28 23:26:44 +00:00
$field [ 'length' ] = $this -> conn -> varchar_max_length ;
2006-10-19 20:56:59 +00:00
}
$length = ( ! empty ( $field [ 'length' ])) ? $field [ 'length' ] : false ;
$fixed = ( ! empty ( $field [ 'fixed' ])) ? $field [ 'fixed' ] : false ;
return $fixed ? ( $length ? 'CHAR(' . $length . ')' : 'CHAR(255)' )
2006-12-14 12:25:34 +00:00
: ( $length ? 'VARCHAR(' . $length . ')' : 'TEXT' );
2006-10-19 20:56:59 +00:00
case 'clob' :
if ( ! empty ( $field [ 'length' ])) {
$length = $field [ 'length' ];
if ( $length <= 255 ) {
return 'TINYTEXT' ;
} elseif ( $length <= 65532 ) {
return 'TEXT' ;
} elseif ( $length <= 16777215 ) {
return 'MEDIUMTEXT' ;
}
}
return 'LONGTEXT' ;
case 'blob' :
if ( ! empty ( $field [ 'length' ])) {
$length = $field [ 'length' ];
if ( $length <= 255 ) {
return 'TINYBLOB' ;
} elseif ( $length <= 65532 ) {
return 'BLOB' ;
} elseif ( $length <= 16777215 ) {
return 'MEDIUMBLOB' ;
}
}
return 'LONGBLOB' ;
case 'integer' :
2006-12-10 17:28:20 +00:00
case 'enum' :
2006-10-19 20:56:59 +00:00
if ( ! empty ( $field [ 'length' ])) {
$length = $field [ 'length' ];
if ( $length <= 1 ) {
return 'TINYINT' ;
} elseif ( $length == 2 ) {
return 'SMALLINT' ;
} elseif ( $length == 3 ) {
return 'MEDIUMINT' ;
} elseif ( $length == 4 ) {
return 'INT' ;
} elseif ( $length > 4 ) {
return 'BIGINT' ;
}
}
return 'INT' ;
case 'boolean' :
return 'TINYINT(1)' ;
case 'date' :
return 'DATE' ;
case 'time' :
return 'TIME' ;
case 'timestamp' :
return 'DATETIME' ;
case 'float' :
return 'DOUBLE' ;
case 'decimal' :
$length = ! empty ( $field [ 'length' ]) ? $field [ 'length' ] : 18 ;
2006-11-28 23:26:44 +00:00
return 'DECIMAL(' . $length . ',' . 0 . ')' ; //$this->dbh->options['decimal_places'] . ')';
2006-10-19 20:56:59 +00:00
}
return '' ;
}
2006-10-23 16:19:47 +00:00
/**
* Maps a native array description of a field to a MDB2 datatype and length
*
* @ param array $field native field description
* @ return array containing the various possible types , length , sign , fixed
*/
2006-11-30 14:40:50 +00:00
public function getPortableDeclaration ( array $field ) {
$dbType = strtolower ( $field [ 'type' ]);
$dbType = strtok ( $dbType , '(), ' );
if ( $dbType == 'national' ) {
$dbType = strtok ( '(), ' );
2006-10-23 16:19:47 +00:00
}
if ( ! empty ( $field [ 'length' ])) {
$length = $field [ 'length' ];
$decimal = '' ;
} else {
$length = strtok ( '(), ' );
$decimal = strtok ( '(), ' );
}
$type = array ();
$unsigned = $fixed = null ;
2006-11-30 14:40:50 +00:00
switch ( $dbType ) {
2006-10-29 23:24:50 +00:00
case 'tinyint' :
$type [] = 'integer' ;
2006-10-23 16:19:47 +00:00
$type [] = 'boolean' ;
if ( preg_match ( '/^(is|has)/' , $field [ 'name' ])) {
$type = array_reverse ( $type );
}
2006-10-29 23:24:50 +00:00
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
$length = 1 ;
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'smallint' :
$type [] = 'integer' ;
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
$length = 2 ;
break ;
case 'mediumint' :
$type [] = 'integer' ;
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
$length = 3 ;
break ;
case 'int' :
case 'integer' :
$type [] = 'integer' ;
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
$length = 4 ;
break ;
case 'bigint' :
$type [] = 'integer' ;
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
$length = 8 ;
break ;
case 'tinytext' :
case 'mediumtext' :
case 'longtext' :
case 'text' :
case 'text' :
case 'varchar' :
$fixed = false ;
case 'string' :
case 'char' :
$type [] = 'text' ;
if ( $length == '1' ) {
2006-10-23 16:19:47 +00:00
$type [] = 'boolean' ;
if ( preg_match ( '/^(is|has)/' , $field [ 'name' ])) {
$type = array_reverse ( $type );
}
2006-11-30 14:40:50 +00:00
} elseif ( strstr ( $dbType , 'text' )) {
2006-10-29 23:24:50 +00:00
$type [] = 'clob' ;
if ( $decimal == 'binary' ) {
$type [] = 'blob' ;
}
}
if ( $fixed !== false ) {
$fixed = true ;
2006-10-23 16:19:47 +00:00
}
break ;
2006-10-29 23:24:50 +00:00
case 'enum' :
$type [] = 'text' ;
preg_match_all ( '/\'.+\'/U' , $field [ 'type' ], $matches );
$length = 0 ;
$fixed = false ;
if ( is_array ( $matches )) {
foreach ( $matches [ 0 ] as $value ) {
$length = max ( $length , strlen ( $value ) - 2 );
}
if ( $length == '1' && count ( $matches [ 0 ]) == 2 ) {
$type [] = 'boolean' ;
if ( preg_match ( '/^(is|has)/' , $field [ 'name' ])) {
$type = array_reverse ( $type );
}
}
}
$type [] = 'integer' ;
case 'set' :
$fixed = false ;
$type [] = 'text' ;
$type [] = 'integer' ;
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'date' :
$type [] = 'date' ;
$length = null ;
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'datetime' :
case 'timestamp' :
$type [] = 'timestamp' ;
$length = null ;
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'time' :
$type [] = 'time' ;
$length = null ;
break ;
case 'float' :
case 'double' :
case 'real' :
$type [] = 'float' ;
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'unknown' :
case 'decimal' :
case 'numeric' :
$type [] = 'decimal' ;
$unsigned = preg_match ( '/ unsigned/i' , $field [ 'type' ]);
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'tinyblob' :
case 'mediumblob' :
case 'longblob' :
case 'blob' :
$type [] = 'blob' ;
$length = null ;
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
case 'year' :
$type [] = 'integer' ;
$type [] = 'date' ;
$length = null ;
2006-10-23 16:19:47 +00:00
break ;
2006-10-29 23:24:50 +00:00
default :
2006-11-30 14:40:50 +00:00
throw new Doctrine_DataDict_Mysql_Exception ( 'unknown database attribute type: ' . $dbType );
2006-10-23 16:19:47 +00:00
}
return array ( $type , $length , $unsigned , $fixed );
}
2006-11-25 10:59:33 +00:00
/**
* Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration to be used in statements like CREATE TABLE .
*
* @ param string $charset name of the charset
* @ return string DBMS specific SQL code portion needed to set the CHARACTER SET
* of a field declaration .
*/
public function getCharsetFieldDeclaration ( $charset ) {
return 'CHARACTER SET ' . $charset ;
}
/**
* Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE .
*
* @ param string $collation name of the collation
* @ return string DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration .
*/
public function getCollationFieldDeclaration ( $collation ) {
return 'COLLATE ' . $collation ;
}
/**
* Obtain DBMS specific SQL code portion needed to declare an integer type
* field to be used in statements like CREATE TABLE .
*
* @ param string $name name the field to be declared .
* @ param string $field associative array with the name of the properties
* of the field being declared as array indexes .
* Currently , the types of supported field
* properties are as follows :
*
* unsigned
* Boolean flag that indicates whether the field
* should be declared as unsigned integer if
* possible .
*
* default
* Integer value to be used as default for this
* field .
*
* notnull
* Boolean flag that indicates whether this field is
* constrained to not be set to null .
* @ return string DBMS specific SQL code portion that should be used to
* declare the specified field .
*/
public function getIntegerDeclaration ( $name , $field ) {
$default = $autoinc = '' ;
if ( ! empty ( $field [ 'autoincrement' ])) {
$autoinc = ' AUTO_INCREMENT PRIMARY KEY' ;
} elseif ( array_key_exists ( 'default' , $field )) {
if ( $field [ 'default' ] === '' ) {
$field [ 'default' ] = empty ( $field [ 'notnull' ]) ? null : 0 ;
}
$default = ' DEFAULT ' . $this -> conn -> getDbh () -> quote ( $field [ 'default' ]);
2006-11-27 22:22:31 +00:00
}
/**
elseif ( empty ( $field [ 'notnull' ])) {
2006-11-25 10:59:33 +00:00
$default = ' DEFAULT NULL' ;
}
2006-11-27 22:22:31 +00:00
*/
2006-11-25 10:59:33 +00:00
2006-11-27 22:22:31 +00:00
$notnull = ( isset ( $field [ 'notnull' ]) && $field [ 'notnull' ]) ? ' NOT NULL' : '' ;
$unsigned = ( isset ( $field [ 'unsigned' ]) && $field [ 'unsigned' ]) ? ' UNSIGNED' : '' ;
2006-11-26 19:48:55 +00:00
2006-11-25 10:59:33 +00:00
$name = $this -> conn -> quoteIdentifier ( $name , true );
2006-11-26 19:48:55 +00:00
return $name . ' ' . $this -> getNativeDeclaration ( $field ) . $unsigned . $default . $notnull . $autoinc ;
2006-11-25 10:59:33 +00:00
}
2006-09-25 21:16:08 +00:00
/**
* lists all databases
*
* @ return array
*/
public function listDatabases () {
2006-10-30 20:53:25 +00:00
$sql = 'SHOW DATABASES' ;
2006-10-31 18:48:13 +00:00
return $this -> dbh -> query ( $sql ) -> fetchAll ( PDO :: FETCH_COLUMN );
2006-09-25 21:16:08 +00:00
}
/**
* lists all availible database functions
*
* @ return array
*/
public function listFunctions () {
}
/**
* lists all database triggers
*
* @ param string | null $database
* @ return array
*/
public function listTriggers ( $database = null ) {
}
/**
* lists all database sequences
*
* @ param string | null $database
* @ return array
*/
public function listSequences ( $database = null ) {
}
/**
* lists table constraints
*
* @ param string $table database table name
* @ return array
*/
public function listTableConstraints ( $table ) {
2006-11-03 20:16:19 +00:00
$sql = 'select KCU.COLUMN_NAME as referencingColumn, TC.CONSTRAINT_NAME as constraintName, KCU.REFERENCED_TABLE_SCHEMA as referencedTableSchema, KCU.REFERENCED_TABLE_NAME as referencedTable, KCU.REFERENCED_COLUMN_NAME as referencedColumn from INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC inner JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU on TC.CONSTRAINT_NAME=KCU.CONSTRAINT_NAME and TC.TABLE_SCHEMA = KCU.TABLE_SCHEMA and TC.TABLE_NAME=KCU.TABLE_NAME WHERE TC.TABLE_SCHEMA=database() AND TC.TABLE_NAME="' . $table . '" AND CONSTRAINT_TYPE="FOREIGN KEY"' ;
2006-11-23 22:54:10 +00:00
return $this -> dbh -> query ( $sql ) -> fetchAll ( PDO :: FETCH_ASSOC );
2006-09-25 21:16:08 +00:00
}
/**
* lists table constraints
*
* @ param string $table database table name
* @ return array
*/
public function listTableColumns ( $table ) {
$sql = " DESCRIBE $table " ;
$result = $this -> dbh -> query ( $sql ) -> fetchAll ( PDO :: FETCH_ASSOC );
$description = array ();
2006-10-30 20:53:25 +00:00
foreach ( $result as $key => $val2 ) {
$val = array ();
foreach ( array_keys ( $val2 ) as $valKey ){ // lowercase the key names
$val [ strtolower ( $valKey )] = $val2 [ $valKey ];
}
2006-09-25 21:24:31 +00:00
$description = array (
2006-09-25 21:16:08 +00:00
'name' => $val [ 'field' ],
'type' => $val [ 'type' ],
'primary' => ( strtolower ( $val [ 'key' ]) == 'pri' ),
'default' => $val [ 'default' ],
'notnull' => ( bool ) ( $val [ 'null' ] != 'YES' ),
2006-11-23 22:54:10 +00:00
'autoinc' => ( bool ) ( strpos ( $val [ 'extra' ], 'auto_increment' ) > - 1 ),
2006-09-25 21:16:08 +00:00
);
$columns [ $val [ 'field' ]] = new Doctrine_Schema_Column ( $description );
}
return $columns ;
}
/**
* lists table constraints
*
* @ param string $table database table name
* @ return array
*/
public function listTableIndexes ( $table ) {
}
/**
* lists tables
*
* @ param string | null $database
* @ return array
*/
public function listTables ( $database = null ) {
2006-10-19 20:56:59 +00:00
$sql = 'SHOW TABLES' ;
2006-09-25 21:16:08 +00:00
2006-10-31 18:48:13 +00:00
return $this -> dbh -> query ( $sql ) -> fetchAll ( PDO :: FETCH_COLUMN );
2006-09-25 21:16:08 +00:00
}
/**
* lists table triggers
*
* @ param string $table database table name
* @ return array
*/
public function listTableTriggers ( $table ) {
}
/**
* lists table views
*
* @ param string $table database table name
* @ return array
*/
public function listTableViews ( $table ) {
}
/**
* lists database users
*
* @ return array
*/
public function listUsers () {
}
/**
* lists database views
*
* @ param string | null $database
* @ return array
*/
public function listViews ( $database = null ) {
}
}