Skip to content

Commit

Permalink
Merge pull request #3512 from moufmouf/comments_on_table_in_all_db
Browse files Browse the repository at this point in the history
Support for comments on table in all databases
  • Loading branch information
morozov authored Aug 8, 2019
2 parents 29486f0 + 62c2a8b commit 9ff47e7
Show file tree
Hide file tree
Showing 18 changed files with 269 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/en/reference/schema-representation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ example shows:
$myTable->addColumn("username", "string", array("length" => 32));
$myTable->setPrimaryKey(array("id"));
$myTable->addUniqueIndex(array("username"));
$myTable->setComment('Some comment');
$schema->createSequence("my_table_seq");
$myForeign = $schema->createTable("my_foreign");
Expand Down
14 changes: 14 additions & 0 deletions lib/Doctrine/DBAL/Platforms/AbstractPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,9 @@ public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDE

$sql = $this->_getCreateTableSQL($tableName, $columns, $options);
if ($this->supportsCommentOnStatement()) {
if ($table->hasOption('comment')) {
$sql[] = $this->getCommentOnTableSQL($tableName, $table->getOption('comment'));
}
foreach ($table->getColumns() as $column) {
$comment = $this->getColumnComment($column);

Expand All @@ -1621,6 +1624,17 @@ public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDE
return array_merge($sql, $columnSql);
}

protected function getCommentOnTableSQL(string $tableName, ?string $comment) : string
{
$tableName = new Identifier($tableName);

return sprintf(
'COMMENT ON TABLE %s IS %s',
$tableName->getQuotedName($this),
$this->quoteStringLiteral((string) $comment)
);
}

/**
* @param string $tableName
* @param string $columnName
Expand Down
13 changes: 13 additions & 0 deletions lib/Doctrine/DBAL/Platforms/DB2Platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -900,4 +900,17 @@ protected function getReservedKeywordsClass()
{
return Keywords\DB2Keywords::class;
}

public function getListTableCommentsSQL(string $table) : string
{
return sprintf(
<<<'SQL'
SELECT REMARKS
FROM SYSIBM.SYSTABLES
WHERE NAME = UPPER( %s )
SQL
,
$this->quoteStringLiteral($table)
);
}
}
4 changes: 1 addition & 3 deletions lib/Doctrine/DBAL/Platforms/MySqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -519,9 +519,7 @@ private function buildTableOptions(array $options)

// Comment
if (isset($options['comment'])) {
$comment = trim($options['comment'], " '");

$tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($comment));
$tableOptions[] = sprintf('COMMENT = %s ', $this->quoteStringLiteral($options['comment']));
}

// Row format
Expand Down
21 changes: 21 additions & 0 deletions lib/Doctrine/DBAL/Platforms/OraclePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -1182,4 +1182,25 @@ public function getBlobTypeDeclarationSQL(array $field)
{
return 'BLOB';
}

public function getListTableCommentsSQL(string $table, ?string $database = null) : string
{
$tableCommentsName = 'user_tab_comments';
$ownerCondition = '';

if ($database !== null && $database !== '/') {
$tableCommentsName = 'all_tab_comments';
$ownerCondition = ' AND owner = ' . $this->quoteStringLiteral($this->normalizeIdentifier($database)->getName());
}

return sprintf(
<<<'SQL'
SELECT comments FROM %s WHERE table_name = %s%s
SQL
,
$tableCommentsName,
$this->quoteStringLiteral($this->normalizeIdentifier($table)->getName()),
$ownerCondition
);
}
}
15 changes: 15 additions & 0 deletions lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -1252,4 +1252,19 @@ private function getOldColumnComment(ColumnDiff $columnDiff) : ?string
{
return $columnDiff->fromColumn ? $this->getColumnComment($columnDiff->fromColumn) : null;
}

public function getListTableMetadataSQL(string $table, ?string $schema = null) : string
{
if ($schema !== null) {
$table = $schema . '.' . $table;
}

return sprintf(
<<<'SQL'
SELECT obj_description(%s::regclass) AS table_comment;
SQL
,
$this->quoteStringLiteral($table)
);
}
}
36 changes: 36 additions & 0 deletions lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,11 @@ protected function _getCreateTableSQL($tableName, array $columns, array $options
$defaultConstraintsSql = [];
$commentsSql = [];

$tableComment = $options['comment'] ?? null;
if ($tableComment !== null) {
$commentsSql[] = $this->getCommentOnTableSQL($tableName, $tableComment);
}

// @todo does other code breaks because of this?
// force primary keys to be not null
foreach ($columns as &$column) {
Expand Down Expand Up @@ -1656,4 +1661,35 @@ private function generateIdentifierName($identifier)

return strtoupper(dechex(crc32($identifier->getName())));
}

protected function getCommentOnTableSQL(string $tableName, ?string $comment) : string
{
return sprintf(
<<<'SQL'
EXEC sys.sp_addextendedproperty @name=N'MS_Description',
@value=N%s, @level0type=N'SCHEMA', @level0name=N'dbo',
@level1type=N'TABLE', @level1name=N%s
SQL
,
$this->quoteStringLiteral((string) $comment),
$this->quoteStringLiteral($tableName)
);
}

public function getListTableMetadataSQL(string $table) : string
{
return sprintf(
<<<'SQL'
SELECT
p.value AS [table_comment]
FROM
sys.tables AS tbl
INNER JOIN sys.extended_properties AS p ON p.major_id=tbl.object_id AND p.minor_id=0 AND p.class=1
WHERE
(tbl.name=N%s and SCHEMA_NAME(tbl.schema_id)=N'dbo' and p.name=N'MS_Description')
SQL
,
$this->quoteStringLiteral($table)
);
}
}
15 changes: 14 additions & 1 deletion lib/Doctrine/DBAL/Platforms/SqlitePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use function strlen;
use function strpos;
use function strtolower;
use function trim;

/**
* The SqlitePlatform class describes the specifics and dialects of the SQLite
Expand Down Expand Up @@ -332,7 +333,14 @@ protected function _getCreateTableSQL($name, array $columns, array $options = []
}
}

$query = ['CREATE TABLE ' . $name . ' (' . $queryFields . ')'];
$tableComment = '';
if (isset($options['comment'])) {
$comment = trim($options['comment'], " '");

$tableComment = $this->getInlineTableCommentSQL($comment);
}

$query = ['CREATE TABLE ' . $name . ' ' . $tableComment . '(' . $queryFields . ')'];

if (isset($options['alter']) && $options['alter'] === true) {
return $query;
Expand Down Expand Up @@ -605,6 +613,11 @@ public function getInlineColumnCommentSQL($comment)
return '--' . str_replace("\n", "\n--", $comment) . "\n";
}

private function getInlineTableCommentSQL(string $comment) : string
{
return $this->getInlineColumnCommentSQL($comment);
}

/**
* {@inheritDoc}
*/
Expand Down
15 changes: 15 additions & 0 deletions lib/Doctrine/DBAL/Schema/DB2SchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Doctrine\DBAL\Schema;

use Doctrine\DBAL\Platforms\DB2Platform;
use Doctrine\DBAL\Types\Type;
use const CASE_LOWER;
use function array_change_key_case;
Expand Down Expand Up @@ -209,4 +210,18 @@ protected function _getPortableViewDefinition($view)

return new View($view['name'], $sql);
}

public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);

/** @var DB2Platform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableCommentsSQL($tableName);

$tableOptions = $this->_conn->fetchAssoc($sql);
$table->addOption('comment', $tableOptions['REMARKS']);

return $table;
}
}
14 changes: 14 additions & 0 deletions lib/Doctrine/DBAL/Schema/OracleSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,18 @@ private function killUserSessions($user)
);
}
}

public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);

/** @var OraclePlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableCommentsSQL($tableName);

$tableOptions = $this->_conn->fetchAssoc($sql);
$table->addOption('comment', $tableOptions['COMMENTS']);

return $table;
}
}
15 changes: 15 additions & 0 deletions lib/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -489,4 +489,19 @@ private function parseDefaultExpression(?string $default) : ?string

return str_replace("''", "'", $default);
}

public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);

/** @var PostgreSqlPlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableMetadataSQL($tableName);

$tableOptions = $this->_conn->fetchAssoc($sql);

$table->addOption('comment', $tableOptions['table_comment']);

return $table;
}
}
19 changes: 19 additions & 0 deletions lib/Doctrine/DBAL/Schema/SQLServerSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\DBAL\Types\Type;
use PDOException;
use Throwable;
Expand Down Expand Up @@ -325,4 +326,22 @@ private function closeActiveDatabaseConnections($database)
)
);
}

/**
* @param string $tableName
*/
public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);

/** @var SQLServerPlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableMetadataSQL($tableName);

$tableOptions = $this->_conn->fetchAssoc($sql);

$table->addOption('comment', $tableOptions['table_comment']);

return $table;
}
}
37 changes: 37 additions & 0 deletions lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,25 @@ private function parseColumnCollationFromSQL(string $column, string $sql) : ?str
return $match[1];
}

private function parseTableCommentFromSQL(string $table, string $sql) : ?string
{
$pattern = '/\s* # Allow whitespace characters at start of line
CREATE\sTABLE # Match "CREATE TABLE"
(?:\W"' . preg_quote($this->_platform->quoteSingleIdentifier($table), '/') . '"\W|\W' . preg_quote($table, '/')
. '\W) # Match table name (quoted and unquoted)
( # Start capture
(?:\s*--[^\n]*\n?)+ # Capture anything that starts with whitespaces followed by -- until the end of the line(s)
)/ix';

if (preg_match($pattern, $sql, $match) !== 1) {
return null;
}

$comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n"));

return $comment === '' ? null : $comment;
}

private function parseColumnCommentFromSQL(string $column, string $sql) : ?string
{
$pattern = '{[\s(,](?:\W' . preg_quote($this->_platform->quoteSingleIdentifier($column)) . '\W|\W' . preg_quote($column)
Expand Down Expand Up @@ -503,4 +522,22 @@ private function getCreateTableSQL(string $table) : ?string
[$table]
) ?: null;
}

/**
* @param string $tableName
*/
public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);

$tableCreateSql = $this->getCreateTableSQL($tableName) ?? '';

$comment = $this->parseTableCommentFromSQL($tableName, $tableCreateSql);

if ($comment !== null) {
$table->addOption('comment', $comment);
}

return $table;
}
}
13 changes: 13 additions & 0 deletions lib/Doctrine/DBAL/Schema/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -840,4 +840,17 @@ private function normalizeIdentifier($identifier)

return $this->trimQuotes(strtolower($identifier));
}

public function setComment(?string $comment) : self
{
// For keeping backward compatibility with MySQL in previous releases, table comments are stored as options.
$this->addOption('comment', $comment);

return $this;
}

public function getComment() : ?string
{
return $this->_options['comment'] ?? null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,9 @@ public function testListTableColumnsWithFixedStringTypeColumn() : void
self::assertArrayHasKey('test', $columns);
self::assertTrue($columns['test']->getFixed());
}

public function testCommentInTable() : void
{
self::markTestSkipped('Table level comments are not supported on SQLAnywhere');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1594,4 +1594,15 @@ public function testGenerateAnIndexWithPartialColumnLength() : void
$onlineTable = $this->schemaManager->listTableDetails('test_partial_column_index');
self::assertEquals($expected, $onlineTable->getIndexes());
}

public function testCommentInTable() : void
{
$table = new Table('table_with_comment');
$table->addColumn('id', 'integer');
$table->setComment('Foo with control characters \'\\');
$this->schemaManager->dropAndCreateTable($table);

$table = $this->schemaManager->listTableDetails('table_with_comment');
self::assertSame('Foo with control characters \'\\', $table->getComment());
}
}
Loading

0 comments on commit 9ff47e7

Please sign in to comment.