Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of schemas in SQL Server >= 2008 #3020

Merged
merged 1 commit into from
Mar 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/Doctrine/DBAL/Platforms/SQLServer2008Platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@
*/
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}
*/
Expand Down
41 changes: 35 additions & 6 deletions lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@
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
Expand Down Expand Up @@ -330,13 +332,22 @@ public function getCreatePrimaryKeySQL(Index $index, $table)
*/
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
);
Expand Down Expand Up @@ -678,13 +689,22 @@ private function alterColumnRequiresDropDefaultConstraint(ColumnDiff $columnDiff
*/
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
);
Expand All @@ -708,12 +728,21 @@ protected function getAlterColumnCommentSQL($tableName, $columnName, $comment)
*/
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
);
Expand Down
4 changes: 4 additions & 0 deletions lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
*/
protected function _getPortableTableDefinition($table)
{
if (isset($table['schema_name']) && $table['schema_name'] !== 'dbo') {
return $table['schema_name'] . '.' . $table['name'];
}

return $table['name'];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -42,6 +44,23 @@ protected function setUp()
$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?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need adressing before merge?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it’s OK.

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
*/
Expand Down Expand Up @@ -570,6 +589,31 @@ public function testAlterTableScenario()
}
}


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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -577,14 +577,71 @@ public function testGetCreateSchemaSQL()
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
*/
public function getCreateTableColumnCommentsSQL()
{
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",
);
}

Expand All @@ -595,7 +652,7 @@ public function getAlterTableColumnCommentsSQL()
{
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",
);
Expand All @@ -608,7 +665,7 @@ public function getCreateTableColumnTypeCommentsSQL()
{
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",
);
}

Expand Down Expand Up @@ -636,15 +693,15 @@ public function testGeneratesCreateTableSQLWithColumnComments()
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)
);
Expand Down Expand Up @@ -807,27 +864,27 @@ public function testGeneratesAlterTableSQLWithColumnComments()
"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)
);
Expand Down