Unverified Commit 61c5e4e3 authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #3020 from stlrnz/mssql-schema

Improve handling of schemas in SQL Server >= 2008
parents 179ff5d9 3f0fd621
......@@ -27,6 +27,16 @@ namespace Doctrine\DBAL\Platforms;
*/
class SQLServer2008Platform extends SQLServer2005Platform
{
/**
* {@inheritDoc}
*/
public function getListTablesSQL()
{
// "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams
// Category 2 must be ignored as it is "MS SQL Server 'pseudo-system' object[s]" for replication
return "SELECT name, SCHEMA_NAME (uid) AS schema_name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' AND category != 2 ORDER BY name";
}
/**
* {@inheritDoc}
*/
......
......@@ -28,8 +28,10 @@ use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types;
use function explode;
use function implode;
use function sprintf;
use function strpos;
/**
* The SQLServerPlatform provides the behavior, features and SQL dialect of the
......@@ -330,13 +332,22 @@ class SQLServerPlatform extends AbstractPlatform
*/
protected function getCreateColumnCommentSQL($tableName, $columnName, $comment)
{
if (strpos($tableName, '.') !== false) {
[$schemaSQL, $tableSQL] = explode('.', $tableName);
$schemaSQL = $this->quoteStringLiteral($schemaSQL);
$tableSQL = $this->quoteStringLiteral($tableSQL);
} else {
$schemaSQL = "'dbo'";
$tableSQL = $this->quoteStringLiteral($tableName);
}
return $this->getAddExtendedPropertySQL(
'MS_Description',
$comment,
'SCHEMA',
'dbo',
$schemaSQL,
'TABLE',
$tableName,
$tableSQL,
'COLUMN',
$columnName
);
......@@ -678,13 +689,22 @@ class SQLServerPlatform extends AbstractPlatform
*/
protected function getAlterColumnCommentSQL($tableName, $columnName, $comment)
{
if (strpos($tableName, '.') !== false) {
[$schemaSQL, $tableSQL] = explode('.', $tableName);
$schemaSQL = $this->quoteStringLiteral($schemaSQL);
$tableSQL = $this->quoteStringLiteral($tableSQL);
} else {
$schemaSQL = "'dbo'";
$tableSQL = $this->quoteStringLiteral($tableName);
}
return $this->getUpdateExtendedPropertySQL(
'MS_Description',
$comment,
'SCHEMA',
'dbo',
$schemaSQL,
'TABLE',
$tableName,
$tableSQL,
'COLUMN',
$columnName
);
......@@ -708,12 +728,21 @@ class SQLServerPlatform extends AbstractPlatform
*/
protected function getDropColumnCommentSQL($tableName, $columnName)
{
if (strpos($tableName, '.') !== false) {
[$schemaSQL, $tableSQL] = explode('.', $tableName);
$schemaSQL = $this->quoteStringLiteral($schemaSQL);
$tableSQL = $this->quoteStringLiteral($tableSQL);
} else {
$schemaSQL = "'dbo'";
$tableSQL = $this->quoteStringLiteral($tableName);
}
return $this->getDropExtendedPropertySQL(
'MS_Description',
'SCHEMA',
'dbo',
$schemaSQL,
'TABLE',
$tableName,
$tableSQL,
'COLUMN',
$columnName
);
......
......@@ -198,6 +198,10 @@ class SQLServerSchemaManager extends AbstractSchemaManager
*/
protected function _getPortableTableDefinition($table)
{
if (isset($table['schema_name']) && $table['schema_name'] !== 'dbo') {
return $table['schema_name'] . '.' . $table['name'];
}
return $table['name'];
}
......
......@@ -3,11 +3,13 @@
namespace Doctrine\Tests\DBAL\Functional\Schema;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnDiff;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\SchemaDiff;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
......@@ -42,6 +44,23 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->_sm = $this->_conn->getSchemaManager();
}
protected function tearDown()
{
parent::tearDown();
$this->_sm->tryMethod('dropTable', 'testschema.my_table_in_namespace');
//TODO: SchemaDiff does not drop removed namespaces?
try {
//sql server versions below 2016 do not support 'IF EXISTS' so we have to catch the exception here
$this->_conn->exec('DROP SCHEMA testschema');
} catch (DBALException $e) {
return;
}
}
/**
* @group DBAL-1220
*/
......@@ -570,6 +589,31 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
}
}
public function testTableInNamespace()
{
if (! $this->_sm->getDatabasePlatform()->supportsSchemas()) {
$this->markTestSkipped('Schema definition is not supported by this platform.');
}
//create schema
$diff = new SchemaDiff();
$diff->newNamespaces[] = 'testschema';
foreach ($diff->toSql($this->_sm->getDatabasePlatform()) as $sql) {
$this->_conn->exec($sql);
}
//test if table is create in namespace
$this->createTestTable('testschema.my_table_in_namespace');
self::assertContains('testschema.my_table_in_namespace', $this->_sm->listTableNames());
//tables without namespace should be created in default namespace
//default namespaces are ignored in table listings
$this->createTestTable('my_table_not_in_namespace');
self::assertContains('my_table_not_in_namespace', $this->_sm->listTableNames());
}
public function testCreateAndListViews()
{
if (!$this->_sm->getDatabasePlatform()->supportsViews()) {
......
......@@ -577,6 +577,63 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
self::assertEquals('CREATE SCHEMA ' . $schemaName, $sql);
}
public function testCreateTableWithSchemaColumnComments()
{
$table = new Table('testschema.test');
$table->addColumn('id', 'integer', ['comment' => 'This is a comment']);
$table->setPrimaryKey(['id']);
$expectedSql = [
'CREATE TABLE testschema.test (id INT NOT NULL, PRIMARY KEY (id))',
"EXEC sp_addextendedproperty N'MS_Description', N'This is a comment', N'SCHEMA', 'testschema', N'TABLE', 'test', N'COLUMN', id",
];
self::assertEquals($expectedSql, $this->_platform->getCreateTableSQL($table));
}
public function testAlterTableWithSchemaColumnComments()
{
$tableDiff = new TableDiff('testschema.mytable');
$tableDiff->addedColumns['quota'] = new Column('quota', Type::getType('integer'), ['comment' => 'A comment']);
$expectedSql = [
'ALTER TABLE testschema.mytable ADD quota INT NOT NULL',
"EXEC sp_addextendedproperty N'MS_Description', N'A comment', N'SCHEMA', 'testschema', N'TABLE', 'mytable', N'COLUMN', quota",
];
self::assertEquals($expectedSql, $this->_platform->getAlterTableSQL($tableDiff));
}
public function testAlterTableWithSchemaDropColumnComments()
{
$tableDiff = new TableDiff('testschema.mytable');
$tableDiff->changedColumns['quota'] = new ColumnDiff(
'quota',
new Column('quota', Type::getType('integer'), []),
['comment'],
new Column('quota', Type::getType('integer'), ['comment' => 'A comment'])
);
$expectedSql = ["EXEC sp_dropextendedproperty N'MS_Description', N'SCHEMA', 'testschema', N'TABLE', 'mytable', N'COLUMN', quota"];
self::assertEquals($expectedSql, $this->_platform->getAlterTableSQL($tableDiff));
}
public function testAlterTableWithSchemaUpdateColumnComments()
{
$tableDiff = new TableDiff('testschema.mytable');
$tableDiff->changedColumns['quota'] = new ColumnDiff(
'quota',
new Column('quota', Type::getType('integer'), ['comment' => 'B comment']),
['comment'],
new Column('quota', Type::getType('integer'), ['comment' => 'A comment'])
);
$expectedSql = ["EXEC sp_updateextendedproperty N'MS_Description', N'B comment', N'SCHEMA', 'testschema', N'TABLE', 'mytable', N'COLUMN', quota"];
self::assertEquals($expectedSql, $this->_platform->getAlterTableSQL($tableDiff));
}
/**
* @group DBAL-543
*/
......@@ -584,7 +641,7 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
{
return array(
"CREATE TABLE test (id INT NOT NULL, PRIMARY KEY (id))",
"EXEC sp_addextendedproperty N'MS_Description', N'This is a comment', N'SCHEMA', dbo, N'TABLE', test, N'COLUMN', id",
"EXEC sp_addextendedproperty N'MS_Description', N'This is a comment', N'SCHEMA', 'dbo', N'TABLE', 'test', N'COLUMN', id",
);
}
......@@ -595,7 +652,7 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
{
return array(
"ALTER TABLE mytable ADD quota INT NOT NULL",
"EXEC sp_addextendedproperty N'MS_Description', N'A comment', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', quota",
"EXEC sp_addextendedproperty N'MS_Description', N'A comment', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', quota",
// todo
//"EXEC sp_addextendedproperty N'MS_Description', N'B comment', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', baz",
);
......@@ -608,7 +665,7 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
{
return array(
"CREATE TABLE test (id INT NOT NULL, data VARCHAR(MAX) NOT NULL, PRIMARY KEY (id))",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:array)', N'SCHEMA', dbo, N'TABLE', test, N'COLUMN', data",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:array)', N'SCHEMA', 'dbo', N'TABLE', 'test', N'COLUMN', data",
);
}
......@@ -636,15 +693,15 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
self::assertEquals(
array(
"CREATE TABLE mytable (id INT IDENTITY NOT NULL, comment_null INT NOT NULL, comment_false INT NOT NULL, comment_empty_string INT NOT NULL, comment_integer_0 INT NOT NULL, comment_float_0 INT NOT NULL, comment_string_0 INT NOT NULL, comment INT NOT NULL, [comment_quoted] INT NOT NULL, [create] INT NOT NULL, commented_type VARCHAR(MAX) NOT NULL, commented_type_with_comment VARCHAR(MAX) NOT NULL, comment_with_string_literal_char NVARCHAR(255) NOT NULL, PRIMARY KEY (id))",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_integer_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_float_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_string_0",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine 0wnz you!', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine 0wnz comments for explicitly quoted columns!', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', [comment_quoted]",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine 0wnz comments for reserved keyword columns!', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', [create]",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', commented_type",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine array type.(DC2Type:array)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', commented_type_with_comment",
"EXEC sp_addextendedproperty N'MS_Description', N'O''Reilly', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_with_string_literal_char",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_integer_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_float_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_string_0",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine 0wnz you!', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine 0wnz comments for explicitly quoted columns!', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', [comment_quoted]",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine 0wnz comments for reserved keyword columns!', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', [create]",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', commented_type",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine array type.(DC2Type:array)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', commented_type_with_comment",
"EXEC sp_addextendedproperty N'MS_Description', N'O''Reilly', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_with_string_literal_char",
),
$this->_platform->getCreateTableSQL($table)
);
......@@ -807,27 +864,27 @@ abstract class AbstractSQLServerPlatformTestCase extends AbstractPlatformTestCas
"ALTER TABLE mytable ALTER COLUMN commented_type INT NOT NULL",
// Added columns.
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_comment_integer_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_comment_float_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_comment_string_0",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_comment",
"EXEC sp_addextendedproperty N'MS_Description', N'rulez', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', [added_comment_quoted]",
"EXEC sp_addextendedproperty N'MS_Description', N'666', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', [select]",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_commented_type",
"EXEC sp_addextendedproperty N'MS_Description', N'666(DC2Type:array)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_commented_type_with_comment",
"EXEC sp_addextendedproperty N'MS_Description', N'''''', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', added_comment_with_string_literal_char",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_comment_integer_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_comment_float_0",
"EXEC sp_addextendedproperty N'MS_Description', N'0', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_comment_string_0",
"EXEC sp_addextendedproperty N'MS_Description', N'Doctrine', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_comment",
"EXEC sp_addextendedproperty N'MS_Description', N'rulez', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', [added_comment_quoted]",
"EXEC sp_addextendedproperty N'MS_Description', N'666', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', [select]",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_commented_type",
"EXEC sp_addextendedproperty N'MS_Description', N'666(DC2Type:array)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_commented_type_with_comment",
"EXEC sp_addextendedproperty N'MS_Description', N'''''', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', added_comment_with_string_literal_char",
// Changed columns.
"EXEC sp_addextendedproperty N'MS_Description', N'primary', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', id",
"EXEC sp_addextendedproperty N'MS_Description', N'false', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_false",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_empty_string",
"EXEC sp_dropextendedproperty N'MS_Description', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_string_0",
"EXEC sp_dropextendedproperty N'MS_Description', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment",
"EXEC sp_updateextendedproperty N'MS_Description', N'Doctrine array.(DC2Type:array)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', [comment_quoted]",
"EXEC sp_updateextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', [create]",
"EXEC sp_updateextendedproperty N'MS_Description', N'foo', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', commented_type",
"EXEC sp_updateextendedproperty N'MS_Description', N'(DC2Type:array)', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', commented_type_with_comment",
"EXEC sp_updateextendedproperty N'MS_Description', N'''', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', comment_with_string_literal_char",
"EXEC sp_addextendedproperty N'MS_Description', N'primary', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', id",
"EXEC sp_addextendedproperty N'MS_Description', N'false', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_false",
"EXEC sp_addextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_empty_string",
"EXEC sp_dropextendedproperty N'MS_Description', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_string_0",
"EXEC sp_dropextendedproperty N'MS_Description', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment",
"EXEC sp_updateextendedproperty N'MS_Description', N'Doctrine array.(DC2Type:array)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', [comment_quoted]",
"EXEC sp_updateextendedproperty N'MS_Description', N'(DC2Type:object)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', [create]",
"EXEC sp_updateextendedproperty N'MS_Description', N'foo', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', commented_type",
"EXEC sp_updateextendedproperty N'MS_Description', N'(DC2Type:array)', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', commented_type_with_comment",
"EXEC sp_updateextendedproperty N'MS_Description', N'''', N'SCHEMA', 'dbo', N'TABLE', 'mytable', N'COLUMN', comment_with_string_literal_char",
),
$this->_platform->getAlterTableSQL($tableDiff)
);
......
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