diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2025-03-13 12:13:07 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2025-03-13 12:13:07 -0400 |
commit | b200180dec98d1e5e5fd91b09fc543e8c09db9d0 (patch) | |
tree | fa0309830e3dfe66d7334619506c6b8ca19c2e98 | |
parent | 39af32f7883f5e3072aaa8b9c0c6bab7230ee3a3 (diff) | |
download | postgresql-b200180dec98d1e5e5fd91b09fc543e8c09db9d0.tar.gz postgresql-b200180dec98d1e5e5fd91b09fc543e8c09db9d0.zip |
Repair commits 317aba70e et al for -DWRITE_READ_PARSE_PLAN_TREES.
Letting the rewriter keep RangeTblEntry.relid when expanding a view
RTE, without making the outfuncs/readfuncs changes that went along
with that originally, is more problematic than I realized. It causes
WRITE_READ_PARSE_PLAN_TREES testing to fail because outfuncs/readfuncs
don't think relid need be saved in an RTE_SUBQUERY RTE.
There doesn't seem to be any other good route to fixing the whole-row
Var problem solved at f4e7756ef, so we just have to deal with the
consequences. We can make the eventually-produced plan tree safe
for WRITE_READ_PARSE_PLAN_TREES by clearing the relid field at the
end of planning, as was already being done for the functions field.
(The functions field is not problematic here because our abuse of it
is strictly local to the planner.) However, there is no nice fix for
the post-rewrite WRITE_READ_PARSE_PLAN_TREES test.
The solution adopted here is to remove the post-rewrite test in the
affected branches. That's surely less than ideal, but a couple of
arguments can be made why it's not unacceptable. First, the behavior
of outfuncs/readfuncs for parsetrees in these branches is frozen no
matter what, because of catalog stability requirements. So we're not
testing anything that is going to change. Second, testing
WRITE_READ_PARSE_PLAN_TREES at this particular time doesn't correspond
to any direct system functionality requirement, neither rule storage
nor plan transmission.
Reported-by: Andres Freund <andres@anarazel.de>
Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com>
Discussion: https://postgr.es/m/3518c50a-ab18-482f-b916-a37263622501@deepbluecap.com
Backpatch-through: 13-15
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 9 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 4 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 43 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 4 |
4 files changed, 17 insertions, 43 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index e5786455704..86d29ecede3 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -438,6 +438,15 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte) newrte->colcollations = NIL; newrte->securityQuals = NIL; + /* + * Also, if it's a subquery RTE, lose the relid that may have been kept to + * signal that it had been a view. We don't want that to escape the + * planner, mainly because doing so breaks -DWRITE_READ_PARSE_PLAN_TREES + * testing thanks to outfuncs/readfuncs not preserving it. + */ + if (newrte->rtekind == RTE_SUBQUERY) + newrte->relid = InvalidOid; + glob->finalrtable = lappend(glob->finalrtable, newrte); /* diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 95c62a1e8cf..028b37e63fd 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -1828,8 +1828,8 @@ ApplyRetrieveRule(Query *parsetree, /* * Clear fields that should not be set in a subquery RTE. However, we - * retain the relid to support correct operation of makeWholeRowVar during - * planning. + * retain the relid for now, to support correct operation of + * makeWholeRowVar during planning. */ rte->relkind = 0; rte->rellockmode = 0; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 8c624ee6699..bc8dd553a49 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -803,45 +803,10 @@ pg_rewrite_query(Query *query) } #endif -#ifdef WRITE_READ_PARSE_PLAN_TREES - /* Optional debugging check: pass querytree through outfuncs/readfuncs */ - { - List *new_list = NIL; - ListCell *lc; - - /* - * We currently lack outfuncs/readfuncs support for most utility - * statement types, so only attempt to write/read non-utility queries. - */ - foreach(lc, querytree_list) - { - Query *query = castNode(Query, lfirst(lc)); - - if (query->commandType != CMD_UTILITY) - { - char *str = nodeToString(query); - Query *new_query = stringToNodeWithLocations(str); - - /* - * queryId is not saved in stored rules, but we must preserve - * it here to avoid breaking pg_stat_statements. - */ - new_query->queryId = query->queryId; - - new_list = lappend(new_list, new_query); - pfree(str); - } - else - new_list = lappend(new_list, query); - } - - /* This checks both outfuncs/readfuncs and the equal() routines... */ - if (!equal(new_list, querytree_list)) - elog(WARNING, "outfuncs/readfuncs failed to produce equal parse tree"); - else - querytree_list = new_list; - } -#endif + /* + * We don't apply WRITE_READ_PARSE_PLAN_TREES to rewritten query trees, + * because it breaks the hack of preserving relid for rewritten views. + */ if (Debug_print_rewritten) elog_node_display(LOG, "rewritten parse tree", querytree_list, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index af828b84459..4f4612fa39f 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -985,8 +985,8 @@ typedef struct RangeTblEntry * As a special case, relid can also be set in RTE_SUBQUERY RTEs. This * happens when an RTE_RELATION RTE for a view is transformed to an * RTE_SUBQUERY during rewriting. We keep the relid because it is useful - * during planning, cf makeWholeRowVar. (It cannot be relied on during - * execution, because it will not propagate to parallel workers.) + * during planning, cf makeWholeRowVar. (It will not be passed on to the + * executor, however.) * * As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate * that the tuple format of the tuplestore is the same as the referenced |