Commit 66a5b9c3 by Qiang Xue

Merge pull request #351 from yiisoft/mssql

Initial MSSQL support.
parents e1ea91a7 2430ebe9
......@@ -237,10 +237,10 @@ class Connection extends Component
'mysql' => 'yii\db\mysql\Schema', // MySQL
'sqlite' => 'yii\db\sqlite\Schema', // sqlite 3
'sqlite2' => 'yii\db\sqlite\Schema', // sqlite 2
'mssql' => 'yii\db\dao\mssql\Schema', // Mssql driver on windows hosts
'sqlsrv' => 'yii\db\mssql\Schema', // Mssql
'sqlsrv' => 'yii\db\mssql\Schema', // newer MSSQL driver on MS Windows hosts
'oci' => 'yii\db\oci\Schema', // Oracle driver
'dblib' => 'yii\db\mssql\Schema', // dblib drivers on linux (and maybe others os) hosts
'mssql' => 'yii\db\mssql\Schema', // older MSSQL driver on MS Windows hosts
'dblib' => 'yii\db\mssql\Schema', // dblib drivers on GNU/Linux (and maybe other OSes) hosts
);
/**
* @var Transaction the currently active transaction
......
......@@ -429,10 +429,11 @@ class QueryBuilder extends \yii\base\Object
* 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 NotSupportedException if this is not supported by the underlying DBMS
*/
public function checkIntegrity($check = true, $schema = '')
public function checkIntegrity($check = true, $schema = '', $table = '')
{
throw new NotSupportedException($this->db->getDriverName() . ' does not support enabling/disabling integrity check.');
}
......
<?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;
}
}
<?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";
}
}
<?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);
}
}
......@@ -120,12 +120,13 @@ class QueryBuilder extends \yii\db\QueryBuilder
/**
* 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. Meaningless for MySQL.
* @param string $schema the schema of the tables. Meaningless for MySQL.
* @return string the SQL statement for checking integrity
*/
public function checkIntegrity($check = true, $schema = '')
public function checkIntegrity($check = true, $schema = '', $table = '')
{
return 'SET FOREIGN_KEY_CHECKS=' . ($check ? 1 : 0);
return 'SET FOREIGN_KEY_CHECKS = ' . ($check ? 1 : 0);
}
/**
......
......@@ -77,10 +77,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.
* @param string $schema the schema of the tables. Meaningless for SQLite.
* @param string $table the table name. Meaningless for SQLite.
* @throws NotSupportedException this is not supported by SQLite
*/
public function checkIntegrity($check = true, $schema = '')
public function checkIntegrity($check = true, $schema = '', $table = '')
{
throw new NotSupportedException(__METHOD__ . ' is not supported by SQLite.');
}
......
......@@ -14,5 +14,11 @@ return array(
'dsn' => 'sqlite::memory:',
'fixture' => __DIR__ . '/sqlite.sql',
),
),
'sqlsrv' => array(
'dsn' => 'sqlsrv:Server=localhost;Database=test',
'username' => '',
'password' => '',
'fixture' => __DIR__ . '/mssql.sql',
),
)
);
<?php
namespace yiiunit\framework\db\mssql;
class MssqlActiveRecordTest extends \yiiunit\framework\db\ActiveRecordTest
{
protected function setUp()
{
$this->driverName = 'sqlsrv';
parent::setUp();
}
}
<?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();
}
}
<?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)'));
}
}
<?php
namespace yiiunit\framework\db\mssql;
class MssqlQueryTest extends \yiiunit\framework\db\QueryTest
{
public function setUp()
{
$this->driverName = 'sqlsrv';
parent::setUp();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment