diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 8934c04bb2..8e762f824c 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -17,7 +17,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.380 2008/10/04 21:56:54 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.381 2008/10/06 15:15:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1896,7 +1896,7 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc) 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); + cte = GetCTEForRTE(pstate, rte, -1); /* should be analyzed by now */ Assert(IsA(cte->ctequery, Query)); transformLockingClause(pstate, @@ -1989,7 +1989,7 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc) (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); + cte = GetCTEForRTE(pstate, rte, -1); /* should be analyzed by now */ Assert(IsA(cte->ctequery, Query)); transformLockingClause(pstate, diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 870911c062..14ddd34b76 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.137 2008/10/06 02:12:56 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.138 2008/10/06 15:15:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -371,15 +371,23 @@ GetRTEByRangeTablePosn(ParseState *pstate, /* * Fetch the CTE for a CTE-reference RTE. + * + * rtelevelsup is the number of query levels above the given pstate that the + * RTE came from. Callers that don't have this information readily available + * may pass -1 instead. */ CommonTableExpr * -GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte) +GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup) { Index levelsup; ListCell *lc; + /* Determine RTE's levelsup if caller didn't know it */ + if (rtelevelsup < 0) + (void) RTERangeTablePosn(pstate, rte, &rtelevelsup); + Assert(rte->rtekind == RTE_CTE); - levelsup = rte->ctelevelsup; + levelsup = rte->ctelevelsup + rtelevelsup; while (levelsup-- > 0) { pstate = pstate->parentParseState; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index ed54abe703..d83caab7e8 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.166 2008/10/05 22:20:16 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.167 2008/10/06 15:15:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -308,7 +308,7 @@ markTargetListOrigin(ParseState *pstate, TargetEntry *tle, */ if (attnum != InvalidAttrNumber && !rte->self_reference) { - CommonTableExpr *cte = GetCTEForRTE(pstate, rte); + CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup); TargetEntry *ste; /* should be analyzed by now */ @@ -1206,7 +1206,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) /* CTE reference: examine subquery's output expr */ if (!rte->self_reference) { - CommonTableExpr *cte = GetCTEForRTE(pstate, rte); + CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup); TargetEntry *ste; /* should be analyzed by now */ @@ -1230,7 +1230,9 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) MemSet(&mypstate, 0, sizeof(mypstate)); /* this loop must work, since GetCTEForRTE did */ - for (levelsup = 0; levelsup < rte->ctelevelsup; levelsup++) + for (levelsup = 0; + levelsup < rte->ctelevelsup + netlevelsup; + levelsup++) pstate = pstate->parentParseState; mypstate.parentParseState = pstate; mypstate.p_rtable = ((Query *) cte->ctequery)->rtable; diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index f5212c421b..84cfa97ba3 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.60 2008/10/06 02:12:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.61 2008/10/06 15:15:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,8 @@ extern int RTERangeTablePosn(ParseState *pstate, extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate, int varno, int sublevels_up); -extern CommonTableExpr *GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte); +extern CommonTableExpr *GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, + int rtelevelsup); extern Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname, int location); extern Node *colNameToVar(ParseState *pstate, char *colname, bool localonly,