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:
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user