diff options
Diffstat (limited to 'vendor/doctrine/dbal/src/Schema/SQLiteSchemaManager.php')
-rw-r--r-- | vendor/doctrine/dbal/src/Schema/SQLiteSchemaManager.php | 620 |
1 files changed, 620 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Schema/SQLiteSchemaManager.php b/vendor/doctrine/dbal/src/Schema/SQLiteSchemaManager.php new file mode 100644 index 0000000..c001c25 --- /dev/null +++ b/vendor/doctrine/dbal/src/Schema/SQLiteSchemaManager.php | |||
@@ -0,0 +1,620 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Doctrine\DBAL\Schema; | ||
6 | |||
7 | use Doctrine\DBAL\Exception; | ||
8 | use Doctrine\DBAL\Platforms\SQLite; | ||
9 | use Doctrine\DBAL\Platforms\SQLitePlatform; | ||
10 | use Doctrine\DBAL\Result; | ||
11 | use Doctrine\DBAL\Types\StringType; | ||
12 | use Doctrine\DBAL\Types\TextType; | ||
13 | use Doctrine\DBAL\Types\Type; | ||
14 | |||
15 | use function array_change_key_case; | ||
16 | use function array_merge; | ||
17 | use function assert; | ||
18 | use function count; | ||
19 | use function implode; | ||
20 | use function is_string; | ||
21 | use function preg_match; | ||
22 | use function preg_match_all; | ||
23 | use function preg_quote; | ||
24 | use function preg_replace; | ||
25 | use function rtrim; | ||
26 | use function str_contains; | ||
27 | use function str_replace; | ||
28 | use function str_starts_with; | ||
29 | use function strcasecmp; | ||
30 | use function strtolower; | ||
31 | use function trim; | ||
32 | use function usort; | ||
33 | |||
34 | use const CASE_LOWER; | ||
35 | |||
36 | /** | ||
37 | * SQLite SchemaManager. | ||
38 | * | ||
39 | * @extends AbstractSchemaManager<SQLitePlatform> | ||
40 | */ | ||
41 | class SQLiteSchemaManager extends AbstractSchemaManager | ||
42 | { | ||
43 | /** | ||
44 | * {@inheritDoc} | ||
45 | */ | ||
46 | protected function fetchForeignKeyColumnsByTable(string $databaseName): array | ||
47 | { | ||
48 | $columnsByTable = parent::fetchForeignKeyColumnsByTable($databaseName); | ||
49 | |||
50 | if (count($columnsByTable) > 0) { | ||
51 | foreach ($columnsByTable as $table => $columns) { | ||
52 | $columnsByTable[$table] = $this->addDetailsToTableForeignKeyColumns($table, $columns); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | return $columnsByTable; | ||
57 | } | ||
58 | |||
59 | public function createForeignKey(ForeignKeyConstraint $foreignKey, string $table): void | ||
60 | { | ||
61 | $table = $this->introspectTable($table); | ||
62 | |||
63 | $this->alterTable(new TableDiff($table, [], [], [], [], [], [], [], [], [$foreignKey], [], [])); | ||
64 | } | ||
65 | |||
66 | public function dropForeignKey(string $name, string $table): void | ||
67 | { | ||
68 | $table = $this->introspectTable($table); | ||
69 | |||
70 | $foreignKey = $table->getForeignKey($name); | ||
71 | |||
72 | $this->alterTable(new TableDiff($table, [], [], [], [], [], [], [], [], [], [], [$foreignKey])); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * {@inheritDoc} | ||
77 | */ | ||
78 | public function listTableForeignKeys(string $table): array | ||
79 | { | ||
80 | $table = $this->normalizeName($table); | ||
81 | |||
82 | $columns = $this->selectForeignKeyColumns('main', $table) | ||
83 | ->fetchAllAssociative(); | ||
84 | |||
85 | if (count($columns) > 0) { | ||
86 | $columns = $this->addDetailsToTableForeignKeyColumns($table, $columns); | ||
87 | } | ||
88 | |||
89 | return $this->_getPortableTableForeignKeysList($columns); | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * {@inheritDoc} | ||
94 | */ | ||
95 | protected function _getPortableTableDefinition(array $table): string | ||
96 | { | ||
97 | return $table['table_name']; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * {@inheritDoc} | ||
102 | * | ||
103 | * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html | ||
104 | */ | ||
105 | protected function _getPortableTableIndexesList(array $tableIndexes, string $tableName): array | ||
106 | { | ||
107 | $indexBuffer = []; | ||
108 | |||
109 | // fetch primary | ||
110 | $indexArray = $this->connection->fetchAllAssociative('SELECT * FROM PRAGMA_TABLE_INFO (?)', [$tableName]); | ||
111 | |||
112 | usort( | ||
113 | $indexArray, | ||
114 | /** | ||
115 | * @param array<string,mixed> $a | ||
116 | * @param array<string,mixed> $b | ||
117 | */ | ||
118 | static function (array $a, array $b): int { | ||
119 | if ($a['pk'] === $b['pk']) { | ||
120 | return $a['cid'] - $b['cid']; | ||
121 | } | ||
122 | |||
123 | return $a['pk'] - $b['pk']; | ||
124 | }, | ||
125 | ); | ||
126 | |||
127 | foreach ($indexArray as $indexColumnRow) { | ||
128 | if ($indexColumnRow['pk'] === 0 || $indexColumnRow['pk'] === '0') { | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | $indexBuffer[] = [ | ||
133 | 'key_name' => 'primary', | ||
134 | 'primary' => true, | ||
135 | 'non_unique' => false, | ||
136 | 'column_name' => $indexColumnRow['name'], | ||
137 | ]; | ||
138 | } | ||
139 | |||
140 | // fetch regular indexes | ||
141 | foreach ($tableIndexes as $tableIndex) { | ||
142 | // Ignore indexes with reserved names, e.g. autoindexes | ||
143 | if (str_starts_with($tableIndex['name'], 'sqlite_')) { | ||
144 | continue; | ||
145 | } | ||
146 | |||
147 | $keyName = $tableIndex['name']; | ||
148 | $idx = []; | ||
149 | $idx['key_name'] = $keyName; | ||
150 | $idx['primary'] = false; | ||
151 | $idx['non_unique'] = ! $tableIndex['unique']; | ||
152 | |||
153 | $indexArray = $this->connection->fetchAllAssociative('SELECT * FROM PRAGMA_INDEX_INFO (?)', [$keyName]); | ||
154 | |||
155 | foreach ($indexArray as $indexColumnRow) { | ||
156 | $idx['column_name'] = $indexColumnRow['name']; | ||
157 | $indexBuffer[] = $idx; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | return parent::_getPortableTableIndexesList($indexBuffer, $tableName); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * {@inheritDoc} | ||
166 | */ | ||
167 | protected function _getPortableTableColumnList(string $table, string $database, array $tableColumns): array | ||
168 | { | ||
169 | $list = parent::_getPortableTableColumnList($table, $database, $tableColumns); | ||
170 | |||
171 | // find column with autoincrement | ||
172 | $autoincrementColumn = null; | ||
173 | $autoincrementCount = 0; | ||
174 | |||
175 | foreach ($tableColumns as $tableColumn) { | ||
176 | if ($tableColumn['pk'] === 0 || $tableColumn['pk'] === '0') { | ||
177 | continue; | ||
178 | } | ||
179 | |||
180 | $autoincrementCount++; | ||
181 | if ($autoincrementColumn !== null || strtolower($tableColumn['type']) !== 'integer') { | ||
182 | continue; | ||
183 | } | ||
184 | |||
185 | $autoincrementColumn = $tableColumn['name']; | ||
186 | } | ||
187 | |||
188 | if ($autoincrementCount === 1 && $autoincrementColumn !== null) { | ||
189 | foreach ($list as $column) { | ||
190 | if ($autoincrementColumn !== $column->getName()) { | ||
191 | continue; | ||
192 | } | ||
193 | |||
194 | $column->setAutoincrement(true); | ||
195 | } | ||
196 | } | ||
197 | |||
198 | // inspect column collation and comments | ||
199 | $createSql = $this->getCreateTableSQL($table); | ||
200 | |||
201 | foreach ($list as $columnName => $column) { | ||
202 | $type = $column->getType(); | ||
203 | |||
204 | if ($type instanceof StringType || $type instanceof TextType) { | ||
205 | $column->setPlatformOption( | ||
206 | 'collation', | ||
207 | $this->parseColumnCollationFromSQL($columnName, $createSql) ?? 'BINARY', | ||
208 | ); | ||
209 | } | ||
210 | |||
211 | $comment = $this->parseColumnCommentFromSQL($columnName, $createSql); | ||
212 | |||
213 | $column->setComment($comment); | ||
214 | } | ||
215 | |||
216 | return $list; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * {@inheritDoc} | ||
221 | */ | ||
222 | protected function _getPortableTableColumnDefinition(array $tableColumn): Column | ||
223 | { | ||
224 | preg_match('/^([^()]*)\\s*(\\(((\\d+)(,\\s*(\\d+))?)\\))?/', $tableColumn['type'], $matches); | ||
225 | |||
226 | $dbType = trim(strtolower($matches[1])); | ||
227 | |||
228 | $length = $precision = $unsigned = null; | ||
229 | $fixed = $unsigned = false; | ||
230 | $scale = 0; | ||
231 | |||
232 | if (count($matches) >= 6) { | ||
233 | $precision = (int) $matches[4]; | ||
234 | $scale = (int) $matches[6]; | ||
235 | } elseif (count($matches) >= 4) { | ||
236 | $length = (int) $matches[4]; | ||
237 | } | ||
238 | |||
239 | if (str_contains($dbType, ' unsigned')) { | ||
240 | $dbType = str_replace(' unsigned', '', $dbType); | ||
241 | $unsigned = true; | ||
242 | } | ||
243 | |||
244 | $type = $this->platform->getDoctrineTypeMapping($dbType); | ||
245 | $default = $tableColumn['dflt_value']; | ||
246 | if ($default === 'NULL') { | ||
247 | $default = null; | ||
248 | } | ||
249 | |||
250 | if ($default !== null) { | ||
251 | // SQLite returns the default value as a literal expression, so we need to parse it | ||
252 | if (preg_match('/^\'(.*)\'$/s', $default, $matches) === 1) { | ||
253 | $default = str_replace("''", "'", $matches[1]); | ||
254 | } | ||
255 | } | ||
256 | |||
257 | $notnull = (bool) $tableColumn['notnull']; | ||
258 | |||
259 | if (! isset($tableColumn['name'])) { | ||
260 | $tableColumn['name'] = ''; | ||
261 | } | ||
262 | |||
263 | if ($dbType === 'char') { | ||
264 | $fixed = true; | ||
265 | } | ||
266 | |||
267 | $options = [ | ||
268 | 'length' => $length, | ||
269 | 'unsigned' => $unsigned, | ||
270 | 'fixed' => $fixed, | ||
271 | 'notnull' => $notnull, | ||
272 | 'default' => $default, | ||
273 | 'precision' => $precision, | ||
274 | 'scale' => $scale, | ||
275 | ]; | ||
276 | |||
277 | return new Column($tableColumn['name'], Type::getType($type), $options); | ||
278 | } | ||
279 | |||
280 | /** | ||
281 | * {@inheritDoc} | ||
282 | */ | ||
283 | protected function _getPortableViewDefinition(array $view): View | ||
284 | { | ||
285 | return new View($view['name'], $view['sql']); | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * {@inheritDoc} | ||
290 | */ | ||
291 | protected function _getPortableTableForeignKeysList(array $tableForeignKeys): array | ||
292 | { | ||
293 | $list = []; | ||
294 | foreach ($tableForeignKeys as $value) { | ||
295 | $value = array_change_key_case($value, CASE_LOWER); | ||
296 | $id = $value['id']; | ||
297 | if (! isset($list[$id])) { | ||
298 | if (! isset($value['on_delete']) || $value['on_delete'] === 'RESTRICT') { | ||
299 | $value['on_delete'] = null; | ||
300 | } | ||
301 | |||
302 | if (! isset($value['on_update']) || $value['on_update'] === 'RESTRICT') { | ||
303 | $value['on_update'] = null; | ||
304 | } | ||
305 | |||
306 | $list[$id] = [ | ||
307 | 'name' => $value['constraint_name'], | ||
308 | 'local' => [], | ||
309 | 'foreign' => [], | ||
310 | 'foreignTable' => $value['table'], | ||
311 | 'onDelete' => $value['on_delete'], | ||
312 | 'onUpdate' => $value['on_update'], | ||
313 | 'deferrable' => $value['deferrable'], | ||
314 | 'deferred' => $value['deferred'], | ||
315 | ]; | ||
316 | } | ||
317 | |||
318 | $list[$id]['local'][] = $value['from']; | ||
319 | |||
320 | if ($value['to'] === null) { | ||
321 | // Inferring a shorthand form for the foreign key constraint, where the "to" field is empty. | ||
322 | // @see https://www.sqlite.org/foreignkeys.html#fk_indexes. | ||
323 | $foreignTableIndexes = $this->_getPortableTableIndexesList([], $value['table']); | ||
324 | |||
325 | if (! isset($foreignTableIndexes['primary'])) { | ||
326 | continue; | ||
327 | } | ||
328 | |||
329 | $list[$id]['foreign'] = [...$list[$id]['foreign'], ...$foreignTableIndexes['primary']->getColumns()]; | ||
330 | |||
331 | continue; | ||
332 | } | ||
333 | |||
334 | $list[$id]['foreign'][] = $value['to']; | ||
335 | } | ||
336 | |||
337 | return parent::_getPortableTableForeignKeysList($list); | ||
338 | } | ||
339 | |||
340 | /** | ||
341 | * {@inheritDoc} | ||
342 | */ | ||
343 | protected function _getPortableTableForeignKeyDefinition(array $tableForeignKey): ForeignKeyConstraint | ||
344 | { | ||
345 | return new ForeignKeyConstraint( | ||
346 | $tableForeignKey['local'], | ||
347 | $tableForeignKey['foreignTable'], | ||
348 | $tableForeignKey['foreign'], | ||
349 | $tableForeignKey['name'], | ||
350 | [ | ||
351 | 'onDelete' => $tableForeignKey['onDelete'], | ||
352 | 'onUpdate' => $tableForeignKey['onUpdate'], | ||
353 | 'deferrable' => $tableForeignKey['deferrable'], | ||
354 | 'deferred' => $tableForeignKey['deferred'], | ||
355 | ], | ||
356 | ); | ||
357 | } | ||
358 | |||
359 | private function parseColumnCollationFromSQL(string $column, string $sql): ?string | ||
360 | { | ||
361 | $pattern = '{(?:\W' . preg_quote($column) . '\W|\W' | ||
362 | . preg_quote($this->platform->quoteSingleIdentifier($column)) | ||
363 | . '\W)[^,(]+(?:\([^()]+\)[^,]*)?(?:(?:DEFAULT|CHECK)\s*(?:\(.*?\))?[^,]*)*COLLATE\s+["\']?([^\s,"\')]+)}is'; | ||
364 | |||
365 | if (preg_match($pattern, $sql, $match) !== 1) { | ||
366 | return null; | ||
367 | } | ||
368 | |||
369 | return $match[1]; | ||
370 | } | ||
371 | |||
372 | private function parseTableCommentFromSQL(string $table, string $sql): ?string | ||
373 | { | ||
374 | $pattern = '/\s* # Allow whitespace characters at start of line | ||
375 | CREATE\sTABLE # Match "CREATE TABLE" | ||
376 | (?:\W"' . preg_quote($this->platform->quoteSingleIdentifier($table), '/') . '"\W|\W' . preg_quote($table, '/') | ||
377 | . '\W) # Match table name (quoted and unquoted) | ||
378 | ( # Start capture | ||
379 | (?:\s*--[^\n]*\n?)+ # Capture anything that starts with whitespaces followed by -- until the end of the line(s) | ||
380 | )/ix'; | ||
381 | |||
382 | if (preg_match($pattern, $sql, $match) !== 1) { | ||
383 | return null; | ||
384 | } | ||
385 | |||
386 | $comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n")); | ||
387 | |||
388 | return $comment === '' ? null : $comment; | ||
389 | } | ||
390 | |||
391 | private function parseColumnCommentFromSQL(string $column, string $sql): string | ||
392 | { | ||
393 | $pattern = '{[\s(,](?:\W' . preg_quote($this->platform->quoteSingleIdentifier($column)) | ||
394 | . '\W|\W' . preg_quote($column) . '\W)(?:\([^)]*?\)|[^,(])*?,?((?:(?!\n))(?:\s*--[^\n]*\n?)+)}i'; | ||
395 | |||
396 | if (preg_match($pattern, $sql, $match) !== 1) { | ||
397 | return ''; | ||
398 | } | ||
399 | |||
400 | $comment = preg_replace('{^\s*--}m', '', rtrim($match[1], "\n")); | ||
401 | assert(is_string($comment)); | ||
402 | |||
403 | return $comment; | ||
404 | } | ||
405 | |||
406 | /** @throws Exception */ | ||
407 | private function getCreateTableSQL(string $table): string | ||
408 | { | ||
409 | $sql = $this->connection->fetchOne( | ||
410 | <<<'SQL' | ||
411 | SELECT sql | ||
412 | FROM ( | ||
413 | SELECT * | ||
414 | FROM sqlite_master | ||
415 | UNION ALL | ||
416 | SELECT * | ||
417 | FROM sqlite_temp_master | ||
418 | ) | ||
419 | WHERE type = 'table' | ||
420 | AND name = ? | ||
421 | SQL | ||
422 | , | ||
423 | [$table], | ||
424 | ); | ||
425 | |||
426 | if ($sql !== false) { | ||
427 | return $sql; | ||
428 | } | ||
429 | |||
430 | return ''; | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * @param list<array<string,mixed>> $columns | ||
435 | * | ||
436 | * @return list<array<string,mixed>> | ||
437 | * | ||
438 | * @throws Exception | ||
439 | */ | ||
440 | private function addDetailsToTableForeignKeyColumns(string $table, array $columns): array | ||
441 | { | ||
442 | $foreignKeyDetails = $this->getForeignKeyDetails($table); | ||
443 | $foreignKeyCount = count($foreignKeyDetails); | ||
444 | |||
445 | foreach ($columns as $i => $column) { | ||
446 | // SQLite identifies foreign keys in reverse order of appearance in SQL | ||
447 | $columns[$i] = array_merge($column, $foreignKeyDetails[$foreignKeyCount - $column['id'] - 1]); | ||
448 | } | ||
449 | |||
450 | return $columns; | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * @return list<array<string, mixed>> | ||
455 | * | ||
456 | * @throws Exception | ||
457 | */ | ||
458 | private function getForeignKeyDetails(string $table): array | ||
459 | { | ||
460 | $createSql = $this->getCreateTableSQL($table); | ||
461 | |||
462 | if ( | ||
463 | preg_match_all( | ||
464 | '# | ||
465 | (?:CONSTRAINT\s+(\S+)\s+)? | ||
466 | (?:FOREIGN\s+KEY[^)]+\)\s*)? | ||
467 | REFERENCES\s+\S+\s*(?:\([^)]+\))? | ||
468 | (?: | ||
469 | [^,]*? | ||
470 | (NOT\s+DEFERRABLE|DEFERRABLE) | ||
471 | (?:\s+INITIALLY\s+(DEFERRED|IMMEDIATE))? | ||
472 | )?#isx', | ||
473 | $createSql, | ||
474 | $match, | ||
475 | ) === 0 | ||
476 | ) { | ||
477 | return []; | ||
478 | } | ||
479 | |||
480 | $names = $match[1]; | ||
481 | $deferrable = $match[2]; | ||
482 | $deferred = $match[3]; | ||
483 | $details = []; | ||
484 | |||
485 | for ($i = 0, $count = count($match[0]); $i < $count; $i++) { | ||
486 | $details[] = [ | ||
487 | 'constraint_name' => $names[$i] ?? '', | ||
488 | 'deferrable' => isset($deferrable[$i]) && strcasecmp($deferrable[$i], 'deferrable') === 0, | ||
489 | 'deferred' => isset($deferred[$i]) && strcasecmp($deferred[$i], 'deferred') === 0, | ||
490 | ]; | ||
491 | } | ||
492 | |||
493 | return $details; | ||
494 | } | ||
495 | |||
496 | public function createComparator(): Comparator | ||
497 | { | ||
498 | return new SQLite\Comparator($this->platform); | ||
499 | } | ||
500 | |||
501 | protected function selectTableNames(string $databaseName): Result | ||
502 | { | ||
503 | $sql = <<<'SQL' | ||
504 | SELECT name AS table_name | ||
505 | FROM sqlite_master | ||
506 | WHERE type = 'table' | ||
507 | AND name != 'sqlite_sequence' | ||
508 | AND name != 'geometry_columns' | ||
509 | AND name != 'spatial_ref_sys' | ||
510 | UNION ALL | ||
511 | SELECT name | ||
512 | FROM sqlite_temp_master | ||
513 | WHERE type = 'table' | ||
514 | ORDER BY name | ||
515 | SQL; | ||
516 | |||
517 | return $this->connection->executeQuery($sql); | ||
518 | } | ||
519 | |||
520 | protected function selectTableColumns(string $databaseName, ?string $tableName = null): Result | ||
521 | { | ||
522 | $sql = <<<'SQL' | ||
523 | SELECT t.name AS table_name, | ||
524 | c.* | ||
525 | FROM sqlite_master t | ||
526 | JOIN pragma_table_info(t.name) c | ||
527 | SQL; | ||
528 | |||
529 | $conditions = [ | ||
530 | "t.type = 'table'", | ||
531 | "t.name NOT IN ('geometry_columns', 'spatial_ref_sys', 'sqlite_sequence')", | ||
532 | ]; | ||
533 | $params = []; | ||
534 | |||
535 | if ($tableName !== null) { | ||
536 | $conditions[] = 't.name = ?'; | ||
537 | $params[] = str_replace('.', '__', $tableName); | ||
538 | } | ||
539 | |||
540 | $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY t.name, c.cid'; | ||
541 | |||
542 | return $this->connection->executeQuery($sql, $params); | ||
543 | } | ||
544 | |||
545 | protected function selectIndexColumns(string $databaseName, ?string $tableName = null): Result | ||
546 | { | ||
547 | $sql = <<<'SQL' | ||
548 | SELECT t.name AS table_name, | ||
549 | i.* | ||
550 | FROM sqlite_master t | ||
551 | JOIN pragma_index_list(t.name) i | ||
552 | SQL; | ||
553 | |||
554 | $conditions = [ | ||
555 | "t.type = 'table'", | ||
556 | "t.name NOT IN ('geometry_columns', 'spatial_ref_sys', 'sqlite_sequence')", | ||
557 | ]; | ||
558 | $params = []; | ||
559 | |||
560 | if ($tableName !== null) { | ||
561 | $conditions[] = 't.name = ?'; | ||
562 | $params[] = str_replace('.', '__', $tableName); | ||
563 | } | ||
564 | |||
565 | $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY t.name, i.seq'; | ||
566 | |||
567 | return $this->connection->executeQuery($sql, $params); | ||
568 | } | ||
569 | |||
570 | protected function selectForeignKeyColumns(string $databaseName, ?string $tableName = null): Result | ||
571 | { | ||
572 | $sql = <<<'SQL' | ||
573 | SELECT t.name AS table_name, | ||
574 | p.* | ||
575 | FROM sqlite_master t | ||
576 | JOIN pragma_foreign_key_list(t.name) p | ||
577 | ON p."seq" != '-1' | ||
578 | SQL; | ||
579 | |||
580 | $conditions = [ | ||
581 | "t.type = 'table'", | ||
582 | "t.name NOT IN ('geometry_columns', 'spatial_ref_sys', 'sqlite_sequence')", | ||
583 | ]; | ||
584 | $params = []; | ||
585 | |||
586 | if ($tableName !== null) { | ||
587 | $conditions[] = 't.name = ?'; | ||
588 | $params[] = str_replace('.', '__', $tableName); | ||
589 | } | ||
590 | |||
591 | $sql .= ' WHERE ' . implode(' AND ', $conditions) . ' ORDER BY t.name, p.id DESC, p.seq'; | ||
592 | |||
593 | return $this->connection->executeQuery($sql, $params); | ||
594 | } | ||
595 | |||
596 | /** | ||
597 | * {@inheritDoc} | ||
598 | */ | ||
599 | protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array | ||
600 | { | ||
601 | if ($tableName === null) { | ||
602 | $tables = $this->listTableNames(); | ||
603 | } else { | ||
604 | $tables = [$tableName]; | ||
605 | } | ||
606 | |||
607 | $tableOptions = []; | ||
608 | foreach ($tables as $table) { | ||
609 | $comment = $this->parseTableCommentFromSQL($table, $this->getCreateTableSQL($table)); | ||
610 | |||
611 | if ($comment === null) { | ||
612 | continue; | ||
613 | } | ||
614 | |||
615 | $tableOptions[$table]['comment'] = $comment; | ||
616 | } | ||
617 | |||
618 | return $tableOptions; | ||
619 | } | ||
620 | } | ||