Fix GetCTEForRTE() to deal with the possibility that the RTE it's given came
from a query level above the current ParseState.
This commit is contained in:
parent
5f853c6556
commit
e64bb65aff
@ -17,7 +17,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query")));
|
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 */
|
/* should be analyzed by now */
|
||||||
Assert(IsA(cte->ctequery, Query));
|
Assert(IsA(cte->ctequery, Query));
|
||||||
transformLockingClause(pstate,
|
transformLockingClause(pstate,
|
||||||
@ -1989,7 +1989,7 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc)
|
|||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"),
|
errmsg("SELECT FOR UPDATE/SHARE cannot be applied to an outer-level WITH query"),
|
||||||
parser_errposition(pstate, thisrel->location)));
|
parser_errposition(pstate, thisrel->location)));
|
||||||
cte = GetCTEForRTE(pstate, rte);
|
cte = GetCTEForRTE(pstate, rte, -1);
|
||||||
/* should be analyzed by now */
|
/* should be analyzed by now */
|
||||||
Assert(IsA(cte->ctequery, Query));
|
Assert(IsA(cte->ctequery, Query));
|
||||||
transformLockingClause(pstate,
|
transformLockingClause(pstate,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* 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 *
|
CommonTableExpr *
|
||||||
GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte)
|
GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
|
||||||
{
|
{
|
||||||
Index levelsup;
|
Index levelsup;
|
||||||
ListCell *lc;
|
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);
|
Assert(rte->rtekind == RTE_CTE);
|
||||||
levelsup = rte->ctelevelsup;
|
levelsup = rte->ctelevelsup + rtelevelsup;
|
||||||
while (levelsup-- > 0)
|
while (levelsup-- > 0)
|
||||||
{
|
{
|
||||||
pstate = pstate->parentParseState;
|
pstate = pstate->parentParseState;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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)
|
if (attnum != InvalidAttrNumber && !rte->self_reference)
|
||||||
{
|
{
|
||||||
CommonTableExpr *cte = GetCTEForRTE(pstate, rte);
|
CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
|
||||||
TargetEntry *ste;
|
TargetEntry *ste;
|
||||||
|
|
||||||
/* should be analyzed by now */
|
/* should be analyzed by now */
|
||||||
@ -1206,7 +1206,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
|||||||
/* CTE reference: examine subquery's output expr */
|
/* CTE reference: examine subquery's output expr */
|
||||||
if (!rte->self_reference)
|
if (!rte->self_reference)
|
||||||
{
|
{
|
||||||
CommonTableExpr *cte = GetCTEForRTE(pstate, rte);
|
CommonTableExpr *cte = GetCTEForRTE(pstate, rte, netlevelsup);
|
||||||
TargetEntry *ste;
|
TargetEntry *ste;
|
||||||
|
|
||||||
/* should be analyzed by now */
|
/* should be analyzed by now */
|
||||||
@ -1230,7 +1230,9 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
|
|||||||
|
|
||||||
MemSet(&mypstate, 0, sizeof(mypstate));
|
MemSet(&mypstate, 0, sizeof(mypstate));
|
||||||
/* this loop must work, since GetCTEForRTE did */
|
/* 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;
|
pstate = pstate->parentParseState;
|
||||||
mypstate.parentParseState = pstate;
|
mypstate.parentParseState = pstate;
|
||||||
mypstate.p_rtable = ((Query *) cte->ctequery)->rtable;
|
mypstate.p_rtable = ((Query *) cte->ctequery)->rtable;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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,
|
extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate,
|
||||||
int varno,
|
int varno,
|
||||||
int sublevels_up);
|
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,
|
extern Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
||||||
char *colname, int location);
|
char *colname, int location);
|
||||||
extern Node *colNameToVar(ParseState *pstate, char *colname, bool localonly,
|
extern Node *colNameToVar(ParseState *pstate, char *colname, bool localonly,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user