diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-09-29 18:21:41 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-09-29 18:21:41 +0000 |
commit | 3a94e789f5c9537d804210be3cb26f7fb08e3b9e (patch) | |
tree | f1eac12405e3c0ded881d7dd7e59cec35b30c335 /src/backend/nodes | |
parent | 6f64c2e54a0b14154a335249f4dca91a39c61c50 (diff) | |
download | postgresql-3a94e789f5c9537d804210be3cb26f7fb08e3b9e.tar.gz |
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!
Diffstat (limited to 'src/backend/nodes')
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 71 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 46 | ||||
-rw-r--r-- | src/backend/nodes/list.c | 55 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 130 | ||||
-rw-r--r-- | src/backend/nodes/print.c | 37 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 172 |
6 files changed, 297 insertions, 214 deletions
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index d6883bb339..808ffbd075 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 51a7a03fc1..bcb8e396ed 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -312,6 +312,17 @@ _equalRangeTblRef(RangeTblRef *a, RangeTblRef *b) } 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) { if (a->jointype != b->jointype) @@ -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; @@ -1677,17 +1692,6 @@ _equalSortClause(SortClause *a, SortClause *b) } 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) { if (!equalstr(a->constr_name, b->constr_name)) @@ -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; diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c index e94b357d24..358e6a7eb6 100644 --- a/src/backend/nodes/list.c +++ b/src/backend/nodes/list.c @@ -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); +#include "nodes/parsenodes.h" - 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. diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 8b24b82122..39bc497343 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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 @@ -536,6 +535,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 */ static void @@ -864,6 +876,18 @@ _outRangeTblRef(StringInfo str, RangeTblRef *node) } /* + * FromExpr + */ +static void +_outFromExpr(StringInfo str, FromExpr *node) +{ + appendStringInfo(str, " FROMEXPR :fromlist "); + _outNode(str, node->fromlist); + appendStringInfo(str, " :quals "); + _outNode(str, node->quals); +} + +/* * JoinExpr */ static void @@ -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; diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index 3f48cb0b9e..a0417f8108 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -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; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 00a6407db8..da0ba22684 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -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; } @@ -562,6 +561,29 @@ _readTidScan() } /* ---------------- + * _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 * * Sort is a subclass of Plan @@ -1182,6 +1204,30 @@ _readRangeTblRef() } /* ---------------- + * _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 * * JoinExpr is a subclass of Node @@ -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; - - return local_node; -} - -static RowMark * -_readRowMark() -{ - RowMark *local_node = makeNode(RowMark); - char *token; - int length; + token = lsptok(NULL, &length); /* eat :checkForRead */ + token = lsptok(NULL, &length); /* get :checkForRead */ + local_node->checkForRead = (token[0] == 't') ? true : false; - token = lsptok(NULL, &length); /* eat :rti */ - token = lsptok(NULL, &length); /* get :rti */ - local_node->rti = strtoul(token, NULL, 10); + token = lsptok(NULL, &length); /* eat :checkForWrite */ + token = lsptok(NULL, &length); /* get :checkForWrite */ + local_node->checkForWrite = (token[0] == 't') ? true : false; - 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; } |