diff --git a/framework/db/dao/ColumnSchema.php b/framework/db/dao/ColumnSchema.php index 3b4e413..dd7256a 100644 --- a/framework/db/dao/ColumnSchema.php +++ b/framework/db/dao/ColumnSchema.php @@ -8,13 +8,15 @@ * @license http://www.yiiframework.com/license/ */ +namespace yii\db\dao; + /** * ColumnSchema class describes the column meta data of a database table. * * @author Qiang Xue * @since 2.0 */ -class ColumnSchema extends CComponent +class ColumnSchema extends \yii\base\Component { /** * @var string name of this column (without quotes). @@ -30,7 +32,7 @@ class ColumnSchema extends CComponent public $allowNull; /** * @var string logical type of this column. Possible logic types include: - * string, text, boolean, integer, float, decimal, datetime, timestamp, time, date, binary + * string, text, boolean, smallint, integer, bigint, float, decimal, datetime, timestamp, time, date, binary */ public $type; /** @@ -47,6 +49,10 @@ class ColumnSchema extends CComponent */ public $defaultValue; /** + * @var array enumerable values + */ + public $enumValues; + /** * @var integer size of the column. */ public $size; @@ -63,69 +69,37 @@ class ColumnSchema extends CComponent */ public $isPrimaryKey; /** - * @var boolean whether this column is a foreign key - */ - public $isForeignKey; - /** * @var boolean whether this column is auto-incremental */ public $autoIncrement = false; - - /** - * Initializes the column with its DB type and default value. - * This sets up the column's PHP type, size, precision, scale as well as default value. - * @param string $dbType the column's DB type - * @param mixed $defaultValue the default value + * @var boolean whether this column is unsigned. This is only meaningful + * when [[type]] is `integer` or `bigint`. */ - public function init($dbType, $defaultValue) - { - $this->dbType = $dbType; - $this->extractType($dbType); - $this->extractLimit($dbType); - if ($defaultValue !== null) - $this->extractDefault($defaultValue); - } + public $unsigned; /** * Extracts the PHP type from DB type. - * @param string $dbType DB type - */ - protected function extractType($dbType) - { - if (stripos($dbType, 'int') !== false && stripos($dbType, 'unsigned int') === false) - $this->type = 'integer'; - elseif (stripos($dbType, 'bool') !== false) - $this->type = 'boolean'; - elseif (preg_match('/(real|floa|doub)/i', $dbType)) - $this->type = 'double'; - else - $this->type = 'string'; - } - - /** - * Extracts size, precision and scale information from column's DB type. - * @param string $dbType the column's DB type */ - protected function extractLimit($dbType) + protected function getPhpType() { - if (strpos($dbType, '(') && preg_match('/\((.*)\)/', $dbType, $matches)) - { - $values = explode(',', $matches[1]); - $this->size = $this->precision = (int)$values[0]; - if (isset($values[1])) - $this->scale = (int)$values[1]; + static $typeMap = array( // logical type => php type + 'smallint' => 'integer', + 'integer' => 'integer', + 'bigint' => 'integer', + 'boolean' => 'boolean', + 'float' => 'double', + ); + if (isset($typeMap[$this->type])) { + if ($this->type === 'bigint') { + return PHP_INT_SIZE == 8 && !$this->unsigned ? 'integer' : 'string'; + } + elseif ($this->type === 'integer') { + return PHP_INT_SIZE == 4 && $this->unsigned ? 'string' : 'integer'; + } + return $typeMap[$this->type]; } - } - - /** - * Extracts the default value for the column. - * The value is typecasted to correct PHP type. - * @param mixed $defaultValue the default value obtained from metadata - */ - protected function extractDefault($defaultValue) - { - $this->defaultValue = $this->typecast($defaultValue); + return 'string'; } /** @@ -135,17 +109,14 @@ class ColumnSchema extends CComponent */ public function typecast($value) { - if (gettype($value) === $this->type || $value === null || $value instanceof CDbExpression) + if ($value === null || gettype($value) === $this->phpType || $value instanceof Expression) { return $value; - if ($value === '') - return $this->type === 'string' ? '' : null; - switch ($this->type) - { + } + switch ($this->phpType) { case 'string': return (string)$value; case 'integer': return (integer)$value; case 'boolean': return (boolean)$value; - case 'double': - default: return $value; } + return $value; } } diff --git a/framework/db/dao/QueryBuilder.php b/framework/db/dao/QueryBuilder.php index 6d97876..c32a429 100644 --- a/framework/db/dao/QueryBuilder.php +++ b/framework/db/dao/QueryBuilder.php @@ -151,7 +151,7 @@ class QueryBuilder extends \yii\base\Component public function dropColumn($table, $column) { return "ALTER TABLE " . $this->quoteTableName($table) - . " DROP COLUMN " . $this->quoteColumnName($column); + . " DROP COLUMN " . $this->quoteSimpleColumnName($column); } /** @@ -165,8 +165,8 @@ class QueryBuilder extends \yii\base\Component public function renameColumn($table, $name, $newName) { return "ALTER TABLE " . $this->quoteTableName($table) - . " RENAME COLUMN " . $this->quoteColumnName($name) - . " TO " . $this->quoteColumnName($newName); + . " RENAME COLUMN " . $this->quoteSimpleColumnName($name) + . " TO " . $this->quoteSimpleColumnName($newName); } /** @@ -181,8 +181,8 @@ class QueryBuilder extends \yii\base\Component public function alterColumn($table, $column, $type) { return 'ALTER TABLE ' . $this->quoteTableName($table) . ' CHANGE ' - . $this->quoteColumnName($column) . ' ' - . $this->quoteColumnName($column) . ' ' + . $this->quoteSimpleColumnName($column) . ' ' + . $this->quoteSimpleColumnName($column) . ' ' . $this->getColumnType($type); } diff --git a/framework/db/dao/Schema.php b/framework/db/dao/Schema.php index 179a1b9..a831a31 100644 --- a/framework/db/dao/Schema.php +++ b/framework/db/dao/Schema.php @@ -18,18 +18,18 @@ namespace yii\db\dao; */ abstract class Schema extends \yii\base\Component { + public $connection; + private $_tableNames = array(); private $_tables = array(); - private $_connection; private $_builder; - private $_cacheExclude = array(); /** * Loads the metadata for the specified table. * @param string $name table name - * @return CDbTableSchema driver dependent table metadata, null if the table does not exist. + * @return TableSchema driver dependent table metadata, null if the table does not exist. */ - abstract protected function loadTable($name); + abstract protected function loadTableSchema($name); /** * Constructor. @@ -37,17 +37,7 @@ abstract class Schema extends \yii\base\Component */ public function __construct($connection) { - $this->_connection = $connection; - foreach ($connection->schemaCachingExclude as $name) - $this->_cacheExclude[$name] = true; - } - - /** - * @return Connection database connection. The connection is active. - */ - public function getConnection() - { - return $this->_connection; + $this->connection = $connection; } /** @@ -62,13 +52,13 @@ abstract class Schema extends \yii\base\Component } if (strpos($name, '{{') !== false) { - $realName = preg_replace('/\{\{(.*?)\}\}/', $this->_connection->tablePrefix . '$1', $name); + $realName = preg_replace('/\{\{(.*?)\}\}/', $this->connection->tablePrefix . '$1', $name); } else { $realName = $name; } - - $db = $this->_connection; + + $db = $this->connection; // temporarily disable query caching if ($db->queryCachingDuration >= 0) { @@ -77,7 +67,7 @@ abstract class Schema extends \yii\base\Component } if (!in_array($name, $db->schemaCachingExclude) && $db->schemaCachingDuration >= 0 && ($cache = \Yii::app()->getComponent($db->schemaCacheID)) !== null) { - $key = __CLASS__ . ":{$db->dsn}/{$db->username}/{$name}"; + $key = __CLASS__ . "/{$db->dsn}/{$db->username}/{$name}"; if (($table = $cache->get($key)) === false) { $table = $this->loadTableSchema($realName); if ($table !== null) { @@ -102,15 +92,14 @@ abstract class Schema extends \yii\base\Component * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema. * @return array the metadata for all tables in the database. * Each array element is an instance of {@link CDbTableSchema} (or its child class). - * The array keys are table names. */ - public function getTables($schema = '') + public function getTableSchemas($schema = '') { $tables = array(); - foreach ($this->getTableNames($schema) as $name) - { - if (($table = $this->getTable($name)) !== null) - $tables[$name] = $table; + foreach ($this->getTableNames($schema) as $name) { + if (($table = $this->getTableSchema($name)) !== null) { + $tables[] = $table; + } } return $tables; } @@ -123,20 +112,21 @@ abstract class Schema extends \yii\base\Component */ public function getTableNames($schema = '') { - if (!isset($this->_tableNames[$schema])) + if (!isset($this->_tableNames[$schema])) { $this->_tableNames[$schema] = $this->findTableNames($schema); + } return $this->_tableNames[$schema]; } /** - * @return CDbCommandBuilder the SQL command builder for this connection. + * @return QueryBuilder the query builder for this connection. */ - public function getCommandBuilder() + public function getQueryBuilder() { - if ($this->_builder !== null) - return $this->_builder; - else - return $this->_builder = $this->createCommandBuilder(); + if ($this->_builder === null) { + $this->_builder = $this->createQueryBuilder(); + } + return $this->_builder; } /** @@ -146,7 +136,7 @@ abstract class Schema extends \yii\base\Component */ public function refresh() { - $db = $this->_connection; + $db = $this->connection; if ($db->schemaCachingDuration >= 0 && ($cache = \Yii::app()->getComponent($db->schemaCacheID)) !== null) { foreach ($this->_tables as $name => $table) { $key = __CLASS__ . ":{$db->dsn}/{$db->username}/{$name}"; @@ -155,7 +145,6 @@ abstract class Schema extends \yii\base\Component } $this->_tables = array(); $this->_tableNames = array(); - $this->_builder = null; } /** @@ -167,11 +156,13 @@ abstract class Schema extends \yii\base\Component */ public function quoteTableName($name) { - if (strpos($name, '.') === false) + if (strpos($name, '.') === false) { return $this->quoteSimpleTableName($name); + } $parts = explode('.', $name); - foreach ($parts as $i => $part) + foreach ($parts as $i => $part) { $parts[$i] = $this->quoteSimpleTableName($part); + } return implode('.', $parts); } @@ -184,7 +175,7 @@ abstract class Schema extends \yii\base\Component */ public function quoteSimpleTableName($name) { - return "'" . $name . "'"; + return strpos($name, "'") !== false ? $name : "'" . $name . "'"; } /** @@ -196,14 +187,13 @@ abstract class Schema extends \yii\base\Component */ public function quoteColumnName($name) { - if (($pos = strrpos($name, '.')) !== false) - { + if (($pos = strrpos($name, '.')) !== false) { $prefix = $this->quoteTableName(substr($name, 0, $pos)) . '.'; $name = substr($name, $pos + 1); } else $prefix = ''; - return $prefix . ($name === '*' ? $name : $this->quoteSimpleColumnName($name)); + return $prefix . $this->quoteSimpleColumnName($name); } /** @@ -211,45 +201,18 @@ abstract class Schema extends \yii\base\Component * A simple column name does not contain prefix. * @param string $name column name * @return string the properly quoted column name - * @since 1.1.6 */ public function quoteSimpleColumnName($name) { - return '"' . $name . '"'; - } - - /** - * Compares two table names. - * The table names can be either quoted or unquoted. This method - * will consider both cases. - * @param string $name1 table name 1 - * @param string $name2 table name 2 - * @return boolean whether the two table names refer to the same table. - */ - public function compareTableNames($name1, $name2) - { - $name1 = str_replace(array('"', '`', "'"), '', $name1); - $name2 = str_replace(array('"', '`', "'"), '', $name2); - if (($pos = strrpos($name1, '.')) !== false) - $name1 = substr($name1, $pos + 1); - if (($pos = strrpos($name2, '.')) !== false) - $name2 = substr($name2, $pos + 1); - if ($this->_connection->tablePrefix !== null) - { - if (strpos($name1, '{') !== false) - $name1 = $this->_connection->tablePrefix . str_replace(array('{', '}'), '', $name1); - if (strpos($name2, '{') !== false) - $name2 = $this->_connection->tablePrefix . str_replace(array('{', '}'), '', $name2); - } - return $name1 === $name2; + return strpos($name, '"') !== false || $name === '*' ? $name : '"' . $name . '"'; } /** - * Creates a command builder for the database. - * This method may be overridden by child classes to create a DBMS-specific command builder. - * @return CDbCommandBuilder command builder instance + * Creates a query builder for the database. + * This method may be overridden by child classes to create a DBMS-specific query builder. + * @return QueryBuilder query builder instance */ - protected function createQueryBuilder() + public function createQueryBuilder() { return new QueryBuilder($this); } diff --git a/framework/db/dao/TableSchema.php b/framework/db/dao/TableSchema.php index be97032..a7bdae7 100644 --- a/framework/db/dao/TableSchema.php +++ b/framework/db/dao/TableSchema.php @@ -39,7 +39,7 @@ class TableSchema extends \yii\base\Component */ public $name; /** - * @var string quoted name of this table. This may include [[schemaName]] if it is not empty. + * @var string quoted name of this table. This will include [[schemaName]] if it is not empty. */ public $quotedName; /** @@ -51,7 +51,15 @@ class TableSchema extends \yii\base\Component */ public $sequenceName; /** - * @var array foreign keys of this table. The array is indexed by column name. Each value is an array of foreign table name and foreign column name. + * @var array foreign keys of this table. Each array element is of the following structure: + * + * ~~~ + * array( + * 'ForeignTableName', + * 'fk1' => 'pk1', // pk1 is in foreign table + * 'fk2' => 'pk2', // if composite foreign key + * ) + * ~~~ */ public $foreignKeys = array(); /** diff --git a/framework/db/dao/mysql/ColumnSchema.php b/framework/db/dao/mysql/ColumnSchema.php index 671dd12..f9f2b61 100644 --- a/framework/db/dao/mysql/ColumnSchema.php +++ b/framework/db/dao/mysql/ColumnSchema.php @@ -8,6 +8,8 @@ * @license http://www.yiiframework.com/license/ */ +namespace yii\db\dao\mysql; + /** * ColumnSchema class describes the column meta data of a MySQL table. * @@ -20,18 +22,76 @@ class ColumnSchema extends \yii\db\dao\ColumnSchema * Extracts the PHP type from DB type. * @param string $dbType DB type */ - protected function extractType($dbType) + public function initTypes($dbType) { - if (strncmp($dbType, 'enum', 4) === 0) - $this->type = 'string'; - elseif (strpos($dbType, 'float') !== false || strpos($dbType, 'double') !== false) - $this->type = 'double'; - elseif (strpos($dbType, 'bool') !== false) - $this->type = 'boolean'; - elseif (strpos($dbType, 'int') === 0 && strpos($dbType, 'unsigned') === false || preg_match('/(bit|tinyint|smallint|mediumint)/', $dbType)) - $this->type = 'integer'; - else - $this->type = 'string'; + static $typeMap = array( // dbType => type + 'tinyint' => 'smallint', + 'bit' => 'smallint', + 'smallint' => 'smallint', + 'mediumint' => 'integer', + 'int' => 'integer', + 'integer' => 'integer', + 'bigint' => 'bigint', + 'float' => 'float', + 'double' => 'float', + 'real' => 'float', + 'decimal' => 'decimal', + 'numeric' => 'decimal', + 'tinytext' => 'text', + 'mediumtext' => 'text', + 'longtext' => 'text', + 'text' => 'text', + 'varchar' => 'string', + 'string' => 'string', + 'char' => 'string', + 'datetime' => 'datetime', + 'year' => 'date', + 'date' => 'date', + 'time' => 'time', + 'timestamp' => 'timestamp', + 'enum' => 'enum', + ); + + $this->dbType = $dbType; + $this->type = 'string'; + $this->unsigned = strpos($this->dbType, 'unsigned') !== false; + + if (preg_match('/^(\w+)(?:\(([^\)]+)\))?/', $this->dbType, $matches)) { + $type = $matches[1]; + if (isset($typeMap[$type])) { + $this->type = $typeMap[$type]; + } + + if (!empty($matches[2])) { + if ($this->type === 'enum') { + $values = explode(',', $matches[2]); + foreach ($values as $i => $value) { + $values[$i] = trim($value, "'"); + } + $this->enumValues = $values; + } + else { + $values = explode(',', $matches[2]); + $this->size = $this->precision = (int)$values[0]; + if (isset($values[1])) { + $this->scale = (int)$values[1]; + } + if ($this->size === 1 && ($type === 'tinyint' || $type === 'bit')) { + $this->type = 'boolean'; + } + elseif ($type === 'bit') { + if ($this->size > 32) { + $this->type = 'bigint'; + } + elseif ($this->size === 32) { + $this->type = 'integer'; + } + } + } + } + } + + $this->phpType = $this->getPhpType(); } /** @@ -39,32 +99,13 @@ class ColumnSchema extends \yii\db\dao\ColumnSchema * The value is typecasted to correct PHP type. * @param mixed $defaultValue the default value obtained from metadata */ - protected function extractDefault($defaultValue) + public function initDefaultValue($defaultValue) { - if ($this->dbType === 'timestamp' && $defaultValue === 'CURRENT_TIMESTAMP') + if ($this->type === 'timestamp' && $defaultValue === 'CURRENT_TIMESTAMP') { $this->defaultValue = null; - else - parent::extractDefault($defaultValue); - } - - /** - * Extracts size, precision and scale information from column's DB type. - * @param string $dbType the column's DB type - */ - protected function extractLimit($dbType) - { - if (strncmp($dbType, 'enum', 4) === 0 && preg_match('/\((.*)\)/', $dbType, $matches)) - { - $values = explode(',', $matches[1]); - $size = 0; - foreach ($values as $value) - { - if (($n = strlen($value)) > $size) - $size = $n; - } - $this->size = $this->precision = $size-2; } - else - parent::extractLimit($dbType); + else { + $this->defaultValue = $this->typecast($defaultValue); + } } } \ No newline at end of file diff --git a/framework/db/dao/mysql/QueryBuilder.php b/framework/db/dao/mysql/QueryBuilder.php new file mode 100644 index 0000000..9ec5842 --- /dev/null +++ b/framework/db/dao/mysql/QueryBuilder.php @@ -0,0 +1,93 @@ + + * @link http://www.yiiframework.com/ + * @copyright Copyright © 2008-2012 Yii Software LLC + * @license http://www.yiiframework.com/license/ + */ + +namespace yii\db\dao\mysql; + +/** + * QueryBuilder builds a SQL statement based on the specification given as a [[Query]] object. + * + * @author Qiang Xue + * @since 2.0 + */ +class QueryBuilder extends \yii\db\dao\QueryBuilder +{ + /** + * @var array the abstract column types mapped to physical column types. + */ + public $columnTypes = array( + 'pk' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY', + 'string' => 'varchar(255)', + 'text' => 'text', + 'smallint' => 'smallint', + 'integer' => 'int(11)', + 'bigint'=> 'bigint', + 'boolean' => 'tinyint(1)', + 'float' => 'float', + 'decimal' => 'decimal', + 'money' => 'decimal(19,4)', + 'datetime' => 'datetime', + 'timestamp' => 'timestamp', + 'time' => 'time', + 'date' => 'date', + 'binary' => 'blob', + ); + + /** + * Builds a SQL statement for renaming a column. + * @param string $table the table whose column is to be renamed. The name will be properly quoted by the method. + * @param string $name the old name of the column. The name will be properly quoted by the method. + * @param string $newName the new name of the column. The name will be properly quoted by the method. + * @return string the SQL statement for renaming a DB column. + * @since 1.1.6 + */ + public function renameColumn($table, $name, $newName) + { + $db = $this->getDbConnection(); + $row = $db->createCommand('SHOW CREATE TABLE ' . $db->quoteTableName($table))->queryRow(); + if ($row === false) + throw new CDbException(Yii::t('yii', 'Unable to find "{column}" in table "{table}".', array('{column}' => $name, '{table}' => $table))); + if (isset($row['Create Table'])) + $sql = $row['Create Table']; + else + { + $row = array_values($row); + $sql = $row[1]; + } + if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) + { + foreach ($matches[1] as $i => $c) + { + if ($c === $name) + { + return "ALTER TABLE " . $db->quoteTableName($table) + . " CHANGE " . $db->quoteColumnName($name) + . ' ' . $db->quoteColumnName($newName) . ' ' . $matches[2][$i]; + } + } + } + + // try to give back a SQL anyway + return "ALTER TABLE " . $db->quoteTableName($table) + . " CHANGE " . $db->quoteColumnName($name) . ' ' . $newName; + } + + /** + * Builds a SQL statement for dropping a foreign key constraint. + * @param string $name the name of the foreign key constraint to be dropped. The name will be properly quoted by the method. + * @param string $table the table whose foreign is to be dropped. The name will be properly quoted by the method. + * @return string the SQL statement for dropping a foreign key constraint. + * @since 1.1.6 + */ + public function dropForeignKey($name, $table) + { + return 'ALTER TABLE ' . $this->quoteTableName($table) + . ' DROP FOREIGN KEY ' . $this->quoteColumnName($name); + } +} diff --git a/framework/db/dao/mysql/Schema.php b/framework/db/dao/mysql/Schema.php index 751ca5c..a11ad40 100644 --- a/framework/db/dao/mysql/Schema.php +++ b/framework/db/dao/mysql/Schema.php @@ -1,53 +1,32 @@ * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2011 Yii Software LLC + * @copyright Copyright © 2008-2012 Yii Software LLC * @license http://www.yiiframework.com/license/ */ +namespace yii\db\dao\mysql; + /** - * CMysqlSchema is the class for retrieving metadata information from a MySQL database (version 4.1.x and 5.x). + * Schema is the class for retrieving metadata information from a MySQL database (version 4.1.x and 5.x). * * @author Qiang Xue - * @version $Id: CMysqlSchema.php 3304 2011-06-23 14:53:50Z qiang.xue $ - * @package system.db.schema.mysql - * @since 1.0 + * @since 2.0 */ -class CMysqlSchema extends CDbSchema +class Schema extends \yii\db\dao\Schema { /** - * @var array the abstract column types mapped to physical column types. - * @since 1.1.6 - */ - public $columnTypes = array( - 'pk' => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY', - 'string' => 'varchar(255)', - 'text' => 'text', - 'integer' => 'int(11)', - 'float' => 'float', - 'decimal' => 'decimal', - 'datetime' => 'datetime', - 'timestamp' => 'timestamp', - 'time' => 'time', - 'date' => 'date', - 'binary' => 'blob', - 'boolean' => 'tinyint(1)', - 'money' => 'decimal(19,4)', - ); - - /** * Quotes a table name for use in a query. * A simple table name does not schema prefix. * @param string $name table name * @return string the properly quoted table name - * @since 1.1.6 */ public function quoteSimpleTableName($name) { - return '`' . $name . '`'; + return strpos($name, "`") !== false ? $name : "`" . $name . "`"; } /** @@ -55,75 +34,26 @@ class CMysqlSchema extends CDbSchema * A simple column name does not contain prefix. * @param string $name column name * @return string the properly quoted column name - * @since 1.1.6 */ public function quoteSimpleColumnName($name) { - return '`' . $name . '`'; - } - - /** - * Compares two table names. - * The table names can be either quoted or unquoted. This method - * will consider both cases. - * @param string $name1 table name 1 - * @param string $name2 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)); - } - - /** - * Resets the sequence value of a table's primary key. - * The sequence will be reset such that the primary key of the next new row inserted - * will have the specified value or 1. - * @param CDbTableSchema $table the table schema whose primary key sequence will be reset - * @param mixed $value the value for the primary key of the next new row inserted. If this is not set, - * the next new row's primary key will have a value 1. - * @since 1.1 - */ - public function resetSequence($table, $value = null) - { - if ($table->sequenceName !== null) - { - if ($value === null) - $value = $this->getDbConnection()->createCommand("SELECT MAX(` {$table->primaryKey}`) FROM {$table->rawName}")->queryScalar() + 1; - else - $value = (int)$value; - $this->getDbConnection()->createCommand("ALTER TABLE {$table->rawName} AUTO_INCREMENT=$value")->execute(); - } - } - - /** - * Enables or disables integrity check. - * @param boolean $check whether to turn on or off the integrity check. - * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema. - * @since 1.1 - */ - public function checkIntegrity($check = true, $schema = '') - { - $this->getDbConnection()->createCommand('SET FOREIGN_KEY_CHECKS=' . ($check ? 1 : 0))->execute(); + return strpos($name, '`') !== false || $name === '*' ? $name : '`' . $name . '`'; } /** * Loads the metadata for the specified table. * @param string $name table name - * @return CMysqlTableSchema driver dependent table metadata. Null if the table does not exist. + * @return TableSchema driver dependent table metadata. Null if the table does not exist. */ - protected function loadTable($name) + protected function loadTableSchema($name) { - $table = new CMysqlTableSchema; + $table = new TableSchema; $this->resolveTableNames($table, $name); - if ($this->findColumns($table)) - { + if ($this->findColumns($table)) { $this->findConstraints($table); return $table; } - else - return null; } /** @@ -134,52 +64,15 @@ class CMysqlSchema extends CDbSchema protected function resolveTableNames($table, $name) { $parts = explode('.', str_replace('`', '', $name)); - if (isset($parts[1])) - { + if (isset($parts[1])) { $table->schemaName = $parts[0]; $table->name = $parts[1]; - $table->rawName = $this->quoteTableName($table->schemaName) . '.' . $this->quoteTableName($table->name); + $table->quotedName = $this->quoteSimpleTableName($table->schemaName) . '.' . $this->quoteSimpleTableName($table->name); } - else - { + else { $table->name = $parts[0]; - $table->rawName = $this->quoteTableName($table->name); - } - } - - /** - * Collects the table column metadata. - * @param CMysqlTableSchema $table 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; - elseif (is_string($table->primaryKey)) - $table->primaryKey = array($table->primaryKey, $c->name); - else - $table->primaryKey[] = $c->name; - if ($c->autoIncrement) - $table->sequenceName = ''; - } + $table->quotedName = $this->quoteSimpleTableName($table->name); } - return true; } /** @@ -189,27 +82,51 @@ class CMysqlSchema extends CDbSchema */ protected function createColumn($column) { - $c = new CMysqlColumnSchema; + $c = new ColumnSchema; + $c->name = $column['Field']; - $c->rawName = $this->quoteColumnName($c->name); + $c->quotedName = $this->quoteSimpleColumnName($c->name); $c->allowNull = $column['Null'] === 'YES'; $c->isPrimaryKey = strpos($column['Key'], 'PRI') !== false; - $c->isForeignKey = false; - $c->init($column['Type'], $column['Default']); - $c->autoIncrement = strpos(strtolower($column['Extra']), 'auto_increment') !== false; + $c->autoIncrement = stripos($column['Extra'], 'auto_increment') !== false; + $c->initTypes($column['Type']); + $c->initDefaultValue($column['Default']); return $c; } /** - * @return float server version. + * Collects the table column metadata. + * @param CMysqlTableSchema $table the table metadata + * @return boolean whether the table exists in the database */ - protected function getServerVersion() + protected function findColumns($table) { - $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]); + $sql = 'SHOW COLUMNS FROM ' . $table->quotedName; + try { + $columns = $this->connection->createCommand($sql)->queryAll(); + } + catch(\Exception $e) { + return false; + } + foreach ($columns as $column) { + $table->columns[$c->name] = $c = $this->createColumn($column); + if ($c->isPrimaryKey) { + if ($table->primaryKey === null) { + $table->primaryKey = $c->name; + } + elseif (is_string($table->primaryKey)) { + $table->primaryKey = array($table->primaryKey, $c->name); + } + else { + $table->primaryKey[] = $c->name; + } + if ($c->autoIncrement) { + $table->sequenceName = ''; + } + } + } + return true; } /** @@ -218,23 +135,21 @@ class CMysqlSchema extends CDbSchema */ protected function findConstraints($table) { - $row = $this->getDbConnection()->createCommand('SHOW CREATE TABLE ' . $table->rawName)->queryRow(); + $row = $this->connection->createCommand('SHOW CREATE TABLE ' . $table->quotedName)->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)) + foreach ($row as $sql) { + if (preg_match_all($regexp, $sql, $matches, PREG_SET_ORDER)) { + foreach ($matches as $match) { + $fks = array_map('trim', explode(',', str_replace('`', '', $match[1]))); + $pks = array_map('trim', explode(',', str_replace('`', '', $match[3]))); + $constraint = array(str_replace('`', '', $match[2])), + foreach ($fks as $k => $name) { + $constraint[$name] = $pks[$k]; + } + $table->foreignKeys[] = $constraint; + } break; - } - 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; } } } @@ -244,67 +159,16 @@ class CMysqlSchema extends CDbSchema * @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema. * If not empty, the returned table names will be prefixed with the schema name. * @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; - } - - /** - * Builds a SQL statement for renaming a column. - * @param string $table the table whose column is to be renamed. The name will be properly quoted by the method. - * @param string $name the old name of the column. The name will be properly quoted by the method. - * @param string $newName the new name of the column. The name will be properly quoted by the method. - * @return string the SQL statement for renaming a DB column. - * @since 1.1.6 - */ - public function renameColumn($table, $name, $newName) - { - $db = $this->getDbConnection(); - $row = $db->createCommand('SHOW CREATE TABLE ' . $db->quoteTableName($table))->queryRow(); - if ($row === false) - throw new CDbException(Yii::t('yii', 'Unable to find "{column}" in table "{table}".', array('{column}' => $name, '{table}' => $table))); - if (isset($row['Create Table'])) - $sql = $row['Create Table']; - else - { - $row = array_values($row); - $sql = $row[1]; + if ($schema === '') { + return $this->connection->createCommand('SHOW TABLES')->queryColumn(); } - if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) - { - foreach ($matches[1] as $i => $c) - { - if ($c === $name) - { - return "ALTER TABLE " . $db->quoteTableName($table) - . " CHANGE " . $db->quoteColumnName($name) - . ' ' . $db->quoteColumnName($newName) . ' ' . $matches[2][$i]; - } - } + $names = $this->connection->createCommand('SHOW TABLES FROM ' . $this->quoteSimpleTableName($schema))->queryColumn(); + foreach ($names as &$name) { + $name = $schema . '.' . $name; } - - // try to give back a SQL anyway - return "ALTER TABLE " . $db->quoteTableName($table) - . " CHANGE " . $db->quoteColumnName($name) . ' ' . $newName; - } - - /** - * Builds a SQL statement for dropping a foreign key constraint. - * @param string $name the name of the foreign key constraint to be dropped. The name will be properly quoted by the method. - * @param string $table the table whose foreign is to be dropped. The name will be properly quoted by the method. - * @return string the SQL statement for dropping a foreign key constraint. - * @since 1.1.6 - */ - public function dropForeignKey($name, $table) - { - return 'ALTER TABLE ' . $this->quoteTableName($table) - . ' DROP FOREIGN KEY ' . $this->quoteColumnName($name); + return $names; } } diff --git a/framework/db/dao/mysql/TableSchema.php b/framework/db/dao/mysql/TableSchema.php deleted file mode 100644 index 42dcb51..0000000 --- a/framework/db/dao/mysql/TableSchema.php +++ /dev/null @@ -1,24 +0,0 @@ - - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2012 Yii Software LLC - * @license http://www.yiiframework.com/license/ - */ - -/** - * TableSchema represents the metadata for a MySQL table. - * - * @author Qiang Xue - * @since 2.0 - */ -class TableSchema extends CDbTableSchema -{ - /** - * @var string name of the schema (database) that this table belongs to. - * Defaults to null, meaning no schema (or the current database). - */ - public $schemaName; -}