mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 14:46:19 +08:00 
			
		
		
		
	...
This commit is contained in:
		@ -11,7 +11,7 @@
 | 
				
			|||||||
namespace yii\db\dao;
 | 
					namespace yii\db\dao;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * ColumnSchema class describes the meta data of a column in a database table.
 | 
					 * ColumnSchema class describes the metadata of a column in a database table.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Qiang Xue <qiang.xue@gmail.com>
 | 
					 * @author Qiang Xue <qiang.xue@gmail.com>
 | 
				
			||||||
 * @since 2.0
 | 
					 * @since 2.0
 | 
				
			||||||
 | 
				
			|||||||
@ -464,7 +464,7 @@ class Connection extends \yii\base\ApplicationComponent
 | 
				
			|||||||
			if (isset($this->driverMap[$driver])) {
 | 
								if (isset($this->driverMap[$driver])) {
 | 
				
			||||||
				return $this->_driver = \Yii::createObject($this->driverMap[$driver], $this);
 | 
									return $this->_driver = \Yii::createObject($this->driverMap[$driver], $this);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				throw new Exception("Connection does not support reading meta data for '$driver' database.");
 | 
									throw new Exception("Connection does not support reading metadata for '$driver' database.");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,11 +15,11 @@ use yii\db\Exception;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Driver is the base class for all database driver classes.
 | 
					 * Driver is the base class for all database driver classes.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Driver implements the DBMS-specific methods to support retrieving meta data of a database.
 | 
					 * Driver implements the DBMS-specific methods to support retrieving metadata of a database.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @property QueryBuilder $queryBuilder the query builder for this connection.
 | 
					 * @property QueryBuilder $queryBuilder the query builder for this connection.
 | 
				
			||||||
 * @property array $tableNames the names of all tables in this database.
 | 
					 * @property array $tableNames the names of all tables in this database.
 | 
				
			||||||
 * @property array $tableSchemas the meta data for all tables in this database.
 | 
					 * @property array $tableSchemas the metadata for all tables in this database.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Qiang Xue <qiang.xue@gmail.com>
 | 
					 * @author Qiang Xue <qiang.xue@gmail.com>
 | 
				
			||||||
 * @since 2.0
 | 
					 * @since 2.0
 | 
				
			||||||
@ -54,7 +54,7 @@ abstract class Driver extends \yii\base\Object
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	private $_tableNames = array();
 | 
						private $_tableNames = array();
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @var array list of loaded table meta data (table name => TableSchema)
 | 
						 * @var array list of loaded table metadata (table name => TableSchema)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	private $_tables = array();
 | 
						private $_tables = array();
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@
 | 
				
			|||||||
namespace yii\db\dao;
 | 
					namespace yii\db\dao;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * TableSchema represents the meta data of a database table.
 | 
					 * TableSchema represents the metadata of a database table.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @property array $columnNames list of column names
 | 
					 * @property array $columnNames list of column names
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ use yii\db\dao\TableSchema;
 | 
				
			|||||||
use yii\db\dao\ColumnSchema;
 | 
					use yii\db\dao\ColumnSchema;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Driver is the class for retrieving meta data from a MySQL database (version 4.1.x and 5.x).
 | 
					 * Driver is the class for retrieving metadata from a MySQL database (version 4.1.x and 5.x).
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Qiang Xue <qiang.xue@gmail.com>
 | 
					 * @author Qiang Xue <qiang.xue@gmail.com>
 | 
				
			||||||
 * @since 2.0
 | 
					 * @since 2.0
 | 
				
			||||||
@ -24,7 +24,7 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @var array mapping from physical column types (keys) to abstract column types (values)
 | 
						 * @var array mapping from physical column types (keys) to abstract column types (values)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public $typeMap = array( // dbType => type
 | 
						public $typeMap = array(
 | 
				
			||||||
		'tinyint' => self::TYPE_SMALLINT,
 | 
							'tinyint' => self::TYPE_SMALLINT,
 | 
				
			||||||
		'bit' => self::TYPE_SMALLINT,
 | 
							'bit' => self::TYPE_SMALLINT,
 | 
				
			||||||
		'smallint' => self::TYPE_SMALLINT,
 | 
							'smallint' => self::TYPE_SMALLINT,
 | 
				
			||||||
@ -74,6 +74,16 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
		return strpos($name, '`') !== false || $name === '*' ? $name : '`' . $name . '`';
 | 
							return strpos($name, '`') !== false || $name === '*' ? $name : '`' . $name . '`';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 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
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public function createQueryBuilder()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return new QueryBuilder($this->connection);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Loads the metadata for the specified table.
 | 
						 * Loads the metadata for the specified table.
 | 
				
			||||||
	 * @param string $name table name
 | 
						 * @param string $name table name
 | 
				
			||||||
@ -91,9 +101,9 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Generates various kinds of table names.
 | 
						 * Resolves the table name and schema name (if any).
 | 
				
			||||||
	 * @param \yii\db\dao\TableSchema $table the table instance
 | 
						 * @param \yii\db\dao\TableSchema $table the table metadata object
 | 
				
			||||||
	 * @param string $name the unquoted table name
 | 
						 * @param string $name the table name
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected function resolveTableNames($table, $name)
 | 
						protected function resolveTableNames($table, $name)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -127,16 +137,17 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
		$this->resolveColumnType($c);
 | 
							$this->resolveColumnType($c);
 | 
				
			||||||
		$c->resolvePhpType();
 | 
							$c->resolvePhpType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$this->resolveDefaultValue($c, $column['Default']);
 | 
							$this->resolveColumnDefault($c, $column['Default']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return $c;
 | 
							return $c;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @param \yii\db\dao\ColumnSchema $column
 | 
						 * Resolves the default value for the column.
 | 
				
			||||||
	 * @param string $value
 | 
						 * @param \yii\db\dao\ColumnSchema $column the column metadata object
 | 
				
			||||||
 | 
						 * @param string $value the default value fetched from database
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected function resolveDefaultValue($column, $value)
 | 
						protected function resolveColumnDefault($column, $value)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if ($column->type !== 'timestamp' || $value !== 'CURRENT_TIMESTAMP') {
 | 
							if ($column->type !== 'timestamp' || $value !== 'CURRENT_TIMESTAMP') {
 | 
				
			||||||
			$column->defaultValue = $column->typecast($value);
 | 
								$column->defaultValue = $column->typecast($value);
 | 
				
			||||||
@ -144,8 +155,8 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Extracts the PHP type from DB type.
 | 
						 * Resolves the abstract data type for the column.
 | 
				
			||||||
	 * @param \yii\db\dao\ColumnSchema $column the column
 | 
						 * @param \yii\db\dao\ColumnSchema $column the column metadata object
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public function resolveColumnType($column)
 | 
						public function resolveColumnType($column)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -186,7 +197,7 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Collects the table column metadata.
 | 
						 * Collects the metadata of table columns.
 | 
				
			||||||
	 * @param \yii\db\dao\TableSchema $table the table metadata
 | 
						 * @param \yii\db\dao\TableSchema $table the table metadata
 | 
				
			||||||
	 * @return boolean whether the table exists in the database
 | 
						 * @return boolean whether the table exists in the database
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
@ -195,21 +206,21 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
		$sql = 'SHOW COLUMNS FROM ' . $table->quotedName;
 | 
							$sql = 'SHOW COLUMNS FROM ' . $table->quotedName;
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			$columns = $this->connection->createCommand($sql)->queryAll();
 | 
								$columns = $this->connection->createCommand($sql)->queryAll();
 | 
				
			||||||
		}
 | 
							} catch (\Exception $e) {
 | 
				
			||||||
		catch (\Exception $e) {
 | 
					 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		foreach ($columns as $column) {
 | 
							foreach ($columns as $column) {
 | 
				
			||||||
			$table->columns[$c->name] = $c = $this->createColumn($column);
 | 
								$column = $this->createColumn($column);
 | 
				
			||||||
			if ($c->isPrimaryKey) {
 | 
								$table->columns[$column->name] = $column;
 | 
				
			||||||
 | 
								if ($column->isPrimaryKey) {
 | 
				
			||||||
				if ($table->primaryKey === null) {
 | 
									if ($table->primaryKey === null) {
 | 
				
			||||||
					$table->primaryKey = $c->name;
 | 
										$table->primaryKey = $column->name;
 | 
				
			||||||
				} elseif (is_string($table->primaryKey)) {
 | 
									} elseif (is_string($table->primaryKey)) {
 | 
				
			||||||
					$table->primaryKey = array($table->primaryKey, $c->name);
 | 
										$table->primaryKey = array($table->primaryKey, $column->name);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					$table->primaryKey[] = $c->name;
 | 
										$table->primaryKey[] = $column->name;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if ($c->autoIncrement) {
 | 
									if ($column->autoIncrement) {
 | 
				
			||||||
					$table->sequenceName = '';
 | 
										$table->sequenceName = '';
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -224,20 +235,23 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
	protected function findConstraints($table)
 | 
						protected function findConstraints($table)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$row = $this->connection->createCommand('SHOW CREATE TABLE ' . $table->quotedName)->queryRow();
 | 
							$row = $this->connection->createCommand('SHOW CREATE TABLE ' . $table->quotedName)->queryRow();
 | 
				
			||||||
		$matches = array();
 | 
							if (isset($row['Create Table'])) {
 | 
				
			||||||
 | 
								$sql = $row['Create Table'];
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								$row = array_values($row);
 | 
				
			||||||
 | 
								$sql = $row[1];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$regexp = '/FOREIGN KEY\s+\(([^\)]+)\)\s+REFERENCES\s+([^\(^\s]+)\s*\(([^\)]+)\)/mi';
 | 
							$regexp = '/FOREIGN KEY\s+\(([^\)]+)\)\s+REFERENCES\s+([^\(^\s]+)\s*\(([^\)]+)\)/mi';
 | 
				
			||||||
		foreach ($row as $sql) {
 | 
							if (preg_match_all($regexp, $sql, $matches, PREG_SET_ORDER)) {
 | 
				
			||||||
			if (preg_match_all($regexp, $sql, $matches, PREG_SET_ORDER)) {
 | 
								foreach ($matches as $match) {
 | 
				
			||||||
				foreach ($matches as $match) {
 | 
									$fks = array_map('trim', explode(',', str_replace('`', '', $match[1])));
 | 
				
			||||||
					$fks = array_map('trim', explode(',', str_replace('`', '', $match[1])));
 | 
									$pks = array_map('trim', explode(',', str_replace('`', '', $match[3])));
 | 
				
			||||||
					$pks = array_map('trim', explode(',', str_replace('`', '', $match[3])));
 | 
									$constraint = array(str_replace('`', '', $match[2]));
 | 
				
			||||||
					$constraint = array(str_replace('`', '', $match[2]));
 | 
									foreach ($fks as $k => $name) {
 | 
				
			||||||
					foreach ($fks as $k => $name) {
 | 
										$constraint[$name] = $pks[$k];
 | 
				
			||||||
						$constraint[$name] = $pks[$k];
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					$table->foreignKeys[] = $constraint;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									$table->foreignKeys[] = $constraint;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -255,19 +269,9 @@ class Driver extends \yii\db\dao\Driver
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		$sql = 'SHOW TABLES FROM ' . $this->quoteSimpleTableName($schema);
 | 
							$sql = 'SHOW TABLES FROM ' . $this->quoteSimpleTableName($schema);
 | 
				
			||||||
		$names = $this->connection->createCommand($sql)->queryColumn();
 | 
							$names = $this->connection->createCommand($sql)->queryColumn();
 | 
				
			||||||
		foreach ($names as &$name) {
 | 
							foreach ($names as $i => $name) {
 | 
				
			||||||
			$name = $schema . '.' . $name;
 | 
								$names[$i] = $schema . '.' . $name;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return $names;
 | 
							return $names;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * 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
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public function createQueryBuilder()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return new QueryBuilder($this->connection);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace yii\db\dao\mysql;
 | 
					namespace yii\db\dao\mysql;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use yii\db\Exception;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * QueryBuilder builds a SQL statement based on the specification given as a [[Query]] object.
 | 
					 * QueryBuilder builds a SQL statement based on the specification given as a [[Query]] object.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -42,16 +44,17 @@ class QueryBuilder extends \yii\db\dao\QueryBuilder
 | 
				
			|||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Builds a SQL statement for renaming a column.
 | 
						 * 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 $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 $oldName 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.
 | 
						 * @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.
 | 
						 * @return string the SQL statement for renaming a DB column.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public function renameColumn($table, $name, $newName)
 | 
						public function renameColumn($table, $oldName, $newName)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$quotedTable = $this->driver->quoteTableName($table);
 | 
							$quotedTable = $this->driver->quoteTableName($table);
 | 
				
			||||||
		$row = $this->connection->createCommand('SHOW CREATE TABLE ' . $quotedTable)->queryRow();
 | 
							$row = $this->connection->createCommand('SHOW CREATE TABLE ' . $quotedTable)->queryRow();
 | 
				
			||||||
		if ($row === false)
 | 
							if ($row === false) {
 | 
				
			||||||
			throw new CDbException(Yii::t('yii', 'Unable to find "{column}" in table "{table}".', array('{column}' => $name, '{table}' => $table)));
 | 
								throw new Exception("Unable to find '$oldName' in table '$table'.");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (isset($row['Create Table'])) {
 | 
							if (isset($row['Create Table'])) {
 | 
				
			||||||
			$sql = $row['Create Table'];
 | 
								$sql = $row['Create Table'];
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
@ -60,14 +63,14 @@ class QueryBuilder extends \yii\db\dao\QueryBuilder
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) {
 | 
							if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) {
 | 
				
			||||||
			foreach ($matches[1] as $i => $c) {
 | 
								foreach ($matches[1] as $i => $c) {
 | 
				
			||||||
				if ($c === $name) {
 | 
									if ($c === $oldName) {
 | 
				
			||||||
					return "ALTER TABLE $quotedTable CHANGE " . $this->driver->quoteColumnName($name)
 | 
										return "ALTER TABLE $quotedTable CHANGE " . $this->driver->quoteColumnName($oldName)
 | 
				
			||||||
						. ' ' . $this->driver->quoteColumnName($newName) . ' ' . $matches[2][$i];
 | 
											. ' ' . $this->driver->quoteColumnName($newName) . ' ' . $matches[2][$i];
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// try to give back a SQL anyway
 | 
							// try to give back a SQL anyway
 | 
				
			||||||
		return "ALTER TABLE $quotedTable CHANGE " . $this->driver->quoteColumnName($name) . ' ' . $newName;
 | 
							return "ALTER TABLE $quotedTable CHANGE " . $this->driver->quoteColumnName($oldName) . ' ' . $newName;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user