From 6ed01e96451431f01a70ba222d98f02e4c53a2c7 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 18 Jan 2013 08:35:09 -0500 Subject: [PATCH] DB cleanup. --- framework/YiiBase.php | 5 +++-- framework/base/Model.php | 4 ++-- framework/base/Theme.php | 6 ++++-- framework/db/Command.php | 37 +++++++++++++++++++++++++++++++++ framework/db/Connection.php | 9 ++++---- framework/db/QueryBuilder.php | 13 +++++++++--- framework/db/TableSchema.php | 4 ---- framework/db/Transaction.php | 6 +++--- framework/db/mysql/QueryBuilder.php | 41 +++++++++++++++++++++++++++++++++++++ framework/db/mysql/Schema.php | 4 +++- framework/web/Request.php | 22 ++++++++++---------- 11 files changed, 119 insertions(+), 32 deletions(-) diff --git a/framework/YiiBase.php b/framework/YiiBase.php index 70593bf..213b81c 100644 --- a/framework/YiiBase.php +++ b/framework/YiiBase.php @@ -8,6 +8,7 @@ */ use yii\base\Exception; +use yii\base\InvalidCallException; /** * Gets the application start timestamp. @@ -345,7 +346,7 @@ class YiiBase * @param string|array $config the configuration. It can be either a string representing the class name * or an array representing the object configuration. * @return mixed the created object - * @throws \yii\base\BadConfigException if the configuration is invalid. + * @throws InvalidConfigException if the configuration is invalid. */ public static function createObject($config) { @@ -358,7 +359,7 @@ class YiiBase $class = $config['class']; unset($config['class']); } else { - throw new \yii\base\BadConfigException('Object configuration must be an array containing a "class" element.'); + throw new InvalidCallException('Object configuration must be an array containing a "class" element.'); } if (!class_exists($class, false)) { diff --git a/framework/base/Model.php b/framework/base/Model.php index 72ea6e6..8d9a35c 100644 --- a/framework/base/Model.php +++ b/framework/base/Model.php @@ -312,7 +312,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess * Creates validator objects based on the validation rules specified in [[rules()]]. * Unlike [[getValidators()]], each time this method is called, a new list of validators will be returned. * @return Vector validators - * @throws BadConfigException if any validation rule configuration is invalid + * @throws InvalidConfigException if any validation rule configuration is invalid */ public function createValidators() { @@ -324,7 +324,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess $validator = Validator::createValidator($rule[1], $this, $rule[0], array_slice($rule, 2)); $validators->add($validator); } else { - throw new BadConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.'); + throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.'); } } return $validators; diff --git a/framework/base/Theme.php b/framework/base/Theme.php index 238f034..ec58807 100644 --- a/framework/base/Theme.php +++ b/framework/base/Theme.php @@ -9,6 +9,8 @@ namespace yii\base; +use yii\base\InvalidConfigException; + /** * Theme represents an application theme. * @@ -25,12 +27,12 @@ class Theme extends ApplicationComponent if ($this->basePath !== null) { $this->basePath = \Yii::getAlias($this->basePath, true); } else { - throw new BadConfigException("Theme.basePath must be set."); + throw new InvalidConfigException("Theme.basePath must be set."); } if ($this->baseUrl !== null) { $this->baseUrl = \Yii::getAlias($this->baseUrl, true); } else { - throw new BadConfigException("Theme.baseUrl must be set."); + throw new InvalidConfigException("Theme.baseUrl must be set."); } } diff --git a/framework/db/Command.php b/framework/db/Command.php index 811e993..722358f 100644 --- a/framework/db/Command.php +++ b/framework/db/Command.php @@ -9,6 +9,8 @@ namespace yii\db; +use yii\base\NotSupportedException; + /** * Command represents a SQL statement to be executed against a database. * @@ -259,6 +261,7 @@ class Command extends \yii\base\Component public function execute($params = array()) { $sql = $this->getSql(); + $this->_params = array_merge($this->_params, $params); if ($this->_params === array()) { $paramLog = ''; @@ -268,6 +271,10 @@ class Command extends \yii\base\Component \Yii::trace("Executing SQL: {$sql}{$paramLog}", __CLASS__); + if ($sql == '') { + return 0; + } + try { if ($this->connection->enableProfiling) { \Yii::beginProfile(__METHOD__ . "($sql)", __CLASS__); @@ -707,4 +714,34 @@ class Command extends \yii\base\Component $sql = $this->connection->getQueryBuilder()->dropIndex($name, $table); return $this->setSql($sql); } + + /** + * Creates a SQL command for resetting 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 string $table the name of the table 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. + * @return Command the command object itself + * @throws NotSupportedException if this is not supported by the underlying DBMS + */ + public function resetSequence($table, $value = null) + { + $sql = $this->connection->getQueryBuilder()->resetSequence($table, $value); + return $this->setSql($sql); + } + + /** + * Builds a SQL command for enabling or disabling integrity check. + * @param boolean $check whether to turn on or off the integrity check. + * @param string $schema the schema name of the tables. Defaults to empty string, meaning the current + * or default schema. + * @return Command the command object itself + * @throws NotSupportedException if this is not supported by the underlying DBMS + */ + public function checkIntegrity($check = true, $schema = '') + { + $sql = $this->connection->getQueryBuilder()->checkIntegrity($check, $schema); + return $this->setSql($sql); + } } diff --git a/framework/db/Connection.php b/framework/db/Connection.php index 5fd624f..491df16 100644 --- a/framework/db/Connection.php +++ b/framework/db/Connection.php @@ -9,7 +9,8 @@ namespace yii\db; -use yii\base\BadConfigException; +use yii\base\InvalidConfigException; +use yii\base\NotSupportedException; /** * Connection represents a connection to a database via [PDO](http://www.php.net/manual/en/ref.pdo.php). @@ -317,7 +318,7 @@ class Connection extends \yii\base\ApplicationComponent { if ($this->pdo === null) { if (empty($this->dsn)) { - throw new BadConfigException('Connection.dsn cannot be empty.'); + throw new InvalidConfigException('Connection.dsn cannot be empty.'); } try { \Yii::trace('Opening DB connection: ' . $this->dsn, __CLASS__); @@ -426,7 +427,7 @@ class Connection extends \yii\base\ApplicationComponent /** * Returns the schema information for the database opened by this connection. * @return Schema the schema information for the database opened by this connection. - * @throws BadConfigException if there is no support for the current driver type + * @throws NotSupportedException if there is no support for the current driver type */ public function getSchema() { @@ -439,7 +440,7 @@ class Connection extends \yii\base\ApplicationComponent $this->_schema->connection = $this; return $this->_schema; } else { - throw new BadConfigException("Connection does not support reading schema information for '$driver' DBMS."); + throw new NotSupportedException("Connection does not support reading schema information for '$driver' DBMS."); } } } diff --git a/framework/db/QueryBuilder.php b/framework/db/QueryBuilder.php index 688ebb8..00c711c 100644 --- a/framework/db/QueryBuilder.php +++ b/framework/db/QueryBuilder.php @@ -10,6 +10,7 @@ namespace yii\db; use yii\db\Exception; +use yii\base\NotSupportedException; /** * QueryBuilder builds a SELECT SQL statement based on the specification given as a [[Query]] object. @@ -385,24 +386,30 @@ class QueryBuilder extends \yii\base\Object } /** - * Resets the sequence value of a table's primary key. + * Creates a SQL statement for resetting 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 string $table the table schema whose primary key sequence will be reset + * @param string $table the name of the table 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. + * @return string the SQL statement for resetting sequence + * @throws NotSupportedException if this is not supported by the underlying DBMS */ public function resetSequence($table, $value = null) { + throw new NotSupportedException($this->connection->getDriverName() . ' does not support resetting sequence.'); } /** - * Enables or disables integrity check. + * Builds a SQL statement for enabling or disabling 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. + * @return string the SQL statement for checking integrity + * @throws NotSupportedException if this is not supported by the underlying DBMS */ public function checkIntegrity($check = true, $schema = '') { + throw new NotSupportedException($this->connection->getDriverName() . ' does not support enabling/disabling integrity check.'); } /** diff --git a/framework/db/TableSchema.php b/framework/db/TableSchema.php index f3413bf..987d221 100644 --- a/framework/db/TableSchema.php +++ b/framework/db/TableSchema.php @@ -59,10 +59,6 @@ class TableSchema extends \yii\base\Object * @var ColumnSchema[] column metadata of this table. Each array element is a [[ColumnSchema]] object, indexed by column names. */ public $columns = array(); - /** - * @var string comment of this table - */ - public $comment; /** * Gets the named column metadata. diff --git a/framework/db/Transaction.php b/framework/db/Transaction.php index 4870a08..4380385 100644 --- a/framework/db/Transaction.php +++ b/framework/db/Transaction.php @@ -9,7 +9,7 @@ namespace yii\db; -use yii\base\BadConfigException; +use yii\base\InvalidConfigException; /** * Transaction represents a DB transaction. @@ -60,13 +60,13 @@ class Transaction extends \yii\base\Object /** * Begins a transaction. - * @throws BadConfigException if [[connection]] is null + * @throws InvalidConfigException if [[connection]] is null */ public function begin() { if (!$this->_active) { if ($this->connection === null) { - throw new BadConfigException('Transaction.connection must be set.'); + throw new InvalidConfigException('Transaction.connection must be set.'); } \Yii::trace('Starting transaction', __CLASS__); $this->connection->open(); diff --git a/framework/db/mysql/QueryBuilder.php b/framework/db/mysql/QueryBuilder.php index cab1b14..8a0bb74 100644 --- a/framework/db/mysql/QueryBuilder.php +++ b/framework/db/mysql/QueryBuilder.php @@ -10,6 +10,7 @@ namespace yii\db\mysql; use yii\db\Exception; +use yii\base\InvalidCallException; /** * QueryBuilder is the query builder for MySQL databases. @@ -88,4 +89,44 @@ class QueryBuilder extends \yii\db\QueryBuilder return 'ALTER TABLE ' . $this->connection->quoteTableName($table) . ' DROP FOREIGN KEY ' . $this->connection->quoteColumnName($name); } + + /** + * Creates a SQL statement for resetting 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 string $tableName the name of the table 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. + * @return string the SQL statement for resetting sequence + * @throws InvalidCallException if the table does not exist or there is no sequence associated with the table. + */ + public function resetSequence($tableName, $value = null) + { + $table = $this->connection->getTableSchema($tableName); + if ($table !== null && $table->sequenceName !== null) { + $tableName = $this->connection->quoteTableName($tableName); + if ($value === null) { + $key = reset($table->primaryKey); + $value = $this->connection->createCommand("SELECT MAX(`$key`) FROM $tableName")->queryScalar() + 1; + } else { + $value = (int)$value; + } + return "ALTER TABLE $tableName AUTO_INCREMENT=$value"; + } elseif ($table === null) { + throw new InvalidCallException("Table not found: $tableName"); + } else { + throw new InvalidCallException("There is not sequence associated with table '$tableName'.'"); + } + } + + /** + * Builds a SQL statement for enabling or disabling 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. + * @return string the SQL statement for checking integrity + */ + public function checkIntegrity($check = true, $schema = '') + { + return 'SET FOREIGN_KEY_CHECKS=' . ($check ? 1 : 0); + } } diff --git a/framework/db/mysql/Schema.php b/framework/db/mysql/Schema.php index f7826ed..3352b0d 100644 --- a/framework/db/mysql/Schema.php +++ b/framework/db/mysql/Schema.php @@ -102,7 +102,7 @@ class Schema extends \yii\db\Schema /** * Resolves the table name and schema name (if any). - * @param \yii\db\TableSchema $table the table metadata object + * @param TableSchema $table the table metadata object * @param string $name the table name */ protected function resolveTableNames($table, $name) @@ -129,6 +129,8 @@ class Schema extends \yii\db\Schema $column->allowNull = $info['Null'] === 'YES'; $column->isPrimaryKey = strpos($info['Key'], 'PRI') !== false; $column->autoIncrement = stripos($info['Extra'], 'auto_increment') !== false; + $column->comment = $info['Comment']; + $column->dbType = $info['Type']; $column->unsigned = strpos($column->dbType, 'unsigned') !== false; diff --git a/framework/web/Request.php b/framework/web/Request.php index 31502ef..09e4864 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -9,7 +9,7 @@ namespace yii\web; -use \yii\base\BadConfigException; +use \yii\base\InvalidConfigException; /** * @author Qiang Xue @@ -357,7 +357,7 @@ class Request extends \yii\base\Request * Returns the relative URL of the entry script. * The implementation of this method referenced Zend_Controller_Request_Http in Zend Framework. * @return string the relative URL of the entry script. - * @throws BadConfigException if unable to determine the entry script URL + * @throws InvalidConfigException if unable to determine the entry script URL */ public function getScriptUrl() { @@ -374,7 +374,7 @@ class Request extends \yii\base\Request } elseif (isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'], $_SERVER['DOCUMENT_ROOT']) === 0) { $this->_scriptUrl = str_replace('\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME'])); } else { - throw new BadConfigException('Unable to determine the entry script URL.'); + throw new InvalidConfigException('Unable to determine the entry script URL.'); } } return $this->_scriptUrl; @@ -399,7 +399,7 @@ class Request extends \yii\base\Request * The starting and ending slashes are both removed. * @return string part of the request URL that is after the entry script and before the question mark. * Note, the returned path info is decoded. - * @throws BadConfigException if the path info cannot be determined due to unexpected server configuration + * @throws InvalidConfigException if the path info cannot be determined due to unexpected server configuration */ public function getPathInfo() { @@ -415,7 +415,7 @@ class Request extends \yii\base\Request * The starting and ending slashes are both removed. * @return string part of the request URL that is after the entry script and before the question mark. * Note, the returned path info is decoded. - * @throws BadConfigException if the path info cannot be determined due to unexpected server configuration + * @throws InvalidConfigException if the path info cannot be determined due to unexpected server configuration */ protected function resolvePathInfo() { @@ -479,7 +479,7 @@ class Request extends \yii\base\Request * The implementation of this method referenced Zend_Controller_Request_Http in Zend Framework. * @return string the request URI portion for the currently requested URL. * Note that the URI returned is URL-encoded. - * @throws BadConfigException if the request URI cannot be determined due to unusual server configuration + * @throws InvalidConfigException if the request URI cannot be determined due to unusual server configuration */ public function getRequestUri() { @@ -496,7 +496,7 @@ class Request extends \yii\base\Request * The implementation of this method referenced Zend_Controller_Request_Http in Zend Framework. * @return string|boolean the request URI portion for the currently requested URL. * Note that the URI returned is URL-encoded. - * @throws BadConfigException if the request URI cannot be determined due to unusual server configuration + * @throws InvalidConfigException if the request URI cannot be determined due to unusual server configuration */ protected function resolveRequestUri() { @@ -517,7 +517,7 @@ class Request extends \yii\base\Request $requestUri .= '?' . $_SERVER['QUERY_STRING']; } } else { - throw new BadConfigException('Unable to determine the request URI.'); + throw new InvalidConfigException('Unable to determine the request URI.'); } return $requestUri; } @@ -599,7 +599,7 @@ class Request extends \yii\base\Request /** * Returns entry script file path. * @return string entry script file path (processed w/ realpath()) - * @throws BadConfigException if the entry script file path cannot be determined automatically. + * @throws InvalidConfigException if the entry script file path cannot be determined automatically. */ public function getScriptFile() { @@ -615,13 +615,13 @@ class Request extends \yii\base\Request * However, in some server configuration, this may not be correct or feasible. * This setter is provided so that the entry script file path can be manually specified. * @param string $value the entry script file path - * @throws BadConfigException if the provided entry script file path is invalid. + * @throws InvalidConfigException if the provided entry script file path is invalid. */ public function setScriptFile($value) { $this->_scriptFile = realpath($value); if ($this->_scriptFile === false || !is_file($this->_scriptFile)) { - throw new BadConfigException('Unable to determine the entry script file path.'); + throw new InvalidConfigException('Unable to determine the entry script file path.'); } }