From ca0830e5a27a1a7e58bc62b4b7950c1bf96d882c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 12 Mar 2025 11:47:19 -0400 Subject: Build whole-row Vars the same way during parsing and planning. makeWholeRowVar() has different rules for constructing a whole-row Var depending on the kind of RTE it's representing. This turns out to be problematic because the rewriter and planner can convert view RTEs and set-returning-function RTEs into subquery RTEs; so a whole-row Var made during planning might look different from one made by the parser. In isolation this doesn't cause any problem, but if a query contains Vars made both ways for the same varno, there are cross-checks in the executor that will complain. This manifests for UPDATE, DELETE, and MERGE queries that use whole-row table references. To fix, we need makeWholeRowVar() to produce the same result from an inlined RTE as it would have for the original. For an inlined view, we can use RangeTblEntry.relid to detect that this had been a view RTE. For inlined SRFs, make a data structure definition change akin to commit 47bb9db75, and say that we won't clear RangeTblEntry.functions until the end of planning. That allows makeWholeRowVar() to repeat what it would have done with the unmodified RTE. Reported-by: Duncan Sands Reported-by: Dean Rasheed Diagnosed-by: Tender Wang Author: Tom Lane Reviewed-by: Dean Rasheed Discussion: https://postgr.es/m/3518c50a-ab18-482f-b916-a37263622501@deepbluecap.com Backpatch-through: 13 --- src/backend/optimizer/prep/prepjointree.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/backend/optimizer/prep') diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index e7e8c1499f2..2c6faad4dae 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -908,8 +908,14 @@ preprocess_function_rtes(PlannerInfo *root) rte->rtekind = RTE_SUBQUERY; rte->subquery = funcquery; rte->security_barrier = false; - /* Clear fields that should not be set in a subquery RTE */ - rte->functions = NIL; + + /* + * Clear fields that should not be set in a subquery RTE. + * However, we leave rte->functions filled in for the moment, + * in case makeWholeRowVar needs to consult it. We'll clear + * it in setrefs.c (see add_rte_to_flat_rtable) so that this + * abuse of the data structure doesn't escape the planner. + */ rte->funcordinality = false; } } -- cgit v1.2.3