Skip to content

Commit

Permalink
Support table and column comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov committed Jan 16, 2024
1 parent 0992809 commit 17a84b1
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 6 deletions.
90 changes: 84 additions & 6 deletions src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
use function strncasecmp;
use function strtolower;

use const PREG_SET_ORDER;

/**
* Implements the SQLite Server specific schema, supporting SQLite 3.3.0 or higher.
*
Expand Down Expand Up @@ -155,8 +157,11 @@ protected function loadTableSchema(string $name): TableSchemaInterface|null

$table->name($name);
$table->fullName($name);
$table->createSql($this->getCreateTableSql($name));
$this->findTableComment($table);

if ($this->findColumns($table)) {
$this->findComments($table);
$this->findConstraints($table);

return $table;
Expand Down Expand Up @@ -294,12 +299,7 @@ protected function loadTableUniques(string $tableName): array
*/
protected function loadTableChecks(string $tableName): array
{
$sql = $this->db->createCommand(
'SELECT `sql` FROM `sqlite_master` WHERE name = :tableName',
[':tableName' => $tableName],
)->queryScalar();

$sql = ($sql === false || $sql === null) ? '' : (string) $sql;
$sql = $this->getCreateTableSql($tableName);

$code = (new SqlTokenizer($sql))->tokenize();
$pattern = (new SqlTokenizer('any CREATE any TABLE any()'))->tokenize();
Expand Down Expand Up @@ -741,6 +741,84 @@ protected function getCacheTag(): string
return md5(serialize(array_merge([self::class], $this->generateCacheKey())));
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
private function findTableComment(TableSchemaInterface $tableSchema): void
{
$sql = $tableSchema->getCreateSql();

if (preg_match('#^[^(]+?((?:\s*--[^\n]*|\s*/\*.*?\*/)+)\s*\(#', $sql, $matches) === 1) {

Check failure on line 753 in src/Schema.php

View workflow job for this annotation

GitHub Actions / PHP 8.0

PossiblyNullArgument

src/Schema.php:753:73: PossiblyNullArgument: Argument 2 of preg_match cannot be null, possibly null value provided (see https://psalm.dev/078)

Check failure on line 753 in src/Schema.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

PossiblyNullArgument

src/Schema.php:753:73: PossiblyNullArgument: Argument 2 of preg_match cannot be null, possibly null value provided (see https://psalm.dev/078)

Check failure on line 753 in src/Schema.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

PossiblyNullArgument

src/Schema.php:753:73: PossiblyNullArgument: Argument 2 of preg_match cannot be null, possibly null value provided (see https://psalm.dev/078)
$comment = $this->filterComment($matches[1]);
$tableSchema->comment($comment);
}
}

/**
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
private function findComments(TableSchemaInterface $tableSchema): void
{
$sql = $tableSchema->getCreateSql();

preg_match('#^(?:[^(]*--[^\n]*|[^(]*/\*.*?\*/)*[^(]*\((.*)\)[^)]*$#s', $sql, $matches);

Check failure on line 768 in src/Schema.php

View workflow job for this annotation

GitHub Actions / PHP 8.0

PossiblyNullArgument

src/Schema.php:768:80: PossiblyNullArgument: Argument 2 of preg_match cannot be null, possibly null value provided (see https://psalm.dev/078)

Check failure on line 768 in src/Schema.php

View workflow job for this annotation

GitHub Actions / PHP 8.1

PossiblyNullArgument

src/Schema.php:768:80: PossiblyNullArgument: Argument 2 of preg_match cannot be null, possibly null value provided (see https://psalm.dev/078)

Check failure on line 768 in src/Schema.php

View workflow job for this annotation

GitHub Actions / PHP 8.2

PossiblyNullArgument

src/Schema.php:768:80: PossiblyNullArgument: Argument 2 of preg_match cannot be null, possibly null value provided (see https://psalm.dev/078)

$columnsDefinition = $matches[1];

$identifierPattern = '(?:([`"])([^`"]+)\1|\[([^\]]+)\]|([A-Za-z_]\w*))';
$notCommaPattern = '(?:[^,]|\([^()]+\))*?';
$commentPattern = '(?:\s*--[^\n]*|\s*/\*.*?\*/)';

$pattern = "#$identifierPattern\s*$notCommaPattern,?($commentPattern+)#";

if (preg_match_all($pattern, $columnsDefinition, $matches, PREG_SET_ORDER)) {
foreach ($matches as $match) {
$columnName = $match[2] ?: $match[3] ?: $match[4];
$comment = $this->filterComment($match[5] ?: $match[6]);

$tableSchema->getColumn($columnName)?->comment($comment);
}
}
}

private function filterComment(string $comment): string
{
preg_match_all('#--([^\n]*)|/\*(.*?)\*/#', $comment, $matches, PREG_SET_ORDER);

$lines = [];

foreach ($matches as $match) {
$lines[] = trim($match[1] ?: $match[2]);
}

return implode("\n", $lines);
}

/**
* Returns the `CREATE TABLE` SQL string.
*
* @param string $name The table name.
*
* @return string The `CREATE TABLE` SQL string.
*
* @throws Exception
* @throws InvalidConfigException
* @throws Throwable
*/
private function getCreateTableSql(string $name): string
{
$sql = $this->db->createCommand(
'SELECT `sql` FROM `sqlite_master` WHERE `name` = :tableName',
[':tableName' => $name],
)->queryScalar();

return (string)$sql;
}

/**
* @throws Throwable
*/
Expand Down
19 changes: 19 additions & 0 deletions tests/SchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,4 +359,23 @@ public function testNotConnectionPDO(): void

$schema->refreshTableSchema('customer');
}

public function testTableComment(): void
{
$db = $this->getConnection(true);
$schema = $db->getSchema();
$table = $schema->getTableSchema('comment');

$this->assertSame("Table comment\nsecond line\nthird line", $table->getComment());
}

public function testColumnComments(): void
{
$db = $this->getConnection(true);
$schema = $db->getSchema();
$table = $schema->getTableSchema('comment');

$this->assertSame('primary key', $table->getColumn('id')->getComment());
$this->assertSame("Column comment\nsecond line\nthird line", $table->getColumn('name')->getComment());
}
}
11 changes: 11 additions & 0 deletions tests/Support/Fixture/sqlite.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ DROP TABLE IF EXISTS "negative_default_values";
DROP TABLE IF EXISTS "animal";
DROP TABLE IF EXISTS "default_pk";
DROP TABLE IF EXISTS "notauto_pk";
DROP TABLE IF EXISTS "comment";
DROP VIEW IF EXISTS "animal_view";
DROP TABLE IF EXISTS "T_constraints_4";
DROP TABLE IF EXISTS "T_constraints_3";
Expand Down Expand Up @@ -173,6 +174,16 @@ CREATE TABLE "timestamp_default" (
timestamp_text TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
); -- STRICT

CREATE TABLE `comment` -- Table comment
-- second line
/* third line */
(
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, -- primary key
`name` varchar(100) -- Column comment
-- second line
/* third line */
);

CREATE VIEW "animal_view" AS SELECT * FROM "animal";

INSERT INTO "animal" ("type") VALUES ('yiiunit\data\ar\Cat');
Expand Down

0 comments on commit 17a84b1

Please sign in to comment.