diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2023-01-18 13:23:57 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2023-01-18 13:23:57 -0500 |
commit | 47bb9db75996232ea71fc1e1888ffb0e70579b54 (patch) | |
tree | 745e1a7755802a7e92cd267bce642358a1f37a0a /src/backend/commands/view.c | |
parent | 8d83a5d0a2673174dc478e707de1f502935391a5 (diff) | |
download | postgresql-47bb9db75996232ea71fc1e1888ffb0e70579b54.tar.gz postgresql-47bb9db75996232ea71fc1e1888ffb0e70579b54.zip |
Get rid of the "new" and "old" entries in a view's rangetable.
The rule system needs "old" and/or "new" pseudo-RTEs in rule actions
that are ON INSERT/UPDATE/DELETE. Historically it's put such entries
into the ON SELECT rules of views as well, but those are really quite
vestigial. The only thing we've used them for is to carry the
view's relid forward to AcquireExecutorLocks (so that we can
re-lock the view to verify it hasn't changed before re-using a plan)
and to carry its relid and permissions data forward to execution-time
permissions checks. What we can do instead of that is to retain
these fields of the RTE_RELATION RTE for the view even after we
convert it to an RTE_SUBQUERY RTE. This requires a tiny amount of
extra complication in the planner and AcquireExecutorLocks, but on
the other hand we can get rid of the logic that moves that data from
one place to another.
The principal immediate benefit of doing this, aside from a small
saving in the pg_rewrite data for views, is that these pseudo-RTEs
no longer trigger ruleutils.c's heuristic about qualifying variable
names when the rangetable's length is more than 1. That results
in quite a number of small simplifications in regression test outputs,
which are all to the good IMO.
Bump catversion because we need to dump a few more fields of
RTE_SUBQUERY RTEs. While those will always be zeroes anyway in
stored rules (because we'd never populate them until query rewrite)
they are useful for debugging, and it seems like we'd better make
sure to transmit such RTEs accurately in plans sent to parallel
workers. I don't think the executor actually examines these fields
after startup, but someday it might.
This is a second attempt at committing 1b4d280ea. The difference
from the first time is that now we can add some filtering rules to
AdjustUpgrade.pm to allow cross-version upgrade testing to pass
despite all the cosmetic changes in CREATE VIEW outputs.
Amit Langote (filtering rules by me)
Discussion: https://postgr.es/m/CA+HiwqEf7gPN4Hn+LoZ4tP2q_Qt7n3vw7-6fJKOf92tSEnX6Gg@mail.gmail.com
Discussion: https://postgr.es/m/891521.1673657296@sss.pgh.pa.us
Diffstat (limited to 'src/backend/commands/view.c')
-rw-r--r-- | src/backend/commands/view.c | 107 |
1 files changed, 0 insertions, 107 deletions
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 0bacb819e52..ff98c773f55 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -353,107 +353,6 @@ DefineViewRules(Oid viewOid, Query *viewParse, bool replace) */ } -/*--------------------------------------------------------------- - * UpdateRangeTableOfViewParse - * - * Update the range table of the given parsetree. - * This update consists of adding two new entries IN THE BEGINNING - * of the range table (otherwise the rule system will die a slow, - * horrible and painful death, and we do not want that now, do we?) - * one for the OLD relation and one for the NEW one (both of - * them refer in fact to the "view" relation). - * - * Of course we must also increase the 'varnos' of all the Var nodes - * by 2... - * - * These extra RT entries are not actually used in the query, - * except for run-time locking. - *--------------------------------------------------------------- - */ -static Query * -UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) -{ - Relation viewRel; - List *new_rt; - ParseNamespaceItem *nsitem; - RangeTblEntry *rt_entry1, - *rt_entry2; - RTEPermissionInfo *rte_perminfo1; - ParseState *pstate; - ListCell *lc; - - /* - * Make a copy of the given parsetree. It's not so much that we don't - * want to scribble on our input, it's that the parser has a bad habit of - * outputting multiple links to the same subtree for constructs like - * BETWEEN, and we mustn't have OffsetVarNodes increment the varno of a - * Var node twice. copyObject will expand any multiply-referenced subtree - * into multiple copies. - */ - viewParse = copyObject(viewParse); - - /* Create a dummy ParseState for addRangeTableEntryForRelation */ - pstate = make_parsestate(NULL); - - /* need to open the rel for addRangeTableEntryForRelation */ - viewRel = relation_open(viewOid, AccessShareLock); - - /* - * Create the 2 new range table entries and form the new range table... - * OLD first, then NEW.... - */ - nsitem = addRangeTableEntryForRelation(pstate, viewRel, - AccessShareLock, - makeAlias("old", NIL), - false, false); - rt_entry1 = nsitem->p_rte; - rte_perminfo1 = nsitem->p_perminfo; - nsitem = addRangeTableEntryForRelation(pstate, viewRel, - AccessShareLock, - makeAlias("new", NIL), - false, false); - rt_entry2 = nsitem->p_rte; - - /* - * Add only the "old" RTEPermissionInfo at the head of view query's list - * and update the other RTEs' perminfoindex accordingly. When rewriting a - * query on the view, ApplyRetrieveRule() will transfer the view - * relation's permission details into this RTEPermissionInfo. That's - * needed because the view's RTE itself will be transposed into a subquery - * RTE that can't carry the permission details; see the code stanza toward - * the end of ApplyRetrieveRule() for how that's done. - */ - viewParse->rteperminfos = lcons(rte_perminfo1, viewParse->rteperminfos); - foreach(lc, viewParse->rtable) - { - RangeTblEntry *rte = lfirst(lc); - - if (rte->perminfoindex > 0) - rte->perminfoindex += 1; - } - - /* - * Also make the "new" RTE's RTEPermissionInfo undiscoverable. This is a - * bit of a hack given that all the non-child RTE_RELATION entries really - * should have a RTEPermissionInfo, but this dummy "new" RTE is going to - * go away anyway in the very near future. - */ - rt_entry2->perminfoindex = 0; - - new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable)); - - viewParse->rtable = new_rt; - - /* - * Now offset all var nodes by 2, and jointree RT indexes too. - */ - OffsetVarNodes((Node *) viewParse, 2, 0); - - relation_close(viewRel, AccessShareLock); - - return viewParse; -} - /* * DefineView * Execute a CREATE VIEW command. @@ -617,12 +516,6 @@ void StoreViewQuery(Oid viewOid, Query *viewParse, bool replace) { /* - * The range table of 'viewParse' does not contain entries for the "OLD" - * and "NEW" relations. So... add them! - */ - viewParse = UpdateRangeTableOfViewParse(viewOid, viewParse); - - /* * Now create the rules associated with the view. */ DefineViewRules(viewOid, viewParse, replace); |