diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-05-12 20:10:05 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-05-12 20:10:05 +0000 |
commit | f9e4f611a18f64fd9106a72ec9af9e2220075780 (patch) | |
tree | bfbc1d3d9fb5a008d8fe3405dce3366659c7e7cc /src/backend/parser/parse_clause.c | |
parent | 71009354c848964e657e540e24dac6b4c9a81570 (diff) | |
download | postgresql-f9e4f611a18f64fd9106a72ec9af9e2220075780.tar.gz postgresql-f9e4f611a18f64fd9106a72ec9af9e2220075780.zip |
First pass at set-returning-functions in FROM, by Joe Conway with
some kibitzing from Tom Lane. Not everything works yet, and there's
no documentation or regression test, but let's commit this so Joe
doesn't need to cope with tracking changes in so many files ...
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r-- | src/backend/parser/parse_clause.c | 85 |
1 files changed, 81 insertions, 4 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 6df4a4fd7dc..19aa688ff94 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.90 2002/04/28 19:54:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.91 2002/05/12 20:10:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "access/heapam.h" #include "nodes/makefuncs.h" +#include "optimizer/clauses.h" #include "optimizer/tlist.h" #include "optimizer/var.h" #include "parser/analyze.h" @@ -49,6 +50,8 @@ static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j, static RangeTblRef *transformTableEntry(ParseState *pstate, RangeVar *r); static RangeTblRef *transformRangeSubselect(ParseState *pstate, RangeSubselect *r); +static RangeTblRef *transformRangeFunction(ParseState *pstate, + RangeFunction *r); static Node *transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels); static Node *buildMergedJoinVar(JoinType jointype, @@ -82,9 +85,9 @@ transformFromClause(ParseState *pstate, List *frmList) /* * The grammar will have produced a list of RangeVars, - * RangeSubselects, and/or JoinExprs. Transform each one (possibly - * adding entries to the rtable), check for duplicate refnames, and - * then add it to the joinlist and namespace. + * RangeSubselects, RangeFunctions, and/or JoinExprs. Transform each one + * (possibly adding entries to the rtable), check for duplicate refnames, + * and then add it to the joinlist and namespace. */ foreach(fl, frmList) { @@ -454,6 +457,71 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) /* + * transformRangeFunction --- transform a function call appearing in FROM + */ +static RangeTblRef * +transformRangeFunction(ParseState *pstate, RangeFunction *r) +{ + Node *funcexpr; + char *funcname; + RangeTblEntry *rte; + RangeTblRef *rtr; + + /* + * Transform the raw FuncCall node + */ + funcexpr = transformExpr(pstate, r->funccallnode); + + Assert(IsA(r->funccallnode, FuncCall)); + funcname = strVal(llast(((FuncCall *) r->funccallnode)->funcname)); + + /* + * Disallow aggregate functions and subselects in the expression. + * (Aggregates clearly make no sense; perhaps later we could support + * subselects, though.) + */ + if (contain_agg_clause(funcexpr)) + elog(ERROR, "cannot use aggregate function in FROM function expression"); + if (contain_subplans(funcexpr)) + elog(ERROR, "cannot use subselect in FROM function expression"); + + /* + * Remove any Iter nodes added by parse_func.c. We oughta get rid of + * Iter completely ... + */ + while (funcexpr && IsA(funcexpr, Iter)) + funcexpr = ((Iter *) funcexpr)->iterexpr; + + /* + * Insist we now have a bare function call (explain.c is the only place + * that depends on this, I think). If this fails, it's probably because + * transformExpr interpreted the function notation as a type coercion. + */ + if (!funcexpr || + !IsA(funcexpr, Expr) || + ((Expr *) funcexpr)->opType != FUNC_EXPR) + elog(ERROR, "Coercion function not allowed in FROM clause"); + + /* + * OK, build an RTE for the function. + */ + rte = addRangeTableEntryForFunction(pstate, funcname, funcexpr, + r->alias, true); + + /* + * We create a RangeTblRef, but we do not add it to the joinlist or + * namespace; our caller must do that if appropriate. + */ + rtr = makeNode(RangeTblRef); + /* assume new rte is at end */ + rtr->rtindex = length(pstate->p_rtable); + Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable)); + + return rtr; +} + + +/* * transformFromClauseItem - * Transform a FROM-clause item, adding any required entries to the * range table list being built in the ParseState, and return the @@ -486,6 +554,15 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels) *containedRels = makeListi1(rtr->rtindex); return (Node *) rtr; } + else if (IsA(n, RangeFunction)) + { + /* function is like a plain relation */ + RangeTblRef *rtr; + + rtr = transformRangeFunction(pstate, (RangeFunction *) n); + *containedRels = makeListi1(rtr->rtindex); + return (Node *) rtr; + } else if (IsA(n, JoinExpr)) { /* A newfangled join expression */ |