Skip to content

Commit 1a20bc9

Browse files
committed
Repair commits 317aba7 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 f4e7756, 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
1 parent d2fb076 commit 1a20bc9

File tree

4 files changed

+17
-43
lines changed

4 files changed

+17
-43
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,15 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
503503
newrte->colcollations = NIL;
504504
newrte->securityQuals = NIL;
505505

506+
/*
507+
* Also, if it's a subquery RTE, lose the relid that may have been kept to
508+
* signal that it had been a view. We don't want that to escape the
509+
* planner, mainly because doing so breaks -DWRITE_READ_PARSE_PLAN_TREES
510+
* testing thanks to outfuncs/readfuncs not preserving it.
511+
*/
512+
if (newrte->rtekind == RTE_SUBQUERY)
513+
newrte->relid = InvalidOid;
514+
506515
glob->finalrtable = lappend(glob->finalrtable, newrte);
507516

508517
/*

src/backend/rewrite/rewriteHandler.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,8 +1858,8 @@ ApplyRetrieveRule(Query *parsetree,
18581858

18591859
/*
18601860
* Clear fields that should not be set in a subquery RTE. However, we
1861-
* retain the relid to support correct operation of makeWholeRowVar during
1862-
* planning.
1861+
* retain the relid for now, to support correct operation of
1862+
* makeWholeRowVar during planning.
18631863
*/
18641864
rte->relkind = 0;
18651865
rte->rellockmode = 0;

src/backend/tcop/postgres.c

Lines changed: 4 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -776,45 +776,10 @@ pg_rewrite_query(Query *query)
776776
}
777777
#endif
778778

779-
#ifdef WRITE_READ_PARSE_PLAN_TREES
780-
/* Optional debugging check: pass querytree through outfuncs/readfuncs */
781-
{
782-
List *new_list = NIL;
783-
ListCell *lc;
784-
785-
/*
786-
* We currently lack outfuncs/readfuncs support for most utility
787-
* statement types, so only attempt to write/read non-utility queries.
788-
*/
789-
foreach(lc, querytree_list)
790-
{
791-
Query *query = castNode(Query, lfirst(lc));
792-
793-
if (query->commandType != CMD_UTILITY)
794-
{
795-
char *str = nodeToString(query);
796-
Query *new_query = stringToNodeWithLocations(str);
797-
798-
/*
799-
* queryId is not saved in stored rules, but we must preserve
800-
* it here to avoid breaking pg_stat_statements.
801-
*/
802-
new_query->queryId = query->queryId;
803-
804-
new_list = lappend(new_list, new_query);
805-
pfree(str);
806-
}
807-
else
808-
new_list = lappend(new_list, query);
809-
}
810-
811-
/* This checks both outfuncs/readfuncs and the equal() routines... */
812-
if (!equal(new_list, querytree_list))
813-
elog(WARNING, "outfuncs/readfuncs failed to produce equal parse tree");
814-
else
815-
querytree_list = new_list;
816-
}
817-
#endif
779+
/*
780+
* We don't apply WRITE_READ_PARSE_PLAN_TREES to rewritten query trees,
781+
* because it breaks the hack of preserving relid for rewritten views.
782+
*/
818783

819784
if (Debug_print_rewritten)
820785
elog_node_display(LOG, "rewritten parse tree", querytree_list,

src/include/nodes/parsenodes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,8 +999,8 @@ typedef struct RangeTblEntry
999999
* As a special case, relid can also be set in RTE_SUBQUERY RTEs. This
10001000
* happens when an RTE_RELATION RTE for a view is transformed to an
10011001
* RTE_SUBQUERY during rewriting. We keep the relid because it is useful
1002-
* during planning, cf makeWholeRowVar. (It cannot be relied on during
1003-
* execution, because it will not propagate to parallel workers.)
1002+
* during planning, cf makeWholeRowVar. (It will not be passed on to the
1003+
* executor, however.)
10041004
*
10051005
* As a special case, RTE_NAMEDTUPLESTORE can also set relid to indicate
10061006
* that the tuple format of the tuplestore is the same as the referenced

0 commit comments

Comments
 (0)