1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

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 ...
This commit is contained in:
Tom Lane
2002-05-12 20:10:05 +00:00
parent 71009354c8
commit f9e4f611a1
48 changed files with 1813 additions and 329 deletions

View File

@ -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)
{
@ -453,6 +456,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
@ -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 */