Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/commands/lockcmds.c9
-rw-r--r--src/backend/commands/view.c107
-rw-r--r--src/backend/nodes/outfuncs.c7
-rw-r--r--src/backend/nodes/readfuncs.c7
-rw-r--r--src/backend/optimizer/plan/setrefs.c26
-rw-r--r--src/backend/parser/parse_relation.c2
-rw-r--r--src/backend/rewrite/rewriteDefine.c7
-rw-r--r--src/backend/rewrite/rewriteHandler.c38
-rw-r--r--src/backend/utils/cache/plancache.c3
9 files changed, 41 insertions, 165 deletions
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index 6bf1b815f01..43c7d7f4bb2 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -195,15 +195,6 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
char relkind = rte->relkind;
char *relname = get_rel_name(relid);
- /*
- * The OLD and NEW placeholder entries in the view's rtable are
- * skipped.
- */
- if (relid == context->viewoid &&
- (strcmp(rte->eref->aliasname, "old") == 0 ||
- strcmp(rte->eref->aliasname, "new") == 0))
- continue;
-
/* Currently, we only allow plain tables or views to be locked. */
if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE &&
relkind != RELKIND_VIEW)
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);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 69324d5a9aa..6b368b08b21 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -512,6 +512,10 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
case RTE_SUBQUERY:
WRITE_NODE_FIELD(subquery);
WRITE_BOOL_FIELD(security_barrier);
+ /* we re-use these RELATION fields, too: */
+ WRITE_OID_FIELD(relid);
+ WRITE_INT_FIELD(rellockmode);
+ WRITE_UINT_FIELD(perminfoindex);
break;
case RTE_JOIN:
WRITE_ENUM_FIELD(jointype, JoinType);
@@ -545,10 +549,11 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
case RTE_NAMEDTUPLESTORE:
WRITE_STRING_FIELD(enrname);
WRITE_FLOAT_FIELD(enrtuples);
- WRITE_OID_FIELD(relid);
WRITE_NODE_FIELD(coltypes);
WRITE_NODE_FIELD(coltypmods);
WRITE_NODE_FIELD(colcollations);
+ /* we re-use these RELATION fields, too: */
+ WRITE_OID_FIELD(relid);
break;
case RTE_RESULT:
/* no extra fields */
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 30cd7a0da6b..f3629cdfd14 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -478,6 +478,10 @@ _readRangeTblEntry(void)
case RTE_SUBQUERY:
READ_NODE_FIELD(subquery);
READ_BOOL_FIELD(security_barrier);
+ /* we re-use these RELATION fields, too: */
+ READ_OID_FIELD(relid);
+ READ_INT_FIELD(rellockmode);
+ READ_UINT_FIELD(perminfoindex);
break;
case RTE_JOIN:
READ_ENUM_FIELD(jointype, JoinType);
@@ -520,10 +524,11 @@ _readRangeTblEntry(void)
case RTE_NAMEDTUPLESTORE:
READ_STRING_FIELD(enrname);
READ_FLOAT_FIELD(enrtuples);
- READ_OID_FIELD(relid);
READ_NODE_FIELD(coltypes);
READ_NODE_FIELD(coltypmods);
READ_NODE_FIELD(colcollations);
+ /* we re-use these RELATION fields, too: */
+ READ_OID_FIELD(relid);
break;
case RTE_RESULT:
/* no extra fields */
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index ed9c1e61876..85ba9d1ca1e 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -405,13 +405,15 @@ add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
*
* At top level, we must add all RTEs so that their indexes in the
* flattened rangetable match up with their original indexes. When
- * recursing, we only care about extracting relation RTEs.
+ * recursing, we only care about extracting relation RTEs (and subquery
+ * RTEs that were once relation RTEs).
*/
foreach(lc, root->parse->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
- if (!recursing || rte->rtekind == RTE_RELATION)
+ if (!recursing || rte->rtekind == RTE_RELATION ||
+ (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid)))
add_rte_to_flat_rtable(glob, root->parse->rteperminfos, rte);
}
@@ -501,8 +503,9 @@ flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt)
{
RangeTblEntry *rte = (RangeTblEntry *) node;
- /* As above, we need only save relation RTEs */
- if (rte->rtekind == RTE_RELATION)
+ /* As above, we need only save relation RTEs and former relations */
+ if (rte->rtekind == RTE_RELATION ||
+ (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid)))
add_rte_to_flat_rtable(cxt->glob, cxt->query->rteperminfos, rte);
return false;
}
@@ -560,7 +563,8 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
glob->finalrtable = lappend(glob->finalrtable, newrte);
/*
- * If it's a plain relation RTE, add the table to relationOids.
+ * If it's a plain relation RTE (or a subquery that was once a view
+ * reference), add the relation OID to relationOids.
*
* We do this even though the RTE might be unreferenced in the plan tree;
* this would correspond to cases such as views that were expanded, child
@@ -570,7 +574,8 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos,
* Note we don't bother to avoid making duplicate list entries. We could,
* but it would probably cost more cycles than it would save.
*/
- if (newrte->rtekind == RTE_RELATION)
+ if (newrte->rtekind == RTE_RELATION ||
+ (newrte->rtekind == RTE_SUBQUERY && OidIsValid(newrte->relid)))
glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
/*
@@ -3403,14 +3408,11 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
- if (rte->rtekind == RTE_RELATION)
+ if (rte->rtekind == RTE_RELATION ||
+ (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid)) ||
+ (rte->rtekind == RTE_NAMEDTUPLESTORE && OidIsValid(rte->relid)))
context->glob->relationOids =
lappend_oid(context->glob->relationOids, rte->relid);
- else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
- OidIsValid(rte->relid))
- context->glob->relationOids =
- lappend_oid(context->glob->relationOids,
- rte->relid);
}
/* And recurse into the query's subexpressions */
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 5389a0eddb6..b490541f03d 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -3834,7 +3834,7 @@ addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
{
RTEPermissionInfo *perminfo;
- Assert(rte->rtekind == RTE_RELATION);
+ Assert(OidIsValid(rte->relid));
Assert(rte->perminfoindex == 0);
/* Nope, so make one and add to the list. */
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 52272202881..e36fc72e1ed 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -633,13 +633,6 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect,
* setRuleCheckAsUser
* Recursively scan a query or expression tree and set the checkAsUser
* field to the given userid in all RTEPermissionInfos of the query.
- *
- * Note: for a view (ON SELECT rule), the checkAsUser field of the OLD
- * RTE entry's RTEPermissionInfo will be overridden when the view rule is
- * expanded, and the checkAsUser for the NEW RTE entry's RTEPermissionInfo is
- * irrelevant because its requiredPerms bits will always be zero. However, for
- * other types of rules it's important to set these fields to match the rule
- * owner. So we just set them always.
*/
void
setRuleCheckAsUser(Node *node, Oid userid)
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 1960dad7013..c74bac20b13 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1715,10 +1715,7 @@ ApplyRetrieveRule(Query *parsetree,
List *activeRIRs)
{
Query *rule_action;
- RangeTblEntry *rte,
- *subrte;
- RTEPermissionInfo *perminfo,
- *sub_perminfo;
+ RangeTblEntry *rte;
RowMarkClause *rc;
if (list_length(rule->actions) != 1)
@@ -1830,32 +1827,20 @@ ApplyRetrieveRule(Query *parsetree,
* original RTE to a subquery RTE.
*/
rte = rt_fetch(rt_index, parsetree->rtable);
- perminfo = getRTEPermissionInfo(parsetree->rteperminfos, rte);
rte->rtekind = RTE_SUBQUERY;
rte->subquery = rule_action;
rte->security_barrier = RelationIsSecurityView(relation);
- /* Clear fields that should not be set in a subquery RTE */
- rte->relid = InvalidOid;
- rte->relkind = 0;
- rte->rellockmode = 0;
- rte->tablesample = NULL;
- rte->perminfoindex = 0; /* no permission checking for this RTE */
- rte->inh = false; /* must not be set for a subquery */
/*
- * We move the view's permission check data down to its RTEPermissionInfo
- * contained in the view query, which the OLD entry in its range table
- * points to.
+ * Clear fields that should not be set in a subquery RTE. Note that we
+ * leave the relid, rellockmode, and perminfoindex fields set, so that the
+ * view relation can be appropriately locked before execution and its
+ * permissions checked.
*/
- subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
- Assert(subrte->relid == relation->rd_id);
- sub_perminfo = getRTEPermissionInfo(rule_action->rteperminfos, subrte);
- sub_perminfo->requiredPerms = perminfo->requiredPerms;
- sub_perminfo->checkAsUser = perminfo->checkAsUser;
- sub_perminfo->selectedCols = perminfo->selectedCols;
- sub_perminfo->insertedCols = perminfo->insertedCols;
- sub_perminfo->updatedCols = perminfo->updatedCols;
+ rte->relkind = 0;
+ rte->tablesample = NULL;
+ rte->inh = false; /* must not be set for a subquery */
return parsetree;
}
@@ -1867,9 +1852,10 @@ ApplyRetrieveRule(Query *parsetree,
* aggregate. We leave it to the planner to detect that.
*
* NB: this must agree with the parser's transformLockingClause() routine.
- * However, unlike the parser we have to be careful not to mark a view's
- * OLD and NEW rels for updating. The best way to handle that seems to be
- * to scan the jointree to determine which rels are used.
+ * However, we used to have to avoid marking a view's OLD and NEW rels for
+ * updating, which motivated scanning the jointree to determine which rels
+ * are used. Possibly that could now be simplified into just scanning the
+ * rangetable as the parser does.
*/
static void
markQueryForLocking(Query *qry, Node *jtnode,
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 92f6d5795fc..77c2ba3f8f4 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -1769,7 +1769,8 @@ AcquireExecutorLocks(List *stmt_list, bool acquire)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
- if (rte->rtekind != RTE_RELATION)
+ if (!(rte->rtekind == RTE_RELATION ||
+ (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid))))
continue;
/*