Commit 84ca5ac4 authored by Benjamin Eberlei's avatar Benjamin Eberlei

Merge branch 'sqlsrv'

parents 173d7ec1 8b29ffe5
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -33,6 +31,7 @@ namespace Doctrine\DBAL\Schema; ...@@ -33,6 +31,7 @@ namespace Doctrine\DBAL\Schema;
*/ */
class MsSqlSchemaManager extends AbstractSchemaManager class MsSqlSchemaManager extends AbstractSchemaManager
{ {
/** /**
* @override * @override
*/ */
...@@ -49,120 +48,50 @@ class MsSqlSchemaManager extends AbstractSchemaManager ...@@ -49,120 +48,50 @@ class MsSqlSchemaManager extends AbstractSchemaManager
$type = array(); $type = array();
$unsigned = $fixed = null; $unsigned = $fixed = null;
if ( ! isset($tableColumn['name'])) { if (!isset($tableColumn['name'])) {
$tableColumn['name'] = ''; $tableColumn['name'] = '';
} }
// Map db type to Doctrine mapping type $default = $tableColumn['COLUMN_DEF'];
switch ($dbType) {
case 'tinyint': while ($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) {
$type = 'boolean'; $default = $default2;
break; }
case 'smallint':
$type = 'smallint'; $length = (int) $tableColumn['LENGTH'];
break;
case 'mediumint': $type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = 'integer'; switch ($type) {
break;
case 'int':
case 'integer':
$type = 'integer';
break;
case 'bigint':
$type = 'bigint';
break;
case 'tinytext':
case 'mediumtext':
case 'longtext':
case 'text':
$type = 'text';
$fixed = false;
break;
case 'varchar':
$fixed = false;
case 'string':
case 'char': case 'char':
$type = 'string';
if ($tableColumn['LENGTH'] == '1') { if ($tableColumn['LENGTH'] == '1') {
$type = 'boolean'; $type = 'boolean';
if (preg_match('/^(is|has)/', $tableColumn['name'])) { if (preg_match('/^(is|has)/', $tableColumn['name'])) {
$type = array_reverse($type); $type = array_reverse($type);
} }
} else if (strstr($dbType, 'text')) {
$type = 'text';
if ($decimal == 'binary') {
$type = 'blob';
}
} }
if ($fixed !== false) {
$fixed = true; $fixed = true;
}
break; break;
case 'set': case 'text':
$fixed = false; $fixed = false;
$type = 'text';
$type = 'integer'; //FIXME:???
break;
case 'date':
$type = 'date';
break;
case 'datetime':
case 'datetime2':
case 'timestamp':
case 'smalldatettime':
$type = 'datetime';
break;
case 'time':
$type = 'time';
break;
case 'float':
case 'double':
case 'real':
case 'numeric':
case 'decimal':
$type = 'decimal';
break;
case 'tinyblob':
case 'mediumblob':
case 'longblob':
case 'blob':
case 'binary':
case 'varbinary':
$type = 'blob';
break; break;
case 'year':
$type = 'integer';
$type = 'date';
break;
case 'geometry':
case 'geometrycollection':
case 'point':
case 'multipoint':
case 'linestring':
case 'multilinestring':
case 'polygon':
case 'multipolygon':
$type = 'blob';
break;
default:
$type = 'string';
} }
switch ($dbType) {
$default = $tableColumn['COLUMN_DEF']; case 'nchar':
case 'nvarchar':
while($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) { case 'ntext':
$default = $default2; // Unicode data requires 2 bytes per character
$length = $length / 2;
break;
} }
$options = array( $options = array(
'length' => ((int) $tableColumn['LENGTH'] == 0 || !in_array($type, array('text', 'string'))) ? null : (int) $tableColumn['LENGTH'], 'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length,
'unsigned' => (bool)$unsigned, 'unsigned' => (bool) $unsigned,
'fixed' => (bool)$fixed, 'fixed' => (bool) $fixed,
'default' => $default !== 'NULL' ? $default : null, 'default' => $default !== 'NULL' ? $default : null,
'notnull' => (bool) ($tableColumn['IS_NULLABLE'] != 'YES'), 'notnull' => (bool) ($tableColumn['IS_NULLABLE'] != 'YES'),
'scale' => $tableColumn['SCALE'], 'scale' => $tableColumn['SCALE'],
'precision' => $tableColumn['PRECISION'], 'precision' => $tableColumn['PRECISION'],
'unique' => false, // @todo
'autoincrement' => $autoincrement, 'autoincrement' => $autoincrement,
); );
...@@ -175,9 +104,9 @@ class MsSqlSchemaManager extends AbstractSchemaManager ...@@ -175,9 +104,9 @@ class MsSqlSchemaManager extends AbstractSchemaManager
protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null)
{ {
$result = array(); $result = array();
foreach($tableIndexRows AS $tableIndex) { foreach ($tableIndexRows AS $tableIndex) {
$indexName = $keyName = $tableIndex['index_name']; $indexName = $keyName = $tableIndex['index_name'];
if(strpos($tableIndex['index_description'], 'primary key') !== false) { if (strpos($tableIndex['index_description'], 'primary key') !== false) {
$keyName = 'primary'; $keyName = 'primary';
} }
$keyName = strtolower($keyName); $keyName = strtolower($keyName);
...@@ -191,7 +120,7 @@ class MsSqlSchemaManager extends AbstractSchemaManager ...@@ -191,7 +120,7 @@ class MsSqlSchemaManager extends AbstractSchemaManager
} }
$indexes = array(); $indexes = array();
foreach($result AS $indexKey => $data) { foreach ($result AS $indexKey => $data) {
$indexes[$indexKey] = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); $indexes[$indexKey] = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']);
} }
...@@ -204,9 +133,9 @@ class MsSqlSchemaManager extends AbstractSchemaManager ...@@ -204,9 +133,9 @@ class MsSqlSchemaManager extends AbstractSchemaManager
public function _getPortableTableForeignKeyDefinition($tableForeignKey) public function _getPortableTableForeignKeyDefinition($tableForeignKey)
{ {
return new ForeignKeyConstraint( return new ForeignKeyConstraint(
(array)$tableForeignKey['ColumnName'], (array) $tableForeignKey['ColumnName'],
$tableForeignKey['ReferenceTableName'], $tableForeignKey['ReferenceTableName'],
(array)$tableForeignKey['ReferenceColumnName'], (array) $tableForeignKey['ReferenceColumnName'],
$tableForeignKey['ForeignKey'], $tableForeignKey['ForeignKey'],
array( array(
'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']), 'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']),
...@@ -239,4 +168,5 @@ class MsSqlSchemaManager extends AbstractSchemaManager ...@@ -239,4 +168,5 @@ class MsSqlSchemaManager extends AbstractSchemaManager
// @todo // @todo
return new View($view['name'], null); return new View($view['name'], null);
} }
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ require_once __DIR__ . '/../../TestInit.php'; ...@@ -9,6 +9,7 @@ require_once __DIR__ . '/../../TestInit.php';
class MsSqlPlatformTest extends AbstractPlatformTestCase class MsSqlPlatformTest extends AbstractPlatformTestCase
{ {
public function createPlatform() public function createPlatform()
{ {
return new MsSqlPlatform; return new MsSqlPlatform;
...@@ -16,13 +17,13 @@ class MsSqlPlatformTest extends AbstractPlatformTestCase ...@@ -16,13 +17,13 @@ class MsSqlPlatformTest extends AbstractPlatformTestCase
public function getGenerateTableSql() public function getGenerateTableSql()
{ {
return 'CREATE TABLE test (id INT IDENTITY NOT NULL, test VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))'; return 'CREATE TABLE test (id INT IDENTITY NOT NULL, test NVARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))';
} }
public function getGenerateTableWithMultiColumnUniqueIndexSql() public function getGenerateTableWithMultiColumnUniqueIndexSql()
{ {
return array( return array(
'CREATE TABLE test (foo VARCHAR(255) DEFAULT NULL, bar VARCHAR(255) DEFAULT NULL)', 'CREATE TABLE test (foo NVARCHAR(255) DEFAULT NULL, bar NVARCHAR(255) DEFAULT NULL)',
'CREATE UNIQUE INDEX test_foo_bar_uniq ON test (foo, bar)' 'CREATE UNIQUE INDEX test_foo_bar_uniq ON test (foo, bar)'
); );
} }
...@@ -33,7 +34,7 @@ class MsSqlPlatformTest extends AbstractPlatformTestCase ...@@ -33,7 +34,7 @@ class MsSqlPlatformTest extends AbstractPlatformTestCase
'ALTER TABLE mytable RENAME TO userlist', 'ALTER TABLE mytable RENAME TO userlist',
'ALTER TABLE mytable ADD quota INT DEFAULT NULL', 'ALTER TABLE mytable ADD quota INT DEFAULT NULL',
'ALTER TABLE mytable DROP COLUMN foo', 'ALTER TABLE mytable DROP COLUMN foo',
'ALTER TABLE mytable CHANGE bar baz VARCHAR(255) DEFAULT \'def\' NOT NULL', 'ALTER TABLE mytable CHANGE bar baz NVARCHAR(255) DEFAULT \'def\' NOT NULL',
); );
} }
...@@ -67,9 +68,6 @@ class MsSqlPlatformTest extends AbstractPlatformTestCase ...@@ -67,9 +68,6 @@ class MsSqlPlatformTest extends AbstractPlatformTestCase
public function testGeneratesDDLSnippets() public function testGeneratesDDLSnippets()
{ {
$dropDatabaseExpectation = <<<DDB $dropDatabaseExpectation = <<<DDB
ALTER DATABASE [foobar]
SET SINGLE_USER --or RESTRICTED_USER
WITH ROLLBACK IMMEDIATE;
DROP DATABASE foobar; DROP DATABASE foobar;
DDB; DDB;
...@@ -99,17 +97,17 @@ DDB; ...@@ -99,17 +97,17 @@ DDB;
public function testGeneratesTypeDeclarationsForStrings() public function testGeneratesTypeDeclarationsForStrings()
{ {
$this->assertEquals( $this->assertEquals(
'CHAR(10)', 'NCHAR(10)',
$this->_platform->getVarcharTypeDeclarationSQL( $this->_platform->getVarcharTypeDeclarationSQL(
array('length' => 10, 'fixed' => true) array('length' => 10, 'fixed' => true)
)); ));
$this->assertEquals( $this->assertEquals(
'VARCHAR(50)', 'NVARCHAR(50)',
$this->_platform->getVarcharTypeDeclarationSQL(array('length' => 50)), $this->_platform->getVarcharTypeDeclarationSQL(array('length' => 50)),
'Variable string declaration is not correct' 'Variable string declaration is not correct'
); );
$this->assertEquals( $this->assertEquals(
'TEXT', 'NTEXT',
$this->_platform->getVarcharTypeDeclarationSQL(array()), $this->_platform->getVarcharTypeDeclarationSQL(array()),
'Long string declaration is not correct' 'Long string declaration is not correct'
); );
...@@ -148,24 +146,31 @@ DDB; ...@@ -148,24 +146,31 @@ DDB;
public function testModifyLimitQuery() public function testModifyLimitQuery()
{ {
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10, 0); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10, 0);
$this->assertEquals('SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 * FROM user) AS inner_tbl) AS outer_tbl', $sql); $this->assertEquals('SELECT TOP 10 * FROM user', $sql);
} }
public function testModifyLimitQueryWithEmptyOffset() public function testModifyLimitQueryWithEmptyOffset()
{ {
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user', 10);
$this->assertEquals('SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 * FROM user) AS inner_tbl) AS outer_tbl', $sql); $this->assertEquals('SELECT TOP 10 * FROM user', $sql);
}
public function testModifyLimitQueryWithOffset()
{
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10, 5);
$this->assertEquals('WITH outer_tbl AS (SELECT ROW_NUMBER() OVER (ORDER BY username DESC) AS "doctrine_rownum", * FROM (SELECT * FROM user) AS inner_tbl) SELECT * FROM outer_tbl WHERE "doctrine_rownum" BETWEEN 6 AND 15', $sql);
} }
public function testModifyLimitQueryWithAscOrderBy() public function testModifyLimitQueryWithAscOrderBy()
{ {
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username ASC', 10); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username ASC', 10);
$this->assertEquals('SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 * FROM user ORDER BY username ASC) AS inner_tbl ORDER BY inner_tbl.u DESC) AS outer_tbl ORDER BY outer_tbl.u ASC', $sql); $this->assertEquals('SELECT TOP 10 * FROM user ORDER BY username ASC', $sql);
} }
public function testModifyLimitQueryWithDescOrderBy() public function testModifyLimitQueryWithDescOrderBy()
{ {
$sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10); $sql = $this->_platform->modifyLimitQuery('SELECT * FROM user ORDER BY username DESC', 10);
$this->assertEquals('SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 * FROM user ORDER BY username DESC) AS inner_tbl ORDER BY inner_tbl.u ASC) AS outer_tbl ORDER BY outer_tbl.u DESC', $sql); $this->assertEquals('SELECT TOP 10 * FROM user ORDER BY username DESC', $sql);
} }
} }
\ No newline at end of file
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