aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/allpaths.c13
-rw-r--r--src/backend/optimizer/prep/preptlist.c27
-rw-r--r--src/backend/optimizer/prep/prepunion.c39
3 files changed, 60 insertions, 19 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 4d868570bcb..b0553894c24 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.176 2008/11/11 18:13:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.177 2008/11/15 19:43:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -284,17 +284,6 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
ListCell *l;
/*
- * XXX for now, can't handle inherited expansion of FOR UPDATE/SHARE; can
- * we do better? (This will take some redesign because the executor
- * currently supposes that every rowMark relation is involved in every row
- * returned by the query.)
- */
- if (get_rowmark(root->parse, parentRTindex))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("SELECT FOR UPDATE/SHARE is not supported for inheritance queries")));
-
- /*
* Initialize to compute size estimates for whole append relation.
*
* We handle width estimates by weighting the widths of different
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 2861125212f..e04e7067664 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -16,7 +16,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.93 2008/11/02 01:45:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.94 2008/11/15 19:43:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -138,6 +138,11 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
char *resname;
TargetEntry *tle;
+ /* ignore child rels */
+ if (rc->rti != rc->prti)
+ continue;
+
+ /* always need the ctid */
var = makeVar(rc->rti,
SelfItemPointerAttributeNumber,
TIDOID,
@@ -153,6 +158,26 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
true);
tlist = lappend(tlist, tle);
+
+ /* if parent of inheritance tree, need the tableoid too */
+ if (rc->isParent)
+ {
+ var = makeVar(rc->rti,
+ TableOidAttributeNumber,
+ OIDOID,
+ -1,
+ 0);
+
+ resname = (char *) palloc(32);
+ snprintf(resname, 32, "tableoid%u", rc->rti);
+
+ tle = makeTargetEntry((Expr *) var,
+ list_length(tlist) + 1,
+ resname,
+ true);
+
+ tlist = lappend(tlist, tle);
+ }
}
}
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index c2113cb2669..bd7c05cc53d 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.161 2008/11/11 18:13:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.162 2008/11/15 19:43:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1169,6 +1169,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
{
Query *parse = root->parse;
Oid parentOID;
+ RowMarkClause *oldrc;
Relation oldrelation;
LOCKMODE lockmode;
List *inhOIDs;
@@ -1209,6 +1210,15 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
}
/*
+ * Find out if parent relation is selected FOR UPDATE/SHARE. If so,
+ * we need to mark its RowMarkClause as isParent = true, and generate
+ * a new RowMarkClause for each child.
+ */
+ oldrc = get_rowmark(parse, rti);
+ if (oldrc)
+ oldrc->isParent = true;
+
+ /*
* Must open the parent relation to examine its tupdesc. We need not lock
* it since the rewriter already obtained at least AccessShareLock on each
* relation used in the query.
@@ -1221,14 +1231,15 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
* in the parse/rewrite/plan pipeline.
*
* If the parent relation is the query's result relation, then we need
- * RowExclusiveLock. Otherwise, check to see if the relation is accessed
- * FOR UPDATE/SHARE or not. We can't just grab AccessShareLock because
- * then the executor would be trying to upgrade the lock, leading to
- * possible deadlocks. (This code should match the parser and rewriter.)
+ * RowExclusiveLock. Otherwise, if it's accessed FOR UPDATE/SHARE, we
+ * need RowShareLock; otherwise AccessShareLock. We can't just grab
+ * AccessShareLock because then the executor would be trying to upgrade
+ * the lock, leading to possible deadlocks. (This code should match the
+ * parser and rewriter.)
*/
if (rti == parse->resultRelation)
lockmode = RowExclusiveLock;
- else if (get_rowmark(parse, rti))
+ else if (oldrc)
lockmode = RowShareLock;
else
lockmode = AccessShareLock;
@@ -1283,6 +1294,22 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
appinfo->parent_reloid = parentOID;
appinfos = lappend(appinfos, appinfo);
+ /*
+ * Build a RowMarkClause if parent is marked FOR UPDATE/SHARE.
+ */
+ if (oldrc)
+ {
+ RowMarkClause *newrc = makeNode(RowMarkClause);
+
+ newrc->rti = childRTindex;
+ newrc->prti = rti;
+ newrc->forUpdate = oldrc->forUpdate;
+ newrc->noWait = oldrc->noWait;
+ newrc->isParent = false;
+
+ parse->rowMarks = lappend(parse->rowMarks, newrc);
+ }
+
/* Close child relations, but keep locks */
if (childOID != parentOID)
heap_close(newrelation, NoLock);