1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Create an RTE field to record the query's lock mode for each relation.

Add RangeTblEntry.rellockmode, which records the appropriate lock mode for
each RTE_RELATION rangetable entry (either AccessShareLock, RowShareLock,
or RowExclusiveLock depending on the RTE's role in the query).

This patch creates the field and makes all creators of RTE nodes fill it
in reasonably, but for the moment nothing much is done with it.  The plan
is to replace assorted post-parser logic that re-determines the right
lockmode to use with simple uses of rte->rellockmode.  For now, just add
Asserts in each of those places that the rellockmode matches what they are
computing today.  (In some cases the match isn't perfect, so the Asserts
are weaker than you might expect; but this seems OK, as per discussion.)

This passes check-world for me, but it seems worth pushing in this state
to see if the buildfarm finds any problems in cases I failed to test.

catversion bump due to change of stored rules.

Amit Langote, reviewed by David Rowley and Jesper Pedersen,
and whacked around a bit more by me

Discussion: https://postgr.es/m/468c85d9-540e-66a2-1dde-fec2b741e688@lab.ntt.co.jp
This commit is contained in:
Tom Lane
2018-09-30 13:55:51 -04:00
parent 8bddc86400
commit fdba460a26
29 changed files with 160 additions and 39 deletions

View File

@ -89,6 +89,10 @@ static Bitmapset *adjust_view_column_set(Bitmapset *cols, List *targetlist);
* These locks will ensure that the relation schemas don't change under us
* while we are rewriting and planning the query.
*
* Caution: this may modify the querytree, therefore caller should usually
* have done a copyObject() to make a writable copy of the querytree in the
* current memory context.
*
* forExecute indicates that the query is about to be executed.
* If so, we'll acquire RowExclusiveLock on the query's resultRelation,
* RowShareLock on any relation accessed FOR [KEY] UPDATE/SHARE, and
@ -101,13 +105,11 @@ static Bitmapset *adjust_view_column_set(Bitmapset *cols, List *targetlist);
* forUpdatePushedDown indicates that a pushed-down FOR [KEY] UPDATE/SHARE
* applies to the current subquery, requiring all rels to be opened with at
* least RowShareLock. This should always be false at the top of the
* recursion. This flag is ignored if forExecute is false.
* recursion. When it is true, we adjust RTE rellockmode fields to reflect
* the higher lock level. This flag is ignored if forExecute is false.
*
* A secondary purpose of this routine is to fix up JOIN RTE references to
* dropped columns (see details below). Because the RTEs are modified in
* place, it is generally appropriate for the caller of this routine to have
* first done a copyObject() to make a writable copy of the querytree in the
* current memory context.
* dropped columns (see details below). Such RTEs are modified in-place.
*
* This processing can, and for efficiency's sake should, be skipped when the
* querytree has just been built by the parser: parse analysis already got
@ -170,12 +172,22 @@ AcquireRewriteLocks(Query *parsetree,
lockmode = AccessShareLock;
else if (rt_index == parsetree->resultRelation)
lockmode = RowExclusiveLock;
else if (forUpdatePushedDown ||
get_parse_rowmark(parsetree, rt_index) != NULL)
else if (forUpdatePushedDown)
{
lockmode = RowShareLock;
/* Upgrade RTE's lock mode to reflect pushed-down lock */
if (rte->rellockmode == AccessShareLock)
rte->rellockmode = RowShareLock;
}
else if (get_parse_rowmark(parsetree, rt_index) != NULL)
lockmode = RowShareLock;
else
lockmode = AccessShareLock;
Assert(!forExecute || lockmode == rte->rellockmode ||
(lockmode == AccessShareLock &&
rte->rellockmode == RowExclusiveLock));
rel = heap_open(rte->relid, lockmode);
/*
@ -1593,6 +1605,7 @@ ApplyRetrieveRule(Query *parsetree,
/* Clear fields that should not be set in a subquery RTE */
rte->relid = InvalidOid;
rte->relkind = 0;
rte->rellockmode = 0;
rte->tablesample = NULL;
rte->inh = false; /* must not be set for a subquery */
@ -2920,8 +2933,14 @@ rewriteTargetView(Query *parsetree, Relation view)
* very much like what the planner would do to "pull up" the view into the
* outer query. Perhaps someday we should refactor things enough so that
* we can share code with the planner.)
*
* Be sure to set rellockmode to the correct thing for the target table.
* Since we copied the whole viewquery above, we can just scribble on
* base_rte instead of copying it.
*/
new_rte = (RangeTblEntry *) base_rte;
new_rte = base_rte;
new_rte->rellockmode = RowExclusiveLock;
parsetree->rtable = lappend(parsetree->rtable, new_rte);
new_rt_index = list_length(parsetree->rtable);
@ -3101,8 +3120,8 @@ rewriteTargetView(Query *parsetree, Relation view)
new_exclRte = addRangeTableEntryForRelation(make_parsestate(NULL),
base_rel,
makeAlias("excluded",
NIL),
RowExclusiveLock,
makeAlias("excluded", NIL),
false, false);
new_exclRte->relkind = RELKIND_COMPOSITE_TYPE;
new_exclRte->requiredPerms = 0;