<?php namespace Doctrine\Tests\DBAL\Platforms; use Doctrine\DBAL\Platforms\SQLServer2008Platform; use Doctrine\DBAL\Types\Type; class SQLServerPlatformTest extends AbstractPlatformTestCase { public function createPlatform() { return new SQLServer2008Platform; } public function getGenerateTableSql() { return 'CREATE TABLE test (id INT IDENTITY NOT NULL, test NVARCHAR(255), PRIMARY KEY (id))'; } public function getGenerateTableWithMultiColumnUniqueIndexSql() { return array( 'CREATE TABLE test (foo NVARCHAR(255), bar NVARCHAR(255))', 'CREATE UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA ON test (foo, bar) WHERE foo IS NOT NULL AND bar IS NOT NULL' ); } public function getGenerateAlterTableSql() { return array( 'ALTER TABLE mytable ADD quota INT', 'ALTER TABLE mytable DROP COLUMN foo', 'ALTER TABLE mytable ALTER COLUMN baz NVARCHAR(255) NOT NULL', "ALTER TABLE mytable ADD CONSTRAINT DF_6B2BD609_78240498 DEFAULT 'def' FOR baz", 'ALTER TABLE mytable ALTER COLUMN bloo BIT NOT NULL', "sp_RENAME 'mytable', 'userlist'", "DECLARE @sql NVARCHAR(MAX) = N''; " . "SELECT @sql += N'EXEC sp_rename N''' + dc.name + ''', N''' " . "+ REPLACE(dc.name, '6B2BD609', 'E2B58069') + ''', ''OBJECT'';' " . "FROM sys.default_constraints dc " . "JOIN sys.tables tbl ON dc.parent_object_id = tbl.object_id " . "WHERE tbl.name = 'userlist';" . "EXEC sp_executesql @sql" ); } /** * @expectedException Doctrine\DBAL\DBALException */ public function testDoesNotSupportRegexp() { $this->_platform->getRegexpExpression(); } public function testGeneratesSqlSnippets() { $this->assertEquals('"', $this->_platform->getIdentifierQuoteCharacter(), 'Identifier quote character is not correct'); $this->assertEquals('(column1 + column2 + column3)', $this->_platform->getConcatExpression('column1', 'column2', 'column3'), 'Concatenation expression is not correct'); } public function testGeneratesTransactionsCommands() { $this->assertEquals( 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', $this->_platform->getSetTransactionIsolationSQL(\Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED) ); $this->assertEquals( 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', $this->_platform->getSetTransactionIsolationSQL(\Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED) ); $this->assertEquals( 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', $this->_platform->getSetTransactionIsolationSQL(\Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ) ); $this->assertEquals( 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', $this->_platform->getSetTransactionIsolationSQL(\Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE) ); } public function testGeneratesDDLSnippets() { $dropDatabaseExpectation = 'DROP DATABASE foobar'; $this->assertEquals('SELECT * FROM SYS.DATABASES', $this->_platform->getListDatabasesSQL()); $this->assertEquals('CREATE DATABASE foobar', $this->_platform->getCreateDatabaseSQL('foobar')); $this->assertEquals($dropDatabaseExpectation, $this->_platform->getDropDatabaseSQL('foobar')); $this->assertEquals('DROP TABLE foobar', $this->_platform->getDropTableSQL('foobar')); } public function testGeneratesTypeDeclarationForIntegers() { $this->assertEquals( 'INT', $this->_platform->getIntegerTypeDeclarationSQL(array()) ); $this->assertEquals( 'INT IDENTITY', $this->_platform->getIntegerTypeDeclarationSQL(array('autoincrement' => true) )); $this->assertEquals( 'INT IDENTITY', $this->_platform->getIntegerTypeDeclarationSQL( array('autoincrement' => true, 'primary' => true) )); } public function testGeneratesTypeDeclarationsForStrings() { $this->assertEquals( 'NCHAR(10)', $this->_platform->getVarcharTypeDeclarationSQL( array('length' => 10, 'fixed' => true) )); $this->assertEquals( 'NVARCHAR(50)', $this->_platform->getVarcharTypeDeclarationSQL(array('length' => 50)), 'Variable string declaration is not correct' ); $this->assertEquals( 'NVARCHAR(255)', $this->_platform->getVarcharTypeDeclarationSQL(array()), 'Long string declaration is not correct' ); } public function testPrefersIdentityColumns() { $this->assertTrue($this->_platform->prefersIdentityColumns()); } public function testSupportsIdentityColumns() { $this->assertTrue($this->_platform->supportsIdentityColumns()); } public function testSupportsSchemas() { $this->assertTrue($this->_platform->supportsSchemas()); } public function testDoesNotSupportSavePoints() { $this->assertTrue($this->_platform->supportsSavepoints()); } public function getGenerateIndexSql() { return 'CREATE INDEX my_idx ON mytable (user_name, last_login)'; } public function getGenerateUniqueIndexSql() { return 'CREATE UNIQUE INDEX index_name ON test (test, test2) WHERE test IS NOT NULL AND test2 IS NOT NULL'; } public function getGenerateForeignKeySql() { return 'ALTER TABLE test ADD FOREIGN KEY (fk_name_id) REFERENCES other_table (id)'; } public function testModifyLimitQuery() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10, 0); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM user) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithEmptyOffset() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM user) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithOffset() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10, 5); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY username DESC) AS doctrine_rownum FROM user) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql); } public function testModifyLimitQueryWithAscOrderBy() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username ASC', 10); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY username ASC) AS doctrine_rownum FROM user) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithDescOrderBy() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY username DESC) AS doctrine_rownum FROM user) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithMultipleOrderBy() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC, usereamil ASC', 10); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY username DESC, usereamil ASC) AS doctrine_rownum FROM user) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithSubSelect() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname) dctrn_result', 10); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithSubSelectAndOrder() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname ORDER BY u.name DESC) dctrn_result', 10); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY u.name DESC) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } public function testModifyLimitQueryWithSubSelectAndMultipleOrder() { $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id as uid, u.name as uname ORDER BY u.name DESC, id ASC) dctrn_result', 10, 5); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY u.name DESC, id ASC) AS doctrine_rownum FROM (SELECT u.id as uid, u.name as uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM (SELECT u.id uid, u.name uname ORDER BY u.name DESC, id ASC) dctrn_result', 10, 5); $this->assertEquals('SELECT * FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY u.name DESC, id ASC) AS doctrine_rownum FROM (SELECT u.id uid, u.name uname) dctrn_result) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15', $sql); } public function testModifyLimitQueryWithFromColumnNames() { $sql = $this->_platform->modifyLimitQuery('SELECT a.fromFoo, fromBar FROM foo', 10); $this->assertEquals('SELECT * FROM (SELECT a.fromFoo, fromBar, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS doctrine_rownum FROM foo) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 1 AND 10', $sql); } /** * @group DDC-2470 */ public function testModifyLimitQueryWithOrderByClause() { $sql = 'SELECT m0_.NOMBRE AS NOMBRE0, m0_.FECHAINICIO AS FECHAINICIO1, m0_.FECHAFIN AS FECHAFIN2 FROM MEDICION m0_ WITH (NOLOCK) INNER JOIN ESTUDIO e1_ ON m0_.ESTUDIO_ID = e1_.ID INNER JOIN CLIENTE c2_ ON e1_.CLIENTE_ID = c2_.ID INNER JOIN USUARIO u3_ ON c2_.ID = u3_.CLIENTE_ID WHERE u3_.ID = ? ORDER BY m0_.FECHAINICIO DESC'; $expected = 'SELECT * FROM (SELECT m0_.NOMBRE AS NOMBRE0, m0_.FECHAINICIO AS FECHAINICIO1, m0_.FECHAFIN AS FECHAFIN2, ROW_NUMBER() OVER (ORDER BY m0_.FECHAINICIO DESC) AS doctrine_rownum FROM MEDICION m0_ WITH (NOLOCK) INNER JOIN ESTUDIO e1_ ON m0_.ESTUDIO_ID = e1_.ID INNER JOIN CLIENTE c2_ ON e1_.CLIENTE_ID = c2_.ID INNER JOIN USUARIO u3_ ON c2_.ID = u3_.CLIENTE_ID WHERE u3_.ID = ?) AS doctrine_tbl WHERE doctrine_rownum BETWEEN 6 AND 15'; $actual = $this->_platform->modifyLimitQuery($sql, 10, 5); $this->assertEquals($expected, $actual); } /** * @group DDC-1360 */ public function testQuoteIdentifier() { $this->assertEquals('[fo][o]', $this->_platform->quoteIdentifier('fo]o')); $this->assertEquals('[test]', $this->_platform->quoteIdentifier('test')); $this->assertEquals('[test].[test]', $this->_platform->quoteIdentifier('test.test')); } /** * @group DDC-1360 */ public function testQuoteSingleIdentifier() { $this->assertEquals('[fo][o]', $this->_platform->quoteSingleIdentifier('fo]o')); $this->assertEquals('[test]', $this->_platform->quoteSingleIdentifier('test')); $this->assertEquals('[test.test]', $this->_platform->quoteSingleIdentifier('test.test')); } /** * @group DBAL-220 */ public function testCreateClusteredIndex() { $idx = new \Doctrine\DBAL\Schema\Index('idx', array('id')); $idx->addFlag('clustered'); $this->assertEquals('CREATE CLUSTERED INDEX idx ON tbl (id)', $this->_platform->getCreateIndexSQL($idx, 'tbl')); } /** * @group DBAL-220 */ public function testCreateNonClusteredPrimaryKeyInTable() { $table = new \Doctrine\DBAL\Schema\Table("tbl"); $table->addColumn("id", "integer"); $table->setPrimaryKey(Array("id")); $table->getIndex('primary')->addFlag('nonclustered'); $this->assertEquals(array('CREATE TABLE tbl (id INT NOT NULL, PRIMARY KEY NONCLUSTERED (id))'), $this->_platform->getCreateTableSQL($table)); } /** * @group DBAL-220 */ public function testCreateNonClusteredPrimaryKey() { $idx = new \Doctrine\DBAL\Schema\Index('idx', array('id'), false, true); $idx->addFlag('nonclustered'); $this->assertEquals('ALTER TABLE tbl ADD PRIMARY KEY NONCLUSTERED (id)', $this->_platform->getCreatePrimaryKeySQL($idx, 'tbl')); } public function testAlterAddPrimaryKey() { $idx = new \Doctrine\DBAL\Schema\Index('idx', array('id'), false, true); $this->assertEquals('ALTER TABLE tbl ADD PRIMARY KEY (id)', $this->_platform->getCreateIndexSQL($idx, 'tbl')); } protected function getQuotedColumnInPrimaryKeySQL() { return array( 'CREATE TABLE [quoted] ([create] NVARCHAR(255) NOT NULL, PRIMARY KEY ([create]))', ); } protected function getQuotedColumnInIndexSQL() { return array( 'CREATE TABLE [quoted] ([create] NVARCHAR(255) NOT NULL)', 'CREATE INDEX IDX_22660D028FD6E0FB ON [quoted] ([create])', ); } protected function getQuotedColumnInForeignKeySQL() { return array( 'CREATE TABLE [quoted] ([create] NVARCHAR(255) NOT NULL, foo NVARCHAR(255) NOT NULL)', 'ALTER TABLE [quoted] ADD CONSTRAINT FK_22660D028FD6E0FB8C736521 FOREIGN KEY ([create], foo) REFERENCES [foreign] ([create], bar)', ); } }