@@ -646,44 +646,55 @@ async def get_related_tables(self, table_name: str) -> Dict[str, List[str]]:
646646 conn = await self .get_connection ()
647647 try :
648648 cursor = conn .cursor ()
649+ requested_table = table_name .upper ()
649650 schema = await self ._get_effective_schema (conn )
650-
651- # Get tables referenced by this table
652- referenced_tables_result = await self ._execute_cursor_fetch (cursor , """
653- SELECT /*+ RESULT_CACHE LEADING(ac acc) USE_NL(acc) */
654- DISTINCT acc.table_name AS referenced_table
655- FROM all_constraints ac
656- JOIN all_cons_columns acc ON acc.constraint_name = ac.r_constraint_name
657- AND acc.owner = ac.owner
658- WHERE ac.constraint_type = 'R'
659- AND ac.table_name = :table_name
660- AND ac.owner = :owner
661- """ , table_name = table_name .upper (), owner = schema )
662-
663- referenced_tables = [row [0 ] for row in referenced_tables_result ]
664-
665- # Get tables that reference this table
666- referencing_tables_result = await self ._execute_cursor_fetch (cursor , """
667- WITH pk_constraints AS (
668- SELECT /*+ MATERIALIZE */ constraint_name
669- FROM all_constraints
670- WHERE table_name = :table_name
671- AND constraint_type IN ('P', 'U')
672- AND owner = :owner
673- )
674- SELECT /*+ RESULT_CACHE LEADING(ac pk) USE_NL(pk) */ DISTINCT ac.table_name AS referencing_table
675- FROM all_constraints ac
676- JOIN pk_constraints pk ON ac.r_constraint_name = pk.constraint_name
677- WHERE ac.constraint_type = 'R'
678- AND ac.owner = :owner
679- """ , table_name = table_name .upper (), owner = schema )
680-
681- referencing_tables = [row [0 ] for row in referencing_tables_result ]
682-
683- return {
684- 'referenced_tables' : referenced_tables ,
685- 'referencing_tables' : referencing_tables
686- }
651+
652+ # Helper to run the two directional queries for a given owner
653+ async def _run_for_owner (owner : str ):
654+ # Tables this table references (parent tables)
655+ ref_rows = await self ._execute_cursor_fetch (cursor , """
656+ SELECT /*+ RESULT_CACHE */ DISTINCT parent_cols.table_name
657+ FROM all_constraints fk
658+ JOIN all_constraints pk
659+ ON pk.constraint_name = fk.r_constraint_name
660+ AND pk.owner = fk.r_owner
661+ JOIN all_cons_columns parent_cols
662+ ON parent_cols.constraint_name = pk.constraint_name
663+ AND parent_cols.owner = pk.owner
664+ WHERE fk.constraint_type = 'R'
665+ AND fk.table_name = :table_name
666+ AND fk.owner = :owner
667+ """ , table_name = requested_table , owner = owner )
668+
669+ # Tables that reference this table (child tables)
670+ referencing_rows = await self ._execute_cursor_fetch (cursor , """
671+ SELECT /*+ RESULT_CACHE */ DISTINCT fk.table_name
672+ FROM all_constraints pk
673+ JOIN all_constraints fk
674+ ON fk.r_constraint_name = pk.constraint_name
675+ AND fk.r_owner = pk.owner
676+ WHERE pk.constraint_type IN ('P','U')
677+ AND pk.table_name = :table_name
678+ AND pk.owner = :owner
679+ AND fk.constraint_type = 'R'
680+ """ , table_name = requested_table , owner = owner )
681+
682+ return [r [0 ] for r in ref_rows ], [r [0 ] for r in referencing_rows ]
683+
684+ # First attempt with the effective schema (target_schema or connection user)
685+ referenced_tables , referencing_tables = await _run_for_owner (schema )
686+
687+ # If nothing found at all, attempt to discover actual owner of the table and retry once
688+ if not referenced_tables and not referencing_tables :
689+ owner_rows = await self ._execute_cursor_fetch (cursor , """
690+ SELECT DISTINCT owner FROM all_tables WHERE table_name = :table_name
691+ """ , table_name = requested_table )
692+ if owner_rows :
693+ actual_owner = owner_rows [0 ][0 ]
694+ if actual_owner and actual_owner .upper () != schema :
695+ referenced_tables , referencing_tables = await _run_for_owner (actual_owner .upper ())
696+
697+ return { 'referenced_tables' : referenced_tables , 'referencing_tables' : referencing_tables }
687698
688699 finally :
689700 await self ._close_connection (conn )
0 commit comments