*** pgsql/src/backend/optimizer/prep/prepunion.c 2008/11/11 18:13:32 1.161 --- pgsql/src/backend/optimizer/prep/prepunion.c 2008/11/15 19:43:46 1.162 *************** *** 22,28 **** * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.160 2008/10/22 20:17:52 tgl Exp $ * *------------------------------------------------------------------------- */ --- 22,28 ---- * * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.161 2008/11/11 18:13:32 tgl Exp $ * *------------------------------------------------------------------------- */ *************** expand_inherited_rtentry(PlannerInfo *ro *** 1169,1174 **** --- 1169,1175 ---- { Query *parse = root->parse; Oid parentOID; + RowMarkClause *oldrc; Relation oldrelation; LOCKMODE lockmode; List *inhOIDs; *************** expand_inherited_rtentry(PlannerInfo *ro *** 1209,1214 **** --- 1210,1224 ---- } /* + * 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. *************** expand_inherited_rtentry(PlannerInfo *ro *** 1221,1234 **** * 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.) */ if (rti == parse->resultRelation) lockmode = RowExclusiveLock; ! else if (get_rowmark(parse, rti)) lockmode = RowShareLock; else lockmode = AccessShareLock; --- 1231,1245 ---- * in the parse/rewrite/plan pipeline. * * If the parent relation is the query's result relation, then we need ! * 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 (oldrc) lockmode = RowShareLock; else lockmode = AccessShareLock; *************** expand_inherited_rtentry(PlannerInfo *ro *** 1283,1288 **** --- 1294,1315 ---- 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);