aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/analyze.c64
-rw-r--r--src/backend/parser/parse_clause.c5
-rw-r--r--src/backend/parser/parse_cte.c4
-rw-r--r--src/backend/parser/parse_expr.c4
-rw-r--r--src/backend/parser/parse_relation.c59
-rw-r--r--src/backend/rewrite/rewriteHandler.c32
-rw-r--r--src/include/parser/analyze.h5
-rw-r--r--src/include/parser/parse_node.h3
-rw-r--r--src/include/parser/parse_relation.h3
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);