PG18: Fix "Unrecognized range table id" in INSERT .. SELECT planning (#8256)

The error `Unrecognized range table id` seen in regress test
`insert_select_into_local_tables` is a consequence of the INSERT ..
SELECT planner getting confused by a SELECT query with a GROUP BY and
hence a Group RTE, introduced in PG18 (commit 247dea89f). The solution
is to flatten the relevant parts of the SELECT query before preparing
the INSERT .. SELECT query tree for use by Citus.
pull/8260/head^2
Colm 2025-10-17 11:21:25 +01:00 committed by GitHub
parent 5d71fca3b4
commit 3ca66e1fcc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 23 additions and 7 deletions

View File

@ -428,11 +428,10 @@ CreateInsertSelectIntoLocalTablePlan(uint64 planId, Query *insertSelectQuery,
ParamListInfo boundParams, bool hasUnresolvedParams, ParamListInfo boundParams, bool hasUnresolvedParams,
PlannerRestrictionContext *plannerRestrictionContext) PlannerRestrictionContext *plannerRestrictionContext)
{ {
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
PrepareInsertSelectForCitusPlanner(insertSelectQuery); PrepareInsertSelectForCitusPlanner(insertSelectQuery);
/* get the SELECT query (may have changed after PrepareInsertSelectForCitusPlanner) */ /* get the SELECT query (may have changed after PrepareInsertSelectForCitusPlanner) */
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
Query *selectQuery = selectRte->subquery; Query *selectQuery = selectRte->subquery;
bool allowRecursivePlanning = true; bool allowRecursivePlanning = true;
@ -513,6 +512,24 @@ PrepareInsertSelectForCitusPlanner(Query *insertSelectQuery)
bool isWrapped = false; bool isWrapped = false;
#if PG_VERSION_NUM >= PG_VERSION_18
/*
* PG18 is stricter about GroupRTE/GroupVar. For INSERT SELECT with a GROUP BY,
* flatten the SELECTs targetList and havingQual so Vars point to base RTEs and
* avoid Unrecognized range table id.
*/
if (selectRte->subquery->hasGroupRTE)
{
Query *selectQuery = selectRte->subquery;
selectQuery->targetList = (List *)
flatten_group_exprs(NULL, selectQuery,
(Node *) selectQuery->targetList);
selectQuery->havingQual =
flatten_group_exprs(NULL, selectQuery, selectQuery->havingQual);
}
#endif
if (selectRte->subquery->setOperations != NULL) if (selectRte->subquery->setOperations != NULL)
{ {
/* /*
@ -1431,11 +1448,6 @@ static DistributedPlan *
CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse, ParamListInfo boundParams) CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse, ParamListInfo boundParams)
{ {
Query *insertSelectQuery = copyObject(parse); Query *insertSelectQuery = copyObject(parse);
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
RangeTblEntry *insertRte = ExtractResultRelationRTEOrError(insertSelectQuery);
Oid targetRelationId = insertRte->relid;
DistributedPlan *distributedPlan = CitusMakeNode(DistributedPlan); DistributedPlan *distributedPlan = CitusMakeNode(DistributedPlan);
distributedPlan->modLevel = RowModifyLevelForQuery(insertSelectQuery); distributedPlan->modLevel = RowModifyLevelForQuery(insertSelectQuery);
@ -1450,6 +1462,7 @@ CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse, ParamListInfo bou
PrepareInsertSelectForCitusPlanner(insertSelectQuery); PrepareInsertSelectForCitusPlanner(insertSelectQuery);
/* get the SELECT query (may have changed after PrepareInsertSelectForCitusPlanner) */ /* get the SELECT query (may have changed after PrepareInsertSelectForCitusPlanner) */
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
Query *selectQuery = selectRte->subquery; Query *selectQuery = selectRte->subquery;
/* /*
@ -1472,6 +1485,9 @@ CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse, ParamListInfo bou
PlannedStmt *selectPlan = pg_plan_query(selectQueryCopy, NULL, cursorOptions, PlannedStmt *selectPlan = pg_plan_query(selectQueryCopy, NULL, cursorOptions,
boundParams); boundParams);
/* decide whether we can repartition the results */
RangeTblEntry *insertRte = ExtractResultRelationRTEOrError(insertSelectQuery);
Oid targetRelationId = insertRte->relid;
bool repartitioned = IsRedistributablePlan(selectPlan->planTree) && bool repartitioned = IsRedistributablePlan(selectPlan->planTree) &&
IsSupportedRedistributionTarget(targetRelationId); IsSupportedRedistributionTarget(targetRelationId);