1515use Yiisoft \Db \Exception \NotSupportedException ;
1616use Yiisoft \Db \Helper \DbArrayHelper ;
1717use Yiisoft \Db \Schema \Column \ColumnInterface ;
18+ use Yiisoft \Db \Schema \SchemaInterface ;
19+ use Yiisoft \Db \Schema \TableSchema ;
1820use Yiisoft \Db \Schema \TableSchemaInterface ;
1921
2022use function array_change_key_case ;
2123use function array_column ;
2224use function array_map ;
23- use function implode ;
2425use function in_array ;
2526use function preg_replace ;
2627use function strtolower ;
5960 */
6061final class Schema extends AbstractPdoSchema
6162{
62- public function __construct ( protected ConnectionInterface $ db , SchemaCache $ schemaCache , string $ defaultSchema )
63+ protected function findConstraints ( TableSchemaInterface $ table ): void
6364 {
64- $ this ->defaultSchema = $ defaultSchema ;
65- parent ::__construct ($ db , $ schemaCache );
65+ $ tableName = $ this ->resolveFullName ($ table ->getName (), $ table ->getSchemaName ());
66+
67+ $ table ->checks (...$ this ->getTableMetadata ($ tableName , SchemaInterface::CHECKS ));
68+ $ table ->foreignKeys (...$ this ->getTableMetadata ($ tableName , SchemaInterface::FOREIGN_KEYS ));
69+ $ table ->indexes (...$ this ->getTableMetadata ($ tableName , SchemaInterface::INDEXES ));
6670 }
6771
68- protected function resolveTableName ( string $ name ): TableSchemaInterface
72+ public function __construct ( protected ConnectionInterface $ db , SchemaCache $ schemaCache , string $ defaultSchema )
6973 {
70- $ resolvedName = new TableSchema ();
71-
72- $ parts = $ this ->db ->getQuoter ()->getTableNameParts ($ name );
73-
74- $ resolvedName ->name ($ parts ['name ' ]);
75- $ resolvedName ->schemaName ($ parts ['schemaName ' ] ?? $ this ->defaultSchema );
76-
77- $ resolvedName ->fullName (
78- $ resolvedName ->getSchemaName () !== $ this ->defaultSchema ?
79- implode ('. ' , $ parts ) : $ resolvedName ->getName ()
80- );
81-
82- return $ resolvedName ;
74+ $ this ->defaultSchema = $ defaultSchema ;
75+ parent ::__construct ($ db , $ schemaCache );
8376 }
8477
8578 /**
@@ -109,7 +102,7 @@ protected function findTableComment(TableSchemaInterface $tableSchema): void
109102 SQL ;
110103
111104 $ comment = $ this ->db ->createCommand ($ sql , [
112- ':schemaName ' => $ tableSchema ->getSchemaName (),
105+ ':schemaName ' => $ tableSchema ->getSchemaName () ?: $ this -> defaultSchema ,
113106 ':tableName ' => $ tableSchema ->getName (),
114107 ])->queryScalar ();
115108
@@ -216,23 +209,19 @@ protected function loadResultColumn(array $metadata): ColumnInterface|null
216209
217210 protected function loadTableSchema (string $ name ): TableSchemaInterface |null
218211 {
219- $ table = $ this ->resolveTableName ($ name );
220- $ this ->findTableComment ($ table );
212+ $ table = new TableSchema (...$ this ->db ->getQuoter ()->getTableNameParts ($ name ));
221213
222214 if ($ this ->findColumns ($ table )) {
215+ $ this ->findTableComment ($ table );
223216 $ this ->findConstraints ($ table );
217+ $ table ->sequenceName ($ this ->getTableSequenceName ($ table ->getName ()));
218+
224219 return $ table ;
225220 }
226221
227222 return null ;
228223 }
229224
230- protected function loadTablePrimaryKey (string $ tableName ): Index |null
231- {
232- /** @var Index|null */
233- return $ this ->loadTableConstraints ($ tableName , self ::PRIMARY_KEY );
234- }
235-
236225 protected function loadTableForeignKeys (string $ tableName ): array
237226 {
238227 /** @var ForeignKey[] */
@@ -277,7 +266,7 @@ protected function loadTableIndexes(string $tableName): array
277266 }
278267
279268 /** @var string[] $columnNames */
280- $ result [] = new Index (
269+ $ result [$ name ] = new Index (
281270 $ name ,
282271 $ columnNames ,
283272 (bool ) $ index [0 ]['is_unique ' ],
@@ -288,12 +277,6 @@ protected function loadTableIndexes(string $tableName): array
288277 return $ result ;
289278 }
290279
291- protected function loadTableUniques (string $ tableName ): array
292- {
293- /** @var Index[] */
294- return $ this ->loadTableConstraints ($ tableName , self ::UNIQUES );
295- }
296-
297280 protected function loadTableChecks (string $ tableName ): array
298281 {
299282 /** @var Check[] */
@@ -317,7 +300,7 @@ protected function loadTableDefaultValues(string $tableName): array
317300 */
318301 protected function findColumns (TableSchemaInterface $ table ): bool
319302 {
320- $ schemaName = $ table ->getSchemaName ();
303+ $ schemaName = $ table ->getSchemaName () ?: $ this -> defaultSchema ;
321304 $ tableName = $ table ->getName ();
322305
323306 $ sql = <<<SQL
@@ -468,136 +451,17 @@ private function loadColumn(array $info): ColumnInterface
468451 return $ this ->db ->getColumnFactory ()->fromDbType ($ dbType , $ columnInfo );
469452 }
470453
471- /**
472- * Finds constraints and fills them into TableSchemaInterface object passed.
473- *
474- * @psalm-suppress PossiblyNullArrayOffset
475- */
476- protected function findConstraints (TableSchemaInterface $ table ): void
477- {
478- $ sql = <<<SQL
479- SELECT
480- /*+ PUSH_PRED(C) PUSH_PRED(D) PUSH_PRED(E) */
481- D.CONSTRAINT_NAME,
482- D.CONSTRAINT_TYPE,
483- C.COLUMN_NAME,
484- C.POSITION,
485- D.R_CONSTRAINT_NAME,
486- E.TABLE_NAME AS TABLE_REF,
487- F.COLUMN_NAME AS COLUMN_REF,
488- C.TABLE_NAME
489- FROM ALL_CONS_COLUMNS C
490- INNER JOIN ALL_CONSTRAINTS D ON D.OWNER = C.OWNER AND D.CONSTRAINT_NAME = C.CONSTRAINT_NAME
491- LEFT JOIN ALL_CONSTRAINTS E ON E.OWNER = D.R_OWNER AND E.CONSTRAINT_NAME = D.R_CONSTRAINT_NAME
492- LEFT JOIN ALL_CONS_COLUMNS F ON F.OWNER = E.OWNER AND F.CONSTRAINT_NAME = E.CONSTRAINT_NAME AND F.POSITION = C.POSITION
493- WHERE
494- C.OWNER = :schemaName
495- AND C.TABLE_NAME = :tableName
496- ORDER BY D.CONSTRAINT_NAME, C.POSITION
497- SQL ;
498-
499- /**
500- * @psalm-var array{
501- * array{
502- * constraint_name: string,
503- * constraint_type: string,
504- * column_name: string,
505- * position: string|null,
506- * r_constraint_name: string|null,
507- * table_ref: string|null,
508- * column_ref: string|null,
509- * table_name: string
510- * }
511- * } $rows
512- */
513- $ rows = $ this ->db ->createCommand (
514- $ sql ,
515- [':tableName ' => $ table ->getName (), ':schemaName ' => $ table ->getSchemaName ()]
516- )->queryAll ();
517-
518- $ constraints = [];
519-
520- foreach ($ rows as $ row ) {
521- /** @psalm-var string[] $row */
522- $ row = array_change_key_case ($ row );
523-
524- if ($ row ['constraint_type ' ] === 'P ' ) {
525- $ table ->getColumns ()[$ row ['column_name ' ]]->primaryKey (true );
526- $ table ->primaryKey ($ row ['column_name ' ]);
527-
528- if (empty ($ table ->getSequenceName ())) {
529- $ table ->sequenceName ($ this ->getTableSequenceName ($ table ->getName ()));
530- }
531- }
532-
533- if ($ row ['constraint_type ' ] !== 'R ' ) {
534- /**
535- * This condition isn't checked in `WHERE` because of an Oracle Bug:
536- *
537- * @link https://github.com/yiisoft/yii2/pull/8844
538- */
539- continue ;
540- }
541-
542- $ name = $ row ['constraint_name ' ];
543-
544- if (!isset ($ constraints [$ name ])) {
545- $ constraints [$ name ] = [
546- 'tableName ' => $ row ['table_ref ' ],
547- 'columns ' => [],
548- ];
549- }
550-
551- $ constraints [$ name ]['columns ' ][$ row ['column_name ' ]] = $ row ['column_ref ' ];
552- }
553-
554- foreach ($ constraints as $ index => $ constraint ) {
555- $ table ->foreignKey ($ index , [$ constraint ['tableName ' ], ...$ constraint ['columns ' ]]);
556- }
557- }
558-
559- public function findUniqueIndexes (TableSchemaInterface $ table ): array
560- {
561- $ query = <<<SQL
562- SELECT
563- DIC.INDEX_NAME,
564- DIC.COLUMN_NAME
565- FROM ALL_INDEXES DI
566- INNER JOIN ALL_IND_COLUMNS DIC ON DI.TABLE_NAME = DIC.TABLE_NAME AND DI.INDEX_NAME = DIC.INDEX_NAME
567- WHERE
568- DI.UNIQUENESS = 'UNIQUE'
569- AND DIC.TABLE_OWNER = :schemaName
570- AND DIC.TABLE_NAME = :tableName
571- ORDER BY DIC.TABLE_NAME, DIC.INDEX_NAME, DIC.COLUMN_POSITION
572- SQL ;
573- $ result = [];
574-
575- $ rows = $ this ->db ->createCommand (
576- $ query ,
577- [':tableName ' => $ table ->getName (), ':schemaName ' => $ table ->getschemaName ()]
578- )->queryAll ();
579-
580- /** @psalm-var array<array{INDEX_NAME: string, COLUMN_NAME: string}> $rows */
581- foreach ($ rows as $ row ) {
582- $ result [$ row ['INDEX_NAME ' ]][] = $ row ['COLUMN_NAME ' ];
583- }
584-
585- return $ result ;
586- }
587-
588454 /**
589455 * Loads multiple types of constraints and returns the specified ones.
590456 *
591457 * @param string $tableName The table name.
592458 * @param string $returnType The return type:
593- * - primaryKey
594459 * - foreignKeys
595- * - uniques
596460 * - checks
597461 *
598- * @return Check[]|ForeignKey[]|Index|Index[]|null Constraints.
462+ * @return Check[]|ForeignKey[] Constraints.
599463 */
600- private function loadTableConstraints (string $ tableName , string $ returnType ): array | Index | null
464+ private function loadTableConstraints (string $ tableName , string $ returnType ): array
601465 {
602466 $ sql = <<<SQL
603467 SELECT
@@ -616,7 +480,7 @@ private function loadTableConstraints(string $tableName, string $returnType): ar
616480 ON "fuc"."OWNER" = "uc"."R_OWNER" AND "fuc"."CONSTRAINT_NAME" = "uc"."R_CONSTRAINT_NAME"
617481 LEFT JOIN "USER_CONS_COLUMNS" "fuccol"
618482 ON "fuccol"."OWNER" = "fuc"."OWNER" AND "fuccol"."CONSTRAINT_NAME" = "fuc"."CONSTRAINT_NAME" AND "fuccol"."POSITION" = "uccol"."POSITION"
619- WHERE "uc"."OWNER" = :schemaName AND "uc"."TABLE_NAME" = :tableName
483+ WHERE "uc"."OWNER" = :schemaName AND "uc"."TABLE_NAME" = :tableName AND "uc"."CONSTRAINT_TYPE" IN ('R', 'C')
620484 ORDER BY "uccol"."POSITION" ASC
621485 SQL ;
622486
@@ -630,9 +494,7 @@ private function loadTableConstraints(string $tableName, string $returnType): ar
630494 $ constraints = DbArrayHelper::arrange ($ constraints , ['type ' , 'name ' ]);
631495
632496 $ result = [
633- self ::PRIMARY_KEY => null ,
634497 self ::FOREIGN_KEYS => [],
635- self ::UNIQUES => [],
636498 self ::CHECKS => [],
637499 ];
638500
@@ -642,41 +504,21 @@ private function loadTableConstraints(string $tableName, string $returnType): ar
642504 * @psalm-var ConstraintArray $constraint
643505 */
644506 foreach ($ names as $ name => $ constraint ) {
645- switch ($ type ) {
646- case 'P ' :
647- $ result [self ::PRIMARY_KEY ] = new Index (
648- $ name ,
649- array_column ($ constraint , 'column_name ' ),
650- true ,
651- true ,
652- );
653- break ;
654- case 'R ' :
655- $ result [self ::FOREIGN_KEYS ][] = new ForeignKey (
656- $ name ,
657- array_column ($ constraint , 'column_name ' ),
658- $ constraint [0 ]['foreign_table_schema ' ],
659- $ constraint [0 ]['foreign_table_name ' ],
660- array_column ($ constraint , 'foreign_column_name ' ),
661- $ constraint [0 ]['on_delete ' ],
662- null ,
663- );
664- break ;
665- case 'U ' :
666- $ result [self ::UNIQUES ][] = new Index (
667- $ name ,
668- array_column ($ constraint , 'column_name ' ),
669- true ,
670- );
671- break ;
672- case 'C ' :
673- $ result [self ::CHECKS ][] = new Check (
674- $ name ,
675- array_column ($ constraint , 'column_name ' ),
676- $ constraint [0 ]['check_expr ' ],
677- );
678- break ;
679- }
507+ match ($ type ) {
508+ 'R ' => $ result [self ::FOREIGN_KEYS ][$ name ] = new ForeignKey (
509+ $ name ,
510+ array_column ($ constraint , 'column_name ' ),
511+ $ constraint [0 ]['foreign_table_schema ' ],
512+ $ constraint [0 ]['foreign_table_name ' ],
513+ array_column ($ constraint , 'foreign_column_name ' ),
514+ $ constraint [0 ]['on_delete ' ],
515+ ),
516+ 'C ' => $ result [self ::CHECKS ][$ name ] = new Check (
517+ $ name ,
518+ array_column ($ constraint , 'column_name ' ),
519+ $ constraint [0 ]['check_expr ' ],
520+ ),
521+ };
680522 }
681523 }
682524
0 commit comments