4
4
5
5
namespace Yiisoft \Db \Sqlite ;
6
6
7
- use Throwable ;
8
7
use Yiisoft \Db \Constant \ColumnType ;
9
8
use Yiisoft \Db \Constant \ReferentialAction ;
10
9
use Yiisoft \Db \Constraint \Check ;
11
10
use Yiisoft \Db \Constraint \ForeignKey ;
12
11
use Yiisoft \Db \Constraint \Index ;
13
12
use Yiisoft \Db \Driver \Pdo \AbstractPdoSchema ;
14
- use Yiisoft \Db \Exception \Exception ;
15
- use Yiisoft \Db \Exception \InvalidConfigException ;
16
13
use Yiisoft \Db \Exception \NotSupportedException ;
17
14
use Yiisoft \Db \Helper \DbArrayHelper ;
18
15
use Yiisoft \Db \Schema \Column \ColumnInterface ;
16
+ use Yiisoft \Db \Schema \SchemaInterface ;
17
+ use Yiisoft \Db \Schema \TableSchema ;
19
18
use Yiisoft \Db \Schema \TableSchemaInterface ;
20
19
21
20
use function array_change_key_case ;
68
67
*/
69
68
final class Schema extends AbstractPdoSchema
70
69
{
70
+ protected function findConstraints (TableSchemaInterface $ table ): void
71
+ {
72
+ $ tableName = $ this ->resolveFullName ($ table ->getName (), $ table ->getSchemaName ());
73
+
74
+ $ table ->checks (...$ this ->getTableMetadata ($ tableName , SchemaInterface::CHECKS ));
75
+ $ table ->foreignKeys (...$ this ->getTableMetadata ($ tableName , SchemaInterface::FOREIGN_KEYS ));
76
+ $ table ->indexes (...$ this ->getTableMetadata ($ tableName , SchemaInterface::INDEXES ));
77
+ }
78
+
71
79
protected function findTableNames (string $ schema = '' ): array
72
80
{
73
81
/** @var string[] */
@@ -78,10 +86,7 @@ protected function findTableNames(string $schema = ''): array
78
86
79
87
protected function loadTableSchema (string $ name ): TableSchemaInterface |null
80
88
{
81
- $ table = new TableSchema ();
82
-
83
- $ table ->name ($ name );
84
- $ table ->fullName ($ name );
89
+ $ table = new TableSchema ($ name );
85
90
86
91
if ($ this ->findColumns ($ table )) {
87
92
$ this ->findConstraints ($ table );
@@ -92,12 +97,6 @@ protected function loadTableSchema(string $name): TableSchemaInterface|null
92
97
return null ;
93
98
}
94
99
95
- protected function loadTablePrimaryKey (string $ tableName ): Index |null
96
- {
97
- /** @var Index|null */
98
- return $ this ->loadTableConstraints ($ tableName , self ::PRIMARY_KEY );
99
- }
100
-
101
100
protected function loadTableForeignKeys (string $ tableName ): array
102
101
{
103
102
$ result = [];
@@ -138,14 +137,45 @@ protected function loadTableForeignKeys(string $tableName): array
138
137
139
138
protected function loadTableIndexes (string $ tableName ): array
140
139
{
141
- /** @var Index[] */
142
- return $ this ->loadTableConstraints ( $ tableName, self :: INDEXES );
143
- }
140
+ $ indexList = $ this -> db
141
+ -> createCommand ( ' PRAGMA INDEX_LIST( ' . $ this ->db -> getQuoter ()-> quoteValue ( $ tableName) . ' ) ' )
142
+ -> queryAll ();
144
143
145
- protected function loadTableUniques (string $ tableName ): array
146
- {
147
- /** @var Index[] */
148
- return $ this ->loadTableConstraints ($ tableName , self ::UNIQUES );
144
+ /** @psalm-var IndexListInfo[] $indexes */
145
+ $ indexes = array_map (array_change_key_case (...), $ indexList );
146
+ $ result = [];
147
+ $ hasPrimaryKey = false ;
148
+
149
+ foreach ($ indexes as $ index ) {
150
+ $ columns = $ this ->getPragmaIndexInfo ($ index ['name ' ]);
151
+
152
+ $ result [$ index ['name ' ]] = new Index (
153
+ $ index ['name ' ],
154
+ array_column ($ columns , 'name ' ),
155
+ (bool ) $ index ['unique ' ],
156
+ $ index ['origin ' ] === 'pk ' ,
157
+ );
158
+
159
+ $ hasPrimaryKey = $ hasPrimaryKey || $ index ['origin ' ] === 'pk ' ;
160
+ }
161
+
162
+ if (!$ hasPrimaryKey ) {
163
+ /**
164
+ * Extra check for PK in case of `INTEGER PRIMARY KEY` with ROWID.
165
+ *
166
+ * @link https://www.sqlite.org/lang_createtable.html#primkeyconst
167
+ */
168
+ $ tableColumns = $ this ->loadTableColumnsInfo ($ tableName );
169
+
170
+ foreach ($ tableColumns as $ tableColumn ) {
171
+ if ($ tableColumn ['pk ' ] > 0 ) {
172
+ $ result ['' ] = new Index ('' , [$ tableColumn ['name ' ]], true , true );
173
+ break ;
174
+ }
175
+ }
176
+ }
177
+
178
+ return $ result ;
149
179
}
150
180
151
181
protected function loadTableChecks (string $ tableName ): array
@@ -199,15 +229,11 @@ protected function loadTableDefaultValues(string $tableName): array
199
229
*
200
230
* @param TableSchemaInterface $table The table metadata.
201
231
*
202
- * @throws Exception
203
- * @throws InvalidConfigException
204
- * @throws Throwable
205
- *
206
232
* @return bool Whether the table exists in the database.
207
233
*/
208
234
protected function findColumns (TableSchemaInterface $ table ): bool
209
235
{
210
- $ columns = $ this ->getPragmaTableInfo ($ table ->getName ());
236
+ $ columns = $ this ->loadTableColumnsInfo ($ table ->getName ());
211
237
$ jsonColumns = $ this ->getJsonColumns ($ table );
212
238
213
239
foreach ($ columns as $ info ) {
@@ -220,10 +246,6 @@ protected function findColumns(TableSchemaInterface $table): bool
220
246
221
247
$ column = $ this ->loadColumn ($ info );
222
248
$ table ->column ($ info ['name ' ], $ column );
223
-
224
- if ($ column ->isPrimaryKey ()) {
225
- $ table ->primaryKey ($ info ['name ' ]);
226
- }
227
249
}
228
250
229
251
$ column = count ($ table ->getPrimaryKey ()) === 1 ? $ table ->getColumn ($ table ->getPrimaryKey ()[0 ]) : null ;
@@ -236,49 +258,6 @@ protected function findColumns(TableSchemaInterface $table): bool
236
258
return !empty ($ columns );
237
259
}
238
260
239
- /**
240
- * Collects the foreign key column details for the given table.
241
- *
242
- * @param TableSchemaInterface $table The table metadata.
243
- */
244
- protected function findConstraints (TableSchemaInterface $ table ): void
245
- {
246
- /** @psalm-var ForeignKey[] $foreignKeysList */
247
- $ foreignKeysList = $ this ->getTableForeignKeys ($ table ->getName (), true );
248
-
249
- foreach ($ foreignKeysList as $ foreignKey ) {
250
- /** @var array<string> $columnNames */
251
- $ columnNames = $ foreignKey ->columnNames ;
252
- $ columnNames = array_combine ($ columnNames , $ foreignKey ->foreignColumnNames );
253
-
254
- $ foreignReference = [$ foreignKey ->foreignTableName , ...$ columnNames ];
255
-
256
- /** @psalm-suppress InvalidCast */
257
- $ table ->foreignKey ($ foreignKey ->name , $ foreignReference );
258
- }
259
- }
260
-
261
- public function findUniqueIndexes (TableSchemaInterface $ table ): array
262
- {
263
- /** @psalm-var IndexListInfo[] $indexList */
264
- $ indexList = $ this ->getPragmaIndexList ($ table ->getName ());
265
- $ uniqueIndexes = [];
266
-
267
- foreach ($ indexList as $ index ) {
268
- $ indexName = $ index ['name ' ];
269
- $ indexInfo = $ this ->getPragmaIndexInfo ($ index ['name ' ]);
270
-
271
- if ($ index ['unique ' ]) {
272
- $ uniqueIndexes [$ indexName ] = [];
273
- foreach ($ indexInfo as $ row ) {
274
- $ uniqueIndexes [$ indexName ][] = $ row ['name ' ];
275
- }
276
- }
277
- }
278
-
279
- return $ uniqueIndexes ;
280
- }
281
-
282
261
/**
283
262
* @throws NotSupportedException
284
263
*/
@@ -353,71 +332,14 @@ private function loadColumn(array $info): ColumnInterface
353
332
*/
354
333
private function loadTableColumnsInfo (string $ tableName ): array
355
334
{
356
- $ tableColumns = $ this ->getPragmaTableInfo ($ tableName );
335
+ $ tableColumns = $ this ->db ->createCommand (
336
+ 'PRAGMA TABLE_INFO( ' . $ this ->db ->getQuoter ()->quoteSimpleTableName ($ tableName ) . ') '
337
+ )->queryAll ();
338
+
357
339
/** @psalm-var ColumnInfo[] */
358
340
return array_map (array_change_key_case (...), $ tableColumns );
359
341
}
360
342
361
- /**
362
- * Loads multiple types of constraints and returns the specified ones.
363
- *
364
- * @param string $tableName The table name.
365
- * @param string $returnType Return type: (primaryKey, indexes, uniques).
366
- *
367
- * @psalm-return Index[]|Index|null
368
- */
369
- private function loadTableConstraints (string $ tableName , string $ returnType ): array |Index |null
370
- {
371
- $ indexList = $ this ->getPragmaIndexList ($ tableName );
372
- /** @psalm-var IndexListInfo[] $indexes */
373
- $ indexes = array_map (array_change_key_case (...), $ indexList );
374
- $ result = [
375
- self ::PRIMARY_KEY => null ,
376
- self ::INDEXES => [],
377
- self ::UNIQUES => [],
378
- ];
379
-
380
- foreach ($ indexes as $ index ) {
381
- $ columns = $ this ->getPragmaIndexInfo ($ index ['name ' ]);
382
-
383
- if ($ index ['origin ' ] === 'pk ' ) {
384
- $ result [self ::PRIMARY_KEY ] = new Index ('' , array_column ($ columns , 'name ' ), true , true );
385
- } elseif ($ index ['origin ' ] === 'u ' ) {
386
- $ result [self ::UNIQUES ][] = new Index ($ index ['name ' ], array_column ($ columns , 'name ' ), true );
387
- }
388
-
389
- $ result [self ::INDEXES ][] = new Index (
390
- $ index ['name ' ],
391
- array_column ($ columns , 'name ' ),
392
- (bool ) $ index ['unique ' ],
393
- $ index ['origin ' ] === 'pk ' ,
394
- );
395
- }
396
-
397
- if (!isset ($ result [self ::PRIMARY_KEY ])) {
398
- /**
399
- * Extra check for PK in case of `INTEGER PRIMARY KEY` with ROWID.
400
- *
401
- * @link https://www.sqlite.org/lang_createtable.html#primkeyconst
402
- */
403
- $ tableColumns = $ this ->loadTableColumnsInfo ($ tableName );
404
-
405
- foreach ($ tableColumns as $ tableColumn ) {
406
- if ($ tableColumn ['pk ' ] > 0 ) {
407
- $ result [self ::PRIMARY_KEY ] = new Index ('' , [$ tableColumn ['name ' ]], true , true );
408
- $ result [self ::INDEXES ][] = $ result [self ::PRIMARY_KEY ];
409
- break ;
410
- }
411
- }
412
- }
413
-
414
- foreach ($ result as $ type => $ data ) {
415
- $ this ->setTableMetadata ($ tableName , $ type , $ data );
416
- }
417
-
418
- return $ result [$ returnType ];
419
- }
420
-
421
343
/**
422
344
* @psalm-return list<ForeignKeyInfo>
423
345
*/
@@ -448,28 +370,6 @@ private function getPragmaIndexInfo(string $name): array
448
370
return $ column ;
449
371
}
450
372
451
- /**
452
- * @psalm-return IndexListInfo[]
453
- */
454
- private function getPragmaIndexList (string $ tableName ): array
455
- {
456
- /** @psalm-var IndexListInfo[] */
457
- return $ this ->db
458
- ->createCommand ('PRAGMA INDEX_LIST( ' . $ this ->db ->getQuoter ()->quoteValue ($ tableName ) . ') ' )
459
- ->queryAll ();
460
- }
461
-
462
- /**
463
- * @psalm-return ColumnInfo[]
464
- */
465
- private function getPragmaTableInfo (string $ tableName ): array
466
- {
467
- /** @psalm-var ColumnInfo[] */
468
- return $ this ->db ->createCommand (
469
- 'PRAGMA TABLE_INFO( ' . $ this ->db ->getQuoter ()->quoteSimpleTableName ($ tableName ) . ') '
470
- )->queryAll ();
471
- }
472
-
473
373
protected function findViewNames (string $ schema = '' ): array
474
374
{
475
375
/** @var string[] */
@@ -484,7 +384,7 @@ private function getJsonColumns(TableSchemaInterface $table): array
484
384
{
485
385
$ result = [];
486
386
/** @psalm-var Check[] $checks */
487
- $ checks = $ this ->getTableChecks (( string ) $ table ->getFullName ());
387
+ $ checks = $ this ->getTableChecks ($ table ->getFullName ());
488
388
$ regexp = '/\bjson_valid\(\s*["`\[]?(.+?)["`\]]?\s*\)/i ' ;
489
389
490
390
foreach ($ checks as $ check ) {
0 commit comments