Commit f2e6fa86 authored by Steve Müller's avatar Steve Müller

add support for column comments in SQL Server

parent 25a1cced
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
namespace Doctrine\DBAL\Platforms; namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\LockMode; use Doctrine\DBAL\LockMode;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\DBALException; use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\ForeignKeyConstraint;
...@@ -234,21 +235,25 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -234,21 +235,25 @@ class SQLServerPlatform extends AbstractPlatform
protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{ {
$defaultConstraintsSql = array(); $defaultConstraintsSql = array();
$commentsSql = array();
// @todo does other code breaks because of this? // @todo does other code breaks because of this?
// force primary keys to be not null // force primary keys to be not null
foreach ($columns as &$column) { foreach ($columns as &$column) {
/** @var $column \Doctrine\DBAL\Schema\Column */
if (isset($column['primary']) && $column['primary']) { if (isset($column['primary']) && $column['primary']) {
$column['notnull'] = true; $column['notnull'] = true;
} }
/** // Build default constraints SQL statements.
* Build default constraints SQL statements
*/
if ( ! empty($column['default']) || is_numeric($column['default'])) { if ( ! empty($column['default']) || is_numeric($column['default'])) {
$defaultConstraintsSql[] = 'ALTER TABLE ' . $tableName . $defaultConstraintsSql[] = 'ALTER TABLE ' . $tableName .
' ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $column); ' ADD' . $this->getDefaultConstraintDeclarationSQL($tableName, $column);
} }
if ( ! empty($column['comment']) || is_numeric($column['comment'])) {
$commentsSql[] = $this->getCreateColumnCommentSQL($tableName, $column['name'], $column['comment']);
}
} }
$columnListSql = $this->getColumnDeclarationListSQL($columns); $columnListSql = $this->getColumnDeclarationListSQL($columns);
...@@ -289,7 +294,7 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -289,7 +294,7 @@ class SQLServerPlatform extends AbstractPlatform
} }
} }
return array_merge($sql, $defaultConstraintsSql); return array_merge($sql, $commentsSql, $defaultConstraintsSql);
} }
/** /**
...@@ -304,6 +309,37 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -304,6 +309,37 @@ class SQLServerPlatform extends AbstractPlatform
return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')'; return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index->getQuotedColumns($this)) . ')';
} }
/**
* Returns the SQL statement for creating a column comment.
*
* SQL Server does not support native column comments,
* therefore the extended properties functionality is used
* as a workaround to store them.
* The property name used to store column comments is "MS_Description"
* which provides compatibility with SQL Server Management Studio,
* as column comments are stored in the same property there when
* specifying a column's "Description" attribute.
*
* @param string $tableName The quoted table name to which the column belongs.
* @param string $columnName The quoted column name to create the comment for.
* @param string $comment The column's comment.
*
* @return string
*/
protected function getCreateColumnCommentSQL($tableName, $columnName, $comment)
{
return $this->getAddExtendedPropertySQL(
'MS_Description',
$comment,
'SCHEMA',
'dbo',
'TABLE',
$tableName,
'COLUMN',
$columnName
);
}
/** /**
* Returns the SQL snippet for declaring a default constraint. * Returns the SQL snippet for declaring a default constraint.
* *
...@@ -399,6 +435,7 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -399,6 +435,7 @@ class SQLServerPlatform extends AbstractPlatform
$queryParts = array(); $queryParts = array();
$sql = array(); $sql = array();
$columnSql = array(); $columnSql = array();
$commentsSql = array();
/** @var \Doctrine\DBAL\Schema\Column $column */ /** @var \Doctrine\DBAL\Schema\Column $column */
foreach ($diff->addedColumns as $column) { foreach ($diff->addedColumns as $column) {
...@@ -413,6 +450,16 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -413,6 +450,16 @@ class SQLServerPlatform extends AbstractPlatform
$columnDef['name'] = $column->getQuotedName($this); $columnDef['name'] = $column->getQuotedName($this);
$queryParts[] = 'ADD' . $this->getDefaultConstraintDeclarationSQL($diff->name, $columnDef); $queryParts[] = 'ADD' . $this->getDefaultConstraintDeclarationSQL($diff->name, $columnDef);
} }
$comment = $this->getColumnComment($column);
if ( ! empty($comment) || is_numeric($comment)) {
$commentsSql[] = $this->getCreateColumnCommentSQL(
$diff->name,
$column->getQuotedName($this),
$comment
);
}
} }
foreach ($diff->removedColumns as $column) { foreach ($diff->removedColumns as $column) {
...@@ -429,9 +476,39 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -429,9 +476,39 @@ class SQLServerPlatform extends AbstractPlatform
continue; continue;
} }
$fromColumn = $columnDiff->fromColumn;
$fromColumnDefault = isset($fromColumn) ? $fromColumn->getDefault() : null;
$column = $columnDiff->column; $column = $columnDiff->column;
$comment = $this->getColumnComment($column);
$hasComment = ! empty ($comment) || is_numeric($comment);
if ($columnDiff->fromColumn instanceof Column) {
$fromComment = $this->getColumnComment($columnDiff->fromColumn);
$hasFromComment = ! empty ($fromComment) || is_numeric($fromComment);
if ($hasFromComment && $hasComment && $fromComment != $comment) {
$commentsSql[] = $this->getAlterColumnCommentSQL(
$diff->name,
$column->getQuotedName($this),
$comment
);
} elseif ($hasFromComment && ! $hasComment) {
$commentsSql[] = $this->getDropColumnCommentSQL($diff->name, $column->getQuotedName($this));
} elseif ($hasComment) {
$commentsSql[] = $this->getCreateColumnCommentSQL(
$diff->name,
$column->getQuotedName($this),
$comment
);
}
} else {
// todo: Original comment cannot be determined. What to do? Add, update, drop or skip?
}
// Do not add query part if only comment has changed.
if ($columnDiff->hasChanged('comment') && count($columnDiff->changedProperties) === 1) {
continue;
}
$fromColumnDefault = isset($columnDiff->fromColumn) ? $columnDiff->fromColumn->getDefault() : null;
$columnDef = $column->toArray(); $columnDef = $column->toArray();
$columnDefaultHasChanged = $columnDiff->hasChanged('default'); $columnDefaultHasChanged = $columnDiff->hasChanged('default');
...@@ -459,7 +536,9 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -459,7 +536,9 @@ class SQLServerPlatform extends AbstractPlatform
continue; continue;
} }
$sql[] = "sp_RENAME '". $diff->name. ".". $oldColumnName . "' , '".$column->getQuotedName($this)."', 'COLUMN'"; $sql[] = "sp_RENAME '". $diff->name. ".". $oldColumnName . "', '".$column->getQuotedName($this)."', 'COLUMN'";
// todo: Find a way how to implement column comment alteration statements for renamed columns.
$columnDef = $column->toArray(); $columnDef = $column->toArray();
...@@ -494,7 +573,7 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -494,7 +573,7 @@ class SQLServerPlatform extends AbstractPlatform
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
} }
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSql);
if ($diff->newName !== false) { if ($diff->newName !== false) {
$sql[] = "sp_RENAME '" . $diff->name . "', '" . $diff->newName . "'"; $sql[] = "sp_RENAME '" . $diff->name . "', '" . $diff->newName . "'";
...@@ -520,6 +599,163 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -520,6 +599,163 @@ class SQLServerPlatform extends AbstractPlatform
return array_merge($sql, $tableSql, $columnSql); return array_merge($sql, $tableSql, $columnSql);
} }
/**
* Returns the SQL statement for altering a column comment.
*
* SQL Server does not support native column comments,
* therefore the extended properties functionality is used
* as a workaround to store them.
* The property name used to store column comments is "MS_Description"
* which provides compatibility with SQL Server Management Studio,
* as column comments are stored in the same property there when
* specifying a column's "Description" attribute.
*
* @param string $tableName The quoted table name to which the column belongs.
* @param string $columnName The quoted column name to alter the comment for.
* @param string $comment The column's comment.
*
* @return string
*/
protected function getAlterColumnCommentSQL($tableName, $columnName, $comment)
{
return $this->getUpdateExtendedPropertySQL(
'MS_Description',
$comment,
'SCHEMA',
'dbo',
'TABLE',
$tableName,
'COLUMN',
$columnName
);
}
/**
* Returns the SQL statement for dropping a column comment.
*
* SQL Server does not support native column comments,
* therefore the extended properties functionality is used
* as a workaround to store them.
* The property name used to store column comments is "MS_Description"
* which provides compatibility with SQL Server Management Studio,
* as column comments are stored in the same property there when
* specifying a column's "Description" attribute.
*
* @param string $tableName The quoted table name to which the column belongs.
* @param string $columnName The quoted column name to drop the comment for.
*
* @return string
*/
protected function getDropColumnCommentSQL($tableName, $columnName)
{
return $this->getDropExtendedPropertySQL(
'MS_Description',
'SCHEMA',
'dbo',
'TABLE',
$tableName,
'COLUMN',
$columnName
);
}
/**
* Returns the SQL statement for adding an extended property to a database object.
*
* @param string $name The name of the property to add.
* @param string|null $value The value of the property to add.
* @param string|null $level0Type The type of the object at level 0 the property belongs to.
* @param string|null $level0Name The name of the object at level 0 the property belongs to.
* @param string|null $level1Type The type of the object at level 1 the property belongs to.
* @param string|null $level1Name The name of the object at level 1 the property belongs to.
* @param string|null $level2Type The type of the object at level 2 the property belongs to.
* @param string|null $level2Name The name of the object at level 2 the property belongs to.
*
* @return string
*
* @link http://msdn.microsoft.com/en-us/library/ms180047%28v=sql.90%29.aspx
*/
public function getAddExtendedPropertySQL(
$name,
$value = null,
$level0Type = null,
$level0Name = null,
$level1Type = null,
$level1Name = null,
$level2Type = null,
$level2Name = null
) {
return "EXEC sp_addextendedproperty " .
"N'" . $name . "', N'" . $value . "', " .
"N'" . $level0Type . "', " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name;
}
/**
* Returns the SQL statement for dropping an extended property from a database object.
*
* @param string $name The name of the property to drop.
* @param string|null $level0Type The type of the object at level 0 the property belongs to.
* @param string|null $level0Name The name of the object at level 0 the property belongs to.
* @param string|null $level1Type The type of the object at level 1 the property belongs to.
* @param string|null $level1Name The name of the object at level 1 the property belongs to.
* @param string|null $level2Type The type of the object at level 2 the property belongs to.
* @param string|null $level2Name The name of the object at level 2 the property belongs to.
*
* @return string
*
* @link http://technet.microsoft.com/en-gb/library/ms178595%28v=sql.90%29.aspx
*/
public function getDropExtendedPropertySQL(
$name,
$level0Type = null,
$level0Name = null,
$level1Type = null,
$level1Name = null,
$level2Type = null,
$level2Name = null
) {
return "EXEC sp_dropextendedproperty " .
"N'" . $name . "', " .
"N'" . $level0Type . "', " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name;
}
/**
* Returns the SQL statement for updating an extended property of a database object.
*
* @param string $name The name of the property to update.
* @param string|null $value The value of the property to update.
* @param string|null $level0Type The type of the object at level 0 the property belongs to.
* @param string|null $level0Name The name of the object at level 0 the property belongs to.
* @param string|null $level1Type The type of the object at level 1 the property belongs to.
* @param string|null $level1Name The name of the object at level 1 the property belongs to.
* @param string|null $level2Type The type of the object at level 2 the property belongs to.
* @param string|null $level2Name The name of the object at level 2 the property belongs to.
*
* @return string
*
* @link http://msdn.microsoft.com/en-us/library/ms186885%28v=sql.90%29.aspx
*/
public function getUpdateExtendedPropertySQL(
$name,
$value = null,
$level0Type = null,
$level0Name = null,
$level1Type = null,
$level1Name = null,
$level2Type = null,
$level2Name = null
) {
return "EXEC sp_updateextendedproperty " .
"N'" . $name . "', N'" . $value . "', " .
"N'" . $level0Type . "', " . $level0Name . ', ' .
"N'" . $level1Type . "', " . $level1Name . ', ' .
"N'" . $level2Type . "', " . $level2Name;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
...@@ -550,7 +786,8 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -550,7 +786,8 @@ class SQLServerPlatform extends AbstractPlatform
col.scale, col.scale,
col.precision, col.precision,
col.is_identity AS autoincrement, col.is_identity AS autoincrement,
col.collation_name AS collation col.collation_name AS collation,
CAST(prop.value AS NVARCHAR(MAX)) AS comment -- CAST avoids driver error for sql_variant type
FROM sys.columns AS col FROM sys.columns AS col
JOIN sys.types AS type JOIN sys.types AS type
ON col.user_type_id = type.user_type_id ON col.user_type_id = type.user_type_id
...@@ -559,6 +796,10 @@ class SQLServerPlatform extends AbstractPlatform ...@@ -559,6 +796,10 @@ class SQLServerPlatform extends AbstractPlatform
LEFT JOIN sys.default_constraints def LEFT JOIN sys.default_constraints def
ON col.default_object_id = def.object_id ON col.default_object_id = def.object_id
AND col.object_id = def.parent_object_id AND col.object_id = def.parent_object_id
LEFT JOIN sys.extended_properties AS prop
ON obj.object_id = prop.major_id
AND col.column_id = prop.minor_id
AND prop.name = 'MS_Description'
WHERE obj.type = 'U' WHERE obj.type = 'U'
AND obj.name = '$table'"; AND obj.name = '$table'";
} }
......
...@@ -80,6 +80,8 @@ class SQLServerSchemaManager extends AbstractSchemaManager ...@@ -80,6 +80,8 @@ class SQLServerSchemaManager extends AbstractSchemaManager
} }
$type = $this->_platform->getDoctrineTypeMapping($dbType); $type = $this->_platform->getDoctrineTypeMapping($dbType);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
switch ($type) { switch ($type) {
case 'char': case 'char':
...@@ -99,6 +101,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager ...@@ -99,6 +101,7 @@ class SQLServerSchemaManager extends AbstractSchemaManager
'scale' => $tableColumn['scale'], 'scale' => $tableColumn['scale'],
'precision' => $tableColumn['precision'], 'precision' => $tableColumn['precision'],
'autoincrement' => (bool) $tableColumn['autoincrement'], 'autoincrement' => (bool) $tableColumn['autoincrement'],
'comment' => $tableColumn['comment'] !== '' ? $tableColumn['comment'] : null,
); );
$platformOptions = array( $platformOptions = array(
......
...@@ -164,4 +164,169 @@ class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -164,4 +164,169 @@ class SQLServerSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertNull($columns['df_current_timestamp']->getDefault()); $this->assertNull($columns['df_current_timestamp']->getDefault());
$this->assertEquals(666, $columns['df_integer']->getDefault()); $this->assertEquals(666, $columns['df_integer']->getDefault());
} }
/**
* @group DBAL-543
*/
public function testColumnComments()
{
$table = new Table('sqlsrv_column_comment');
$table->addColumn('id', 'integer', array('autoincrement' => true));
$table->addColumn('comment_null', 'integer', array('comment' => null));
$table->addColumn('comment_false', 'integer', array('comment' => false));
$table->addColumn('comment_empty_string', 'integer', array('comment' => ''));
$table->addColumn('comment_integer_0', 'integer', array('comment' => 0));
$table->addColumn('comment_float_0', 'integer', array('comment' => 0.0));
$table->addColumn('comment_string_0', 'integer', array('comment' => '0'));
$table->addColumn('comment', 'integer', array('comment' => 'Doctrine 0wnz you!'));
$table->addColumn('`comment_quoted`', 'integer', array('comment' => 'Doctrine 0wnz comments for explicitely quoted columns!'));
$table->addColumn('create', 'integer', array('comment' => 'Doctrine 0wnz comments for reserved keyword columns!'));
$table->addColumn('commented_type', 'object');
$table->addColumn('commented_type_with_comment', 'array', array('comment' => 'Doctrine array type.'));
$table->setPrimaryKey(array('id'));
$this->_sm->createTable($table);
$columns = $this->_sm->listTableColumns("sqlsrv_column_comment");
$this->assertEquals(12, count($columns));
$this->assertNull($columns['id']->getComment());
$this->assertNull($columns['comment_null']->getComment());
$this->assertNull($columns['comment_false']->getComment());
$this->assertNull($columns['comment_empty_string']->getComment());
$this->assertEquals('0', $columns['comment_integer_0']->getComment());
$this->assertEquals('0', $columns['comment_float_0']->getComment());
$this->assertEquals('0', $columns['comment_string_0']->getComment());
$this->assertEquals('Doctrine 0wnz you!', $columns['comment']->getComment());
$this->assertEquals('Doctrine 0wnz comments for explicitely quoted columns!', $columns['comment_quoted']->getComment());
$this->assertEquals('Doctrine 0wnz comments for reserved keyword columns!', $columns['[create]']->getComment());
$this->assertNull($columns['commented_type']->getComment());
$this->assertEquals('Doctrine array type.', $columns['commented_type_with_comment']->getComment());
$tableDiff = new TableDiff('sqlsrv_column_comment');
$tableDiff->fromTable = $table;
$tableDiff->addedColumns['added_comment_none'] = new Column('added_comment_none', Type::getType('integer'));
$tableDiff->addedColumns['added_comment_null'] = new Column('added_comment_null', Type::getType('integer'), array('comment' => null));
$tableDiff->addedColumns['added_comment_false'] = new Column('added_comment_false', Type::getType('integer'), array('comment' => false));
$tableDiff->addedColumns['added_comment_empty_string'] = new Column('added_comment_empty_string', Type::getType('integer'), array('comment' => ''));
$tableDiff->addedColumns['added_comment_integer_0'] = new Column('added_comment_integer_0', Type::getType('integer'), array('comment' => 0));
$tableDiff->addedColumns['added_comment_float_0'] = new Column('added_comment_float_0', Type::getType('integer'), array('comment' => 0.0));
$tableDiff->addedColumns['added_comment_string_0'] = new Column('added_comment_string_0', Type::getType('integer'), array('comment' => '0'));
$tableDiff->addedColumns['added_comment'] = new Column('added_comment', Type::getType('integer'), array('comment' => 'Doctrine'));
$tableDiff->addedColumns['`added_comment_quoted`'] = new Column('`added_comment_quoted`', Type::getType('integer'), array('comment' => 'rulez'));
$tableDiff->addedColumns['select'] = new Column('select', Type::getType('integer'), array('comment' => '666'));
$tableDiff->addedColumns['added_commented_type'] = new Column('added_commented_type', Type::getType('object'));
$tableDiff->addedColumns['added_commented_type_with_comment'] = new Column('added_commented_type_with_comment', Type::getType('array'), array('comment' => '666'));
$tableDiff->renamedColumns['comment_float_0'] = new Column('comment_double_0', Type::getType('decimal'), array('comment' => 'Double for real!'));
// Add comment to non-commented column.
$tableDiff->changedColumns['id'] = new ColumnDiff(
'id',
new Column('id', Type::getType('integer'), array('autoincrement' => true, 'comment' => 'primary')),
array('comment'),
new Column('id', Type::getType('integer'), array('autoincrement' => true))
);
// Remove comment from null-commented column.
$tableDiff->changedColumns['comment_null'] = new ColumnDiff(
'comment_null',
new Column('comment_null', Type::getType('string')),
array('type'),
new Column('comment_null', Type::getType('integer'), array('comment' => null))
);
// Add comment to false-commented column.
$tableDiff->changedColumns['comment_false'] = new ColumnDiff(
'comment_false',
new Column('comment_false', Type::getType('integer'), array('comment' => 'false')),
array('comment'),
new Column('comment_false', Type::getType('integer'), array('comment' => false))
);
// Change type to custom type from empty string commented column.
$tableDiff->changedColumns['comment_empty_string'] = new ColumnDiff(
'comment_empty_string',
new Column('comment_empty_string', Type::getType('object')),
array('type'),
new Column('comment_empty_string', Type::getType('integer'), array('comment' => ''))
);
// Change comment to false-comment from zero-string commented column.
$tableDiff->changedColumns['comment_string_0'] = new ColumnDiff(
'comment_string_0',
new Column('comment_string_0', Type::getType('integer'), array('comment' => false)),
array('comment'),
new Column('comment_string_0', Type::getType('integer'), array('comment' => '0'))
);
// Remove comment from regular commented column.
$tableDiff->changedColumns['comment'] = new ColumnDiff(
'comment',
new Column('comment', Type::getType('integer')),
array('comment'),
new Column('comment', Type::getType('integer'), array('comment' => 'Doctrine 0wnz you!'))
);
// Change comment and change type to custom type from regular commented column.
$tableDiff->changedColumns['`comment_quoted`'] = new ColumnDiff(
'`comment_quoted`',
new Column('`comment_quoted`', Type::getType('array'), array('comment' => 'Doctrine array.')),
array('comment', 'type'),
new Column('`comment_quoted`', Type::getType('integer'), array('comment' => 'Doctrine 0wnz you!'))
);
// Remove comment and change type to custom type from regular commented column.
$tableDiff->changedColumns['create'] = new ColumnDiff(
'create',
new Column('create', Type::getType('object')),
array('comment', 'type'),
new Column('create', Type::getType('integer'), array('comment' => 'Doctrine 0wnz comments for reserved keyword columns!'))
);
// Add comment and change custom type to regular type from non-commented column.
$tableDiff->changedColumns['commented_type'] = new ColumnDiff(
'commented_type',
new Column('commented_type', Type::getType('integer'), array('comment' => 'foo')),
array('comment', 'type'),
new Column('commented_type', Type::getType('object'))
);
// Remove comment from commented custom type column.
$tableDiff->changedColumns['commented_type_with_comment'] = new ColumnDiff(
'commented_type_with_comment',
new Column('commented_type_with_comment', Type::getType('array')),
array('comment'),
new Column('commented_type_with_comment', Type::getType('array'), array('comment' => 'Doctrine array type.'))
);
$tableDiff->removedColumns['comment_integer_0'] = new Column('comment_integer_0', Type::getType('integer'), array('comment' => 0));
$this->_sm->alterTable($tableDiff);
$columns = $this->_sm->listTableColumns("sqlsrv_column_comment");
$this->assertEquals(23, count($columns));
$this->assertEquals('primary', $columns['id']->getComment());
$this->assertNull($columns['comment_null']->getComment());
$this->assertEquals('false', $columns['comment_false']->getComment());
$this->assertNull($columns['comment_empty_string']->getComment());
$this->assertEquals('0', $columns['comment_double_0']->getComment());
$this->assertNull($columns['comment_string_0']->getComment());
$this->assertNull($columns['comment']->getComment());
$this->assertEquals('Doctrine array.', $columns['comment_quoted']->getComment());
$this->assertNull($columns['[create]']->getComment());
$this->assertEquals('foo', $columns['commented_type']->getComment());
$this->assertNull($columns['commented_type_with_comment']->getComment());
$this->assertNull($columns['added_comment_none']->getComment());
$this->assertNull($columns['added_comment_null']->getComment());
$this->assertNull($columns['added_comment_false']->getComment());
$this->assertNull($columns['added_comment_empty_string']->getComment());
$this->assertEquals('0', $columns['added_comment_integer_0']->getComment());
$this->assertEquals('0', $columns['added_comment_float_0']->getComment());
$this->assertEquals('0', $columns['added_comment_string_0']->getComment());
$this->assertEquals('Doctrine', $columns['added_comment']->getComment());
$this->assertEquals('rulez', $columns['added_comment_quoted']->getComment());
$this->assertEquals('666', $columns['[select]']->getComment());
$this->assertNull($columns['added_commented_type']->getComment());
$this->assertEquals('666', $columns['added_commented_type_with_comment']->getComment());
}
} }
...@@ -522,7 +522,9 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -522,7 +522,9 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
*/ */
public function testGetColumnComment() public function testGetColumnComment()
{ {
if (!$this->_conn->getDatabasePlatform()->supportsInlineColumnComments() && !$this->_conn->getDatabasePlatform()->supportsCommentOnStatement()) { if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
! $this->_conn->getDatabasePlatform()->getName() == 'mssql') {
$this->markTestSkipped('Database does not support column comments.'); $this->markTestSkipped('Database does not support column comments.');
} }
...@@ -556,7 +558,9 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -556,7 +558,9 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
*/ */
public function testAutomaticallyAppendCommentOnMarkedColumns() public function testAutomaticallyAppendCommentOnMarkedColumns()
{ {
if (!$this->_conn->getDatabasePlatform()->supportsInlineColumnComments() && !$this->_conn->getDatabasePlatform()->supportsCommentOnStatement()) { if ( ! $this->_conn->getDatabasePlatform()->supportsInlineColumnComments() &&
! $this->_conn->getDatabasePlatform()->supportsCommentOnStatement() &&
! $this->_conn->getDatabasePlatform()->getName() == 'mssql') {
$this->markTestSkipped('Database does not support column comments.'); $this->markTestSkipped('Database does not support column comments.');
} }
......
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
namespace Doctrine\Tests\DBAL\Platforms; namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Platforms\SQLServer2008Platform; use Doctrine\DBAL\Platforms\SQLServer2008Platform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnDiff;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
class SQLServerPlatformTest extends AbstractPlatformTestCase class SQLServerPlatformTest extends AbstractPlatformTestCase
...@@ -342,4 +346,247 @@ class SQLServerPlatformTest extends AbstractPlatformTestCase ...@@ -342,4 +346,247 @@ class SQLServerPlatformTest extends AbstractPlatformTestCase
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
} }
} }
/**
* @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",
);
}
/**
* @group DBAL-543
*/
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",
// todo
//"EXEC sp_addextendedproperty N'MS_Description', N'B comment', N'SCHEMA', dbo, N'TABLE', mytable, N'COLUMN', baz",
);
}
/**
* @group DBAL-543
*/
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",
);
}
/**
* @group DBAL-543
*/
public function testGeneratesCreateTableSQLWithColumnComments()
{
$table = new Table('mytable');
$table->addColumn('id', 'integer', array('autoincrement' => true));
$table->addColumn('comment_null', 'integer', array('comment' => null));
$table->addColumn('comment_false', 'integer', array('comment' => false));
$table->addColumn('comment_empty_string', 'integer', array('comment' => ''));
$table->addColumn('comment_integer_0', 'integer', array('comment' => 0));
$table->addColumn('comment_float_0', 'integer', array('comment' => 0.0));
$table->addColumn('comment_string_0', 'integer', array('comment' => '0'));
$table->addColumn('comment', 'integer', array('comment' => 'Doctrine 0wnz you!'));
$table->addColumn('`comment_quoted`', 'integer', array('comment' => 'Doctrine 0wnz comments for explicitely quoted columns!'));
$table->addColumn('create', 'integer', array('comment' => 'Doctrine 0wnz comments for reserved keyword columns!'));
$table->addColumn('commented_type', 'object');
$table->addColumn('commented_type_with_comment', 'array', array('comment' => 'Doctrine array type.'));
$table->setPrimaryKey(array('id'));
$this->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, 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 explicitely 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",
),
$this->_platform->getCreateTableSQL($table)
);
}
/**
* @group DBAL-543
*/
public function testGeneratesAlterTableSQLWithColumnComments()
{
$table = new Table('mytable');
$table->addColumn('id', 'integer', array('autoincrement' => true));
$table->addColumn('comment_null', 'integer', array('comment' => null));
$table->addColumn('comment_false', 'integer', array('comment' => false));
$table->addColumn('comment_empty_string', 'integer', array('comment' => ''));
$table->addColumn('comment_integer_0', 'integer', array('comment' => 0));
$table->addColumn('comment_float_0', 'integer', array('comment' => 0.0));
$table->addColumn('comment_string_0', 'integer', array('comment' => '0'));
$table->addColumn('comment', 'integer', array('comment' => 'Doctrine 0wnz you!'));
$table->addColumn('`comment_quoted`', 'integer', array('comment' => 'Doctrine 0wnz comments for explicitely quoted columns!'));
$table->addColumn('create', 'integer', array('comment' => 'Doctrine 0wnz comments for reserved keyword columns!'));
$table->addColumn('commented_type', 'object');
$table->addColumn('commented_type_with_comment', 'array', array('comment' => 'Doctrine array type.'));
$table->setPrimaryKey(array('id'));
$tableDiff = new TableDiff('mytable');
$tableDiff->fromTable = $table;
$tableDiff->addedColumns['added_comment_none'] = new Column('added_comment_none', Type::getType('integer'));
$tableDiff->addedColumns['added_comment_null'] = new Column('added_comment_null', Type::getType('integer'), array('comment' => null));
$tableDiff->addedColumns['added_comment_false'] = new Column('added_comment_false', Type::getType('integer'), array('comment' => false));
$tableDiff->addedColumns['added_comment_empty_string'] = new Column('added_comment_empty_string', Type::getType('integer'), array('comment' => ''));
$tableDiff->addedColumns['added_comment_integer_0'] = new Column('added_comment_integer_0', Type::getType('integer'), array('comment' => 0));
$tableDiff->addedColumns['added_comment_float_0'] = new Column('added_comment_float_0', Type::getType('integer'), array('comment' => 0.0));
$tableDiff->addedColumns['added_comment_string_0'] = new Column('added_comment_string_0', Type::getType('integer'), array('comment' => '0'));
$tableDiff->addedColumns['added_comment'] = new Column('added_comment', Type::getType('integer'), array('comment' => 'Doctrine'));
$tableDiff->addedColumns['`added_comment_quoted`'] = new Column('`added_comment_quoted`', Type::getType('integer'), array('comment' => 'rulez'));
$tableDiff->addedColumns['select'] = new Column('select', Type::getType('integer'), array('comment' => '666'));
$tableDiff->addedColumns['added_commented_type'] = new Column('added_commented_type', Type::getType('object'));
$tableDiff->addedColumns['added_commented_type_with_comment'] = new Column('added_commented_type_with_comment', Type::getType('array'), array('comment' => '666'));
$tableDiff->renamedColumns['comment_float_0'] = new Column('comment_double_0', Type::getType('decimal'), array('comment' => 'Double for real!'));
// Add comment to non-commented column.
$tableDiff->changedColumns['id'] = new ColumnDiff(
'id',
new Column('id', Type::getType('integer'), array('autoincrement' => true, 'comment' => 'primary')),
array('comment'),
new Column('id', Type::getType('integer'), array('autoincrement' => true))
);
// Remove comment from null-commented column.
$tableDiff->changedColumns['comment_null'] = new ColumnDiff(
'comment_null',
new Column('comment_null', Type::getType('string')),
array('type'),
new Column('comment_null', Type::getType('integer'), array('comment' => null))
);
// Add comment to false-commented column.
$tableDiff->changedColumns['comment_false'] = new ColumnDiff(
'comment_false',
new Column('comment_false', Type::getType('integer'), array('comment' => 'false')),
array('comment'),
new Column('comment_false', Type::getType('integer'), array('comment' => false))
);
// Change type to custom type from empty string commented column.
$tableDiff->changedColumns['comment_empty_string'] = new ColumnDiff(
'comment_empty_string',
new Column('comment_empty_string', Type::getType('object')),
array('type'),
new Column('comment_empty_string', Type::getType('integer'), array('comment' => ''))
);
// Change comment to false-comment from zero-string commented column.
$tableDiff->changedColumns['comment_string_0'] = new ColumnDiff(
'comment_string_0',
new Column('comment_string_0', Type::getType('integer'), array('comment' => false)),
array('comment'),
new Column('comment_string_0', Type::getType('integer'), array('comment' => '0'))
);
// Remove comment from regular commented column.
$tableDiff->changedColumns['comment'] = new ColumnDiff(
'comment',
new Column('comment', Type::getType('integer')),
array('comment'),
new Column('comment', Type::getType('integer'), array('comment' => 'Doctrine 0wnz you!'))
);
// Change comment and change type to custom type from regular commented column.
$tableDiff->changedColumns['`comment_quoted`'] = new ColumnDiff(
'`comment_quoted`',
new Column('`comment_quoted`', Type::getType('array'), array('comment' => 'Doctrine array.')),
array('comment', 'type'),
new Column('`comment_quoted`', Type::getType('integer'), array('comment' => 'Doctrine 0wnz you!'))
);
// Remove comment and change type to custom type from regular commented column.
$tableDiff->changedColumns['create'] = new ColumnDiff(
'create',
new Column('create', Type::getType('object')),
array('comment', 'type'),
new Column('create', Type::getType('integer'), array('comment' => 'Doctrine 0wnz comments for reserved keyword columns!'))
);
// Add comment and change custom type to regular type from non-commented column.
$tableDiff->changedColumns['commented_type'] = new ColumnDiff(
'commented_type',
new Column('commented_type', Type::getType('integer'), array('comment' => 'foo')),
array('comment', 'type'),
new Column('commented_type', Type::getType('object'))
);
// Remove comment from commented custom type column.
$tableDiff->changedColumns['commented_type_with_comment'] = new ColumnDiff(
'commented_type_with_comment',
new Column('commented_type_with_comment', Type::getType('array')),
array('comment'),
new Column('commented_type_with_comment', Type::getType('array'), array('comment' => 'Doctrine array type.'))
);
$tableDiff->removedColumns['comment_integer_0'] = new Column('comment_integer_0', Type::getType('integer'), array('comment' => 0));
$this->assertEquals(
array(
// Renamed columns.
"sp_RENAME 'mytable.comment_float_0', 'comment_double_0', 'COLUMN'",
// Added columns.
"ALTER TABLE mytable ADD added_comment_none INT NOT NULL",
"ALTER TABLE mytable ADD added_comment_null INT NOT NULL",
"ALTER TABLE mytable ADD added_comment_false INT NOT NULL",
"ALTER TABLE mytable ADD added_comment_empty_string INT NOT NULL",
"ALTER TABLE mytable ADD added_comment_integer_0 INT NOT NULL",
"ALTER TABLE mytable ADD added_comment_float_0 INT NOT NULL",
"ALTER TABLE mytable ADD added_comment_string_0 INT NOT NULL",
"ALTER TABLE mytable ADD added_comment INT NOT NULL",
"ALTER TABLE mytable ADD [added_comment_quoted] INT NOT NULL",
"ALTER TABLE mytable ADD [select] INT NOT NULL",
"ALTER TABLE mytable ADD added_commented_type VARCHAR(MAX) NOT NULL",
"ALTER TABLE mytable ADD added_commented_type_with_comment VARCHAR(MAX) NOT NULL",
"ALTER TABLE mytable DROP COLUMN comment_integer_0",
"ALTER TABLE mytable ALTER COLUMN comment_null NVARCHAR(255) NOT NULL",
"ALTER TABLE mytable ALTER COLUMN comment_empty_string VARCHAR(MAX) NOT NULL",
"ALTER TABLE mytable ALTER COLUMN [comment_quoted] VARCHAR(MAX) NOT NULL",
"ALTER TABLE mytable ALTER COLUMN [create] VARCHAR(MAX) NOT NULL",
"ALTER TABLE mytable ALTER COLUMN commented_type INT NOT NULL",
// Renamed columns.
"ALTER TABLE mytable ALTER COLUMN comment_double_0 NUMERIC(10, 0) 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",
// 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",
),
$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