Skip to content

Commit fb2a02b

Browse files
committed
Reflection: added comment to Column and Table
1 parent 42c5f52 commit fb2a02b

17 files changed

+128
-42
lines changed

src/Database/Driver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ function applyLimit(string &$sql, ?int $limit, ?int $offset): void;
6969

7070
/**
7171
* Returns a list of all tables in the database.
72-
* @return list<array{name: string, fullName: string, view: bool}>
72+
* @return list<array{name: string, fullName: ?string, view: bool, comment: ?string}>
7373
*/
7474
function getTables(): array;
7575

7676
/**
7777
* Returns metadata for all columns in a table.
78-
* @return list<array{name: string, table: string, nativetype: string, size: int|null, nullable: bool, default: mixed, autoincrement: bool, primary: bool, vendor: array}>
78+
* @return list<array{name: string, table: string, nativetype: string, size: ?int, nullable: bool, default: mixed, autoincrement: bool, primary: bool, comment: ?string, vendor: array}>
7979
*/
8080
function getColumns(string $table): array;
8181

src/Database/Drivers/MsSqlDriver.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,25 @@ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
9090
public function getTables(): array
9191
{
9292
$tables = [];
93-
$rows = $this->connection->query('SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES');
93+
$rows = $this->connection->query(<<<'X'
94+
SELECT
95+
TABLE_SCHEMA,
96+
TABLE_NAME,
97+
TABLE_TYPE,
98+
CAST(ISNULL(p.value, '') AS VARCHAR(255)) AS comment
99+
FROM
100+
INFORMATION_SCHEMA.TABLES t
101+
LEFT JOIN
102+
sys.extended_properties p ON p.major_id = OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME)
103+
AND p.minor_id = 0
104+
AND p.name = 'MS_Description'
105+
X);
106+
94107
while ($row = $rows->fetch()) {
95108
$tables[] = [
96109
'name' => $row['TABLE_SCHEMA'] . '.' . $row['TABLE_NAME'],
97110
'view' => ($row['TABLE_TYPE'] ?? null) === 'VIEW',
111+
'comment' => $row['comment'] ?? '',
98112
];
99113
}
100114

@@ -109,18 +123,23 @@ public function getColumns(string $table): array
109123

110124
$rows = $this->connection->query(<<<'X'
111125
SELECT
112-
COLUMN_NAME,
113-
DATA_TYPE,
114-
CHARACTER_MAXIMUM_LENGTH,
115-
NUMERIC_PRECISION,
116-
IS_NULLABLE,
117-
COLUMN_DEFAULT,
118-
DOMAIN_NAME
126+
c.COLUMN_NAME,
127+
c.DATA_TYPE,
128+
c.CHARACTER_MAXIMUM_LENGTH,
129+
c.NUMERIC_PRECISION,
130+
c.IS_NULLABLE,
131+
c.COLUMN_DEFAULT,
132+
c.DOMAIN_NAME,
133+
CAST(p.value AS NVARCHAR(4000)) AS comment
119134
FROM
120-
INFORMATION_SCHEMA.COLUMNS
135+
INFORMATION_SCHEMA.COLUMNS c
136+
LEFT JOIN sys.extended_properties p ON
137+
p.major_id = OBJECT_ID(c.TABLE_SCHEMA + '.' + c.TABLE_NAME) AND
138+
p.minor_id = COLUMNPROPERTY(OBJECT_ID(c.TABLE_SCHEMA + '.' + c.TABLE_NAME), c.COLUMN_NAME, 'ColumnId') AND
139+
p.name = 'MS_Description'
121140
WHERE
122-
TABLE_SCHEMA = ?
123-
AND TABLE_NAME = ?
141+
c.TABLE_SCHEMA = ?
142+
AND c.TABLE_NAME = ?
124143
X, $table_schema, $table_name);
125144

126145
while ($row = $rows->fetch()) {
@@ -134,6 +153,7 @@ public function getColumns(string $table): array
134153
'default' => $row['COLUMN_DEFAULT'],
135154
'autoincrement' => $row['DOMAIN_NAME'] === 'COUNTER',
136155
'primary' => $row['COLUMN_NAME'] === 'ID',
156+
'comment' => $row['comment'] ?? '',
137157
'vendor' => (array) $row,
138158
];
139159
}

src/Database/Drivers/MySqlDriver.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,17 @@ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
128128
public function getTables(): array
129129
{
130130
$tables = [];
131-
$rows = $this->connection->query('SHOW FULL TABLES');
132-
while ($row = $rows->fetch()) {
131+
$query = $this->connection->query(<<<'XX'
132+
SELECT TABLE_NAME, TABLE_TYPE, TABLE_COMMENT
133+
FROM information_schema.TABLES
134+
WHERE TABLE_SCHEMA = DATABASE()
135+
XX);
136+
137+
while ($row = $query->fetch()) {
133138
$tables[] = [
134-
'name' => $row[0],
135-
'view' => ($row[1] ?? null) === 'VIEW',
139+
'name' => $row['TABLE_NAME'],
140+
'view' => $row['TABLE_TYPE'] === 'VIEW',
141+
'comment' => $row['TABLE_COMMENT'],
136142
];
137143
}
138144

@@ -145,7 +151,7 @@ public function getColumns(string $table): array
145151
$columns = [];
146152
$rows = $this->connection->query('SHOW FULL COLUMNS FROM ' . $this->delimite($table));
147153
while ($row = $rows->fetch()) {
148-
$row = array_change_key_case((array) $row, CASE_LOWER);
154+
$row = array_change_key_case((array) $row);
149155
$typeInfo = Nette\Database\Helpers::parseColumnType($row['type']);
150156
$columns[] = [
151157
'name' => $row['field'],
@@ -156,6 +162,7 @@ public function getColumns(string $table): array
156162
'default' => $row['default'],
157163
'autoincrement' => $row['extra'] === 'auto_increment',
158164
'primary' => $row['key'] === 'PRI',
165+
'comment' => $row['comment'],
159166
'vendor' => $row,
160167
];
161168
}

src/Database/Drivers/OciDriver.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ public function getTables(): array
109109
$tables[] = [
110110
'name' => $row[0],
111111
'view' => $row[1] === 'VIEW',
112+
'comment' => null,
112113
];
113114
}
114115
}

src/Database/Drivers/PgSqlDriver.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@ public function getTables(): array
113113
SELECT DISTINCT ON (c.relname)
114114
c.relname::varchar AS name,
115115
c.relkind IN ('v', 'm') AS view,
116-
n.nspname::varchar || '.' || c.relname::varchar AS "fullName"
116+
n.nspname::varchar || '.' || c.relname::varchar AS "fullName",
117+
coalesce(d.description, '') AS comment
117118
FROM
118119
pg_catalog.pg_class AS c
119120
JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
121+
LEFT JOIN pg_catalog.pg_description d ON d.objoid = c.oid AND d.objsubid = 0
120122
WHERE
121123
c.relkind IN ('r', 'v', 'm', 'p')
122124
AND n.nspname = ANY (pg_catalog.current_schemas(FALSE))
@@ -150,6 +152,7 @@ public function getColumns(string $table): array
150152
pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass)::varchar AS default,
151153
coalesce(co.contype = 'p' AND (seq.relname IS NOT NULL OR strpos(pg_catalog.pg_get_expr(ad.adbin, ad.adrelid), 'nextval') = 1), FALSE) AS autoincrement,
152154
coalesce(co.contype = 'p', FALSE) AS primary,
155+
coalesce(col_description(c.oid, a.attnum)::varchar, '') AS comment,
153156
coalesce(seq.relname, substring(pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass) from 'nextval[(]''"?([^''"]+)')) AS sequence
154157
FROM
155158
pg_catalog.pg_attribute AS a

src/Database/Drivers/SqliteDriver.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public function getTables(): array
127127
$tables[] = [
128128
'name' => $row['name'],
129129
'view' => (bool) $row['view'],
130+
'comment' => null,
130131
];
131132
}
132133

@@ -161,6 +162,7 @@ public function getColumns(string $table): array
161162
'default' => $row['dflt_value'],
162163
'autoincrement' => $createSql && preg_match($pattern, $createSql['sql']),
163164
'primary' => $row['pk'] > 0,
165+
'comment' => null,
164166
'vendor' => (array) $row,
165167
];
166168
}

src/Database/Drivers/SqlsrvDriver.php

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,21 +90,27 @@ public function getTables(): array
9090
$tables = [];
9191
$rows = $this->connection->query(<<<'X'
9292
SELECT
93-
name,
94-
CASE type
93+
o.name,
94+
CASE o.type
9595
WHEN 'U' THEN 0
9696
WHEN 'V' THEN 1
97-
END AS [view]
97+
END AS [view],
98+
CAST(p.value AS VARCHAR(255)) AS comment
9899
FROM
99-
sys.objects
100+
sys.objects o
101+
LEFT JOIN
102+
sys.extended_properties p ON p.major_id = o.object_id
103+
AND p.minor_id = 0
104+
AND p.name = 'MS_Description'
100105
WHERE
101-
type IN ('U', 'V')
106+
o.type IN ('U', 'V')
102107
X);
103108

104109
while ($row = $rows->fetch()) {
105110
$tables[] = [
106111
'name' => $row['name'],
107112
'view' => (bool) $row['view'],
113+
'comment' => $row['comment'] ?? '',
108114
];
109115
}
110116

@@ -131,13 +137,18 @@ public function getColumns(string $table): array
131137
CASE WHEN i.index_id IS NULL
132138
THEN 0
133139
ELSE 1
134-
END AS [primary]
140+
END AS [primary],
141+
CAST(ep.value AS VARCHAR(255)) AS comment
135142
FROM
136143
sys.columns c
137144
JOIN sys.objects o ON c.object_id = o.object_id
138145
LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
139146
LEFT JOIN sys.key_constraints k ON o.object_id = k.parent_object_id AND k.type = 'PK'
140147
LEFT JOIN sys.index_columns i ON k.parent_object_id = i.object_id AND i.index_id = k.unique_index_id AND i.column_id = c.column_id
148+
LEFT JOIN sys.extended_properties ep ON
149+
ep.major_id = c.object_id AND
150+
ep.minor_id = c.column_id AND
151+
ep.name = 'MS_Description'
141152
WHERE
142153
o.type IN ('U', 'V')
143154
AND o.name = ?
@@ -149,6 +160,7 @@ public function getColumns(string $table): array
149160
$row['nullable'] = (bool) $row['nullable'];
150161
$row['autoincrement'] = (bool) $row['autoincrement'];
151162
$row['primary'] = (bool) $row['primary'];
163+
$row['comment'] ??= '';
152164

153165
$columns[] = $row;
154166
}

src/Database/Reflection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private function initTables(): void
8484
{
8585
$res = [];
8686
foreach ($this->driver->getTables() as $row) {
87-
$res[$row['fullName'] ?? $row['name']] = new Table($this, $row['name'], $row['view'], $row['fullName'] ?? null);
87+
$res[$row['fullName'] ?? $row['name']] = new Table($this, $row['name'], $row['view'], $row['fullName'] ?? null, $row['comment'] ?? null);
8888
}
8989
$this->tables = $res;
9090
}

src/Database/Reflection/Column.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function __construct(
2525
public readonly mixed $default = null,
2626
public readonly bool $autoIncrement = false,
2727
public readonly bool $primary = false,
28+
public readonly ?string $comment = null,
2829
public readonly array $vendor = [],
2930
) {
3031
}

src/Database/Reflection/Table.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public function __construct(
3434
public readonly string $name,
3535
public readonly bool $view = false,
3636
public readonly ?string $fullName = null,
37+
public readonly ?string $comment = null,
3738
) {
3839
unset($this->columns, $this->indexes, $this->primaryKey, $this->foreignKeys);
3940
}
@@ -53,7 +54,7 @@ private function initColumns(): void
5354
{
5455
$res = [];
5556
foreach ($this->reflection->getDriver()->getColumns($this->name) as $row) {
56-
$res[$row['name']] = new Column($row['name'], $this, $row['nativetype'], $row['size'], $row['nullable'], $row['default'], $row['autoincrement'], $row['primary'], $row['vendor']);
57+
$res[$row['name']] = new Column($row['name'], $this, $row['nativetype'], $row['size'], $row['nullable'], $row['default'], $row['autoincrement'], $row['primary'], $row['comment'] ?? null, $row['vendor']);
5758
}
5859
$this->columns = $res;
5960
}

0 commit comments

Comments
 (0)