mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +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:
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.182 2002/04/28 19:54:28 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.183 2002/05/12 20:10:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -310,6 +310,23 @@ _copySubqueryScan(SubqueryScan *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _copyFunctionScan
|
||||
* ----------------
|
||||
*/
|
||||
static FunctionScan *
|
||||
_copyFunctionScan(FunctionScan *from)
|
||||
{
|
||||
FunctionScan *newnode = makeNode(FunctionScan);
|
||||
|
||||
/*
|
||||
* copy node superclass fields
|
||||
*/
|
||||
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
||||
CopyScanFields((Scan *) from, (Scan *) newnode);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* CopyJoinFields
|
||||
@@ -1083,7 +1100,7 @@ _copyRelOptInfo(RelOptInfo *from)
|
||||
Node_Copy(from, newnode, cheapest_total_path);
|
||||
newnode->pruneable = from->pruneable;
|
||||
|
||||
newnode->issubquery = from->issubquery;
|
||||
newnode->rtekind = from->rtekind;
|
||||
Node_Copy(from, newnode, indexlist);
|
||||
newnode->pages = from->pages;
|
||||
newnode->tuples = from->tuples;
|
||||
@@ -1473,6 +1490,7 @@ _copyRangeTblEntry(RangeTblEntry *from)
|
||||
newnode->rtekind = from->rtekind;
|
||||
newnode->relid = from->relid;
|
||||
Node_Copy(from, newnode, subquery);
|
||||
Node_Copy(from, newnode, funcexpr);
|
||||
newnode->jointype = from->jointype;
|
||||
Node_Copy(from, newnode, joinaliasvars);
|
||||
Node_Copy(from, newnode, alias);
|
||||
@@ -1690,6 +1708,17 @@ _copyRangeSubselect(RangeSubselect *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static RangeFunction *
|
||||
_copyRangeFunction(RangeFunction *from)
|
||||
{
|
||||
RangeFunction *newnode = makeNode(RangeFunction);
|
||||
|
||||
Node_Copy(from, newnode, funccallnode);
|
||||
Node_Copy(from, newnode, alias);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static TypeCast *
|
||||
_copyTypeCast(TypeCast *from)
|
||||
{
|
||||
@@ -2621,6 +2650,9 @@ copyObject(void *from)
|
||||
case T_SubqueryScan:
|
||||
retval = _copySubqueryScan(from);
|
||||
break;
|
||||
case T_FunctionScan:
|
||||
retval = _copyFunctionScan(from);
|
||||
break;
|
||||
case T_Join:
|
||||
retval = _copyJoin(from);
|
||||
break;
|
||||
@@ -3001,6 +3033,9 @@ copyObject(void *from)
|
||||
case T_RangeSubselect:
|
||||
retval = _copyRangeSubselect(from);
|
||||
break;
|
||||
case T_RangeFunction:
|
||||
retval = _copyRangeFunction(from);
|
||||
break;
|
||||
case T_TypeName:
|
||||
retval = _copyTypeName(from);
|
||||
break;
|
||||
|
@@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.130 2002/04/28 19:54:28 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.131 2002/05/12 20:10:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1573,6 +1573,17 @@ _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalRangeFunction(RangeFunction *a, RangeFunction *b)
|
||||
{
|
||||
if (!equal(a->funccallnode, b->funccallnode))
|
||||
return false;
|
||||
if (!equal(a->alias, b->alias))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalTypeName(TypeName *a, TypeName *b)
|
||||
{
|
||||
@@ -1678,6 +1689,8 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
|
||||
return false;
|
||||
if (!equal(a->subquery, b->subquery))
|
||||
return false;
|
||||
if (!equal(a->funcexpr, b->funcexpr))
|
||||
return false;
|
||||
if (a->jointype != b->jointype)
|
||||
return false;
|
||||
if (!equal(a->joinaliasvars, b->joinaliasvars))
|
||||
@@ -2166,6 +2179,9 @@ equal(void *a, void *b)
|
||||
case T_RangeSubselect:
|
||||
retval = _equalRangeSubselect(a, b);
|
||||
break;
|
||||
case T_RangeFunction:
|
||||
retval = _equalRangeFunction(a, b);
|
||||
break;
|
||||
case T_TypeName:
|
||||
retval = _equalTypeName(a, b);
|
||||
break;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.157 2002/04/28 19:54:28 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.158 2002/05/12 20:10:03 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@@ -551,6 +551,18 @@ _outSubqueryScan(StringInfo str, SubqueryScan *node)
|
||||
_outNode(str, node->subplan);
|
||||
}
|
||||
|
||||
/*
|
||||
* FunctionScan is a subclass of Scan
|
||||
*/
|
||||
static void
|
||||
_outFunctionScan(StringInfo str, FunctionScan *node)
|
||||
{
|
||||
appendStringInfo(str, " FUNCTIONSCAN ");
|
||||
_outPlanInfo(str, (Plan *) node);
|
||||
|
||||
appendStringInfo(str, " :scanrelid %u ", node->scan.scanrelid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Material is a subclass of Plan
|
||||
*/
|
||||
@@ -980,6 +992,10 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
|
||||
appendStringInfo(str, ":subquery ");
|
||||
_outNode(str, node->subquery);
|
||||
break;
|
||||
case RTE_FUNCTION:
|
||||
appendStringInfo(str, ":funcexpr ");
|
||||
_outNode(str, node->funcexpr);
|
||||
break;
|
||||
case RTE_JOIN:
|
||||
appendStringInfo(str, ":jointype %d :joinaliasvars ",
|
||||
(int) node->jointype);
|
||||
@@ -1598,6 +1614,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_SubqueryScan:
|
||||
_outSubqueryScan(str, obj);
|
||||
break;
|
||||
case T_FunctionScan:
|
||||
_outFunctionScan(str, obj);
|
||||
break;
|
||||
case T_Material:
|
||||
_outMaterial(str, obj);
|
||||
break;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.54 2002/03/24 04:31:07 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.55 2002/05/12 20:10:03 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -254,12 +254,33 @@ print_rt(List *rtable)
|
||||
{
|
||||
RangeTblEntry *rte = lfirst(l);
|
||||
|
||||
if (rte->rtekind == RTE_RELATION)
|
||||
printf("%d\t%s\t%u",
|
||||
i, rte->eref->aliasname, rte->relid);
|
||||
else
|
||||
printf("%d\t%s\t[subquery]",
|
||||
i, rte->eref->aliasname);
|
||||
switch (rte->rtekind)
|
||||
{
|
||||
case RTE_RELATION:
|
||||
printf("%d\t%s\t%u",
|
||||
i, rte->eref->aliasname, rte->relid);
|
||||
break;
|
||||
case RTE_SUBQUERY:
|
||||
printf("%d\t%s\t[subquery]",
|
||||
i, rte->eref->aliasname);
|
||||
break;
|
||||
case RTE_FUNCTION:
|
||||
printf("%d\t%s\t[rangefunction]",
|
||||
i, rte->eref->aliasname);
|
||||
break;
|
||||
case RTE_JOIN:
|
||||
printf("%d\t%s\t[join]",
|
||||
i, rte->eref->aliasname);
|
||||
break;
|
||||
case RTE_SPECIAL:
|
||||
printf("%d\t%s\t[special]",
|
||||
i, rte->eref->aliasname);
|
||||
break;
|
||||
default:
|
||||
printf("%d\t%s\t[unknown rtekind]",
|
||||
i, rte->eref->aliasname);
|
||||
}
|
||||
|
||||
printf("\t%s\t%s\n",
|
||||
(rte->inh ? "inh" : ""),
|
||||
(rte->inFromCl ? "inFromCl" : ""));
|
||||
@@ -459,6 +480,8 @@ plannode_type(Plan *p)
|
||||
return "TIDSCAN";
|
||||
case T_SubqueryScan:
|
||||
return "SUBQUERYSCAN";
|
||||
case T_FunctionScan:
|
||||
return "FUNCTIONSCAN";
|
||||
case T_Join:
|
||||
return "JOIN";
|
||||
case T_NestLoop:
|
||||
@@ -489,12 +512,8 @@ plannode_type(Plan *p)
|
||||
}
|
||||
|
||||
/*
|
||||
prints the ascii description of the plan nodes
|
||||
does this recursively by doing a depth-first traversal of the
|
||||
plan tree. for SeqScan and IndexScan, the name of the table is also
|
||||
printed out
|
||||
|
||||
*/
|
||||
* Recursively prints a simple text description of the plan tree
|
||||
*/
|
||||
void
|
||||
print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
|
||||
{
|
||||
@@ -523,6 +542,13 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
|
||||
rte = rt_fetch(((IndexScan *) p)->scan.scanrelid, parsetree->rtable);
|
||||
StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN);
|
||||
}
|
||||
else if (IsA(p, FunctionScan))
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
|
||||
rte = rt_fetch(((FunctionScan *) p)->scan.scanrelid, parsetree->rtable);
|
||||
StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN);
|
||||
}
|
||||
else
|
||||
extraInfo[0] = '\0';
|
||||
if (extraInfo[0] != '\0')
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.120 2002/04/28 19:54:28 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.121 2002/05/12 20:10:03 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
@@ -651,6 +651,24 @@ _readSubqueryScan(void)
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readFunctionScan
|
||||
*
|
||||
* FunctionScan is a subclass of Scan
|
||||
* ----------------
|
||||
*/
|
||||
static FunctionScan *
|
||||
_readFunctionScan(void)
|
||||
{
|
||||
FunctionScan *local_node;
|
||||
|
||||
local_node = makeNode(FunctionScan);
|
||||
|
||||
_getScan((Scan *) local_node);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readSort
|
||||
*
|
||||
@@ -1514,6 +1532,11 @@ _readRangeTblEntry(void)
|
||||
local_node->subquery = nodeRead(true); /* now read it */
|
||||
break;
|
||||
|
||||
case RTE_FUNCTION:
|
||||
token = pg_strtok(&length); /* eat :funcexpr */
|
||||
local_node->funcexpr = nodeRead(true); /* now read it */
|
||||
break;
|
||||
|
||||
case RTE_JOIN:
|
||||
token = pg_strtok(&length); /* eat :jointype */
|
||||
token = pg_strtok(&length); /* get jointype */
|
||||
@@ -2031,6 +2054,8 @@ parsePlanString(void)
|
||||
return_value = _readTidScan();
|
||||
else if (length == 12 && strncmp(token, "SUBQUERYSCAN", length) == 0)
|
||||
return_value = _readSubqueryScan();
|
||||
else if (length == 12 && strncmp(token, "FUNCTIONSCAN", length) == 0)
|
||||
return_value = _readFunctionScan();
|
||||
else if (length == 4 && strncmp(token, "SORT", length) == 0)
|
||||
return_value = _readSort();
|
||||
else if (length == 6 && strncmp(token, "AGGREG", length) == 0)
|
||||
|
Reference in New Issue
Block a user