diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 13 | ||||
-rw-r--r-- | src/backend/optimizer/prep/preptlist.c | 27 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 39 |
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); |