diff options
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index a9211cfe931..099bb714831 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.323 2005/07/28 22:27:00 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.324 2005/08/01 20:31:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -134,7 +134,7 @@ static void transformFKConstraints(ParseState *pstate, bool isAddConstraint); static void applyColumnNames(List *dst, List *src); static List *getSetColTypes(ParseState *pstate, Node *node); -static void transformLocking(Query *qry, List *lockedRels, bool forUpdate); +static void transformLockingClause(Query *qry, LockingClause *lc); static void transformConstraintAttrs(List *constraintList); static void transformColumnType(ParseState *pstate, ColumnDef *column); static void release_pstate_resources(ParseState *pstate); @@ -1812,8 +1812,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) qry->commandType = CMD_SELECT; - /* make FOR UPDATE/FOR SHARE list available to addRangeTableEntry */ - pstate->p_lockedRels = stmt->lockedRels; + /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */ + pstate->p_locking_clause = stmt->lockingClause; /* process the FROM clause */ transformFromClause(pstate, stmt->fromClause); @@ -1872,8 +1872,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) if (pstate->p_hasAggs || qry->groupClause || qry->havingQual) parseCheckAggregates(pstate, qry); - if (stmt->lockedRels != NIL) - transformLocking(qry, stmt->lockedRels, stmt->forUpdate); + if (stmt->lockingClause) + transformLockingClause(qry, stmt->lockingClause); return qry; } @@ -1901,8 +1901,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) List *sortClause; Node *limitOffset; Node *limitCount; - List *lockedRels; - bool forUpdate; + LockingClause *lockingClause; Node *node; ListCell *left_tlist, *dtlist; @@ -1940,16 +1939,15 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) sortClause = stmt->sortClause; limitOffset = stmt->limitOffset; limitCount = stmt->limitCount; - lockedRels = stmt->lockedRels; - forUpdate = stmt->forUpdate; + lockingClause = stmt->lockingClause; stmt->sortClause = NIL; stmt->limitOffset = NULL; stmt->limitCount = NULL; - stmt->lockedRels = NIL; + stmt->lockingClause = NULL; /* We don't support FOR UPDATE/SHARE with set ops at the moment. */ - if (lockedRels) + if (lockingClause) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SELECT FOR UPDATE/SHARE is not allowed with UNION/INTERSECT/EXCEPT"))); @@ -2089,8 +2087,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) if (pstate->p_hasAggs || qry->groupClause || qry->havingQual) parseCheckAggregates(pstate, qry); - if (lockedRels != NIL) - transformLocking(qry, lockedRels, forUpdate); + if (lockingClause) + transformLockingClause(qry, lockingClause); return qry; } @@ -2114,7 +2112,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) (errcode(ERRCODE_SYNTAX_ERROR), errmsg("INTO is only allowed on first SELECT of UNION/INTERSECT/EXCEPT"))); /* We don't support FOR UPDATE/SHARE with set ops at the moment. */ - if (stmt->lockedRels) + if (stmt->lockingClause) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("SELECT FOR UPDATE/SHARE is not allowed with UNION/INTERSECT/EXCEPT"))); @@ -2134,7 +2132,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) { Assert(stmt->larg != NULL && stmt->rarg != NULL); if (stmt->sortClause || stmt->limitOffset || stmt->limitCount || - stmt->lockedRels) + stmt->lockingClause) isLeaf = true; else isLeaf = false; @@ -2760,24 +2758,40 @@ CheckSelectLocking(Query *qry, bool forUpdate) * in rewriteHandler.c. */ static void -transformLocking(Query *qry, List *lockedRels, bool forUpdate) +transformLockingClause(Query *qry, LockingClause *lc) { + List *lockedRels = lc->lockedRels; List *rowMarks; ListCell *l; ListCell *rt; Index i; + LockingClause *allrels; - if (qry->rowMarks && forUpdate != qry->forUpdate) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot use both FOR UPDATE and FOR SHARE in one query"))); - qry->forUpdate = forUpdate; + if (qry->rowMarks) + { + if (lc->forUpdate != qry->forUpdate) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot use both FOR UPDATE and FOR SHARE in one query"))); + if (lc->nowait != qry->rowNoWait) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot use both wait and NOWAIT in one query"))); + } + qry->forUpdate = lc->forUpdate; + qry->rowNoWait = lc->nowait; + + CheckSelectLocking(qry, lc->forUpdate); + + /* make a clause we can pass down to subqueries to select all rels */ + allrels = makeNode(LockingClause); + allrels->lockedRels = NIL; /* indicates all rels */ + allrels->forUpdate = lc->forUpdate; + allrels->nowait = lc->nowait; - CheckSelectLocking(qry, forUpdate); - rowMarks = qry->rowMarks; - if (linitial(lockedRels) == NULL) + if (lockedRels == NIL) { /* all regular tables used in query */ i = 0; @@ -2799,8 +2813,7 @@ transformLocking(Query *qry, List *lockedRels, bool forUpdate) * FOR UPDATE/SHARE of subquery is propagated to all * of subquery's rels */ - transformLocking(rte->subquery, list_make1(NULL), - forUpdate); + transformLockingClause(rte->subquery, allrels); break; default: /* ignore JOIN, SPECIAL, FUNCTION RTEs */ @@ -2836,8 +2849,7 @@ transformLocking(Query *qry, List *lockedRels, bool forUpdate) * FOR UPDATE/SHARE of subquery is propagated to * all of subquery's rels */ - transformLocking(rte->subquery, list_make1(NULL), - forUpdate); + transformLockingClause(rte->subquery, allrels); break; case RTE_JOIN: ereport(ERROR, |