diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/parser/analyze.c | 64 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 5 | ||||
-rw-r--r-- | src/backend/parser/parse_cte.c | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 59 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 32 | ||||
-rw-r--r-- | src/include/parser/analyze.h | 5 | ||||
-rw-r--r-- | src/include/parser/parse_node.h | 3 | ||||
-rw-r--r-- | src/include/parser/parse_relation.h | 3 |
9 files changed, 59 insertions, 120 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 7c67c3a7119..f0af9a6d661 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -17,7 +17,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.389.2.2 2009/09/09 03:33:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.389.2.3 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -138,12 +138,14 @@ parse_analyze_varparams(Node *parseTree, const char *sourceText, */ Query * parse_sub_analyze(Node *parseTree, ParseState *parentParseState, - CommonTableExpr *parentCTE) + CommonTableExpr *parentCTE, + bool locked_from_parent) { ParseState *pstate = make_parsestate(parentParseState); Query *query; pstate->p_parent_cte = parentCTE; + pstate->p_locked_from_parent = locked_from_parent; query = transformStmt(pstate, parseTree); @@ -1424,7 +1426,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt, * of this sub-query, because they are not in the toplevel pstate's * namespace list. */ - selectQuery = parse_sub_analyze((Node *) stmt, pstate, NULL); + selectQuery = parse_sub_analyze((Node *) stmt, pstate, NULL, false); /* * Check for bogus references to Vars on the current query level (but @@ -2043,7 +2045,7 @@ CheckSelectLocking(Query *qry) * This basically involves replacing names by integer relids. * * NB: if you need to change this, see also markQueryForLocking() - * in rewriteHandler.c, and isLockedRel() in parse_relation.c. + * in rewriteHandler.c, and isLockedRefname() in parse_relation.c. */ static void transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc) @@ -2085,32 +2087,8 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc) */ transformLockingClause(pstate, rte->subquery, allrels); break; - case RTE_CTE: - { - /* - * We allow FOR UPDATE/SHARE of a WITH query to be - * propagated into the WITH, but it doesn't seem very - * sane to allow this for a reference to an - * outer-level WITH. And it definitely wouldn't work - * for a self-reference, since we're not done - * analyzing the CTE anyway. - */ - CommonTableExpr *cte; - - if (rte->ctelevelsup > 0 || rte->self_reference) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"))); - cte = GetCTEForRTE(pstate, rte, -1); - /* should be analyzed by now */ - Assert(IsA(cte->ctequery, Query)); - transformLockingClause(pstate, - (Query *) cte->ctequery, - allrels); - } - break; default: - /* ignore JOIN, SPECIAL, FUNCTION RTEs */ + /* ignore JOIN, SPECIAL, FUNCTION, VALUES, CTE RTEs */ break; } } @@ -2177,30 +2155,10 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc) parser_errposition(pstate, thisrel->location))); break; case RTE_CTE: - { - /* - * We allow FOR UPDATE/SHARE of a WITH query - * to be propagated into the WITH, but it - * doesn't seem very sane to allow this for a - * reference to an outer-level WITH. And it - * definitely wouldn't work for a - * self-reference, since we're not done - * analyzing the CTE anyway. - */ - CommonTableExpr *cte; - - if (rte->ctelevelsup > 0 || rte->self_reference) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"), - parser_errposition(pstate, thisrel->location))); - cte = GetCTEForRTE(pstate, rte, -1); - /* should be analyzed by now */ - Assert(IsA(cte->ctequery, Query)); - transformLockingClause(pstate, - (Query *) cte->ctequery, - allrels); - } + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("SELECT FOR UPDATE/SHARE cannot be applied to a WITH query"), + parser_errposition(pstate, thisrel->location))); break; default: elog(ERROR, "unrecognized RTE type: %d", diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 16ff39653c5..fee3829fec4 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.189.2.2 2009/09/09 03:33:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.189.2.3 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -479,7 +479,8 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) /* * Analyze and transform the subquery. */ - query = parse_sub_analyze(r->subquery, pstate, NULL); + query = parse_sub_analyze(r->subquery, pstate, NULL, + isLockedRefname(pstate, r->alias->aliasname)); /* * Check that we got something reasonable. Many of these conditions are diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c index 0b3f861b50f..41c913c869a 100644 --- a/src/backend/parser/parse_cte.c +++ b/src/backend/parser/parse_cte.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_cte.c,v 2.6.2.1 2009/09/09 03:33:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_cte.c,v 2.6.2.2 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -229,7 +229,7 @@ analyzeCTE(ParseState *pstate, CommonTableExpr *cte) /* Analysis not done already */ Assert(IsA(cte->ctequery, SelectStmt)); - query = parse_sub_analyze(cte->ctequery, pstate, cte); + query = parse_sub_analyze(cte->ctequery, pstate, cte, false); cte->ctequery = (Node *) query; /* diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 45c0a0970b1..d0e568525c6 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.241.2.1 2009/09/09 03:33:01 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.241.2.2 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1251,7 +1251,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink) return result; pstate->p_hasSubLinks = true; - qtree = parse_sub_analyze(sublink->subselect, pstate, NULL); + qtree = parse_sub_analyze(sublink->subselect, pstate, NULL, false); /* * Check that we got something reasonable. Many of these conditions are diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index b506c042c54..ffa5e8ac68b 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.142 2009/06/11 14:49:00 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.142.2.1 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,7 +41,6 @@ static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location); static void markRTEForSelectPriv(ParseState *pstate, RangeTblEntry *rte, int rtindex, AttrNumber col); -static bool isLockedRel(ParseState *pstate, char *refname); static void expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up, int location, bool include_dropped, @@ -920,7 +919,7 @@ addRangeTableEntry(ParseState *pstate, * to a rel in a statement, be careful to get the right access level * depending on whether we're doing SELECT FOR UPDATE/SHARE. */ - lockmode = isLockedRel(pstate, refname) ? RowShareLock : AccessShareLock; + lockmode = isLockedRefname(pstate, refname) ? RowShareLock : AccessShareLock; rel = parserOpenTable(pstate, relation, lockmode); rte->relid = RelationGetRelid(rel); @@ -1465,40 +1464,46 @@ addRangeTableEntryForCTE(ParseState *pstate, /* * Has the specified refname been selected FOR UPDATE/FOR SHARE? * - * Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE. + * This is used when we have not yet done transformLockingClause, but need + * to know the correct lock to take during initial opening of relations. + * + * Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE, + * since the table-level lock is the same either way. */ -static bool -isLockedRel(ParseState *pstate, char *refname) +bool +isLockedRefname(ParseState *pstate, const char *refname) { - /* Outer loop to check parent query levels as well as this one */ - while (pstate != NULL) + ListCell *l; + + /* + * If we are in a subquery specified as locked FOR UPDATE/SHARE from + * parent level, then act as though there's a generic FOR UPDATE here. + */ + if (pstate->p_locked_from_parent) + return true; + + foreach(l, pstate->p_locking_clause) { - ListCell *l; + LockingClause *lc = (LockingClause *) lfirst(l); - foreach(l, pstate->p_locking_clause) + if (lc->lockedRels == NIL) { - LockingClause *lc = (LockingClause *) lfirst(l); + /* all tables used in query */ + return true; + } + else + { + /* just the named tables */ + ListCell *l2; - if (lc->lockedRels == NIL) - { - /* all tables used in query */ - return true; - } - else + foreach(l2, lc->lockedRels) { - /* just the named tables */ - ListCell *l2; - - foreach(l2, lc->lockedRels) - { - RangeVar *thisrel = (RangeVar *) lfirst(l2); + RangeVar *thisrel = (RangeVar *) lfirst(l2); - if (strcmp(refname, thisrel->relname) == 0) - return true; - } + if (strcmp(refname, thisrel->relname) == 0) + return true; } } - pstate = pstate->parentParseState; } return false; } diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index b3a18134539..89ef9a356d2 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.186.2.1 2009/09/02 17:52:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.186.2.2 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1242,35 +1242,7 @@ markQueryForLocking(Query *qry, Node *jtnode, bool forUpdate, bool noWait) markQueryForLocking(rte->subquery, (Node *) rte->subquery->jointree, forUpdate, noWait); } - else if (rte->rtekind == RTE_CTE) - { - /* - * We allow FOR UPDATE/SHARE of a WITH query to be propagated into - * the WITH, but it doesn't seem very sane to allow this for a - * reference to an outer-level WITH (compare - * transformLockingClause). Which simplifies life here. - */ - CommonTableExpr *cte = NULL; - ListCell *lc; - - if (rte->ctelevelsup > 0 || rte->self_reference) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"))); - foreach(lc, qry->cteList) - { - cte = (CommonTableExpr *) lfirst(lc); - if (strcmp(cte->ctename, rte->ctename) == 0) - break; - } - if (lc == NULL) /* shouldn't happen */ - elog(ERROR, "could not find CTE \"%s\"", rte->ctename); - /* should be analyzed by now */ - Assert(IsA(cte->ctequery, Query)); - markQueryForLocking((Query *) cte->ctequery, - (Node *) ((Query *) cte->ctequery)->jointree, - forUpdate, noWait); - } + /* other RTE types are unaffected by FOR UPDATE */ } else if (IsA(jtnode, FromExpr)) { diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index 63b1cf1d950..41b162d3bc3 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/analyze.h,v 1.40.2.1 2009/09/09 03:33:01 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/analyze.h,v 1.40.2.2 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,8 @@ extern Query *parse_analyze_varparams(Node *parseTree, const char *sourceText, Oid **paramTypes, int *numParams); extern Query *parse_sub_analyze(Node *parseTree, ParseState *parentParseState, - CommonTableExpr *parentCTE); + CommonTableExpr *parentCTE, + bool locked_from_parent); extern Query *transformStmt(ParseState *pstate, Node *parseTree); extern bool analyze_requires_snapshot(Node *parseTree); diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 84a32b20835..25c8d7f0cd9 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.62.2.1 2009/09/09 03:33:01 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.62.2.2 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,6 +104,7 @@ typedef struct ParseState bool p_hasSubLinks; bool p_is_insert; bool p_is_update; + bool p_locked_from_parent; Relation p_target_relation; RangeTblEntry *p_target_rangetblentry; } ParseState; diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index ec0fb09d605..ca1da1cc3e2 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.64 2009/06/11 14:49:11 momjian Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.64.2.1 2009/10/27 17:11:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -84,6 +84,7 @@ extern RangeTblEntry *addRangeTableEntryForCTE(ParseState *pstate, Index levelsup, Alias *alias, bool inFromCl); +extern bool isLockedRefname(ParseState *pstate, const char *refname); extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToRelNameSpace, bool addToVarNameSpace); |