Skip to content

Commit f2c27eb

Browse files
author
liushengsong
committed
Fix ORCA foreign scan crash with RTEPermissionInfo mismatch
BuildForeignScan() calls build_simple_rel() which looks up RTEPermissionInfo via root->parse->rteperminfos using the RTE's perminfoindex. When ORCA translates DXL back to a PlannedStmt, it creates new RTEs with its own perminfoindex numbering, but passes m_orig_query (the rewritten query) to BuildForeignScan. After the rewriter expands external table ON SELECT rules into subqueries, the outer query's rteperminfos shrinks, causing a mismatch: e.g. perminfoindex=2 but rteperminfos has only 1 entry. Fix by temporarily swapping m_orig_query->rteperminfos with ORCA's own perminfos list around CreateForeignScan calls, so the indices are consistent. This covers both static and dynamic foreign scans.
1 parent 44bbe12 commit f2c27eb

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,24 @@ CTranslatorDXLToPlStmt::TranslateDXLTblScan(
659659

660660
// The postgres_fdw wrapper does not support row level security. So
661661
// passing only the query_quals while creating the foreign scan node.
662+
//
663+
// BuildForeignScan internally calls build_simple_rel which looks up
664+
// RTEPermissionInfo via root->parse->rteperminfos. The RTE here was
665+
// newly created by ORCA with its own perminfoindex numbering, which
666+
// may not match m_orig_query->rteperminfos (e.g. after the rewriter
667+
// expands external-table ON SELECT rules into subqueries the outer
668+
// query's rteperminfos shrinks). Temporarily swap in ORCA's own
669+
// perminfos list so the indices are consistent.
670+
Query *orig_query = m_dxl_to_plstmt_context->m_orig_query;
671+
List *saved_perminfos = orig_query->rteperminfos;
672+
orig_query->rteperminfos =
673+
m_dxl_to_plstmt_context->GetPermInfosList();
674+
662675
ForeignScan *foreign_scan =
663676
gpdb::CreateForeignScan(oidRel, index, query_quals, targetlist,
664-
m_dxl_to_plstmt_context->m_orig_query, rte);
677+
orig_query, rte);
678+
679+
orig_query->rteperminfos = saved_perminfos;
665680
foreign_scan->scan.scanrelid = index;
666681
plan = &(foreign_scan->scan.plan);
667682
plan_return = (Plan *) foreign_scan;
@@ -4611,9 +4626,15 @@ CTranslatorDXLToPlStmt::TranslateDXLDynForeignScan(
46114626
RelationGetDescr(childRel),
46124627
index, qual, targetlist);
46134628

4629+
// Same perminfos swap as in the non-dynamic foreign scan path above.
4630+
Query *orig_query = m_dxl_to_plstmt_context->m_orig_query;
4631+
List *saved_perminfos = orig_query->rteperminfos;
4632+
orig_query->rteperminfos =
4633+
m_dxl_to_plstmt_context->GetPermInfosList();
4634+
46144635
ForeignScan *foreign_scan_first_part =
46154636
gpdb::CreateForeignScan(oid_first_child, index, qual, targetlist,
4616-
m_dxl_to_plstmt_context->m_orig_query, rte);
4637+
orig_query, rte);
46174638

46184639
// Set the plan fields to the first partition. We still want the plan type to be
46194640
// a dynamic foreign scan
@@ -4645,11 +4666,14 @@ CTranslatorDXLToPlStmt::TranslateDXLDynForeignScan(
46454666

46464667
ForeignScan *foreign_scan =
46474668
gpdb::CreateForeignScan(rte->relid, index, qual, targetlist,
4648-
m_dxl_to_plstmt_context->m_orig_query, rte);
4669+
orig_query, rte);
46494670

46504671
dyn_foreign_scan->fdw_private_list = gpdb::LAppend(
46514672
dyn_foreign_scan->fdw_private_list, foreign_scan->fdw_private);
46524673
}
4674+
4675+
orig_query->rteperminfos = saved_perminfos;
4676+
46534677
// convert qual and targetlist back to root relation. This is used by the
46544678
// executor node to remap to the children
46554679
gpdb::RelationWrapper prevRel = gpdb::GetRelation(rte->relid);

0 commit comments

Comments
 (0)