diff --git a/framework/db/mysql/Schema.php b/framework/db/mysql/Schema.php index 3352b0d..6781fdf 100644 --- a/framework/db/mysql/Schema.php +++ b/framework/db/mysql/Schema.php @@ -121,7 +121,7 @@ class Schema extends \yii\db\Schema * @param array $info column information * @return ColumnSchema the column schema object */ - protected function loadColumn($info) + protected function loadColumnSchema($info) { $column = new ColumnSchema; @@ -190,7 +190,7 @@ class Schema extends \yii\db\Schema return false; } foreach ($columns as $info) { - $column = $this->loadColumn($info); + $column = $this->loadColumnSchema($info); $table->columns[$column->name] = $column; if ($column->isPrimaryKey) { $table->primaryKey[] = $column->name; diff --git a/framework/db/sqlite/QueryBuilder.php b/framework/db/sqlite/QueryBuilder.php index 3cb0ed5..da7d428 100644 --- a/framework/db/sqlite/QueryBuilder.php +++ b/framework/db/sqlite/QueryBuilder.php @@ -10,9 +10,11 @@ namespace yii\db\sqlite; use yii\db\Exception; +use yii\base\NotSupportedException; +use yii\base\InvalidCallException; /** - * QueryBuilder is the query builder for MySQL databases. + * QueryBuilder is the query builder for SQLite databases. * * @author Qiang Xue * @since 2.0 @@ -22,29 +24,55 @@ class QueryBuilder extends \yii\db\QueryBuilder /** * @var array mapping from abstract column types (keys) to physical column types (values). */ - public $typeMap = array(Driver::TYPE_PK => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL', Driver::TYPE_STRING => 'varchar(255)', Driver::TYPE_TEXT => 'text', Driver::TYPE_SMALLINT => 'smallint', Driver::TYPE_INTEGER => 'integer', Driver::TYPE_BIGINT => 'bigint', Driver::TYPE_FLOAT => 'float', Driver::TYPE_DECIMAL => 'decimal', Driver::TYPE_DATETIME => 'datetime', Driver::TYPE_TIMESTAMP => 'timestamp', Driver::TYPE_TIME => 'time', Driver::TYPE_DATE => 'date', Driver::TYPE_BINARY => 'blob', Driver::TYPE_BOOLEAN => 'tinyint(1)', Driver::TYPE_MONEY => 'decimal(19,4)',); + public $typeMap = array( + Schema::TYPE_PK => 'integer PRIMARY KEY AUTOINCREMENT NOT NULL', + Schema::TYPE_STRING => 'varchar(255)', + Schema::TYPE_TEXT => 'text', + Schema::TYPE_SMALLINT => 'smallint', + Schema::TYPE_INTEGER => 'integer', + Schema::TYPE_BIGINT => 'bigint', + Schema::TYPE_FLOAT => 'float', + Schema::TYPE_DECIMAL => 'decimal', + Schema::TYPE_DATETIME => 'datetime', + Schema::TYPE_TIMESTAMP => 'timestamp', + Schema::TYPE_TIME => 'time', + Schema::TYPE_DATE => 'date', + Schema::TYPE_BINARY => 'blob', + Schema::TYPE_BOOLEAN => 'tinyint(1)', + Schema::TYPE_MONEY => 'decimal(19,4)', + ); /** - * 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 $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($table, $value = null) + public function resetSequence($tableName, $value = null) { - if ($table->sequenceName !== null) { + $db = $this->connection; + $table = $db->getTableSchema($tableName); + if ($table !== null && $table->sequenceName !== null) { if ($value === null) { - $value = $this->connection->createCommand("SELECT MAX(`{$table->primaryKey[0]}`) FROM {$table->quotedName}")->queryScalar(); + $key = reset($table->primaryKey); + $tableName = $db->quoteTableName($tableName); + $value = $db->createCommand("SELECT MAX('$key') FROM $tableName")->queryScalar(); } else { $value = (int)$value - 1; } try { // it's possible sqlite_sequence does not exist - $this->connection->createCommand("UPDATE sqlite_sequence SET seq='$value' WHERE name='{$table->name}'")->execute(); + $db->createCommand("UPDATE sqlite_sequence SET seq='$value' WHERE name='{$table->name}'")->execute(); } catch (Exception $e) { } + } elseif ($table === null) { + throw new InvalidCallException("Table not found: $tableName"); + } else { + throw new InvalidCallException("There is not sequence associated with table '$tableName'.'"); } } @@ -52,10 +80,11 @@ class QueryBuilder extends \yii\db\QueryBuilder * 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. + * @throws NotSupportedException this is not supported by SQLite */ public function checkIntegrity($check = true, $schema = '') { - // SQLite doesn't enforce integrity + throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.'); } /** @@ -65,7 +94,7 @@ class QueryBuilder extends \yii\db\QueryBuilder */ public function truncateTable($table) { - return "DELETE FROM " . $this->quoteTableName($table); + return "DELETE FROM " . $this->connection->quoteTableName($table); } /** @@ -76,7 +105,7 @@ class QueryBuilder extends \yii\db\QueryBuilder */ public function dropIndex($name, $table) { - return 'DROP INDEX ' . $this->quoteTableName($name); + return 'DROP INDEX ' . $this->connection->quoteTableName($name); } /** @@ -84,10 +113,11 @@ class QueryBuilder extends \yii\db\QueryBuilder * @param string $table the table whose column is to be dropped. The name will be properly quoted by the method. * @param string $column the name of the column to be dropped. The name will be properly quoted by the method. * @return string the SQL statement for dropping a DB column. + * @throws NotSupportedException this is not supported by SQLite */ public function dropColumn($table, $column) { - throw new Exception(__METHOD__ . ' is not supported by SQLite.'); + throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.'); } /** @@ -96,10 +126,11 @@ class QueryBuilder extends \yii\db\QueryBuilder * @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. * @return string the SQL statement for renaming a DB column. + * @throws NotSupportedException this is not supported by SQLite */ public function renameColumn($table, $oldName, $newName) { - throw new Exception(__METHOD__ . ' is not supported by SQLite.'); + throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.'); } /** @@ -115,10 +146,11 @@ class QueryBuilder extends \yii\db\QueryBuilder * @param string $delete the ON DELETE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL * @param string $update the ON UPDATE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL * @return string the SQL statement for adding a foreign key constraint to an existing table. + * @throws NotSupportedException this is not supported by SQLite */ public function addForeignKey($name, $table, $columns, $refTable, $refColumns, $delete = null, $update = null) { - throw new Exception(__METHOD__ . ' is not supported by SQLite.'); + throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.'); } /** @@ -126,10 +158,11 @@ class QueryBuilder extends \yii\db\QueryBuilder * @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. + * @throws NotSupportedException this is not supported by SQLite */ public function dropForeignKey($name, $table) { - throw new Exception(__METHOD__ . ' is not supported by SQLite.'); + throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.'); } /** @@ -141,9 +174,10 @@ class QueryBuilder extends \yii\db\QueryBuilder * in the generated SQL. For example, 'string' will be turned into 'varchar(255)', while 'string not null' * will become 'varchar(255) not null'. * @return string the SQL statement for changing the definition of a column. + * @throws NotSupportedException this is not supported by SQLite */ public function alterColumn($table, $column, $type) { - throw new Exception(__METHOD__ . ' is not supported by SQLite.'); + throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.'); } } diff --git a/framework/db/sqlite/Schema.php b/framework/db/sqlite/Schema.php index 903a8b2..52abed5 100644 --- a/framework/db/sqlite/Schema.php +++ b/framework/db/sqlite/Schema.php @@ -76,7 +76,7 @@ class Schema extends \yii\db\Schema /** * Loads the metadata for the specified table. * @param string $name table name - * @return \yii\db\TableSchema 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 loadTableSchema($name) { @@ -86,12 +86,14 @@ class Schema extends \yii\db\Schema if ($this->findColumns($table)) { $this->findConstraints($table); return $table; + } else { + return null; } } /** * Collects the table column metadata. - * @param \yii\db\TableSchema $table the table metadata + * @param TableSchema $table the table metadata * @return boolean whether the table exists in the database */ protected function findColumns($table) @@ -102,8 +104,8 @@ class Schema extends \yii\db\Schema return false; } - foreach ($columns as $column) { - $column = $this->createColumn($column); + foreach ($columns as $info) { + $column = $this->loadColumnSchema($info); $table->columns[$column->name] = $column; if ($column->isPrimaryKey) { $table->primaryKey[] = $column->name; @@ -119,7 +121,7 @@ class Schema extends \yii\db\Schema /** * Collects the foreign key column details for the given table. - * @param \yii\db\TableSchema $table the table metadata + * @param TableSchema $table the table metadata */ protected function findConstraints($table) { @@ -131,35 +133,21 @@ class Schema extends \yii\db\Schema } /** - * Creates a table column. - * @param array $column column metadata - * @return ColumnSchema normalized column metadata + * Loads the column information into a [[ColumnSchema]] object. + * @param array $info column information + * @return ColumnSchema the column schema object */ - protected function createColumn($column) + protected function loadColumnSchema($info) { - $c = new ColumnSchema; - $c->name = $column['name']; - $c->allowNull = !$column['notnull']; - $c->isPrimaryKey = $column['pk'] != 0; - - $c->dbType = $column['type']; - $this->resolveColumnType($c); - $c->phpType = $this->getColumnPhpType($this->type); - - $this->resolveColumnDefault($c, $column['dflt_value']); - - return $c; - } + $column = new ColumnSchema; + $column->name = $info['name']; + $column->allowNull = !$info['notnull']; + $column->isPrimaryKey = $info['pk'] != 0; - /** - * Resolves the abstract data type for the column. - * @param \yii\db\ColumnSchema $column the column metadata object - */ - public function resolveColumnType($column) - { - $column->type = self::TYPE_STRING; + $column->dbType = $info['type']; $column->unsigned = strpos($column->dbType, 'unsigned') !== false; + $column->type = self::TYPE_STRING; if (preg_match('/^(\w+)(?:\(([^\)]+)\))?/', $column->dbType, $matches)) { $type = $matches[1]; if (isset($this->typeMap[$type])) { @@ -183,19 +171,15 @@ class Schema extends \yii\db\Schema } } } - } + $column->phpType = $this->getColumnPhpType($this->type); - /** - * Resolves the default value for the column. - * @param \yii\db\ColumnSchema $column the column metadata object - * @param string $value the default value fetched from database - */ - protected function resolveColumnDefault($column, $value) - { + $value = $info['dflt_value']; if ($column->type === 'string') { $column->defaultValue = trim($value, "'\""); } else { $column->defaultValue = $column->typecast(strcasecmp($value, 'null') ? $value : null); } + + return $column; } }