aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_clause.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r--src/backend/parser/parse_clause.c58
1 files changed, 54 insertions, 4 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 2f547f29be6..dbf17759617 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.179 2008/09/01 20:42:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.180 2008/10/04 21:56:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,6 +54,8 @@ static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j,
List *relnamespace,
Relids containedRels);
static RangeTblEntry *transformTableEntry(ParseState *pstate, RangeVar *r);
+static RangeTblEntry *transformCTEReference(ParseState *pstate, RangeVar *r,
+ CommonTableExpr *cte, Index levelsup);
static RangeTblEntry *transformRangeSubselect(ParseState *pstate,
RangeSubselect *r);
static RangeTblEntry *transformRangeFunction(ParseState *pstate,
@@ -422,6 +424,20 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
return rte;
}
+/*
+ * transformCTEReference --- transform a RangeVar that references a common
+ * table expression (ie, a sub-SELECT defined in a WITH clause)
+ */
+static RangeTblEntry *
+transformCTEReference(ParseState *pstate, RangeVar *r,
+ CommonTableExpr *cte, Index levelsup)
+{
+ RangeTblEntry *rte;
+
+ rte = addRangeTableEntryForCTE(pstate, cte, levelsup, r->alias, true);
+
+ return rte;
+}
/*
* transformRangeSubselect --- transform a sub-SELECT appearing in FROM
@@ -609,12 +625,46 @@ transformFromClauseItem(ParseState *pstate, Node *n,
{
if (IsA(n, RangeVar))
{
- /* Plain relation reference */
+ /* Plain relation reference, or perhaps a CTE reference */
+ RangeVar *rv = (RangeVar *) n;
RangeTblRef *rtr;
- RangeTblEntry *rte;
+ RangeTblEntry *rte = NULL;
int rtindex;
- rte = transformTableEntry(pstate, (RangeVar *) n);
+ /*
+ * If it is an unqualified name, it might be a reference to some
+ * CTE visible in this or a parent query.
+ */
+ if (!rv->schemaname)
+ {
+ ParseState *ps;
+ Index levelsup;
+
+ for (ps = pstate, levelsup = 0;
+ ps != NULL;
+ ps = ps->parentParseState, levelsup++)
+ {
+ ListCell *lc;
+
+ foreach(lc, ps->p_ctenamespace)
+ {
+ CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
+
+ if (strcmp(rv->relname, cte->ctename) == 0)
+ {
+ rte = transformCTEReference(pstate, rv, cte, levelsup);
+ break;
+ }
+ }
+ if (rte)
+ break;
+ }
+ }
+
+ /* if not found as a CTE, must be a table reference */
+ if (!rte)
+ rte = transformTableEntry(pstate, rv);
+
/* assume new rte is at end */
rtindex = list_length(pstate->p_rtable);
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));