From 659ec42bdb9deb6f2428296ced5b6ada32a42f6e Mon Sep 17 00:00:00 2001 From: Mehmet Yilmaz Date: Mon, 24 Mar 2025 12:09:59 +0000 Subject: [PATCH] Remove unused functions and comments related to nextval handling in insert-select planner --- .../planner/insert_select_planner.c | 208 ------------------ .../distributed/insert_select_planner.h | 2 - 2 files changed, 210 deletions(-) diff --git a/src/backend/distributed/planner/insert_select_planner.c b/src/backend/distributed/planner/insert_select_planner.c index 893f16ed2..ce61bd0ae 100644 --- a/src/backend/distributed/planner/insert_select_planner.c +++ b/src/backend/distributed/planner/insert_select_planner.c @@ -107,10 +107,6 @@ static void ResetTargetEntryResno(List *targetList); static void ProcessEntryPair(TargetEntry *insertEntry, TargetEntry *selectEntry, Form_pg_attribute attr, int targetEntryIndex, List **projectedEntries, List **nonProjectedEntries); - static List * - TargetEntryList(List *expressionList); - static int -FindRTEIndexInQuery(Query *query, RangeTblEntry *rte); /* depth of current insert/select planner. */ @@ -308,17 +304,6 @@ CreateDistributedInsertSelectPlan(Query *originalQuery, distributedPlan->modLevel = RowModifyLevelForQuery(originalQuery); - /* - * Check for volatile functions (e.g. nextval) in the target list. - * If present, call our rewrite function to "split" the query. - */ - if (contain_nextval_expression_walker((Node *) originalQuery->targetList, NULL)) - { - originalQuery = RewriteInsertSelectForPartialNextval(originalQuery); - } - - - /* * Error semantics for INSERT ... SELECT queries are different than regular * modify queries. Thus, handle separately. @@ -409,199 +394,6 @@ CreateDistributedInsertSelectPlan(Query *originalQuery, } -/* - * RewriteInsertSelectForPartialNextval - * - * Given an INSERT ... SELECT query that contains nextval() in its target list, - * rewrite the query so that the inner subquery (which is pushed down to workers) - * returns only the non-volatile (non-nextval) columns. The outer query then - * adds the nextval() calls in its target list. This forces nextval() to be - * evaluated on the coordinator. - * - * For example, this transforms: - * - * INSERT INTO target (col1, col2, col3) - * SELECT col1, nextval('seq'), col3 - * FROM distributed_table; - * - * into a plan roughly equivalent to: - * - * INSERT INTO target (col1, col2, col3) - * SELECT worker.col1, nextval('seq'), worker.col3 - * FROM ( - * SELECT col1, col3 - * FROM distributed_table - * ) AS worker; - */ -Query * -RewriteInsertSelectForPartialNextval(Query *originalQuery) -{ - /* 0) Basic check: should be an INSERT...SELECT query */ - if (originalQuery->commandType != CMD_INSERT) - return originalQuery; - - /* 1) Get the result relation and the SELECT side RTE */ - RangeTblEntry *insertRte = ExtractResultRelationRTEOrError(originalQuery); - RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(originalQuery); - - /* 2) Ensure the SELECT side is an RTE_SUBQUERY. If not, wrap it. */ - if (selectRte->rtekind != RTE_SUBQUERY) - { - Query *fakeSelect = makeNode(Query); - fakeSelect->commandType = CMD_SELECT; - fakeSelect->targetList = copyObject(selectRte->subquery->targetList); - /* Additional fields (rtable, jointree) should be copied as needed */ - selectRte->rtekind = RTE_SUBQUERY; - selectRte->subquery = fakeSelect; - } - - /* Optionally, wrap the subquery to get a clean target list */ - selectRte->subquery = WrapSubquery(selectRte->subquery); - Query *subquery = selectRte->subquery; /* This is now our inner subquery */ - - /* - * 3) Partition the subquery’s target list into: - * - workerExprs: expressions that do NOT contain nextval() - * - volatileExprs: expressions that DO contain nextval() - * - * We'll use a helper function RemoveNextvalFromTargetList() that, - * for each TargetEntry in subquery->targetList, places its expr into one of - * two lists depending on whether contain_nextval_expression_walker() returns true. - */ - List *workerExprs = NIL; - List *volatileExprs = NIL; - ListCell *lc; - foreach(lc, subquery->targetList) - { - TargetEntry *tle = (TargetEntry *) lfirst(lc); - if (contain_nextval_expression_walker((Node *) tle->expr, NULL)) - volatileExprs = lappend(volatileExprs, tle->expr); - else - workerExprs = lappend(workerExprs, tle->expr); - } - - /* - * 4) Build new target lists: - * - * For the inner subquery: Use only the worker expressions. - * For the outer (coordinator) query: Build a target list that combines: - * - Vars that reference the worker subquery’s output columns (for each workerExpr) - * - The volatile expressions (e.g. nextval()) placed in their proper positions. - * - * Here we assume that the original target list order is preserved: - * e.g. if the original target list was: - * [ expr1, expr2 (volatile), expr3 ] - * then the new outer target list should be: - * [ Var(worker_col1), expr2, Var(worker_col2) ] - * - * This example assumes that the order of workerExprs and volatileExprs - * correspond to their positions in the original target list. - * - * A more robust implementation would walk the original target list and, for - * each entry, either replace it with a Var reference (if non-volatile) or - * keep the volatile expression. - */ - - /* Create new inner subquery target list from workerExprs */ - List *newWorkerTList = TargetEntryList(workerExprs); - subquery->targetList = newWorkerTList; /* inner subquery returns only worker columns */ - - /* Build the outer target list */ - List *newOuterTList = NIL; - int outerResno = 1; - int workerIndex = 1; - int volatileIndex = 1; - /* For each original target entry, check if it was volatile or not. - For simplicity, we assume the original order is preserved in the concatenated lists. - A robust solution would store position info. */ - foreach(lc, originalQuery->targetList) - { - TargetEntry *origTle = (TargetEntry *) lfirst(lc); - if (contain_nextval_expression_walker((Node *) origTle->expr, NULL)) - { - /* Keep the volatile expression as is. */ - TargetEntry *newTle = makeTargetEntry(copyObject(origTle->expr), - outerResno, - pstrdup(origTle->resname), - false); - newOuterTList = lappend(newOuterTList, newTle); - volatileIndex++; - } - else - { - /* b) Replace non-volatile expression with a Var reference to the subquery's output. - We need to get the RTE index of the subquery. - */ - int subqueryIndex = FindRTEIndexInQuery(originalQuery, selectRte); - TargetEntry *workerTle = (TargetEntry *) list_nth(newWorkerTList, workerIndex - 1); - Var *v = makeVar(subqueryIndex, /* the RTE index (1-based) */ - workerIndex, /* attribute number within subquery TList */ - exprType((Node *) workerTle->expr), - exprTypmod((Node *) workerTle->expr), - exprCollation((Node *) workerTle->expr), - 0); - TargetEntry *newTle = makeTargetEntry((Expr *) v, - outerResno, - pstrdup(origTle->resname), - false); - newOuterTList = lappend(newOuterTList, newTle); - workerIndex++; - } - outerResno++; - } - originalQuery->targetList = newOuterTList; - - /* Optionally, re-run any target list reordering to align with the physical table's column order */ - ReorderInsertSelectTargetLists(originalQuery, insertRte, selectRte); - - return originalQuery; -} - -/* - * TargetEntryList creates a new target list from a list of expressions. - * Each expression is wrapped in a TargetEntry with an automatically generated - * column name. - */ -static List * -TargetEntryList(List *expressionList) -{ - List *tlist = NIL; - ListCell *cell; - int colIndex = 1; - - foreach(cell, expressionList) - { - Expr *expr = (Expr *) lfirst(cell); - StringInfo colName = makeStringInfo(); - appendStringInfo(colName, "worker_col%d", colIndex); - TargetEntry *tle = makeTargetEntry(expr, colIndex, pstrdup(colName->data), false); - tlist = lappend(tlist, tle); - colIndex++; - } - return tlist; -} - -/* - * FindRTEIndexInQuery returns the 1-based index of the given RTE in query->rtable. - * If not found, returns 0. - */ -static int -FindRTEIndexInQuery(Query *query, RangeTblEntry *rte) -{ - ListCell *cell; - int index = 0; - foreach(cell, query->rtable) - { - index++; - if (lfirst(cell) == (void *) rte) - return index; - } - return 0; -} - - - - /* * InsertSelectHasRouterSelect is a helper function that returns true of the SELECT * part of the INSERT .. SELECT query is a router query. diff --git a/src/include/distributed/insert_select_planner.h b/src/include/distributed/insert_select_planner.h index 4ba2d6027..a9100b02d 100644 --- a/src/include/distributed/insert_select_planner.h +++ b/src/include/distributed/insert_select_planner.h @@ -46,8 +46,6 @@ extern DistributedPlan * CreateInsertSelectIntoLocalTablePlan(uint64 planId, extern char * InsertSelectResultIdPrefix(uint64 planId); extern bool PlanningInsertSelect(void); extern Query * WrapSubquery(Query *subquery); -extern Query * -RewriteInsertSelectForPartialNextval(Query *originalQuery); #endif /* INSERT_SELECT_PLANNER_H */