Qiang Xue
12 years ago
14 changed files with 737 additions and 303 deletions
@ -0,0 +1,61 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\db\mssql; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is an extension of the default PDO class of MSSQL and DBLIB drivers. |
||||||
|
* It provides workarounds for improperly implemented functionalities of the MSSQL and DBLIB drivers. |
||||||
|
* |
||||||
|
* @author Timur Ruziev <resurtm@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class PDO extends \PDO |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Returns value of the last inserted ID. |
||||||
|
* @param string|null $sequence the sequence name. Defaults to null. |
||||||
|
* @return integer last inserted ID value. |
||||||
|
*/ |
||||||
|
public function lastInsertId($sequence = null) |
||||||
|
{ |
||||||
|
return $this->query('SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS bigint)')->fetchColumn(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Starts a transaction. It is necessary to override PDO's method as MSSQL PDO driver does not |
||||||
|
* natively support transactions. |
||||||
|
* @return boolean the result of a transaction start. |
||||||
|
*/ |
||||||
|
public function beginTransaction() |
||||||
|
{ |
||||||
|
$this->exec('BEGIN TRANSACTION'); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Commits a transaction. It is necessary to override PDO's method as MSSQL PDO driver does not |
||||||
|
* natively support transactions. |
||||||
|
* @return boolean the result of a transaction commit. |
||||||
|
*/ |
||||||
|
public function commit() |
||||||
|
{ |
||||||
|
$this->exec('COMMIT TRANSACTION'); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Rollbacks a transaction. It is necessary to override PDO's method as MSSQL PDO driver does not |
||||||
|
* natively support transactions. |
||||||
|
* @return boolean the result of a transaction rollback. |
||||||
|
*/ |
||||||
|
public function rollBack() |
||||||
|
{ |
||||||
|
$this->exec('ROLLBACK TRANSACTION'); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\db\mssql; |
||||||
|
|
||||||
|
use yii\base\InvalidParamException; |
||||||
|
|
||||||
|
/** |
||||||
|
* QueryBuilder is the query builder for MS SQL Server databases (version 2008 and above). |
||||||
|
* |
||||||
|
* @author Timur Ruziev <resurtm@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class QueryBuilder extends \yii\db\QueryBuilder |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @var array mapping from abstract column types (keys) to physical column types (values). |
||||||
|
*/ |
||||||
|
public $typeMap = array( |
||||||
|
Schema::TYPE_PK => 'int IDENTITY PRIMARY KEY', |
||||||
|
Schema::TYPE_STRING => 'varchar(255)', |
||||||
|
Schema::TYPE_TEXT => 'text', |
||||||
|
Schema::TYPE_SMALLINT => 'smallint(6)', |
||||||
|
Schema::TYPE_INTEGER => 'int(11)', |
||||||
|
Schema::TYPE_BIGINT => 'bigint(20)', |
||||||
|
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 => 'binary', |
||||||
|
Schema::TYPE_BOOLEAN => 'tinyint(1)', |
||||||
|
Schema::TYPE_MONEY => 'decimal(19,4)', |
||||||
|
); |
||||||
|
|
||||||
|
// public function update($table, $columns, $condition, &$params) |
||||||
|
// { |
||||||
|
// return ''; |
||||||
|
// } |
||||||
|
|
||||||
|
// public function delete($table, $condition, &$params) |
||||||
|
// { |
||||||
|
// return ''; |
||||||
|
// } |
||||||
|
|
||||||
|
// public function buildLimit($limit, $offset) |
||||||
|
// { |
||||||
|
// return ''; |
||||||
|
// } |
||||||
|
|
||||||
|
// public function resetSequence($table, $value = null) |
||||||
|
// { |
||||||
|
// return ''; |
||||||
|
// } |
||||||
|
|
||||||
|
/** |
||||||
|
* 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. |
||||||
|
* @param string $table the table name. Defaults to empty string, meaning that no table will be changed. |
||||||
|
* @return string the SQL statement for checking integrity |
||||||
|
* @throws InvalidParamException if the table does not exist or there is no sequence associated with the table. |
||||||
|
*/ |
||||||
|
public function checkIntegrity($check = true, $schema = '', $table = '') |
||||||
|
{ |
||||||
|
if ($schema !== '') { |
||||||
|
$table = "{$schema}.{$table}"; |
||||||
|
} |
||||||
|
$table = $this->db->quoteTableName($table); |
||||||
|
if ($this->db->getTableSchema($table) === null) { |
||||||
|
throw new InvalidParamException("Table not found: $table"); |
||||||
|
} |
||||||
|
$enable = $check ? 'CHECK' : 'NOCHECK'; |
||||||
|
return "ALTER TABLE {$table} {$enable} CONSTRAINT ALL"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,364 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\db\mssql; |
||||||
|
|
||||||
|
use yii\db\TableSchema; |
||||||
|
use yii\db\ColumnSchema; |
||||||
|
|
||||||
|
/** |
||||||
|
* Schema is the class for retrieving metadata from a MS SQL Server databases (version 2008 and above). |
||||||
|
* |
||||||
|
* @author Timur Ruziev <resurtm@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class Schema extends \yii\db\Schema |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Default schema name to be used. |
||||||
|
*/ |
||||||
|
const DEFAULT_SCHEMA = 'dbo'; |
||||||
|
|
||||||
|
/** |
||||||
|
* @var array mapping from physical column types (keys) to abstract column types (values) |
||||||
|
*/ |
||||||
|
public $typeMap = array( |
||||||
|
// exact numerics |
||||||
|
'bigint' => self::TYPE_BIGINT, |
||||||
|
'numeric' => self::TYPE_DECIMAL, |
||||||
|
'bit' => self::TYPE_SMALLINT, |
||||||
|
'smallint' => self::TYPE_SMALLINT, |
||||||
|
'decimal' => self::TYPE_DECIMAL, |
||||||
|
'smallmoney' => self::TYPE_MONEY, |
||||||
|
'int' => self::TYPE_INTEGER, |
||||||
|
'tinyint' => self::TYPE_SMALLINT, |
||||||
|
'money' => self::TYPE_MONEY, |
||||||
|
|
||||||
|
// approximate numerics |
||||||
|
'float' => self::TYPE_FLOAT, |
||||||
|
'real' => self::TYPE_FLOAT, |
||||||
|
|
||||||
|
// date and time |
||||||
|
'date' => self::TYPE_DATE, |
||||||
|
'datetimeoffset' => self::TYPE_DATETIME, |
||||||
|
'datetime2' => self::TYPE_DATETIME, |
||||||
|
'smalldatetime' => self::TYPE_DATETIME, |
||||||
|
'datetime' => self::TYPE_DATETIME, |
||||||
|
'time' => self::TYPE_TIME, |
||||||
|
|
||||||
|
// character strings |
||||||
|
'char' => self::TYPE_STRING, |
||||||
|
'varchar' => self::TYPE_STRING, |
||||||
|
'text' => self::TYPE_TEXT, |
||||||
|
|
||||||
|
// unicode character strings |
||||||
|
'nchar' => self::TYPE_STRING, |
||||||
|
'nvarchar' => self::TYPE_STRING, |
||||||
|
'ntext' => self::TYPE_TEXT, |
||||||
|
|
||||||
|
// binary strings |
||||||
|
'binary' => self::TYPE_BINARY, |
||||||
|
'varbinary' => self::TYPE_BINARY, |
||||||
|
'image' => self::TYPE_BINARY, |
||||||
|
|
||||||
|
// other data types |
||||||
|
// 'cursor' type cannot be used with tables |
||||||
|
'timestamp' => self::TYPE_TIMESTAMP, |
||||||
|
'hierarchyid' => self::TYPE_STRING, |
||||||
|
'uniqueidentifier' => self::TYPE_STRING, |
||||||
|
'sql_variant' => self::TYPE_STRING, |
||||||
|
'xml' => self::TYPE_STRING, |
||||||
|
'table' => self::TYPE_STRING, |
||||||
|
); |
||||||
|
|
||||||
|
/** |
||||||
|
* Quotes a table name for use in a query. |
||||||
|
* A simple table name has no schema prefix. |
||||||
|
* @param string $name table name. |
||||||
|
* @return string the properly quoted table name. |
||||||
|
*/ |
||||||
|
public function quoteSimpleTableName($name) |
||||||
|
{ |
||||||
|
return strpos($name, '[') === false ? "[{$name}]" : $name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Quotes a column name for use in a query. |
||||||
|
* A simple column name has no prefix. |
||||||
|
* @param string $name column name. |
||||||
|
* @return string the properly quoted column name. |
||||||
|
*/ |
||||||
|
public function quoteSimpleColumnName($name) |
||||||
|
{ |
||||||
|
return strpos($name, '[') === false && $name !== '*' ? "[{$name}]" : $name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a query builder for the MSSQL database. |
||||||
|
* @return QueryBuilder query builder interface. |
||||||
|
*/ |
||||||
|
public function createQueryBuilder() |
||||||
|
{ |
||||||
|
return new QueryBuilder($this->db); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Loads the metadata for the specified table. |
||||||
|
* @param string $name table name |
||||||
|
* @return TableSchema|null driver dependent table metadata. Null if the table does not exist. |
||||||
|
*/ |
||||||
|
public function loadTableSchema($name) |
||||||
|
{ |
||||||
|
$table = new TableSchema(); |
||||||
|
$this->resolveTableNames($table, $name); |
||||||
|
$this->findPrimaryKeys($table); |
||||||
|
if ($this->findColumns($table)) { |
||||||
|
$this->findForeignKeys($table); |
||||||
|
return $table; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Resolves the table name and schema name (if any). |
||||||
|
* @param TableSchema $table the table metadata object |
||||||
|
* @param string $name the table name |
||||||
|
*/ |
||||||
|
protected function resolveTableNames($table, $name) |
||||||
|
{ |
||||||
|
$parts = explode('.', str_replace(array('[', ']'), '', $name)); |
||||||
|
$partCount = count($parts); |
||||||
|
if ($partCount == 3) { |
||||||
|
// catalog name, schema name and table name passed |
||||||
|
$table->catalogName = $parts[0]; |
||||||
|
$table->schemaName = $parts[1]; |
||||||
|
$table->name = $parts[2]; |
||||||
|
} elseif ($partCount == 2) { |
||||||
|
// only schema name and table name passed |
||||||
|
$table->schemaName = $parts[0]; |
||||||
|
$table->name = $parts[1]; |
||||||
|
} else { |
||||||
|
// only schema name passed |
||||||
|
$table->schemaName = static::DEFAULT_SCHEMA; |
||||||
|
$table->name = $parts[0]; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Loads the column information into a [[ColumnSchema]] object. |
||||||
|
* @param array $info column information |
||||||
|
* @return ColumnSchema the column schema object |
||||||
|
*/ |
||||||
|
protected function loadColumnSchema($info) |
||||||
|
{ |
||||||
|
$column = new ColumnSchema(); |
||||||
|
|
||||||
|
$column->name = $info['COLUMN_NAME']; |
||||||
|
$column->allowNull = $info['IS_NULLABLE'] == 'YES'; |
||||||
|
$column->dbType = $info['DATA_TYPE']; |
||||||
|
$column->enumValues = array(); // mssql has only vague equivalents to enum |
||||||
|
$column->isPrimaryKey = null; // primary key will be determined in findColumns() method |
||||||
|
$column->autoIncrement = $info['IsIdentity'] == 1; |
||||||
|
$column->unsigned = stripos($column->dbType, 'unsigned') !== false; |
||||||
|
$column->comment = $info['Comment'] === null ? '' : $column['Comment']; |
||||||
|
|
||||||
|
$column->type = self::TYPE_STRING; |
||||||
|
if (preg_match('/^(\w+)(?:\(([^\)]+)\))?/', $column->dbType, $matches)) { |
||||||
|
$type = $matches[1]; |
||||||
|
if (isset($this->typeMap[$type])) { |
||||||
|
$column->type = $this->typeMap[$type]; |
||||||
|
} |
||||||
|
if (!empty($matches[2])) { |
||||||
|
$values = explode(',', $matches[2]); |
||||||
|
$column->size = $column->precision = (int)$values[0]; |
||||||
|
if (isset($values[1])) { |
||||||
|
$column->scale = (int)$values[1]; |
||||||
|
} |
||||||
|
if ($column->size === 1 && ($type === 'tinyint' || $type === 'bit')) { |
||||||
|
$column->type = 'boolean'; |
||||||
|
} elseif ($type === 'bit') { |
||||||
|
if ($column->size > 32) { |
||||||
|
$column->type = 'bigint'; |
||||||
|
} elseif ($column->size === 32) { |
||||||
|
$column->type = 'integer'; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$column->phpType = $this->getColumnPhpType($column); |
||||||
|
|
||||||
|
if ($info['COLUMN_DEFAULT'] == '(NULL)') { |
||||||
|
$info['COLUMN_DEFAULT'] = null; |
||||||
|
} |
||||||
|
if ($column->type !== 'timestamp' || $info['COLUMN_DEFAULT'] !== 'CURRENT_TIMESTAMP') { |
||||||
|
$column->defaultValue = $column->typecast($info['COLUMN_DEFAULT']); |
||||||
|
} |
||||||
|
|
||||||
|
return $column; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Collects the metadata of table columns. |
||||||
|
* @param TableSchema $table the table metadata |
||||||
|
* @return boolean whether the table exists in the database |
||||||
|
*/ |
||||||
|
protected function findColumns($table) |
||||||
|
{ |
||||||
|
$columnsTableName = 'information_schema.columns'; |
||||||
|
$whereSql = "[t1].[table_name] = '{$table->name}'"; |
||||||
|
if ($table->catalogName !== null) { |
||||||
|
$columnsTableName = "{$table->catalogName}.{$columnsTableName}"; |
||||||
|
$whereSql .= " AND [t1].[table_catalog] = '{$table->catalogName}'"; |
||||||
|
} |
||||||
|
if ($table->schemaName !== null) { |
||||||
|
$whereSql .= " AND [t1].[table_schema] = '{$table->schemaName}'"; |
||||||
|
} |
||||||
|
$columnsTableName = $this->quoteTableName($columnsTableName); |
||||||
|
|
||||||
|
$sql = <<<SQL |
||||||
|
SELECT |
||||||
|
[t1].*, |
||||||
|
COLUMNPROPERTY(OBJECT_ID([t1].[table_schema] + '.' + [t1].[table_name]), [t1].[column_name], 'IsIdentity') AS IsIdentity, |
||||||
|
CONVERT(VARCHAR, [t2].[value]) AS Comment |
||||||
|
FROM {$columnsTableName} AS [t1] |
||||||
|
LEFT OUTER JOIN [sys].[extended_properties] AS [t2] ON |
||||||
|
[t1].[ordinal_position] = [t2].[minor_id] AND |
||||||
|
OBJECT_NAME([t2].[major_id]) = [t1].[table_name] AND |
||||||
|
[t2].[class] = 1 AND |
||||||
|
[t2].[class_desc] = 'OBJECT_OR_COLUMN' AND |
||||||
|
[t2].[name] = 'MS_Description' |
||||||
|
WHERE {$whereSql} |
||||||
|
SQL; |
||||||
|
|
||||||
|
try { |
||||||
|
$columns = $this->db->createCommand($sql)->queryAll(); |
||||||
|
} catch (\Exception $e) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
foreach ($columns as $column) { |
||||||
|
$column = $this->loadColumnSchema($column); |
||||||
|
if (is_array($table->primaryKey)) { |
||||||
|
foreach ($table->primaryKey as $primaryKeyColumn) { |
||||||
|
if (strcasecmp($column->name, $primaryKeyColumn) === 0) { |
||||||
|
$column->isPrimaryKey = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
$column->isPrimaryKey = strcasecmp($column->name, $table->primaryKey) === 0; |
||||||
|
} |
||||||
|
if ($column->isPrimaryKey && $column->autoIncrement) { |
||||||
|
$table->sequenceName = ''; |
||||||
|
} |
||||||
|
$table->columns[$column->name] = $column; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Collects the primary key column details for the given table. |
||||||
|
* @param TableSchema $table the table metadata |
||||||
|
*/ |
||||||
|
protected function findPrimaryKeys($table) |
||||||
|
{ |
||||||
|
$keyColumnUsageTableName = 'information_schema.key_column_usage'; |
||||||
|
$tableConstraintsTableName = 'information_schema.table_constraints'; |
||||||
|
if ($table->catalogName !== null) { |
||||||
|
$keyColumnUsageTableName = $table->catalogName . '.' . $keyColumnUsageTableName; |
||||||
|
$tableConstraintsTableName = $table->catalogName . '.' . $tableConstraintsTableName; |
||||||
|
} |
||||||
|
$keyColumnUsageTableName = $this->quoteTableName($keyColumnUsageTableName); |
||||||
|
$tableConstraintsTableName = $this->quoteTableName($tableConstraintsTableName); |
||||||
|
|
||||||
|
$sql = <<<SQL |
||||||
|
SELECT |
||||||
|
[kcu].[column_name] AS [field_name] |
||||||
|
FROM {$keyColumnUsageTableName} AS [kcu] |
||||||
|
LEFT JOIN {$tableConstraintsTableName} AS [tc] ON |
||||||
|
[kcu].[table_name] = [tc].[table_name] AND |
||||||
|
[kcu].[constraint_name] = [tc].[constraint_name] |
||||||
|
WHERE |
||||||
|
[tc].[constraint_type] = 'PRIMARY KEY' AND |
||||||
|
[kcu].[table_name] = :tableName AND |
||||||
|
[kcu].[table_schema] = :schemaName |
||||||
|
SQL; |
||||||
|
|
||||||
|
$table->primaryKey = $this->db |
||||||
|
->createCommand($sql, array(':tableName' => $table->name, ':schemaName' => $table->schemaName)) |
||||||
|
->queryColumn(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Collects the foreign key column details for the given table. |
||||||
|
* @param TableSchema $table the table metadata |
||||||
|
*/ |
||||||
|
protected function findForeignKeys($table) |
||||||
|
{ |
||||||
|
$referentialConstraintsTableName = 'information_schema.referential_constraints'; |
||||||
|
$keyColumnUsageTableName = 'information_schema.key_column_usage'; |
||||||
|
if ($table->catalogName !== null) { |
||||||
|
$referentialConstraintsTableName = $table->catalogName . '.' . $referentialConstraintsTableName; |
||||||
|
$keyColumnUsageTableName = $table->catalogName . '.' . $keyColumnUsageTableName; |
||||||
|
} |
||||||
|
$referentialConstraintsTableName = $this->quoteTableName($referentialConstraintsTableName); |
||||||
|
$keyColumnUsageTableName = $this->quoteTableName($keyColumnUsageTableName); |
||||||
|
|
||||||
|
// please refer to the following page for more details: |
||||||
|
// http://msdn2.microsoft.com/en-us/library/aa175805(SQL.80).aspx |
||||||
|
$sql = <<<SQL |
||||||
|
SELECT |
||||||
|
[kcu1].[column_name] AS [fk_column_name], |
||||||
|
[kcu2].[table_name] AS [uq_table_name], |
||||||
|
[kcu2].[column_name] AS [uq_column_name] |
||||||
|
FROM {$referentialConstraintsTableName} AS [rc] |
||||||
|
JOIN {$keyColumnUsageTableName} AS [kcu1] ON |
||||||
|
[kcu1].[constraint_catalog] = [rc].[constraint_catalog] AND |
||||||
|
[kcu1].[constraint_schema] = [rc].[constraint_schema] AND |
||||||
|
[kcu1].[constraint_name] = [rc].[constraint_name] |
||||||
|
JOIN {$keyColumnUsageTableName} AS [kcu2] ON |
||||||
|
[kcu2].[constraint_catalog] = [rc].[constraint_catalog] AND |
||||||
|
[kcu2].[constraint_schema] = [rc].[constraint_schema] AND |
||||||
|
[kcu2].[constraint_name] = [rc].[constraint_name] AND |
||||||
|
[kcu2].[ordinal_position] = [kcu1].[ordinal_position] |
||||||
|
WHERE [kcu1].[table_name] = :tableName |
||||||
|
SQL; |
||||||
|
|
||||||
|
$rows = $this->db->createCommand($sql, array(':tableName' => $table->name))->queryAll(); |
||||||
|
$table->foreignKeys = array(); |
||||||
|
foreach ($rows as $row) { |
||||||
|
$table->foreignKeys[] = array($row['uq_table_name'], $row['fk_column_name'] => $row['uq_column_name']); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns all table names in the database. |
||||||
|
* This method should be overridden by child classes in order to support this feature |
||||||
|
* because the default implementation simply throws an exception. |
||||||
|
* @param string $schema the schema of the tables. Defaults to empty string, meaning the current or default schema. |
||||||
|
* @return array all table names in the database. The names have NO the schema name prefix. |
||||||
|
*/ |
||||||
|
protected function findTableNames($schema = '') |
||||||
|
{ |
||||||
|
if ($schema === '') { |
||||||
|
$schema = static::DEFAULT_SCHEMA; |
||||||
|
} |
||||||
|
|
||||||
|
$sql = <<<SQL |
||||||
|
SELECT [t].[table] |
||||||
|
FROM [information_schema].[tables] AS [t] |
||||||
|
WHERE [t].[table_schema] = :schema AND [t].[table_type] = 'BASE TABLE' |
||||||
|
SQL; |
||||||
|
|
||||||
|
$names = $this->db->createCommand($sql, array(':schema' => $schema))->queryColumn(); |
||||||
|
if ($schema !== static::DEFAULT_SCHEMA) { |
||||||
|
foreach ($names as $index => $name) { |
||||||
|
$names[$index] = $schema . '.' . $name; |
||||||
|
} |
||||||
|
} |
||||||
|
return $names; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* @link http://www.yiiframework.com/ |
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC |
||||||
|
* @license http://www.yiiframework.com/license/ |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace yii\db\mssql; |
||||||
|
|
||||||
|
/** |
||||||
|
* This is an extension of the default PDO class of SQLSRV driver. |
||||||
|
* It provides workarounds for improperly implemented functionalities of the SQLSRV driver. |
||||||
|
* |
||||||
|
* @author Timur Ruziev <resurtm@gmail.com> |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
class SqlsrvPDO extends \PDO |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Returns value of the last inserted ID. |
||||||
|
* |
||||||
|
* SQLSRV driver implements [[PDO::lastInsertId()]] method but with a single peculiarity: |
||||||
|
* when `$sequence` value is a null or an empty string it returns an empty string. |
||||||
|
* But when parameter is not specified it works as expected and returns actual |
||||||
|
* last inserted ID (like the other PDO drivers). |
||||||
|
* @param string|null $sequence the sequence name. Defaults to null. |
||||||
|
* @return integer last inserted ID value. |
||||||
|
*/ |
||||||
|
public function lastInsertId($sequence = null) |
||||||
|
{ |
||||||
|
return !$sequence ? parent::lastInsertId() : parent::lastInsertId($sequence); |
||||||
|
} |
||||||
|
} |
@ -1,306 +1,94 @@ |
|||||||
SET ANSI_NULLS ON |
IF OBJECT_ID('[dbo].[tbl_order_item]', 'U') IS NOT NULL DROP TABLE [dbo].[tbl_order_item]; |
||||||
GO |
IF OBJECT_ID('[dbo].[tbl_item]', 'U') IS NOT NULL DROP TABLE [dbo].[tbl_item]; |
||||||
SET QUOTED_IDENTIFIER ON |
IF OBJECT_ID('[dbo].[tbl_order]', 'U') IS NOT NULL DROP TABLE [dbo].[tbl_order]; |
||||||
GO |
IF OBJECT_ID('[dbo].[tbl_category]', 'U') IS NOT NULL DROP TABLE [dbo].[tbl_category]; |
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[categories]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
IF OBJECT_ID('[dbo].[tbl_customer]', 'U') IS NOT NULL DROP TABLE [dbo].[tbl_customer]; |
||||||
BEGIN |
IF OBJECT_ID('[dbo].[tbl_type]', 'U') IS NOT NULL DROP TABLE [dbo].[tbl_type]; |
||||||
CREATE TABLE [dbo].[categories]( |
|
||||||
|
CREATE TABLE [dbo].[tbl_customer] ( |
||||||
[id] [int] IDENTITY(1,1) NOT NULL, |
[id] [int] IDENTITY(1,1) NOT NULL, |
||||||
|
[email] [varchar](128) NOT NULL, |
||||||
[name] [varchar](128) NOT NULL, |
[name] [varchar](128) NOT NULL, |
||||||
[parent_id] [int] NULL, |
[address] [text], |
||||||
CONSTRAINT [PK_categories] PRIMARY KEY CLUSTERED |
[status] [int] DEFAULT 0, |
||||||
( |
CONSTRAINT [PK_customer] PRIMARY KEY CLUSTERED ( |
||||||
[id] ASC |
[id] ASC |
||||||
) ON [PRIMARY] |
) ON [PRIMARY] |
||||||
) ON [PRIMARY] |
); |
||||||
END |
|
||||||
GO |
CREATE TABLE [dbo].[tbl_category] ( |
||||||
SET ANSI_NULLS ON |
[id] [int] IDENTITY(1,1) NOT NULL, |
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[orders]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[orders]( |
|
||||||
[key1] [int] NOT NULL, |
|
||||||
[key2] [int] NOT NULL, |
|
||||||
[name] [varchar](128) NOT NULL, |
[name] [varchar](128) NOT NULL, |
||||||
CONSTRAINT [PK_orders] PRIMARY KEY CLUSTERED |
CONSTRAINT [PK_category] PRIMARY KEY CLUSTERED ( |
||||||
( |
[id] ASC |
||||||
[key1] ASC, |
) ON [PRIMARY] |
||||||
[key2] ASC |
); |
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] |
CREATE TABLE [dbo].[tbl_item] ( |
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[types]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[types]( |
|
||||||
[int_col] [int] NOT NULL, |
|
||||||
[int_col2] [int] NULL CONSTRAINT [DF_types_int_col2] DEFAULT (1), |
|
||||||
[char_col] [char](100) NOT NULL, |
|
||||||
[char_col2] [varchar](100) NULL CONSTRAINT [DF_types_char_col2] DEFAULT ('something'), |
|
||||||
[char_col3] [text] NULL, |
|
||||||
[float_col] [real] NOT NULL, |
|
||||||
[float_col2] [float] NULL CONSTRAINT [DF_types_float_col2] DEFAULT (1.23), |
|
||||||
[blob_col] [image] NULL, |
|
||||||
[numeric_col] [numeric](5, 2) NULL CONSTRAINT [DF_types_numeric_col] DEFAULT (33.22), |
|
||||||
[time] [datetime] NULL CONSTRAINT [DF_types_time] DEFAULT ('2002-01-01 00:00:00'), |
|
||||||
[bool_col] [bit] NOT NULL, |
|
||||||
[bool_col2] [bit] NOT NULL CONSTRAINT [DF_types_bool_col2] DEFAULT (1) |
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[users]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[users]( |
|
||||||
[id] [int] IDENTITY(1,1) NOT NULL, |
[id] [int] IDENTITY(1,1) NOT NULL, |
||||||
[username] [varchar](128) NOT NULL, |
[name] [varchar](128) NOT NULL, |
||||||
[password] [varchar](128) NOT NULL, |
|
||||||
[email] [varchar](128) NOT NULL, |
|
||||||
CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED |
|
||||||
( |
|
||||||
[id] ASC |
|
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[post_category]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[post_category]( |
|
||||||
[category_id] [int] NOT NULL, |
[category_id] [int] NOT NULL, |
||||||
[post_id] [int] NOT NULL, |
CONSTRAINT [PK_item] PRIMARY KEY CLUSTERED ( |
||||||
CONSTRAINT [PK_post_category] PRIMARY KEY CLUSTERED |
[id] ASC |
||||||
( |
) ON [PRIMARY] |
||||||
[category_id] ASC, |
); |
||||||
[post_id] ASC |
|
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[items]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[items]( |
|
||||||
[id] [int] IDENTITY(1,1) NOT NULL, |
|
||||||
[name] [varchar](128) NULL, |
|
||||||
[col1] [int] NOT NULL, |
|
||||||
[col2] [int] NOT NULL, |
|
||||||
CONSTRAINT [PK_items] PRIMARY KEY CLUSTERED |
|
||||||
( |
|
||||||
[id] ASC |
|
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[comments]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[comments]( |
|
||||||
[id] [int] IDENTITY(1,1) NOT NULL, |
|
||||||
[content] [text] NOT NULL, |
|
||||||
[post_id] [int] NOT NULL, |
|
||||||
[author_id] [int] NOT NULL, |
|
||||||
CONSTRAINT [PK_comments] PRIMARY KEY CLUSTERED |
|
||||||
( |
|
||||||
[id] ASC |
|
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[posts]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[posts]( |
|
||||||
[id] [int] IDENTITY(1,1) NOT NULL, |
|
||||||
[title] [varchar](128) NOT NULL, |
|
||||||
[create_time] [datetime] NOT NULL, |
|
||||||
[author_id] [int] NOT NULL, |
|
||||||
[content] [text] NULL, |
|
||||||
CONSTRAINT [PK_posts] PRIMARY KEY CLUSTERED |
|
||||||
( |
|
||||||
[id] ASC |
|
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
SET ANSI_NULLS ON |
|
||||||
GO |
|
||||||
SET QUOTED_IDENTIFIER ON |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[profiles]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1) |
|
||||||
BEGIN |
|
||||||
CREATE TABLE [dbo].[profiles]( |
|
||||||
[id] [int] IDENTITY(1,1) NOT NULL, |
|
||||||
[first_name] [varchar](128) NOT NULL, |
|
||||||
[last_name] [varchar](128) NOT NULL, |
|
||||||
[user_id] [int] NOT NULL, |
|
||||||
CONSTRAINT [PK_profiles] PRIMARY KEY CLUSTERED |
|
||||||
( |
|
||||||
[id] ASC |
|
||||||
) ON [PRIMARY] |
|
||||||
) ON [PRIMARY] |
|
||||||
END |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_categories_categories]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[categories] WITH CHECK ADD CONSTRAINT [FK_categories_categories] FOREIGN KEY([parent_id]) |
|
||||||
REFERENCES [dbo].[categories] ([id]) |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_post_category_categories]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[post_category] WITH CHECK ADD CONSTRAINT [FK_post_category_categories] FOREIGN KEY([category_id]) |
|
||||||
REFERENCES [dbo].[categories] ([id]) |
|
||||||
ON DELETE CASCADE |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_post_category_posts]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[post_category] WITH NOCHECK ADD CONSTRAINT [FK_post_category_posts] FOREIGN KEY([post_id]) |
|
||||||
REFERENCES [dbo].[posts] ([id]) |
|
||||||
ON DELETE CASCADE |
|
||||||
GO |
|
||||||
ALTER TABLE [dbo].[post_category] CHECK CONSTRAINT [FK_post_category_posts] |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_items_orders]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[items] WITH CHECK ADD CONSTRAINT [FK_items_orders] FOREIGN KEY([col1], [col2]) |
|
||||||
REFERENCES [dbo].[orders] ([key1], [key2]) |
|
||||||
ON DELETE CASCADE |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_comments_users]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[comments] WITH NOCHECK ADD CONSTRAINT [FK_comments_users] FOREIGN KEY([author_id]) |
|
||||||
REFERENCES [dbo].[users] ([id]) |
|
||||||
ON DELETE CASCADE |
|
||||||
GO |
|
||||||
ALTER TABLE [dbo].[comments] CHECK CONSTRAINT [FK_comments_users] |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_post_comment]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[comments] WITH NOCHECK ADD CONSTRAINT [FK_post_comment] FOREIGN KEY([post_id]) |
|
||||||
REFERENCES [dbo].[posts] ([id]) |
|
||||||
ON DELETE CASCADE |
|
||||||
GO |
|
||||||
ALTER TABLE [dbo].[comments] CHECK CONSTRAINT [FK_post_comment] |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_posts_users]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[posts] WITH NOCHECK ADD CONSTRAINT [FK_posts_users] FOREIGN KEY([author_id]) |
|
||||||
REFERENCES [dbo].[users] ([id]) |
|
||||||
GO |
|
||||||
ALTER TABLE [dbo].[posts] CHECK CONSTRAINT [FK_posts_users] |
|
||||||
GO |
|
||||||
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_profile_user]') AND type = 'F') |
|
||||||
ALTER TABLE [dbo].[profiles] WITH NOCHECK ADD CONSTRAINT [FK_profile_user] FOREIGN KEY([user_id]) |
|
||||||
REFERENCES [dbo].[users] ([id]) |
|
||||||
ON DELETE CASCADE |
|
||||||
GO |
|
||||||
ALTER TABLE [dbo].[profiles] CHECK CONSTRAINT [FK_profile_user] |
|
||||||
|
|
||||||
INSERT INTO users (username, password, email) VALUES ('user1','pass1','email1') |
|
||||||
GO |
|
||||||
INSERT INTO users (username, password, email) VALUES ('user2','pass2','email2') |
|
||||||
GO |
|
||||||
INSERT INTO users (username, password, email) VALUES ('user3','pass3','email3') |
|
||||||
GO |
|
||||||
|
|
||||||
INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 1','last 1',1) |
CREATE TABLE [dbo].[tbl_order] ( |
||||||
GO |
[id] [int] IDENTITY(1,1) NOT NULL, |
||||||
INSERT INTO profiles (first_name, last_name, user_id) VALUES ('first 2','last 2',2) |
[customer_id] [int] NOT NULL, |
||||||
GO |
[create_time] [int] NOT NULL, |
||||||
|
[total] [decimal](10,0) NOT NULL, |
||||||
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 1','2000-01-01',1,'content 1') |
CONSTRAINT [PK_order] PRIMARY KEY CLUSTERED ( |
||||||
GO |
[id] ASC |
||||||
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 2','2000-01-02',2,'content 2') |
) ON [PRIMARY] |
||||||
GO |
); |
||||||
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 3','2000-01-03',2,'content 3') |
|
||||||
GO |
|
||||||
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 4','2000-01-04',2,'content 4') |
|
||||||
GO |
|
||||||
INSERT INTO posts (title, create_time, author_id, content) VALUES ('post 5','2000-01-05',3,'content 5') |
|
||||||
GO |
|
||||||
|
|
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 1',1, 2) |
CREATE TABLE [dbo].[tbl_order_item] ( |
||||||
GO |
[order_id] [int] NOT NULL, |
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 2',1, 2) |
[item_id] [int] NOT NULL, |
||||||
GO |
[quantity] [int] NOT NULL, |
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 3',1, 2) |
[subtotal] [decimal](10,0) NOT NULL, |
||||||
GO |
CONSTRAINT [PK_order_item] PRIMARY KEY CLUSTERED ( |
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 4',2, 2) |
[order_id] ASC, |
||||||
GO |
[item_id] ASC |
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 5',2, 2) |
) ON [PRIMARY] |
||||||
GO |
); |
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 6',3, 2) |
|
||||||
GO |
|
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 7',3, 2) |
|
||||||
GO |
|
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 8',3, 2) |
|
||||||
GO |
|
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 9',3, 2) |
|
||||||
GO |
|
||||||
INSERT INTO comments (content, post_id, author_id) VALUES ('comment 10',5, 3) |
|
||||||
GO |
|
||||||
|
|
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 1',NULL) |
CREATE TABLE [dbo].[tbl_type] ( |
||||||
GO |
[int_col] [int] NOT NULL, |
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 2',NULL) |
[int_col2] [int] DEFAULT '1', |
||||||
GO |
[char_col] [char](100) NOT NULL, |
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 3',NULL) |
[char_col2] [varchar](100) DEFAULT 'something', |
||||||
GO |
[char_col3] [text], |
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 4',1) |
[float_col] [decimal](4,3) NOT NULL, |
||||||
GO |
[float_col2] [float] DEFAULT '1.23', |
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 5',1) |
[blob_col] [binary], |
||||||
GO |
[numeric_col] [decimal](5,2) DEFAULT '33.22', |
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 6',5) |
[time] [datetime] NOT NULL DEFAULT '2002-01-01 00:00:00', |
||||||
GO |
[bool_col] [tinyint] NOT NULL, |
||||||
INSERT INTO categories (name, parent_id) VALUES ('cat 7',5) |
[bool_col2] [tinyint] DEFAULT '1' |
||||||
GO |
); |
||||||
|
|
||||||
INSERT INTO post_category (category_id, post_id) VALUES (1,1) |
INSERT INTO [dbo].[tbl_customer] ([email], [name], [address], [status]) VALUES ('user1@example.com', 'user1', 'address1', 1); |
||||||
GO |
INSERT INTO [dbo].[tbl_customer] ([email], [name], [address], [status]) VALUES ('user2@example.com', 'user2', 'address2', 1); |
||||||
INSERT INTO post_category (category_id, post_id) VALUES (2,1) |
INSERT INTO [dbo].[tbl_customer] ([email], [name], [address], [status]) VALUES ('user3@example.com', 'user3', 'address3', 2); |
||||||
GO |
|
||||||
INSERT INTO post_category (category_id, post_id) VALUES (3,1) |
|
||||||
GO |
|
||||||
INSERT INTO post_category (category_id, post_id) VALUES (4,2) |
|
||||||
GO |
|
||||||
INSERT INTO post_category (category_id, post_id) VALUES (1,2) |
|
||||||
GO |
|
||||||
INSERT INTO post_category (category_id, post_id) VALUES (1,3) |
|
||||||
GO |
|
||||||
|
|
||||||
|
INSERT INTO [dbo].[tbl_category] ([name]) VALUES ('Books'); |
||||||
|
INSERT INTO [dbo].[tbl_category] ([name]) VALUES ('Movies'); |
||||||
|
|
||||||
INSERT INTO orders (key1,key2,name) VALUES (1,2,'order 12') |
INSERT INTO [dbo].[tbl_item] ([name], [category_id]) VALUES ('Agile Web Application Development with Yii1.1 and PHP5', 1); |
||||||
GO |
INSERT INTO [dbo].[tbl_item] ([name], [category_id]) VALUES ('Yii 1.1 Application Development Cookbook', 1); |
||||||
INSERT INTO orders (key1,key2,name) VALUES (1,3,'order 13') |
INSERT INTO [dbo].[tbl_item] ([name], [category_id]) VALUES ('Ice Age', 2); |
||||||
GO |
INSERT INTO [dbo].[tbl_item] ([name], [category_id]) VALUES ('Toy Story', 2); |
||||||
INSERT INTO orders (key1,key2,name) VALUES (2,1,'order 21') |
INSERT INTO [dbo].[tbl_item] ([name], [category_id]) VALUES ('Cars', 2); |
||||||
GO |
|
||||||
INSERT INTO orders (key1,key2,name) VALUES (2,2,'order 22') |
|
||||||
GO |
|
||||||
|
|
||||||
|
INSERT INTO [dbo].[tbl_order] ([customer_id], [create_time], [total]) VALUES (1, 1325282384, 110.0); |
||||||
|
INSERT INTO [dbo].[tbl_order] ([customer_id], [create_time], [total]) VALUES (2, 1325334482, 33.0); |
||||||
|
INSERT INTO [dbo].[tbl_order] ([customer_id], [create_time], [total]) VALUES (2, 1325502201, 40.0); |
||||||
|
|
||||||
INSERT INTO items (name,col1,col2) VALUES ('item 1',1,2) |
INSERT INTO [dbo].[tbl_order_item] ([order_id], [item_id], [quantity], [subtotal]) VALUES (1, 1, 1, 30.0); |
||||||
GO |
INSERT INTO [dbo].[tbl_order_item] ([order_id], [item_id], [quantity], [subtotal]) VALUES (1, 2, 2, 40.0); |
||||||
INSERT INTO items (name,col1,col2) VALUES ('item 2',1,2) |
INSERT INTO [dbo].[tbl_order_item] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 4, 1, 10.0); |
||||||
GO |
INSERT INTO [dbo].[tbl_order_item] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 5, 1, 15.0); |
||||||
INSERT INTO items (name,col1,col2) VALUES ('item 3',1,3) |
INSERT INTO [dbo].[tbl_order_item] ([order_id], [item_id], [quantity], [subtotal]) VALUES (2, 3, 1, 8.0); |
||||||
GO |
INSERT INTO [dbo].[tbl_order_item] ([order_id], [item_id], [quantity], [subtotal]) VALUES (3, 2, 1, 40.0); |
||||||
INSERT INTO items (name,col1,col2) VALUES ('item 4',2,2) |
|
||||||
GO |
|
||||||
INSERT INTO items (name,col1,col2) VALUES ('item 5',2,2) |
|
||||||
GO |
|
||||||
|
@ -0,0 +1,12 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace yiiunit\framework\db\mssql; |
||||||
|
|
||||||
|
class MssqlActiveRecordTest extends \yiiunit\framework\db\ActiveRecordTest |
||||||
|
{ |
||||||
|
protected function setUp() |
||||||
|
{ |
||||||
|
$this->driverName = 'sqlsrv'; |
||||||
|
parent::setUp(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,31 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace yiiunit\framework\db\mssql; |
||||||
|
|
||||||
|
class MssqlCommandTest extends \yiiunit\framework\db\CommandTest |
||||||
|
{ |
||||||
|
public function setUp() |
||||||
|
{ |
||||||
|
$this->driverName = 'sqlsrv'; |
||||||
|
parent::setUp(); |
||||||
|
} |
||||||
|
|
||||||
|
function testAutoQuoting() |
||||||
|
{ |
||||||
|
$db = $this->getConnection(false); |
||||||
|
|
||||||
|
$sql = 'SELECT [[id]], [[t.name]] FROM {{tbl_customer}} t'; |
||||||
|
$command = $db->createCommand($sql); |
||||||
|
$this->assertEquals("SELECT [id], [t].[name] FROM [tbl_customer] t", $command->sql); |
||||||
|
} |
||||||
|
|
||||||
|
function testPrepareCancel() |
||||||
|
{ |
||||||
|
$this->markTestIncomplete(); |
||||||
|
} |
||||||
|
|
||||||
|
function testBindParamValue() |
||||||
|
{ |
||||||
|
$this->markTestIncomplete(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace yiiunit\framework\db\mssql; |
||||||
|
|
||||||
|
class MssqlConnectionTest extends \yiiunit\framework\db\ConnectionTest |
||||||
|
{ |
||||||
|
public function setUp() |
||||||
|
{ |
||||||
|
$this->driverName = 'sqlsrv'; |
||||||
|
parent::setUp(); |
||||||
|
} |
||||||
|
|
||||||
|
function testQuoteValue() |
||||||
|
{ |
||||||
|
$connection = $this->getConnection(false); |
||||||
|
$this->assertEquals(123, $connection->quoteValue(123)); |
||||||
|
$this->assertEquals("'string'", $connection->quoteValue('string')); |
||||||
|
$this->assertEquals("'It''s interesting'", $connection->quoteValue("It's interesting")); |
||||||
|
} |
||||||
|
|
||||||
|
function testQuoteTableName() |
||||||
|
{ |
||||||
|
$connection = $this->getConnection(false); |
||||||
|
$this->assertEquals('[table]', $connection->quoteTableName('table')); |
||||||
|
$this->assertEquals('[table]', $connection->quoteTableName('[table]')); |
||||||
|
$this->assertEquals('[schema].[table]', $connection->quoteTableName('schema.table')); |
||||||
|
$this->assertEquals('[schema].[table]', $connection->quoteTableName('schema.[table]')); |
||||||
|
$this->assertEquals('{{table}}', $connection->quoteTableName('{{table}}')); |
||||||
|
$this->assertEquals('(table)', $connection->quoteTableName('(table)')); |
||||||
|
} |
||||||
|
|
||||||
|
function testQuoteColumnName() |
||||||
|
{ |
||||||
|
$connection = $this->getConnection(false); |
||||||
|
$this->assertEquals('[column]', $connection->quoteColumnName('column')); |
||||||
|
$this->assertEquals('[column]', $connection->quoteColumnName('[column]')); |
||||||
|
$this->assertEquals('[table].[column]', $connection->quoteColumnName('table.column')); |
||||||
|
$this->assertEquals('[table].[column]', $connection->quoteColumnName('table.[column]')); |
||||||
|
$this->assertEquals('[[column]]', $connection->quoteColumnName('[[column]]')); |
||||||
|
$this->assertEquals('{{column}}', $connection->quoteColumnName('{{column}}')); |
||||||
|
$this->assertEquals('(column)', $connection->quoteColumnName('(column)')); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue