* @link http://www.yiiframework.com/ * @copyright Copyright © 2008-2009 Yii Software LLC * @license http://www.yiiframework.com/license/ */ prado::using('System.Testing.Data.Schema.TDbSchema'); prado::using('System.Testing.Data.Schema.mysql.TMysqlTableSchema'); prado::using('System.Testing.Data.Schema.mysql.TMysqlColumnSchema'); /** * TMysqlSchema is the class for retrieving metadata information from a MySQL database (version 4.1.x and 5.x). * * @author Qiang Xue * @version $Id: TMysqlSchema.php 2679 2009-06-15 07:49:42Z Christophe.Boulain $ * @package System.Testing.Data.Schema.mysql * @since 1.0 */ class TMysqlSchema extends TDbSchema { private $_tableNames; private $_schemaNames; /** * Quotes a table name for use in a query. * @param string table name * @return string the properly quoted table name */ public function quoteTableName($name) { return '`'.$name.'`'; } /** * Quotes a column name for use in a query. * @param string column name * @return string the properly quoted column name */ public function quoteColumnName($name) { return '`'.$name.'`'; } /** * Compares two table names. * The table names can be either quoted or unquoted. This method * will consider both cases. * @param string table name 1 * @param string table name 2 * @return boolean whether the two table names refer to the same table. */ public function compareTableNames($name1,$name2) { return parent::compareTableNames(strtolower($name1),strtolower($name2)); } /** * Creates a table instance representing the metadata for the named table. * @return TMysqlTableSchema driver dependent table metadata. Null if the table does not exist. */ protected function createTable($name) { $table=new TMysqlTableSchema; $this->resolveTableNames($table,$name); if($this->findColumns($table)) { $this->findConstraints($table); return $table; } else return null; } /** * Generates various kinds of table names. * @param TMysqlTableSchema the table instance * @param string the unquoted table name */ protected function resolveTableNames($table,$name) { $parts=explode('.',str_replace('`','',$name)); if(isset($parts[1])) { $table->schemaName=$parts[0]; $table->name=$parts[1]; $table->rawName=$this->quoteTableName($table->schemaName).'.'.$this->quoteTableName($table->name); } else { $table->name=$parts[0]; $table->rawName=$this->quoteTableName($table->name); } } /** * Collects the table column metadata. * @param TMysqlTableSchema the table metadata * @return boolean whether the table exists in the database */ protected function findColumns($table) { $sql='SHOW COLUMNS FROM '.$table->rawName; try { $columns=$this->getDbConnection()->createCommand($sql)->queryAll(); } catch(Exception $e) { return false; } foreach($columns as $column) { $c=$this->createColumn($column); $table->columns[$c->name]=$c; if($c->isPrimaryKey) { if($table->primaryKey===null) $table->primaryKey=$c->name; else if(is_string($table->primaryKey)) $table->primaryKey=array($table->primaryKey,$c->name); else $table->primaryKey[]=$c->name; if(strpos(strtolower($column['Extra']),'auto_increment')!==false) $table->sequenceName=''; } } return true; } /** * Creates a table column. * @param array column metadata * @return TDbColumnSchema normalized column metadata */ protected function createColumn($column) { $c=new TMysqlColumnSchema; $c->name=$column['Field']; $c->rawName=$this->quoteColumnName($c->name); $c->allowNull=$column['Null']==='YES'; $c->isPrimaryKey=strpos($column['Key'],'PRI')!==false; $c->isForeignKey=false; $c->init($column['Type'],$column['Default']); return $c; } /** * @return float server version. */ protected function getServerVersion() { $version=$this->getDbConnection()->getAttribute(PDO::ATTR_SERVER_VERSION); $digits=array(); preg_match('/(\d+)\.(\d+)\.(\d+)/', $version, $digits); return floatval($digits[1].'.'.$digits[2].$digits[3]); } /** * Collects the foreign key column details for the given table. * @param TMysqlTableSchema the table metadata */ protected function findConstraints($table) { $row=$this->getDbConnection()->createCommand('SHOW CREATE TABLE '.$table->rawName)->queryRow(); $matches=array(); $regexp='/FOREIGN KEY\s+\(([^\)]+)\)\s+REFERENCES\s+([^\(^\s]+)\s*\(([^\)]+)\)/mi'; foreach($row as $sql) { if(preg_match_all($regexp,$sql,$matches,PREG_SET_ORDER)) break; } $foreign = array(); foreach($matches as $match) { $keys=array_map('trim',explode(',',str_replace('`','',$match[1]))); $fks=array_map('trim',explode(',',str_replace('`','',$match[3]))); foreach($keys as $k=>$name) { $table->foreignKeys[$name]=array(str_replace('`','',$match[2]),$fks[$k]); if(isset($table->columns[$name])) $table->columns[$name]->isForeignKey=true; } } } /** * Returns all table names in the database. * @return array all table names in the database. * @since 1.0.2 */ protected function findTableNames($schema='') { if($schema==='') return $this->getDbConnection()->createCommand('SHOW TABLES')->queryColumn(); $names=$this->getDbConnection()->createCommand('SHOW TABLES FROM '.$this->quoteTableName($schema))->queryColumn(); foreach($names as &$name) $name=$schema.'.'.$name; return $names; } }