Commit c1393173 authored by Tom Lane's avatar Tom Lane

Avoid redundant relation lock grabs during planning, and make sure

that we acquire a lock on relations added to the query due to inheritance.
Formerly, no such lock was held throughout planning, which meant that
a schema change could occur to invalidate the plan before it's even
been completed.
parent 353f111f
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.75 2005/04/28 21:47:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.76 2005/05/23 03:01:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -189,9 +189,11 @@ expand_targetlist(List *tlist, int command_type, ...@@ -189,9 +189,11 @@ expand_targetlist(List *tlist, int command_type,
* attributes. * attributes.
* *
* Scan the tuple description in the relation's relcache entry to make * Scan the tuple description in the relation's relcache entry to make
* sure we have all the user attributes in the right order. * sure we have all the user attributes in the right order. We assume
* that the rewriter already acquired at least AccessShareLock on the
* relation, so we need no lock here.
*/ */
rel = heap_open(getrelid(result_relation, range_table), AccessShareLock); rel = heap_open(getrelid(result_relation, range_table), NoLock);
numattrs = RelationGetNumberOfAttributes(rel); numattrs = RelationGetNumberOfAttributes(rel);
...@@ -326,7 +328,7 @@ expand_targetlist(List *tlist, int command_type, ...@@ -326,7 +328,7 @@ expand_targetlist(List *tlist, int command_type,
tlist_item = lnext(tlist_item); tlist_item = lnext(tlist_item);
} }
heap_close(rel, AccessShareLock); heap_close(rel, NoLock);
return new_tlist; return new_tlist;
} }
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.107 2005/05/22 22:30:20 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.108 2005/05/23 03:01:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -67,7 +67,25 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel) ...@@ -67,7 +67,25 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
bool hasindex; bool hasindex;
List *indexinfos = NIL; List *indexinfos = NIL;
relation = heap_open(relationObjectId, AccessShareLock); /*
* Normally, we can assume the rewriter already acquired at least
* AccessShareLock on each relation used in the query. However this
* will not be the case for relations added to the query because they
* are inheritance children of some relation mentioned explicitly.
* For them, this is the first access during the parse/rewrite/plan
* pipeline, and so we need to obtain and keep a suitable lock.
*
* XXX really, a suitable lock is RowShareLock if the relation is
* an UPDATE/DELETE target, and AccessShareLock otherwise. However
* we cannot easily tell here which to get, so for the moment just
* get AccessShareLock always. The executor will get the right lock
* when it runs, which means there is a very small chance of deadlock
* trying to upgrade our lock.
*/
if (rel->reloptkind == RELOPT_BASEREL)
relation = heap_open(relationObjectId, NoLock);
else
relation = heap_open(relationObjectId, AccessShareLock);
rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1; rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1;
rel->max_attr = RelationGetNumberOfAttributes(relation); rel->max_attr = RelationGetNumberOfAttributes(relation);
...@@ -205,8 +223,8 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel) ...@@ -205,8 +223,8 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
rel->indexlist = indexinfos; rel->indexlist = indexinfos;
/* XXX keep the lock here? */ /* close rel, but keep lock if any */
heap_close(relation, AccessShareLock); heap_close(relation, NoLock);
} }
/* /*
...@@ -374,7 +392,8 @@ build_physical_tlist(Query *root, RelOptInfo *rel) ...@@ -374,7 +392,8 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
switch (rte->rtekind) switch (rte->rtekind)
{ {
case RTE_RELATION: case RTE_RELATION:
relation = heap_open(rte->relid, AccessShareLock); /* Assume we already have adequate lock */
relation = heap_open(rte->relid, NoLock);
numattrs = RelationGetNumberOfAttributes(relation); numattrs = RelationGetNumberOfAttributes(relation);
for (attrno = 1; attrno <= numattrs; attrno++) for (attrno = 1; attrno <= numattrs; attrno++)
...@@ -401,7 +420,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel) ...@@ -401,7 +420,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
false)); false));
} }
heap_close(relation, AccessShareLock); heap_close(relation, NoLock);
break; break;
case RTE_SUBQUERY: case RTE_SUBQUERY:
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.65 2005/04/22 21:58:31 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.66 2005/05/23 03:01:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
#include "parser/parsetree.h" #include "parser/parsetree.h"
static RelOptInfo *make_base_rel(Query *root, int relid); static RelOptInfo *make_reloptinfo(Query *root, int relid,
RelOptKind reloptkind);
static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel); static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel);
static List *build_joinrel_restrictlist(Query *root, static List *build_joinrel_restrictlist(Query *root,
RelOptInfo *joinrel, RelOptInfo *joinrel,
...@@ -67,7 +68,7 @@ build_base_rel(Query *root, int relid) ...@@ -67,7 +68,7 @@ build_base_rel(Query *root, int relid)
} }
/* No existing RelOptInfo for this base rel, so make a new one */ /* No existing RelOptInfo for this base rel, so make a new one */
rel = make_base_rel(root, relid); rel = make_reloptinfo(root, relid, RELOPT_BASEREL);
/* and add it to the list */ /* and add it to the list */
root->base_rel_list = lcons(rel, root->base_rel_list); root->base_rel_list = lcons(rel, root->base_rel_list);
...@@ -102,11 +103,8 @@ build_other_rel(Query *root, int relid) ...@@ -102,11 +103,8 @@ build_other_rel(Query *root, int relid)
} }
/* No existing RelOptInfo for this other rel, so make a new one */ /* No existing RelOptInfo for this other rel, so make a new one */
rel = make_base_rel(root, relid);
/* presently, must be an inheritance child rel */ /* presently, must be an inheritance child rel */
Assert(rel->reloptkind == RELOPT_BASEREL); rel = make_reloptinfo(root, relid, RELOPT_OTHER_CHILD_REL);
rel->reloptkind = RELOPT_OTHER_CHILD_REL;
/* and add it to the list */ /* and add it to the list */
root->other_rel_list = lcons(rel, root->other_rel_list); root->other_rel_list = lcons(rel, root->other_rel_list);
...@@ -115,18 +113,18 @@ build_other_rel(Query *root, int relid) ...@@ -115,18 +113,18 @@ build_other_rel(Query *root, int relid)
} }
/* /*
* make_base_rel * make_reloptinfo
* Construct a base-relation RelOptInfo for the specified rangetable index. * Construct a RelOptInfo for the specified rangetable index.
* *
* Common code for build_base_rel and build_other_rel. * Common code for build_base_rel and build_other_rel.
*/ */
static RelOptInfo * static RelOptInfo *
make_base_rel(Query *root, int relid) make_reloptinfo(Query *root, int relid, RelOptKind reloptkind)
{ {
RelOptInfo *rel = makeNode(RelOptInfo); RelOptInfo *rel = makeNode(RelOptInfo);
RangeTblEntry *rte = rt_fetch(relid, root->rtable); RangeTblEntry *rte = rt_fetch(relid, root->rtable);
rel->reloptkind = RELOPT_BASEREL; rel->reloptkind = reloptkind;
rel->relids = bms_make_singleton(relid); rel->relids = bms_make_singleton(relid);
rel->rows = 0; rel->rows = 0;
rel->width = 0; rel->width = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment