From 4a21dfc881bd60e7460c432749fda5643789fd11 Mon Sep 17 00:00:00 2001 From: liushengsong Date: Fri, 27 Mar 2026 15:40:36 +0800 Subject: [PATCH] Fix ORCA permission checking crash with RTEPermissionInfo 1. orca.c: transformGroupedWindows() incorrectly created an RTEPermissionInfo with relid=0 for a subquery RTE. Per PG16 commit a61b1f74, only RTE_RELATION entries need RTEPermissionInfo. This caused Assert(OidIsValid(perminfo->relid)) failure when ORCA translated ROLLUP + window function queries. 2. matview.c: replace_rte_with_delta() converted RTE_RELATION to RTE_SUBQUERY but forgot to clear perminfoindex, causing Assert(rte->rtekind == RTE_RELATION || ...) failure during IVM incremental maintenance with ORCA enabled. Also fix subquery not inheriting rteperminfos, and correct AddPerfmInfo/Perfission typos. Co-Authored-By: Claude Opus 4.6 --- src/backend/commands/matview.c | 2 ++ src/backend/gpopt/gpdbwrappers.cpp | 5 +++-- src/backend/gpopt/translate/CContextDXLToPlStmt.cpp | 8 ++++---- src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp | 2 +- src/backend/optimizer/plan/orca.c | 10 ++++------ src/include/gpopt/translate/CContextDXLToPlStmt.h | 6 +++--- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index de5b6992b6d..81c1a3340fb 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -2340,6 +2340,7 @@ get_prestate_rte(RangeTblEntry *rte, MV_TriggerTable *table, rte->relkind = 0; rte->rellockmode = 0; rte->tablesample = NULL; + rte->perminfoindex = 0; /* subquery RTE does not need permission check */ rte->inh = false; /* must not be set for a subquery */ return rte; @@ -2403,6 +2404,7 @@ replace_rte_with_delta(RangeTblEntry *rte, MV_TriggerTable *table, bool is_new, rte->relkind = 0; rte->rellockmode = 0; rte->tablesample = NULL; + rte->perminfoindex = 0; /* subquery RTE does not need permission check */ rte->inh = false; /* must not be set for a subquery */ return rte; diff --git a/src/backend/gpopt/gpdbwrappers.cpp b/src/backend/gpopt/gpdbwrappers.cpp index 947cd3f985a..5eb9f294641 100644 --- a/src/backend/gpopt/gpdbwrappers.cpp +++ b/src/backend/gpopt/gpdbwrappers.cpp @@ -2818,11 +2818,12 @@ gpdb::TestexprIsHashable(Node *testexpr, List *param_ids) } RTEPermissionInfo * -gpdb::GetRTEPermissionInfo(List *rteperminfos, - const RangeTblEntry *rte) +gpdb::GetRTEPermissionInfo(List *rteperminfos, const RangeTblEntry *rte) { GP_WRAP_START; { + // Cast away const: upstream getRTEPermissionInfo() only reads + // rte->perminfoindex and rte->relid but its signature lacks const. return getRTEPermissionInfo(rteperminfos, (RangeTblEntry *) rte); } GP_WRAP_END; diff --git a/src/backend/gpopt/translate/CContextDXLToPlStmt.cpp b/src/backend/gpopt/translate/CContextDXLToPlStmt.cpp index 16eec1ba5a6..b31508be45c 100644 --- a/src/backend/gpopt/translate/CContextDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CContextDXLToPlStmt.cpp @@ -594,16 +594,16 @@ CContextDXLToPlStmt::GetRTEIndexByAssignedQueryId( //--------------------------------------------------------------------------- // @function: -// CContextDXLToPlStmt::AddPerfmInfo +// CContextDXLToPlStmt::AddPermInfo // // @doc: -// Add a Perfission Info list entry +// Add a Permission Info list entry // //--------------------------------------------------------------------------- void -CContextDXLToPlStmt::AddPerfmInfo(RTEPermissionInfo *pi) +CContextDXLToPlStmt::AddPermInfo(RTEPermissionInfo *pi) { - // add rte to rtable entries list + // add permission info to list m_perminfo_list = gpdb::LAppend(m_perminfo_list, pi); } diff --git a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp index f634786e982..ff259f2db8c 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp @@ -5336,7 +5336,7 @@ CTranslatorDXLToPlStmt::ProcessDXLTblDescr( rte->eref = alias; rte->alias = alias; - m_dxl_to_plstmt_context->AddPerfmInfo(pi); + m_dxl_to_plstmt_context->AddPermInfo(pi); // set up rte <> perm info link. rte->perminfoindex = gpdb::ListLength( diff --git a/src/backend/optimizer/plan/orca.c b/src/backend/optimizer/plan/orca.c index ffebbc8d8d7..255db185c5e 100644 --- a/src/backend/optimizer/plan/orca.c +++ b/src/backend/optimizer/plan/orca.c @@ -518,7 +518,6 @@ transformGroupedWindows(Node *node, void *context) Query *subq; RangeTblEntry *rte; - RTEPermissionInfo *perminfo; RangeTblRef *ref; Alias *alias; bool hadSubLinks = qry->hasSubLinks; @@ -545,6 +544,7 @@ transformGroupedWindows(Node *node, void *context) /* Core of subquery input table expression: */ subq->rtable = qry->rtable; /* before windowing */ + subq->rteperminfos = qry->rteperminfos; /* before windowing */ subq->jointree = qry->jointree; /* before windowing */ subq->targetList = NIL; /* fill in later */ @@ -578,11 +578,9 @@ transformGroupedWindows(Node *node, void *context) rte->eref = NULL; /* fill in later */ rte->inFromCl = true; - perminfo = makeNode(RTEPermissionInfo); - perminfo->requiredPerms = ACL_SELECT; - /* - * Default? rte->inh = 0; rte->checkAsUser = 0; + * Subquery RTEs do not need RTEPermissionInfo. Permission checks + * are performed on the base tables within the subquery itself. */ /* @@ -605,7 +603,7 @@ transformGroupedWindows(Node *node, void *context) /* Core of outer query input table expression: */ qry->rtable = list_make1(rte); - qry->rteperminfos = list_make1(perminfo); + qry->rteperminfos = NIL; qry->jointree = (FromExpr *) makeNode(FromExpr); qry->jointree->fromlist = list_make1(ref); qry->jointree->quals = NULL; diff --git a/src/include/gpopt/translate/CContextDXLToPlStmt.h b/src/include/gpopt/translate/CContextDXLToPlStmt.h index 1b88fb56711..8ff32e9b0f5 100644 --- a/src/include/gpopt/translate/CContextDXLToPlStmt.h +++ b/src/include/gpopt/translate/CContextDXLToPlStmt.h @@ -109,7 +109,7 @@ class CContextDXLToPlStmt // list of all rtable entries List *m_rtable_entries_list; - // list of all rtable entries + // list of all RTEPermissionInfo entries List *m_perminfo_list; // list of all subplan entries @@ -249,8 +249,8 @@ class CContextDXLToPlStmt Index GetRTEIndexByAssignedQueryId(ULONG assigned_query_id_for_target_rel, BOOL *is_rte_exists); - // add a perm info. - void AddPerfmInfo(RTEPermissionInfo *pi); + // add a permission info entry + void AddPermInfo(RTEPermissionInfo *pi); // get perm info from m_perminfo_list by given index RTEPermissionInfo *GetPermInfoByIndex(Index index);