1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-23 03:21:12 +03:00

Subselects in FROM clause, per ISO syntax: FROM (SELECT ...) [AS] alias.

(Don't forget that an alias is required.)  Views reimplemented as expanding
to subselect-in-FROM.  Grouping, aggregates, DISTINCT in views actually
work now (he says optimistically).  No UNION support in subselects/views
yet, but I have some ideas about that.  Rule-related permissions checking
moved out of rewriter and into executor.
INITDB REQUIRED!
This commit is contained in:
Tom Lane
2000-09-29 18:21:41 +00:00
parent 6f64c2e54a
commit 3a94e789f5
77 changed files with 3176 additions and 2661 deletions

View File

@ -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.122 2000/09/20 15:28:01 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.123 2000/09/29 18:21:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -300,6 +300,31 @@ _copyTidScan(TidScan *from)
return newnode;
}
/* ----------------
* _copySubqueryScan
* ----------------
*/
static SubqueryScan *
_copySubqueryScan(SubqueryScan *from)
{
SubqueryScan *newnode = makeNode(SubqueryScan);
/* ----------------
* copy node superclass fields
* ----------------
*/
CopyPlanFields((Plan *) from, (Plan *) newnode);
CopyScanFields((Scan *) from, (Scan *) newnode);
/* ----------------
* copy remainder of node
* ----------------
*/
Node_Copy(from, newnode, subplan);
return newnode;
}
/* ----------------
* CopyJoinFields
@ -913,6 +938,17 @@ _copyRangeTblRef(RangeTblRef *from)
return newnode;
}
static FromExpr *
_copyFromExpr(FromExpr *from)
{
FromExpr *newnode = makeNode(FromExpr);
Node_Copy(from, newnode, fromlist);
Node_Copy(from, newnode, quals);
return newnode;
}
static JoinExpr *
_copyJoinExpr(JoinExpr *from)
{
@ -1025,9 +1061,11 @@ _copyRelOptInfo(RelOptInfo *from)
Node_Copy(from, newnode, cheapest_total_path);
newnode->pruneable = from->pruneable;
newnode->issubquery = from->issubquery;
newnode->indexed = from->indexed;
newnode->pages = from->pages;
newnode->tuples = from->tuples;
Node_Copy(from, newnode, subplan);
Node_Copy(from, newnode, baserestrictinfo);
newnode->baserestrictcost = from->baserestrictcost;
@ -1306,7 +1344,7 @@ _copyRestrictInfo(RestrictInfo *from)
* ----------------
*/
Node_Copy(from, newnode, clause);
newnode->isjoinqual = from->isjoinqual;
newnode->ispusheddown = from->ispusheddown;
Node_Copy(from, newnode, subclauseindices);
newnode->mergejoinoperator = from->mergejoinoperator;
newnode->left_sortop = from->left_sortop;
@ -1392,22 +1430,14 @@ _copyRangeTblEntry(RangeTblEntry *from)
if (from->relname)
newnode->relname = pstrdup(from->relname);
newnode->relid = from->relid;
Node_Copy(from, newnode, subquery);
Node_Copy(from, newnode, alias);
Node_Copy(from, newnode, eref);
newnode->inh = from->inh;
newnode->inFromCl = from->inFromCl;
newnode->skipAcl = from->skipAcl;
return newnode;
}
static RowMark *
_copyRowMark(RowMark *from)
{
RowMark *newnode = makeNode(RowMark);
newnode->rti = from->rti;
newnode->info = from->info;
newnode->checkForRead = from->checkForRead;
newnode->checkForWrite = from->checkForWrite;
newnode->checkAsUser = from->checkAsUser;
return newnode;
}
@ -1674,8 +1704,8 @@ _copyQuery(Query *from)
Node_Copy(from, newnode, jointree);
Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, qual);
Node_Copy(from, newnode, rowMark);
newnode->rowMarks = listCopy(from->rowMarks);
Node_Copy(from, newnode, distinctClause);
Node_Copy(from, newnode, sortClause);
@ -2493,6 +2523,9 @@ copyObject(void *from)
case T_TidScan:
retval = _copyTidScan(from);
break;
case T_SubqueryScan:
retval = _copySubqueryScan(from);
break;
case T_Join:
retval = _copyJoin(from);
break;
@ -2575,6 +2608,9 @@ copyObject(void *from)
case T_RangeTblRef:
retval = _copyRangeTblRef(from);
break;
case T_FromExpr:
retval = _copyFromExpr(from);
break;
case T_JoinExpr:
retval = _copyJoinExpr(from);
break;
@ -2881,9 +2917,6 @@ copyObject(void *from)
case T_CaseWhen:
retval = _copyCaseWhen(from);
break;
case T_RowMark:
retval = _copyRowMark(from);
break;
case T_FkConstraint:
retval = _copyFkConstraint(from);
break;

View File

@ -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.73 2000/09/12 21:06:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.74 2000/09/29 18:21:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -311,6 +311,17 @@ _equalRangeTblRef(RangeTblRef *a, RangeTblRef *b)
return true;
}
static bool
_equalFromExpr(FromExpr *a, FromExpr *b)
{
if (!equal(a->fromlist, b->fromlist))
return false;
if (!equal(a->quals, b->quals))
return false;
return true;
}
static bool
_equalJoinExpr(JoinExpr *a, JoinExpr *b)
{
@ -346,7 +357,7 @@ _equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
/*
* We treat RelOptInfos as equal if they refer to the same base rels
* joined in the same order. Is this sufficient?
* joined in the same order. Is this appropriate/sufficient?
*/
return equali(a->relids, b->relids);
}
@ -495,7 +506,7 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
{
if (!equal(a->clause, b->clause))
return false;
if (a->isjoinqual != b->isjoinqual)
if (a->ispusheddown != b->ispusheddown)
return false;
if (!equal(a->subclauseindices, b->subclauseindices))
return false;
@ -601,9 +612,7 @@ _equalQuery(Query *a, Query *b)
return false;
if (!equal(a->targetList, b->targetList))
return false;
if (!equal(a->qual, b->qual))
return false;
if (!equal(a->rowMark, b->rowMark))
if (!equali(a->rowMarks, b->rowMarks))
return false;
if (!equal(a->distinctClause, b->distinctClause))
return false;
@ -1651,6 +1660,8 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
return false;
if (a->relid != b->relid)
return false;
if (!equal(a->subquery, b->subquery))
return false;
if (!equal(a->alias, b->alias))
return false;
if (!equal(a->eref, b->eref))
@ -1659,7 +1670,11 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
return false;
if (a->inFromCl != b->inFromCl)
return false;
if (a->skipAcl != b->skipAcl)
if (a->checkForRead != b->checkForRead)
return false;
if (a->checkForWrite != b->checkForWrite)
return false;
if (a->checkAsUser != b->checkAsUser)
return false;
return true;
@ -1676,17 +1691,6 @@ _equalSortClause(SortClause *a, SortClause *b)
return true;
}
static bool
_equalRowMark(RowMark *a, RowMark *b)
{
if (a->rti != b->rti)
return false;
if (a->info != b->info)
return false;
return true;
}
static bool
_equalFkConstraint(FkConstraint *a, FkConstraint *b)
{
@ -1835,6 +1839,9 @@ equal(void *a, void *b)
case T_RangeTblRef:
retval = _equalRangeTblRef(a, b);
break;
case T_FromExpr:
retval = _equalFromExpr(a, b);
break;
case T_JoinExpr:
retval = _equalJoinExpr(a, b);
break;
@ -2140,9 +2147,6 @@ equal(void *a, void *b)
case T_CaseWhen:
retval = _equalCaseWhen(a, b);
break;
case T_RowMark:
retval = _equalRowMark(a, b);
break;
case T_FkConstraint:
retval = _equalFkConstraint(a, b);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.33 2000/09/12 21:06:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.34 2000/09/29 18:21:29 tgl Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
@ -23,40 +23,9 @@
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "nodes/parsenodes.h"
/*
* makeList
*
* Take varargs, terminated by -1, and make a List
*/
List *
makeList(void *elem,...)
{
va_list args;
List *retval = NIL;
List *temp = NIL;
List *tempcons = NIL;
va_start(args, elem);
temp = elem;
while (temp != (void *) -1)
{
temp = lcons(temp, NIL);
if (tempcons == NIL)
retval = temp;
else
lnext(tempcons) = temp;
tempcons = temp;
temp = va_arg(args, void *);
}
va_end(args);
return retval;
}
/*
* makeInteger
@ -307,7 +276,7 @@ sameseti(List *list1, List *list2)
* as were in the inputs.
*/
List *
LispUnion(List *l1, List *l2)
set_union(List *l1, List *l2)
{
List *retval = listCopy(l1);
List *i;
@ -321,7 +290,7 @@ LispUnion(List *l1, List *l2)
}
List *
LispUnioni(List *l1, List *l2)
set_unioni(List *l1, List *l2)
{
List *retval = listCopy(l1);
List *i;
@ -385,7 +354,8 @@ intMember(int l1, List *l2)
/*
* lremove
* Removes 'elem' from the the linked list.
* Removes 'elem' from the linked list (destructively changing the list!).
*
* This version matches 'elem' using simple pointer comparison.
* See also LispRemove.
*/
@ -414,7 +384,8 @@ lremove(void *elem, List *list)
/*
* LispRemove
* Removes 'elem' from the the linked list.
* Removes 'elem' from the linked list (destructively changing the list!).
*
* This version matches 'elem' using equal().
* (If there is more than one equal list member, the first is removed.)
* See also lremove.
@ -442,10 +413,12 @@ LispRemove(void *elem, List *list)
return result;
}
#ifdef NOT_USED
/*
* lremovei
* lremove() for integer lists.
*/
List *
intLispRemove(int elem, List *list)
lremovei(int elem, List *list)
{
List *l;
List *prev = NIL;
@ -467,8 +440,6 @@ intLispRemove(int elem, List *list)
return result;
}
#endif
/*
* ltruncate
* Truncate a list to n elements.

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.126 2000/09/12 21:06:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.127 2000/09/29 18:21:29 tgl Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
@ -220,6 +220,9 @@ _outQuery(StringInfo str, Query *node)
if (node->utilityStmt)
{
/*
* Hack to make up for lack of outfuncs for utility-stmt nodes
*/
switch (nodeTag(node->utilityStmt))
{
case T_CreateStmt:
@ -239,7 +242,7 @@ _outQuery(StringInfo str, Query *node)
break;
case T_NotifyStmt:
appendStringInfo(str, " :utility ");
appendStringInfo(str, " :notify ");
_outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname);
break;
@ -250,32 +253,34 @@ _outQuery(StringInfo str, Query *node)
else
appendStringInfo(str, " :utility <>");
appendStringInfo(str, " :resultRelation %u :into ",
appendStringInfo(str, " :resultRelation %d :into ",
node->resultRelation);
_outToken(str, node->into);
appendStringInfo(str,
" :isPortal %s :isBinary %s :isTemp %s :unionall %s :distinctClause ",
appendStringInfo(str, " :isPortal %s :isBinary %s :isTemp %s"
" :unionall %s :hasAggs %s :hasSubLinks %s :rtable ",
node->isPortal ? "true" : "false",
node->isBinary ? "true" : "false",
node->isTemp ? "true" : "false",
node->unionall ? "true" : "false");
_outNode(str, node->distinctClause);
appendStringInfo(str, " :sortClause ");
_outNode(str, node->sortClause);
appendStringInfo(str, " :rtable ");
node->unionall ? "true" : "false",
node->hasAggs ? "true" : "false",
node->hasSubLinks ? "true" : "false");
_outNode(str, node->rtable);
appendStringInfo(str, " :jointree ");
_outNode(str, node->jointree);
appendStringInfo(str, " :targetlist ");
appendStringInfo(str, " :targetList ");
_outNode(str, node->targetList);
appendStringInfo(str, " :qual ");
_outNode(str, node->qual);
appendStringInfo(str, " :rowMarks ");
_outIntList(str, node->rowMarks);
appendStringInfo(str, " :distinctClause ");
_outNode(str, node->distinctClause);
appendStringInfo(str, " :sortClause ");
_outNode(str, node->sortClause);
appendStringInfo(str, " :groupClause ");
_outNode(str, node->groupClause);
@ -283,23 +288,17 @@ _outQuery(StringInfo str, Query *node)
appendStringInfo(str, " :havingQual ");
_outNode(str, node->havingQual);
appendStringInfo(str, " :hasAggs %s :hasSubLinks %s :unionClause ",
node->hasAggs ? "true" : "false",
node->hasSubLinks ? "true" : "false");
_outNode(str, node->unionClause);
appendStringInfo(str, " :intersectClause ");
_outNode(str, node->intersectClause);
appendStringInfo(str, " :unionClause ");
_outNode(str, node->unionClause);
appendStringInfo(str, " :limitOffset ");
_outNode(str, node->limitOffset);
appendStringInfo(str, " :limitCount ");
_outNode(str, node->limitCount);
appendStringInfo(str, " :rowMark ");
_outNode(str, node->rowMark);
}
static void
@ -535,6 +534,19 @@ _outTidScan(StringInfo str, TidScan *node)
}
/*
* SubqueryScan is a subclass of Scan
*/
static void
_outSubqueryScan(StringInfo str, SubqueryScan *node)
{
appendStringInfo(str, " SUBQUERYSCAN ");
_outPlanInfo(str, (Plan *) node);
appendStringInfo(str, " :scanrelid %u :subplan ", node->scan.scanrelid);
_outNode(str, node->subplan);
}
/*
* Material is a subclass of Plan
*/
@ -863,6 +875,18 @@ _outRangeTblRef(StringInfo str, RangeTblRef *node)
node->rtindex);
}
/*
* FromExpr
*/
static void
_outFromExpr(StringInfo str, FromExpr *node)
{
appendStringInfo(str, " FROMEXPR :fromlist ");
_outNode(str, node->fromlist);
appendStringInfo(str, " :quals ");
_outNode(str, node->quals);
}
/*
* JoinExpr
*/
@ -916,36 +940,33 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node)
appendStringInfo(str, " RELOPTINFO :relids ");
_outIntList(str, node->relids);
appendStringInfo(str,
" :rows %.0f :width %d :indexed %s :pages %ld :tuples %.0f :targetlist ",
appendStringInfo(str, " :rows %.0f :width %d :targetlist ",
node->rows,
node->width,
node->indexed ? "true" : "false",
node->pages,
node->tuples);
node->width);
_outNode(str, node->targetlist);
appendStringInfo(str, " :pathlist ");
_outNode(str, node->pathlist);
appendStringInfo(str, " :cheapest_startup_path ");
_outNode(str, node->cheapest_startup_path);
appendStringInfo(str, " :cheapest_total_path ");
_outNode(str, node->cheapest_total_path);
appendStringInfo(str,
" :pruneable %s :baserestrictinfo ",
node->pruneable ? "true" : "false");
_outNode(str, node->baserestrictinfo);
appendStringInfo(str, " :pruneable %s :issubquery %s :indexed %s :pages %ld :tuples %.0f :subplan ",
node->pruneable ? "true" : "false",
node->issubquery ? "true" : "false",
node->indexed ? "true" : "false",
node->pages,
node->tuples);
_outNode(str, node->subplan);
appendStringInfo(str,
" :baserestrictcost %.2f :outerjoinset ",
appendStringInfo(str, " :baserestrictinfo ");
_outNode(str, node->baserestrictinfo);
appendStringInfo(str, " :baserestrictcost %.2f :outerjoinset ",
node->baserestrictcost);
_outIntList(str, node->outerjoinset);
appendStringInfo(str, " :joininfo ");
_outNode(str, node->joininfo);
appendStringInfo(str, " :innerjoin ");
_outNode(str, node->innerjoin);
}
@ -977,21 +998,21 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
{
appendStringInfo(str, " RTE :relname ");
_outToken(str, node->relname);
appendStringInfo(str, " :relid %u :alias ",
appendStringInfo(str, " :relid %u ",
node->relid);
appendStringInfo(str, " :subquery ");
_outNode(str, node->subquery);
appendStringInfo(str, " :alias ");
_outNode(str, node->alias);
appendStringInfo(str, " :eref ");
_outNode(str, node->eref);
appendStringInfo(str, " :inh %s :inFromCl %s :skipAcl %s",
appendStringInfo(str, " :inh %s :inFromCl %s :checkForRead %s"
" :checkForWrite %s :checkAsUser %u",
node->inh ? "true" : "false",
node->inFromCl ? "true" : "false",
node->skipAcl ? "true" : "false");
}
static void
_outRowMark(StringInfo str, RowMark *node)
{
appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
node->checkForRead ? "true" : "false",
node->checkForWrite ? "true" : "false",
node->checkAsUser);
}
/*
@ -1151,8 +1172,8 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
appendStringInfo(str, " RESTRICTINFO :clause ");
_outNode(str, node->clause);
appendStringInfo(str, " :isjoinqual %s :subclauseindices ",
node->isjoinqual ? "true" : "false");
appendStringInfo(str, " :ispusheddown %s :subclauseindices ",
node->ispusheddown ? "true" : "false");
_outNode(str, node->subclauseindices);
appendStringInfo(str, " :mergejoinoperator %u ", node->mergejoinoperator);
@ -1492,6 +1513,9 @@ _outNode(StringInfo str, void *obj)
case T_TidScan:
_outTidScan(str, obj);
break;
case T_SubqueryScan:
_outSubqueryScan(str, obj);
break;
case T_Material:
_outMaterial(str, obj);
break;
@ -1555,6 +1579,9 @@ _outNode(StringInfo str, void *obj)
case T_RangeTblRef:
_outRangeTblRef(str, obj);
break;
case T_FromExpr:
_outFromExpr(str, obj);
break;
case T_JoinExpr:
_outJoinExpr(str, obj);
break;
@ -1573,9 +1600,6 @@ _outNode(StringInfo str, void *obj)
case T_RangeTblEntry:
_outRangeTblEntry(str, obj);
break;
case T_RowMark:
_outRowMark(str, obj);
break;
case T_Path:
_outPath(str, obj);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.41 2000/09/25 18:14:55 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.42 2000/09/29 18:21:29 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -39,7 +39,6 @@ print(void *obj)
s = nodeToString(obj);
printf("%s\n", s);
fflush(stdout);
return;
}
/*
@ -132,10 +131,15 @@ print_rt(List *rtable)
{
RangeTblEntry *rte = lfirst(l);
printf("%d\t%s(%s)\t%u\t%d\t%s\n",
i, rte->relname, rte->eref->relname, rte->relid,
rte->inFromCl,
(rte->inh ? "inh" : ""));
if (rte->relname)
printf("%d\t%s (%s)\t%u",
i, rte->relname, rte->eref->relname, rte->relid);
else
printf("%d\t[subquery] (%s)\t",
i, rte->eref->relname);
printf("\t%s\t%s\n",
(rte->inh ? "inh" : ""),
(rte->inFromCl ? "inFromCl" : ""));
i++;
}
}
@ -286,7 +290,7 @@ plannode_type(Plan *p)
{
switch (nodeTag(p))
{
case T_Plan:
case T_Plan:
return "PLAN";
break;
case T_Result:
@ -304,6 +308,12 @@ plannode_type(Plan *p)
case T_IndexScan:
return "INDEXSCAN";
break;
case T_TidScan:
return "TIDSCAN";
break;
case T_SubqueryScan:
return "SUBQUERYSCAN";
break;
case T_Join:
return "JOIN";
break;
@ -334,9 +344,6 @@ plannode_type(Plan *p)
case T_Group:
return "GROUP";
break;
case T_TidScan:
return "TIDSCAN";
break;
default:
return "UNKNOWN";
break;
@ -372,10 +379,10 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
}
else if (IsA(p, IndexScan))
{
StrNCpy(extraInfo,
((RangeTblEntry *) (nth(((IndexScan *) p)->scan.scanrelid - 1,
parsetree->rtable)))->relname,
NAMEDATALEN);
RangeTblEntry *rte;
rte = rt_fetch(((IndexScan *) p)->scan.scanrelid, parsetree->rtable);
StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
}
else
extraInfo[0] = '\0';
@ -386,7 +393,7 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: ");
print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: ");
if (nodeTag(p) == T_Append)
if (IsA(p, Append))
{
List *lst;
int whichplan = 0;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.96 2000/09/12 21:06:49 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.97 2000/09/29 18:21:29 tgl Exp $
*
* NOTES
* Most of the read functions for plan nodes are tested. (In fact, they
@ -70,13 +70,16 @@ _readQuery()
local_node->commandType = atoi(token);
token = lsptok(NULL, &length); /* skip :utility */
/* we can't get create or index here, can we? */
token = lsptok(NULL, &length); /* get the notify name if any */
token = lsptok(NULL, &length);
if (length == 0)
local_node->utilityStmt = NULL;
else
{
/*
* Hack to make up for lack of readfuncs for utility-stmt nodes
*
* we can't get create or index here, can we?
*/
NotifyStmt *n = makeNode(NotifyStmt);
n->relname = debackslash(token, length);
@ -110,11 +113,13 @@ _readQuery()
token = lsptok(NULL, &length); /* get unionall */
local_node->unionall = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* skip :distinctClause */
local_node->distinctClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip the :hasAggs */
token = lsptok(NULL, &length); /* get hasAggs */
local_node->hasAggs = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* skip :sortClause */
local_node->sortClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip the :hasSubLinks */
token = lsptok(NULL, &length); /* get hasSubLinks */
local_node->hasSubLinks = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* skip :rtable */
local_node->rtable = nodeRead(true);
@ -125,8 +130,14 @@ _readQuery()
token = lsptok(NULL, &length); /* skip :targetlist */
local_node->targetList = nodeRead(true);
token = lsptok(NULL, &length); /* skip :qual */
local_node->qual = nodeRead(true);
token = lsptok(NULL, &length); /* skip :rowMarks */
local_node->rowMarks = toIntList(nodeRead(true));
token = lsptok(NULL, &length); /* skip :distinctClause */
local_node->distinctClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip :sortClause */
local_node->sortClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip :groupClause */
local_node->groupClause = nodeRead(true);
@ -134,20 +145,11 @@ _readQuery()
token = lsptok(NULL, &length); /* skip :havingQual */
local_node->havingQual = nodeRead(true);
token = lsptok(NULL, &length); /* skip the :hasAggs */
token = lsptok(NULL, &length); /* get hasAggs */
local_node->hasAggs = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* skip the :hasSubLinks */
token = lsptok(NULL, &length); /* get hasSubLinks */
local_node->hasSubLinks = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* skip :unionClause */
local_node->unionClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip :intersectClause */
local_node->intersectClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip :unionClause */
local_node->unionClause = nodeRead(true);
token = lsptok(NULL, &length); /* skip :limitOffset */
local_node->limitOffset = nodeRead(true);
@ -155,9 +157,6 @@ _readQuery()
token = lsptok(NULL, &length); /* skip :limitCount */
local_node->limitCount = nodeRead(true);
token = lsptok(NULL, &length); /* skip :rowMark */
local_node->rowMark = nodeRead(true);
return local_node;
}
@ -561,6 +560,29 @@ _readTidScan()
return local_node;
}
/* ----------------
* _readSubqueryScan
*
* SubqueryScan is a subclass of Scan
* ----------------
*/
static SubqueryScan *
_readSubqueryScan()
{
SubqueryScan *local_node;
char *token;
int length;
local_node = makeNode(SubqueryScan);
_getScan((Scan *) local_node);
token = lsptok(NULL, &length); /* eat :subplan */
local_node->subplan = nodeRead(true); /* now read it */
return local_node;
}
/* ----------------
* _readSort
*
@ -1181,6 +1203,30 @@ _readRangeTblRef()
return local_node;
}
/* ----------------
* _readFromExpr
*
* FromExpr is a subclass of Node
* ----------------
*/
static FromExpr *
_readFromExpr()
{
FromExpr *local_node;
char *token;
int length;
local_node = makeNode(FromExpr);
token = lsptok(NULL, &length); /* eat :fromlist */
local_node->fromlist = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* eat :quals */
local_node->quals = nodeRead(true); /* now read it */
return local_node;
}
/* ----------------
* _readJoinExpr
*
@ -1293,22 +1339,6 @@ _readRelOptInfo()
token = lsptok(NULL, &length); /* now read it */
local_node->width = atoi(token);
token = lsptok(NULL, &length); /* get :indexed */
token = lsptok(NULL, &length); /* now read it */
if (!strncmp(token, "true", 4))
local_node->indexed = true;
else
local_node->indexed = false;
token = lsptok(NULL, &length); /* get :pages */
token = lsptok(NULL, &length); /* now read it */
local_node->pages = atol(token);
token = lsptok(NULL, &length); /* get :tuples */
token = lsptok(NULL, &length); /* now read it */
local_node->tuples = atof(token);
token = lsptok(NULL, &length); /* get :targetlist */
local_node->targetlist = nodeRead(true); /* now read it */
@ -1325,6 +1355,25 @@ _readRelOptInfo()
token = lsptok(NULL, &length); /* get :pruneable */
local_node->pruneable = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* get :issubquery */
token = lsptok(NULL, &length); /* now read it */
local_node->issubquery = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* get :indexed */
token = lsptok(NULL, &length); /* now read it */
local_node->indexed = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* get :pages */
token = lsptok(NULL, &length); /* now read it */
local_node->pages = atol(token);
token = lsptok(NULL, &length); /* get :tuples */
token = lsptok(NULL, &length); /* now read it */
local_node->tuples = atof(token);
token = lsptok(NULL, &length); /* get :subplan */
local_node->subplan = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :baserestrictinfo */
local_node->baserestrictinfo = nodeRead(true); /* now read it */
@ -1409,6 +1458,9 @@ _readRangeTblEntry()
token = lsptok(NULL, &length); /* get :relid */
local_node->relid = strtoul(token, NULL, 10);
token = lsptok(NULL, &length); /* eat :subquery */
local_node->subquery = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* eat :alias */
local_node->alias = nodeRead(true); /* now read it */
@ -1423,27 +1475,17 @@ _readRangeTblEntry()
token = lsptok(NULL, &length); /* get :inFromCl */
local_node->inFromCl = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* eat :skipAcl */
token = lsptok(NULL, &length); /* get :skipAcl */
local_node->skipAcl = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* eat :checkForRead */
token = lsptok(NULL, &length); /* get :checkForRead */
local_node->checkForRead = (token[0] == 't') ? true : false;
return local_node;
}
token = lsptok(NULL, &length); /* eat :checkForWrite */
token = lsptok(NULL, &length); /* get :checkForWrite */
local_node->checkForWrite = (token[0] == 't') ? true : false;
static RowMark *
_readRowMark()
{
RowMark *local_node = makeNode(RowMark);
char *token;
int length;
token = lsptok(NULL, &length); /* eat :rti */
token = lsptok(NULL, &length); /* get :rti */
local_node->rti = strtoul(token, NULL, 10);
token = lsptok(NULL, &length); /* eat :info */
token = lsptok(NULL, &length); /* get :info */
local_node->info = strtoul(token, NULL, 10);
token = lsptok(NULL, &length); /* eat :checkAsUser */
token = lsptok(NULL, &length); /* get :checkAsUser */
local_node->checkAsUser = strtoul(token, NULL, 10);
return local_node;
}
@ -1768,9 +1810,9 @@ _readRestrictInfo()
token = lsptok(NULL, &length); /* get :clause */
local_node->clause = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :isjoinqual */
token = lsptok(NULL, &length); /* get :ispusheddown */
token = lsptok(NULL, &length); /* now read it */
local_node->isjoinqual = (token[0] == 't') ? true : false;
local_node->ispusheddown = (token[0] == 't') ? true : false;
token = lsptok(NULL, &length); /* get :subclauseindices */
local_node->subclauseindices = nodeRead(true); /* now read it */
@ -1879,6 +1921,8 @@ parsePlanString(void)
return_value = _readIndexScan();
else if (length == 7 && strncmp(token, "TIDSCAN", length) == 0)
return_value = _readTidScan();
else if (length == 12 && strncmp(token, "SUBQUERYSCAN", length) == 0)
return_value = _readSubqueryScan();
else if (length == 4 && strncmp(token, "SORT", length) == 0)
return_value = _readSort();
else if (length == 6 && strncmp(token, "AGGREG", length) == 0)
@ -1891,6 +1935,8 @@ parsePlanString(void)
return_value = _readRelabelType();
else if (length == 11 && strncmp(token, "RANGETBLREF", length) == 0)
return_value = _readRangeTblRef();
else if (length == 8 && strncmp(token, "FROMEXPR", length) == 0)
return_value = _readFromExpr();
else if (length == 8 && strncmp(token, "JOINEXPR", length) == 0)
return_value = _readJoinExpr();
else if (length == 3 && strncmp(token, "AGG", length) == 0)
@ -1953,10 +1999,8 @@ parsePlanString(void)
return_value = _readCaseExpr();
else if (length == 4 && strncmp(token, "WHEN", length) == 0)
return_value = _readCaseWhen();
else if (length == 7 && strncmp(token, "ROWMARK", length) == 0)
return_value = _readRowMark();
else
elog(ERROR, "badly formatted planstring \"%.10s\"...\n", token);
elog(ERROR, "badly formatted planstring \"%.10s\"...", token);
return (Node *) return_value;
}