cursor.fix1.diff
text/plain
Filename: cursor.fix1.diff
Type: text/plain
Part: 0
Index: src/backend/commands/command.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/commands/command.c,v
retrieving revision 1.141
retrieving revision 1.142
diff -r1.141 -r1.142
101a102
> int result;
170,211c171,174
< /*
< * Determine which direction to go in, and check to see if we're
< * already at the end of the available tuples in that direction. If
< * so, do nothing. (This check exists because not all plan node types
< * are robust about being called again if they've already returned
< * NULL once.) If it's OK to do the fetch, call the executor. Then,
< * update the atStart/atEnd state depending on the number of tuples
< * that were retrieved.
< */
< if (forward)
< {
< if (!portal->atEnd)
< {
< ExecutorRun(queryDesc, estate, EXEC_FOR, (long) count);
< /*
< * I use CMD_UPDATE, because no CMD_MOVE or the like
< * exists, and I would like to provide the same
< * kind of info as CMD_UPDATE
< */
< UpdateCommandInfo(CMD_UPDATE, 0, estate->es_processed);
< if (estate->es_processed > 0)
< portal->atStart = false; /* OK to back up now */
< if (count <= 0 || (int) estate->es_processed < count)
< portal->atEnd = true; /* we retrieved 'em all */
< }
< }
< else
< {
< if (!portal->atStart)
< {
< ExecutorRun(queryDesc, estate, EXEC_BACK, (long) count);
< /*
< * I use CMD_UPDATE, because no CMD_MOVE or the like
< * exists, and I would like to provide the same
< * kind of info as CMD_UPDATE
< */
< UpdateCommandInfo(CMD_UPDATE, 0, estate->es_processed);
< if (estate->es_processed > 0)
< portal->atEnd = false; /* OK to go forward now */
< if (count <= 0 || (int) estate->es_processed < count)
< portal->atStart = true; /* we retrieved 'em all */
< }
---
> result = PortalRun( portal, forward, (long) count, queryDesc->dest, NULL );
>
> if (result > 0) {
> UpdateCommandInfo(CMD_UPDATE, 0, result);
Index: src/backend/commands/explain.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/commands/explain.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -r1.65 -r1.66
185a186,188
> case T_PortalScan:
> pname = "Portal Scan";
> break;
264c267,268
< RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
---
> RangeTblEntry *rte = (RangeTblEntry*)
> rt_fetch(((Scan *) plan)->scanrelid,
268c272
< Assert(rte->relname);
---
> Assert( rte->rtetype == RTE_RELATION );
271,272c275,276
< stringStringInfo(rte->relname));
< if (strcmp(rte->eref->relname, rte->relname) != 0)
---
> stringStringInfo(rte->u.rel.relname));
> if (strcmp(rte->eref->relname, rte->u.rel.relname) != 0)
358c362,364
< RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid,
---
>
> RangeTblEntry *rte = (RangeTblEntry *)
> rt_fetch(subqueryscan->scan.scanrelid,
359a366
>
362,363c369,370
< Assert(rte->subquery != NULL);
< es->rtable = rte->subquery->rtable;
---
> Assert(rte->rtetype == RTE_SUBSELECT);
> es->rtable = rte->u.sub.subquery->rtable;
Index: src/backend/executor/Makefile
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/Makefile,v
retrieving revision 1.16
retrieving revision 1.17
diff -r1.16 -r1.17
19c19,20
< nodeNestloop.o nodeResult.o nodeSeqscan.o nodeSetOp.o nodeSort.o \
---
> nodeNestloop.o nodePortalscan.o nodeResult.o nodeSeqscan.o \
> nodeSetOp.o nodeSort.o \
Index: src/backend/executor/execAmi.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/execAmi.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -r1.58 -r1.59
44a45
> #include "executor/nodePortalscan.h"
187a189,192
> case T_PortalScan:
> state = ((PortalScan *) node)->scan.scanstate;
> break;
>
295a301,304
> break;
>
> case T_PortalScan:
> ExecPortalReScan((PortalScan *) node, exprCtxt, parent);
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.145
retrieving revision 1.146
diff -r1.145 -r1.146
348,349c348,350
< Assert(rte->subquery != NULL);
< ExecCheckQueryPerms(operation, rte->subquery, scan->subplan);
---
> Assert(rte->rtetype == RTE_SUBSELECT);
> ExecCheckQueryPerms(operation, rte->u.sub.subquery,
> scan->subplan);
403,404c404
< if (rte->subquery)
< return;
---
> if (!rte->rtetype == RTE_RELATION) return;
406c406,407
< relName = rte->relname;
---
>
> relName = rte->u.rel.relname;
Index: src/backend/executor/execProcnode.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/execProcnode.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -r1.26 -r1.27
91a92
> #include "executor/nodePortalscan.h"
166a168,172
> case T_PortalScan:
> result = ExecInitPortalScan((PortalScan *) node, estate,
> parent);
> break;
>
292a299,302
> case T_PortalScan:
> result = ExecPortalScan((PortalScan *) node);
> break;
>
384a395,397
> case T_PortalScan:
> return ExecCountSlotsPortalScan((PortalScan *) node);
>
496a510,513
> case T_PortalScan:
> ExecEndPortalScan((PortalScan *) node);
> break;
>
625a643,650
>
> slot = scanstate->cstate.cs_ResultTupleSlot;
> }
> break;
>
> case T_PortalScan:
> {
> CommonScanState *scanstate = ((PortalScan *) node)->scan.scanstate;
Index: src/backend/executor/nodeIndexscan.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/nodeIndexscan.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -r1.62 -r1.63
991c991,993
< reloid = rtentry->relid;
---
> Assert(rtentry->rtetype == RTE_RELATION);
>
> reloid = rtentry->u.rel.relid;
Index: src/backend/executor/nodeSeqscan.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/nodeSeqscan.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -r1.31 -r1.32
161a162
>
163c164,166
< reloid = rtentry->relid;
---
> Assert(rtentry->rtetype == RTE_RELATION);
>
> reloid = rtentry->u.rel.relid;
Index: src/backend/executor/nodeSubqueryscan.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/nodeSubqueryscan.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -r1.9 -r1.10
150c150
< Assert(rte->subquery != NULL);
---
> Assert(rte->rtetype == RTE_SUBSELECT);
155c155,156
< sp_estate->es_range_table = rte->subquery->rtable;
---
> Assert( PointerIsValid(rte->u.sub.subquery) );
> sp_estate->es_range_table = rte->u.sub.subquery->rtable;
Index: src/backend/executor/nodeTidscan.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/nodeTidscan.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -r1.18 -r1.19
460a461
>
462c463
< reloid = rtentry->relid;
---
> Assert(rtentry->rtetype == RTE_RELATION);
463a465
> reloid = rtentry->u.rel.relid;
Index: src/backend/executor/spi.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/executor/spi.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -r1.57 -r1.58
1138,1141c1138,1139
< QueryDesc *querydesc;
< EState *estate;
< MemoryContext oldcontext;
< CommandDest olddest;
---
> int nrows; /* how many records portal returned */
>
1156,1159c1154
< /* Switch to the portals memory context */
< oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
< querydesc = PortalGetQueryDesc(portal);
< estate = PortalGetState(portal);
---
> nrows = PortalRun ( portal, forward, (long) count, dest, NULL);
1161,1195c1156
< /* Save the queries command destination and set it to SPI (for fetch) */
< /* or None (for move) */
< olddest = querydesc->dest;
< querydesc->dest = dest;
<
< /* Run the executor like PerformPortalFetch and remember states */
< if (forward)
< {
< if (!portal->atEnd)
< {
< ExecutorRun(querydesc, estate, EXEC_FOR, (long)count);
< _SPI_current->processed = estate->es_processed;
< if (estate->es_processed > 0)
< portal->atStart = false;
< if (count <= 0 || (int) estate->es_processed < count)
< portal->atEnd = true;
< }
< }
< else
< {
< if (!portal->atStart)
< {
< ExecutorRun(querydesc, estate, EXEC_BACK, (long) count);
< _SPI_current->processed = estate->es_processed;
< if (estate->es_processed > 0)
< portal->atEnd = false;
< if (count <= 0 || estate->es_processed < count)
< portal->atStart = true;
< }
< }
<
< /* Restore the old command destination and switch back to callers */
< /* memory context */
< querydesc->dest = olddest;
< MemoryContextSwitchTo(oldcontext);
---
> _SPI_current->processed = nrows;
Index: src/backend/executor/nodePortalscan.c
===================================================================
RCS file: nodePortalscan.c
diff -N nodePortalscan.c
0a1,258
> /*-------------------------------------------------------------------------
> *
> * nodePortalscan.c
> * Support routines for scanning portals (SELECT * FROM CURSOR FOO).
> *
> *
> * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
> * Portions Copyright (c) 1994, Regents of the University of California
> *
> *
> * IDENTIFICATION
> * $Header$
> *
> *-------------------------------------------------------------------------
> */
> /*
> * INTERFACE ROUTINES
> * ExecPortalScan scans a portal.
> * ExecPortalNext retrieve next tuple in sequential order.
> * ExecInitPortalScan creates and initializes a portalscan node.
> * ExecEndPortalScan releases any storage allocated.
> * ExecPortalReScan rescans the relation
> *
> */
> #include "postgres.h"
>
> #include "catalog/pg_type.h"
> #include "executor/execdebug.h"
> #include "executor/execdefs.h"
> #include "executor/execdesc.h"
> #include "executor/nodePortalscan.h"
> #include "parser/parsetree.h"
> #include "tcop/pquery.h"
>
> static TupleTableSlot *PortalNext(PortalScan *node);
>
> /* ----------------------------------------------------------------
> * Scan Support
> * ----------------------------------------------------------------
> */
> /* ----------------------------------------------------------------
> * PortalNext
> *
> * This is a workhorse for ExecPortalScan
> * ----------------------------------------------------------------
> */
> static TupleTableSlot *
> PortalNext(PortalScan *node)
> {
> PortalScanState *portalstate;
> EState *estate;
> ScanDirection direction;
> TupleTableSlot *slot;
> bool forward;
> Portal portal;
> int ntuples;
>
> /*
> * get information from the estate and scan state
> */
> estate = node->scan.plan.state;
> portalstate = (PortalScanState *) node->scan.scanstate;
> direction = estate->es_direction;
> forward = ScanDirectionIsForward(direction);
> portal = portalstate->portal;
>
> /*
> * get the next tuple from Portal
> */
>
> ntuples = PortalRun(portal, forward, (long) 1, NULL, &slot);
>
> portalstate->csstate.css_ScanTupleSlot = slot;
>
> return slot;
> }
>
> /* ----------------------------------------------------------------
> * ExecPortalScan(node)
> *
> * Scans the portal sequentially and returns the next qualifying
> * tuple.
> * It calls the ExecScan() routine and passes it the access method
> * which retrieve tuples sequentially.
> *
> */
>
> TupleTableSlot *
> ExecPortalScan(PortalScan *node)
> {
> /*
> * use PortalNext as access method
> */
> return ExecScan(&node->scan, (ExecScanAccessMtd) PortalNext);
> }
>
> /* ----------------------------------------------------------------
> * ExecInitPortalScan
> * ----------------------------------------------------------------
> */
> bool
> ExecInitPortalScan(PortalScan *node, EState *estate, Plan *parent)
> {
> PortalScanState *portalstate;
> RangeTblEntry *rte;
> Portal portal;
>
> /*
> * PortalScan should not have any "normal" children.
> */
> Assert(outerPlan((Plan *) node) == NULL);
> Assert(innerPlan((Plan *) node) == NULL);
>
> /*
> * assign the node's execution state
> */
> node->scan.plan.state = estate;
>
> /*
> * create new PortalScanState for node
> */
> portalstate = makeNode(PortalScanState);
> node->scan.scanstate = (CommonScanState *) portalstate;
>
> /*
> * Miscellaneous initialization
> *
> * create expression context for node
> */
> ExecAssignExprContext(estate, &portalstate->csstate.cstate);
>
> #define SUBQUERYSCAN_NSLOTS 1
>
> /*
> * tuple table initialization
> */
> ExecInitResultTupleSlot(estate, &portalstate->csstate.cstate);
>
> /*
> * initialize portal
> *
> * This should agree with ExecInitSubPlan
> */
> rte = rt_fetch( node->scan.scanrelid, estate->es_range_table);
> Assert(rte->rtetype == RTE_PORTAL);
>
> portalstate->csstate.css_ScanTupleSlot = NULL;
> portalstate->csstate.cstate.cs_TupFromTlist = false;
>
> portal = GetPortalByName( rte->u.portal.portalname);
> if (!PointerIsValid(portal))
> elog(ERROR, "InitPortalScan: portal %s disappeared",
> rte->u.portal.portalname);
>
> portalstate->portal = portal;
>
> /*
> * initialize tuple type
> */
> ExecAssignResultTypeFromTL((Plan *) node, &portalstate->csstate.cstate);
> ExecAssignProjectionInfo((Plan *) node, &portalstate->csstate.cstate);
>
> return TRUE;
> }
>
> int
> ExecCountSlotsPortalScan(PortalScan *node)
> {
> /*
> * The subplan has its own tuple table and must not be counted here!
> */
> return ExecCountSlotsNode(outerPlan(node)) +
> ExecCountSlotsNode(innerPlan(node)) +
> SUBQUERYSCAN_NSLOTS;
> }
>
> /* ----------------------------------------------------------------
> * ExecEndPortalScan
> *
> * frees any storage allocated through C routines.
> * ----------------------------------------------------------------
> */
> void
> ExecEndPortalScan(PortalScan *node)
> {
> PortalScanState *portalstate;
>
> /*
> * get information from node
> */
> portalstate = (PortalScanState *) node->scan.scanstate;
>
> /*
> * Free the projection info and the scan attribute info
> *
> * Note: we don't ExecFreeResultType(portalstate) because the rule
> * manager depends on the tupType returned by ExecMain(). So for now,
> * this is freed at end-transaction time. -cim 6/2/91
> */
> ExecFreeProjectionInfo(&portalstate->csstate.cstate);
> ExecFreeExprContext(&portalstate->csstate.cstate);
>
> /*
> * close down portal
> */
> /* XXX */
>
> /*
> * clean up portal's tuple table
> */
> portalstate->csstate.css_ScanTupleSlot = NULL;
>
> /*
> * clean out the upper tuple table
> */
> ExecClearTuple(portalstate->csstate.cstate.cs_ResultTupleSlot);
> }
>
> /* ----------------------------------------------------------------
> * ExecPortalReScan
> *
> * Rescans the relation.
> * ----------------------------------------------------------------
> */
> void
> ExecPortalReScan(PortalScan *node, ExprContext *exprCtxt, Plan *parent)
> {
> PortalScanState *portalstate;
> EState *estate;
>
> portalstate = (PortalScanState *) node->scan.scanstate;
> estate = node->scan.plan.state;
>
> elog(ERROR, "PortalReScan: Cannot rescan portals");
>
> /*
> * ExecReScan doesn't know about my subplan, so I have to do
> * changed-parameter signaling myself.
> */
>
> /*
> if (node->scan.plan.chgParam != NULL)
> SetChangedParamList(node->subplan, node->scan.plan.chgParam);
> */
>
> /*
> * if chgParam of subnode is not null then plan will be re-scanned by
> * first ExecProcNode.
> */
>
> /*
> XXX
> if (node->subplan->chgParam == NULL)
> ExecReScan(node->subplan, NULL, node->subplan);
> */
>
> portalstate->csstate.css_ScanTupleSlot = NULL;
> }
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.155
retrieving revision 1.156
diff -r1.155 -r1.156
229a230,247
> * _copyPortalScan
> * ----------------
> */
> static PortalScan *
> _copyPortalScan(PortalScan *from)
> {
> PortalScan *newnode = makeNode(PortalScan);
>
> /*
> * copy node superclass fields
> */
> CopyPlanFields((Plan *) from, (Plan *) newnode);
> CopyScanFields((Scan *) from, (Scan *) newnode);
>
> return newnode;
> }
>
> /* ----------------
1108c1126
< newnode->issubquery = from->issubquery;
---
> newnode->reltype = from->reltype;
1490,1494d1507
<
< if (from->relname)
< newnode->relname = pstrdup(from->relname);
< newnode->relid = from->relid;
< Node_Copy(from, newnode, subquery);
1502c1515,1529
<
---
> newnode->rtetype = from->rtetype;
> switch (from->rtetype) {
> case RTE_RELATION:
> newnode->u.rel.relname = pstrdup(from->u.rel.relname);
> newnode->u.rel.relid = from->u.rel.relid;
> break;
> case RTE_SUBSELECT:
> Node_Copy(from, newnode, u.sub.subquery);
> break;
> case RTE_PORTAL:
> newnode->u.portal.portalname = pstrdup(from->u.portal.portalname);
> break;
> default:
> elog(ERROR, "copyRTE: Unknown rtetype %d", from->rtetype);
> }
2249d2275
< newnode->freeze = from->freeze;
2555a2582,2584
> break;
> case T_PortalScan:
> retval = _copyPortalScan(from);
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.103
retrieving revision 1.104
diff -r1.103 -r1.104
1119,1120d1118
< if (a->freeze != b->freeze)
< return false;
1600,1605d1597
< if (!equalstr(a->relname, b->relname))
< return false;
< if (a->relid != b->relid)
< return false;
< if (!equal(a->subquery, b->subquery))
< return false;
1620c1612,1631
<
---
> if (a->rtetype != b->rtetype)
> return false;
> switch (a->rtetype) {
> case RTE_RELATION:
> if (!equalstr(a->u.rel.relname, b->u.rel.relname))
> return false;
> if (a->u.rel.relid != b->u.rel.relid)
> return false;
> break;
> case RTE_SUBSELECT:
> if (!equal(a->u.sub.subquery, b->u.sub.subquery))
> return false;
> break;
> case RTE_PORTAL:
> if (!equalstr(a->u.portal.portalname, b->u.portal.portalname))
> return false;
> break;
> default:
> elog(ERROR, "equalRTE: Unknown rtetype %d", a->rtetype);
> }
Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.145
retrieving revision 1.146
diff -r1.145 -r1.146
506a507,516
> * PortalScan is a subclass of Scan
> */
> static void
> _outPortalScan(StringInfo str, PortalScan *node)
> {
> appendStringInfo(str, " PORTALSCAN ");
> _outPlanInfo(str, (Plan *) node);
> }
>
> /*
965,970c975
< appendStringInfo(str, " RTE :relname ");
< _outToken(str, node->relname);
< appendStringInfo(str, " :relid %u ",
< node->relid);
< appendStringInfo(str, " :subquery ");
< _outNode(str, node->subquery);
---
> appendStringInfo(str, " RTE ");
981a987,1004
> appendStringInfo(str, " :rtetype %u ", node->rtetype);
> switch (node->rtetype) {
> case RTE_RELATION:
> appendStringInfo(str, " :relname ");
> _outToken(str, node->u.rel.relname);
> appendStringInfo(str, " :relid %u ", node->u.rel.relid);
> break;
> case RTE_SUBSELECT:
> appendStringInfo(str, " :subquery ");
> _outNode(str, node->u.sub.subquery);
> break;
> case RTE_PORTAL:
> appendStringInfo(str, " :portalname ");
> _outToken(str, node->u.portal.portalname);
> break;
> default:
> elog(ERROR, "outRTE: Unknown rtetype %d", node->rtetype);
> }
1510a1534,1536
> break;
> case T_PortalScan:
> _outPortalScan(str, obj);
Index: src/backend/nodes/print.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/nodes/print.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -r1.47 -r1.48
134c134
< if (rte->relname)
---
> if (rte->rtetype == RTE_RELATION) {
136,137c136,138
< i, rte->relname, rte->eref->relname, rte->relid);
< else
---
> i, rte->u.rel.relname, rte->eref->relname, rte->u.rel.relid);
> }
> else if (rte->rtetype == RTE_SUBSELECT) {
139a141,145
> }
> else if (rte->rtetype == RTE_PORTAL) {
> printf("%d\t[portal] (%s)\t",
> i, rte->eref->relname);
> }
302a309,310
> case T_PortalScan:
> return "PORTALSCAN";
363c371,372
< StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
---
> Assert( rte->rtetype == RTE_RELATION);
> StrNCpy(extraInfo, rte->u.rel.relname, NAMEDATALEN);
370c379,380
< StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
---
> Assert( rte->rtetype == RTE_RELATION);
> StrNCpy(extraInfo, rte->u.rel.relname, NAMEDATALEN);
Index: src/backend/nodes/readfuncs.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/nodes/readfuncs.c,v
retrieving revision 1.112
retrieving revision 1.113
diff -r1.112 -r1.113
1417c1417
< _readRangeTblEntry(void)
---
> _readRangeTblEntry()
1425,1435d1424
< token = pg_strtok(&length); /* eat :relname */
< token = pg_strtok(&length); /* get :relname */
< local_node->relname = nullable_string(token, length);
<
< token = pg_strtok(&length); /* eat :relid */
< token = pg_strtok(&length); /* get :relid */
< local_node->relid = atooid(token);
<
< token = pg_strtok(&length); /* eat :subquery */
< local_node->subquery = nodeRead(true); /* now read it */
<
1461a1451,1476
> token = pg_strtok(&length); /* eat :rtetype */
> token = pg_strtok(&length); /* get :rtetype */
> local_node->rtetype = atoui(token);
>
> switch (local_node->rtetype) {
> case RTE_RELATION:
> token = pg_strtok(&length); /* eat :relname */
> token = pg_strtok(&length); /* get :relname */
> local_node->u.rel.relname = nullable_string(token, length);
>
> token = pg_strtok(&length); /* eat :relid */
> token = pg_strtok(&length); /* get :relid */
> local_node->u.rel.relid = atooid(token);
> break;
> case RTE_SUBSELECT:
> token = pg_strtok(&length); /* eat :subquery */
> local_node->u.sub.subquery = nodeRead(true); /* now read it */
> break;
> case RTE_PORTAL:
> token = pg_strtok(&length); /* eat :portalname */
> token = pg_strtok(&length); /* get :portalname */
> local_node->u.portal.portalname = nullable_string(token, length);
> break;
> default:
> elog(ERROR, "readRTE: Unknown rtetype %d", local_node->rtetype);
> }
1463a1479
>
Index: src/backend/optimizer/path/allpaths.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/path/allpaths.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -r1.78 -r1.79
27a28
> #include "utils/portal.h"
103c104
< if (rel->issubquery)
---
> if (rel->reltype == REL_SUBQUERY)
104a106
> Assert(rte->rtetype == RTE_SUBSELECT);
108c110,143
< else if ((inheritlist = expand_inherted_rtentry(root, rti, true))
---
> else if (rel->reltype == REL_PORTAL)
> {
> /* its a portal, considerably simpler case, as portals
> may not have setops or conditions. We only need
> to fill in the cost info from Portal's own Plan */
> Portal portal;
> QueryDesc *qd;
>
> Assert(rte->rtetype == RTE_PORTAL);
>
> portal = GetPortalByName(rte->u.portal.portalname);
> if (!PointerIsValid(portal))
> elog(ERROR, "set_base_rel_pathlists: Portal %s disappeared",
> rte->u.portal.portalname);
>
> qd = PortalGetQueryDesc(portal);
>
> /* Copy number of output rows from portal info */
> rel->tuples = qd->plantree->plan_rows;
>
> /* Mark rel with estimated output rows, width, etc */
> set_baserel_size_estimates(root, rel);
>
> /* Generate appropriate path */
> add_path(rel, create_portalscan_path(rel, portal) );
>
> /* Select cheapest path (pretty easy in this case...) */
> set_cheapest(rel);
> }
> /* XXX: maybe we can/should determine that a relation is a root of inheritance
> * hierarchy earlier and have REL_INH_ROOT reltype?
> */
> else if (rel->reltype == REL_PLAIN) {
> if ((inheritlist = expand_inherted_rtentry(root, rti, true))
119a155,157
> else
> elog(ERROR,"set_base_rel_pathlists: unknown reltype %d", rel->reltype);
> }
128a167
> Assert( rte->rtetype == RTE_RELATION );
181c220
< Oid parentOID = rte->relid;
---
> Oid parentOID = rte->u.rel.relid;
184a224
> Assert( rte->rtetype == RTE_RELATION );
218c258,261
< childOID = childrte->relid;
---
>
> Assert( childrte->rtetype == RTE_RELATION );
>
> childOID = childrte->u.rel.relid;
279c322,323
< Query *subquery = rte->subquery;
---
> Query *subquery = rte->u.sub.subquery;
> Assert(rte->rtetype == RTE_SUBSELECT);
Index: src/backend/optimizer/path/clausesel.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/path/clausesel.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -r1.46 -r1.47
387c387
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT)
Index: src/backend/optimizer/path/costsize.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/path/costsize.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -r1.78 -r1.79
113c113
< Assert(!baserel->issubquery);
---
> Assert(baserel->reltype == REL_PLAIN);
228c228
< Assert(!baserel->issubquery);
---
> Assert(baserel->reltype == REL_PLAIN);
Index: src/backend/optimizer/plan/createplan.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/plan/createplan.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -r1.108 -r1.109
45a46,47
> static PortalScan *create_portalscan_plan(Path *best_path,
> List *tlist, List *scan_clauses);
71a74,75
> static PortalScan *make_portalscan(List *qptlist, List *qpqual,
> Index scanrelid);
119a124
> case T_PortalScan:
200a206,211
> case T_PortalScan:
> plan = (Scan *) create_portalscan_plan(best_path,
> tlist,
> scan_clauses);
> break;
>
351,352c362
< Assert(length(best_path->parent->relids) == 1);
< Assert(!best_path->parent->issubquery);
---
> Assert(best_path->parent->reltype == REL_PLAIN);
395,396c405
< Assert(length(best_path->path.parent->relids) == 1);
< Assert(!best_path->path.parent->issubquery);
---
> Assert(best_path->path.parent->reltype == REL_PLAIN);
513,514c522
< Assert(length(best_path->path.parent->relids) == 1);
< Assert(!best_path->path.parent->issubquery);
---
> Assert(best_path->path.parent->reltype == REL_PLAIN);
543d550
< Assert(length(best_path->parent->relids) == 1);
545c552
< Assert(best_path->parent->issubquery);
---
> Assert(best_path->parent->reltype == REL_SUBQUERY);
556a564,587
> /*
> * create_portalscan_plan
> * Returns a portalscan plan for the portal scanned by 'best_path'
> * with restriction clauses 'scan_clauses' and targetlist 'tlist'.
> */
> static PortalScan *
> create_portalscan_plan(Path *best_path, List *tlist, List *scan_clauses)
> {
> PortalScan *scan_plan;
> Index scan_relid;
>
> /* there should be exactly one base rel involved... */
> /* and it must be a portal */
> Assert(best_path->parent->reltype == REL_PORTAL);
>
> scan_relid = (Index) lfirsti(best_path->parent->relids);
>
> scan_plan = make_portalscan( tlist, scan_clauses, scan_relid );
>
> copy_path_costsize(&scan_plan->scan.plan, best_path);
>
> return scan_plan;
> }
>
1288a1320,1339
> node->scan.scanstate = (CommonScanState *) NULL;
>
> return node;
> }
>
> PortalScan *
> make_portalscan(List *qptlist,
> List *qpqual,
> Index scanrelid)
> {
> PortalScan *node = makeNode(PortalScan);
> Plan *plan = &node->scan.plan;
>
> /* cost should be inserted by caller */
> plan->state = (EState *) NULL;
> plan->targetlist = qptlist;
> plan->qual = qpqual;
> plan->lefttree = NULL;
> plan->righttree = NULL;
> node->scan.scanrelid = scanrelid;
Index: src/backend/optimizer/plan/planner.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/plan/planner.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -r1.108 -r1.109
271c271,272
< Query *subquery = rte->subquery;
---
> Query *subquery = rte->u.sub.subquery;
>
280c281,282
< if (subquery && is_simple_subquery(subquery) &&
---
> if (rte->rtetype == RTE_SUBSELECT &&
> is_simple_subquery(subquery) &&
Index: src/backend/optimizer/plan/setrefs.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/plan/setrefs.c,v
retrieving revision 1.71
retrieving revision 1.72
diff -r1.71 -r1.72
89a90,93
> case T_PortalScan:
> fix_expr_references(plan, (Node *) plan->targetlist);
> fix_expr_references(plan, (Node *) plan->qual);
> break;
Index: src/backend/optimizer/prep/preptlist.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/prep/preptlist.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -r1.42 -r1.43
61c61
< if (rte->subquery != NULL || rte->relid == InvalidOid)
---
> if (rte->rtetype == RTE_SUBSELECT)
Index: src/backend/optimizer/prep/prepunion.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/prep/prepunion.c,v
retrieving revision 1.66
retrieving revision 1.67
diff -r1.66 -r1.67
84a85
> RangeTblEntry *rte;
97,98c98,102
< leftmostQuery = rt_fetch(((RangeTblRef *) node)->rtindex,
< parse->rtable)->subquery;
---
> rte = rt_fetch(((RangeTblRef *) node)->rtindex, parse->rtable);
> Assert(rte && rte->rtetype == RTE_SUBSELECT);
>
> leftmostQuery = rte->u.sub.subquery;
>
130c134
< Query *subquery = rte->subquery;
---
> Query *subquery = rte->u.sub.subquery;
133a138
> Assert(rte->rtetype == RTE_SUBSELECT);
558c563
< Oid parentOID = rte->relid;
---
> Oid parentOID = rte->u.rel.relid;
561a567
> Assert(rte->rtetype == RTE_RELATION);
566c572
< Assert(parentOID != InvalidOid && rte->subquery == NULL);
---
>
604,605c610,613
< childrte->relname = get_rel_name(childOID);
< childrte->relid = childOID;
---
> Assert(rte->rtetype == RTE_RELATION);
> Assert(childrte->rtetype == RTE_RELATION);
> childrte->u.rel.relname = get_rel_name(childOID);
> childrte->u.rel.relid = childOID;
Index: src/backend/optimizer/util/clauses.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/util/clauses.c,v
retrieving revision 1.88
retrieving revision 1.89
diff -r1.88 -r1.89
1801,1802c1801,1802
< if (rte->subquery)
< if (walker(rte->subquery, context))
---
> if (rte->rtetype == RTE_SUBSELECT)
> if (walker( rte->u.sub.subquery, context))
2182c2182
< RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
---
> RangeTblEntry *rte = lfirst(rt);
2184c2184
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT)
2189,2190c2189,2192
< CHECKFLATCOPY(newrte->subquery, rte->subquery, Query);
< MUTATE(newrte->subquery, newrte->subquery, Query *);
---
> CHECKFLATCOPY(newrte->u.sub.subquery, rte->u.sub.subquery,
> Query);
> MUTATE(newrte->u.sub.subquery, newrte->u.sub.subquery,
> Query *);
Index: src/backend/optimizer/util/pathnode.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/util/pathnode.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -r1.75 -r1.76
436a437,457
> * create_portalscan_path
> * Creates a path corresponding to a sequential scan of a portal,
> * returning the pathnode.
> */
> Path *
> create_portalscan_path(RelOptInfo *rel, Portal portal)
> {
> Path *pathnode = makeNode(Path);
>
> pathnode->pathtype = T_PortalScan;
> pathnode->parent = rel;
> pathnode->pathkeys = NIL; /* for now, assume unordered result */
>
> /* just copy the Portal's own cost estimates */
> pathnode->startup_cost = portal->queryDesc->plantree->startup_cost;
> pathnode->total_cost = portal->queryDesc->plantree->total_cost;
>
> return pathnode;
> }
>
> /*
Index: src/backend/optimizer/util/relnode.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/optimizer/util/relnode.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -r1.33 -r1.34
128c128
< Oid relationObjectId;
---
> RangeTblEntry *rte;
138d137
< rel->issubquery = false;
149,150c148,149
< /* Check rtable to see if it's a plain relation or a subquery */
< relationObjectId = getrelid(relid, root->rtable);
---
> /* Check rtable to see if what kind of a relation it is */
> rte = rt_fetch(relid, root->rtable);
152c151
< if (relationObjectId != InvalidOid)
---
> if (rte->rtetype == RTE_RELATION)
154,155c153,155
< /* Plain relation --- retrieve statistics from the system catalogs */
< bool indexed;
---
> /* Plain relation --- retrieve statistics from the system catalogs */
> bool indexed;
> Oid relationObjectId;
157,160c157,163
< get_relation_info(relationObjectId,
< &indexed, &rel->pages, &rel->tuples);
< if (indexed)
< rel->indexlist = find_secondary_indexes(relationObjectId);
---
> rel->reltype = REL_PLAIN;
> relationObjectId = rte->u.rel.relid;
>
> get_relation_info( relationObjectId,
> &indexed, &rel->pages, &rel->tuples);
> if (indexed)
> rel->indexlist = find_secondary_indexes(relationObjectId);
162c165
< else
---
> else if (rte->rtetype == RTE_SUBSELECT)
164,165c167
< /* subquery --- mark it as such for later processing */
< rel->issubquery = true;
---
> rel->reltype = REL_SUBQUERY;
166a169,174
> else if (rte->rtetype == RTE_PORTAL)
> {
> rel->reltype = REL_PORTAL;
> }
> else
> elog(ERROR, "make_base_rel: Unknown RTE node type %d", nodeTag(rte) );
287a296
> joinrel->reltype = REL_JOIN;
295d303
< joinrel->issubquery = false;
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/parser/analyze.c,v
retrieving revision 1.197
retrieving revision 1.198
diff -r1.197 -r1.198
172d171
<
2020a2020
> RangeTblEntry* leftmostRTE;
2096c2096,2099
< leftmostQuery = rt_fetch(leftmostRTI, pstate->p_rtable)->subquery;
---
> leftmostRTE = rt_fetch(leftmostRTI, pstate->p_rtable);
> Assert(node && leftmostRTE->rtetype == RTE_SUBSELECT);
> leftmostQuery = leftmostRTE->u.sub.subquery;
>
2366c2369
< Query *selectQuery = rte->subquery;
---
> Query *selectQuery = rte->u.sub.subquery;
2369a2373
> Assert(rte->rtetype == RTE_SUBSELECT);
2878c2882
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT)
2881c2885
< transformForUpdate(rte->subquery, makeList1(NULL));
---
> transformForUpdate( rte->u.sub.subquery, makeList1(NULL));
2883c2887
< else
---
> else if ( rte->rtetype == RTE_RELATION )
2888a2893,2900
> else if ( rte->rtetype == RTE_PORTAL )
> {
> /* do nothing */
> }
> else
> {
> elog(ERROR, "FOR UPDATE: unknown RTE type %d", rte->rtetype);
> }
2906c2918
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT)
2909c2921
< transformForUpdate(rte->subquery, makeList1(NULL));
---
> transformForUpdate( rte->u.sub.subquery, makeList1(NULL));
2911c2923
< else
---
> else if (rte->rtetype == RTE_RELATION)
2915a2928,2936
> }
> else if (rte->rtetype == RTE_PORTAL)
> {
> /* do nothing */
> }
> else
> {
> elog(ERROR, "FOR UPDATE: unknown RTE type %d",
> rte->rtetype);
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.249
diff -r2.249 gram.y
3726c3726,3735
< table_ref: relation_expr
---
> table_ref:
> CURSOR relation_name
> {
> PortalRangeVar *n = makeNode(PortalRangeVar);
> n->portal = $2;
> n->name = NULL;
> $$ = (Node *) n;
> }
> |
> relation_expr
5616d5624
< | CURSOR { $$ = "cursor"; }
Index: src/backend/parser/parse_clause.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/parser/parse_clause.c,v
retrieving revision 1.82
retrieving revision 1.83
diff -r1.82 -r1.83
33a34
> #include "utils/portal.h"
82a84
> * FuncRangeVars, PortalRangeVars,
394a397,442
> * transformPortalRange --- transform FROM CURSOR FOO
> */
> static RangeTblRef *
> transformPortalRange(ParseState *pstate, PortalRangeVar *r)
> {
> RangeTblEntry *rte;
> RangeTblRef *rtr;
> Portal portal;
> QueryDesc *queryDesc;
> TupleDesc tupleDesc;
> EState *estate;
> char *portalname;
>
> /* look up information for the portal */
> portalname = r->portal;
> portal = GetPortalByName(portalname);
> if (!PortalIsValid(portal))
> elog(ERROR, "transformPortalRange: portal \"%s\" not found",
> portalname);
>
> queryDesc = PortalGetQueryDesc(portal);
> tupleDesc = PortalGetTupleDesc(portal);
> estate = PortalGetState(portal); /* XXX: check state ? */
>
> if (queryDesc->operation != CMD_SELECT)
> elog(ERROR, "Expected SELECT query from the portal %s", portalname);
>
> /*
> * OK, build an RTE for the subquery.
> */
> rte = addRangeTableEntryForPortal(pstate, portalname, r->name);
>
> /*
> * We create a RangeTblRef, but we do not add it to the joinlist or
> * namespace; our caller must do that if appropriate.
> */
> rtr = makeNode(RangeTblRef);
> /* assume new rte is at end */
> rtr->rtindex = length(pstate->p_rtable);
> Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
>
> return rtr;
> }
>
>
> /*
482a531,539
> *containedRels = makeListi1(rtr->rtindex);
> return (Node *) rtr;
> }
> if (IsA(n, PortalRangeVar))
> {
> /* reference to cursor */
> RangeTblRef *rtr;
>
> rtr = transformPortalRange(pstate, (PortalRangeVar *) n);
Index: src/backend/parser/parse_func.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/parser/parse_func.c,v
retrieving revision 1.110
retrieving revision 1.111
diff -r1.110 -r1.111
389c389,396
< if (rte->relname == NULL)
---
> if (rte->rtetype == RTE_PORTAL)
> {
> /* RTE is a portal reference, possible? not supported yet */
> elog(ERROR, "Cannot pass tuple from portal %s to function %s",
> refname, funcname);
> }
>
> if (rte->rtetype == RTE_SUBSELECT)
410c417
< toid = typenameTypeId(rte->relname);
---
> toid = typenameTypeId( rte->u.rel.relname);
Index: src/backend/parser/parse_node.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/parser/parse_node.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -r1.55 -r1.56
36a37
> #include "utils/portal.h"
173c174
< if (rte->relid != InvalidOid)
---
> if (rte->rtetype == RTE_RELATION)
180c181
< ObjectIdGetDatum(rte->relid),
---
> ObjectIdGetDatum(rte->u.rel.relid),
186c187
< rte->relname, attrno);
---
> rte->u.rel.relname, attrno);
192c193,206
< else
---
> else if (rte->rtetype == RTE_PORTAL)
> { /* Portal RTE, get type info from it */
> TupleDesc tupleDesc =
> GetPortalTupleDescByName(rte->u.portal.portalname);
> Form_pg_attribute att_tup;
>
> Assert( attrno <= (tupleDesc->natts) );
>
> att_tup = tupleDesc->attrs[attrno-1];
>
> vartypeid = att_tup->atttypid;
> type_mod = att_tup->atttypmod;
> }
> else if (rte->rtetype == RTE_SUBSELECT)
197c211
< foreach(tlistitem, rte->subquery->targetList)
---
> foreach(tlistitem, rte->u.sub.subquery->targetList)
210a225,228
> }
> else
> {
> elog(ERROR, "make_var: Unknown RTE type");
Index: src/backend/parser/parse_relation.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/parser/parse_relation.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -r1.56 -r1.57
30a31
> #include "utils/portal.h"
321c322
< if (rte->relid != InvalidOid)
---
> if (rte->rtetype == RTE_RELATION)
329c330
< ObjectIdGetDatum(rte->relid),
---
> ObjectIdGetDatum(rte->u.rel.relid),
513c514,515
< rte->relname = relname;
---
> rte->rtetype = RTE_RELATION;
> rte->u.rel.relname = relname;
515d516
< rte->subquery = NULL;
525c526
< rte->relid = RelationGetRelid(rel);
---
> rte->u.rel.relid = RelationGetRelid(rel);
580c581,649
< return rte;
---
> return (RangeTblEntry *) rte;
> }
>
> /*
> * Add an entry for a portal reference or for a function-used-as-table
> * to the pstate's range table (p_rtable).
> *
> * This is just like addRangeTableEntry() except that it makes a portal RTE.
> */
> RangeTblEntry *
> addRangeTableEntryForPortal(ParseState *pstate,
> char *portalname,
> Attr *alias
> )
> {
> RangeTblEntry *rte = makeNode(RangeTblEntry);
> char *refname = alias ? alias->relname : portalname;
> Attr *eref;
> int maxattrs;
> int numaliases;
> int varattno;
> TupleDesc tupleDesc;
>
> rte->rtetype = RTE_PORTAL;
> rte->u.portal.portalname = portalname;
> rte->alias = alias;
>
> eref = alias ? (Attr *) copyObject(alias) : makeAttr(refname, NULL);
> numaliases = length(eref->attrs);
>
> /* fill in any unspecified alias columns */
> varattno = 0;
>
> tupleDesc = GetPortalTupleDescByName( portalname );
> maxattrs = tupleDesc->natts;
> if (maxattrs < numaliases)
> elog(ERROR, "Portal \"%s\" has %d columns available but %d aliases specified",
> refname, maxattrs, numaliases);
>
> /* fill in any unspecified alias columns */
> for (varattno = numaliases; varattno < maxattrs; varattno++)
> {
> char *attrname;
>
> attrname = pstrdup(NameStr(tupleDesc->attrs[varattno]->attname));
> eref->attrs = lappend(eref->attrs, makeString(attrname));
> }
> rte->eref = eref;
>
> /*----------
> * Flags:
> * - this RTE should be expanded to include descendant tables,
> * - this RTE is in the FROM clause,
> * - this RTE should be checked for read/write access rights.
> */
> rte->inh = false;
> rte->inFromCl = true;
> rte->checkForRead = false;
> rte->checkForWrite = false;
> rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
>
> /*
> * Add completed RTE to pstate's range table list, but not to join
> * list nor namespace --- caller must do that if appropriate.
> */
> if (pstate != NULL)
> pstate->p_rtable = lappend(pstate->p_rtable, rte);
>
> return (RangeTblEntry *) rte;
602,604c671,672
< rte->relname = NULL;
< rte->relid = InvalidOid;
< rte->subquery = subquery;
---
> rte->rtetype = RTE_SUBSELECT;
> rte->u.sub.subquery = subquery;
657c725
< return rte;
---
> return (RangeTblEntry *) rte;
759c827,863
< if (rte->relname)
---
> if (rte->rtetype == RTE_PORTAL)
> {
> /* Portal RTE */
> TupleDesc td;
> int maxattrs;
> td = GetPortalTupleDescByName( rte->u.portal.portalname );
>
> maxattrs = td->natts;
>
> for (varattno = 0; varattno < maxattrs; varattno++)
> {
> Form_pg_attribute attr = td->attrs[varattno];
>
> if (colnames)
> {
> char *label;
>
> if (varattno < length(rte->eref->attrs))
> label = strVal(nth(varattno, rte->eref->attrs));
> else
> label = NameStr(attr->attname);
> *colnames = lappend(*colnames, makeString(pstrdup(label)));
> }
>
> if (colvars)
> {
> Var *varnode;
>
> varnode = makeVar(rtindex, attr->attnum,
> attr->atttypid, attr->atttypmod,
> sublevels_up);
>
> *colvars = lappend(*colvars, varnode);
> }
> }
> }
> else if (rte->rtetype == RTE_RELATION)
765c869
< rel = heap_openr(rte->relname, AccessShareLock);
---
> rel = heap_openr( rte->u.rel.relname, AccessShareLock);
803c907
< else
---
> else if (rte->rtetype == RTE_SUBSELECT)
810c914,915
< foreach(tlistitem, rte->subquery->targetList)
---
> Assert( PointerIsValid(rte->u.sub.subquery) );
> foreach(tlistitem,rte->u.sub.subquery->targetList)
840a946,949
> else
> {
> elog(ERROR, "expandRTE: Unknown RTE type");
> }
916c1025
< * Get an attribute name from a RangeTblEntry
---
> * Get an attribute name from a RangeTblEntryRelation
920c1029
< * get_attname() only works on real relations.
---
> * get_attname() only works on real relations. ??? (below)
928a1038
> *
950c1060
< if (rte->relid == InvalidOid)
---
> if (!rte->rtetype == RTE_RELATION)
957c1067
< attname = get_attname(rte->relid, attnum);
---
> attname = get_attname(rte->u.rel.relid, attnum);
960c1070
< attnum, rte->relid);
---
> attnum, rte->u.rel.relid);
1071a1182,1200
>
> /*
> * getrelid
> *
> * Given the range index of a relation, return the corresponding
> * relation OID. Note that InvalidOid will be returned if the
> * RTE is for not for a relation. (SubSelect or Portal)
> */
>
> /* this used to be a #define */
> Oid getrelid (int rangeindex, List * rangetable) {
> RangeTblEntry *rte = rt_fetch(rangeindex, rangetable);
> if (rte->rtetype == RTE_RELATION) {
> return rte->u.rel.relid;
> } else {
> return InvalidOid;
> }
> }
>
Index: src/backend/rewrite/rewriteDefine.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/rewrite/rewriteDefine.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -r1.63 -r1.64
449c449
< if (rte->subquery)
---
> if ( rte->rtetype == RTE_SUBSELECT )
452c452
< setRuleCheckAsUser(rte->subquery, userid);
---
> setRuleCheckAsUser( rte->u.sub.subquery, userid);
Index: src/backend/rewrite/rewriteHandler.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/rewrite/rewriteHandler.c,v
retrieving revision 1.97
retrieving revision 1.98
diff -r1.97 -r1.98
268,269c268,269
< RangeTblEntry *rte,
< *subrte;
---
> RangeTblEntry *rte;
> RangeTblEntry *subrte;
292,294c292,305
< rte->relname = NULL;
< rte->relid = InvalidOid;
< rte->subquery = rule_action;
---
> /* We have to mutate whatever RTE kind it was into RTESubSelect */
> if ( rte->rtetype == RTE_SUBSELECT )
> {
> /* already was SubSelect, do nothing */
> } else if (rte->rtetype == RTE_RELATION) {
> /* this may be dangerous, as we are changing the type on the fly,
> perhaps its a better idea to copy RTE, then mangle it? */
>
> rte->rtetype = RTE_SUBSELECT;
> } else {
> elog(ERROR, "ApplyRetrieveRule: unknown original RTE type");
> }
>
> rte->u.sub.subquery = rule_action;
302c313,314
< Assert(subrte->relid == relation->rd_id);
---
> Assert( subrte->rtetype == RTE_RELATION );
> Assert( subrte->u.rel.relid == relation->rd_id);
358c370
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT )
361c373
< markQueryForUpdate(rte->subquery, false);
---
> markQueryForUpdate( rte->u.sub.subquery, false);
439a452,461
> * A portal RTE can't have associated rules, so there's nothing
> * to do to this level of the query.
> */
>
> if (rte->rtetype == RTE_PORTAL)
> {
> continue;
> }
>
> /*
444c466
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT)
446c468
< rte->subquery = fireRIRrules(rte->subquery);
---
> rte->u.sub.subquery = fireRIRrules(rte->u.sub.subquery);
461a484,485
> /* by now, we should only have plain RTE to deal with */
> Assert(rte->rtetype == RTE_RELATION);
482c506
< rel = heap_openr(rte->relname, lockmode);
---
> rel = heap_openr(rte->u.rel.relname, lockmode);
490c514
< if (RelationGetRelid(rel) != rte->relid)
---
> if (RelationGetRelid(rel) != rte->u.rel.relid)
492c516
< rte->relname, rte->relid);
---
> rte->u.rel.relname, rte->u.rel.relid);
759a784
> Assert( rt_entry->rtetype == RTE_RELATION );
769c794
< rt_entry_relation = heap_openr(rt_entry->relname, RowExclusiveLock);
---
> rt_entry_relation = heap_openr(rt_entry->u.rel.relname, RowExclusiveLock);
777c802
< if (RelationGetRelid(rt_entry_relation) != rt_entry->relid)
---
> if (RelationGetRelid(rt_entry_relation) != rt_entry->u.rel.relid)
779c804
< rt_entry->relname, rt_entry->relid);
---
> rt_entry->u.rel.relname, rt_entry->u.rel.relid);
946c971
< if (rte->subquery)
---
> if (rte->rtetype == RTE_SUBSELECT)
Index: src/backend/rewrite/rewriteManip.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/rewrite/rewriteManip.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -r1.57 -r1.58
563c563,564
< selectquery = selectrte->subquery;
---
> Assert( selectrte->rtetype == RTE_SUBSELECT );
> selectquery = selectrte->u.sub.subquery;
574c575
< *subquery_ptr = &(selectrte->subquery);
---
> *subquery_ptr = &(selectrte->u.sub.subquery);
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.82
retrieving revision 1.83
diff -r1.82 -r1.83
703,704c703,705
< rte->relname = relname;
< rte->relid = relid;
---
> rte->rtetype = RTE_RELATION;
> rte->u.rel.relname = relname;
> rte->u.rel.relid = relid;
1165,1166c1166,1167
< Query *subquery = rte->subquery;
<
---
> Query *subquery = rte->u.sub.subquery;
> Assert( rte->rtetype == RTE_SUBSELECT );
1244c1245
< RangeTblEntry *select_rte = NULL;
---
> RangeTblEntry *select_rte = NULL; /* rte for underlying SELECT */
1256c1257
< if (rte->subquery == NULL)
---
> if (rte->rtetype != RTE_SUBSELECT)
1266a1268
> Assert( rte->rtetype == RTE_RELATION );
1268c1270
< quote_identifier(rte->relname));
---
> quote_identifier(rte->u.rel.relname));
1304c1306
< get_query_def(select_rte->subquery, buf, NIL);
---
> get_query_def(select_rte->u.sub.subquery, buf, NIL);
1323a1326,1327
>
> Assert(rte->rtetype == RTE_RELATION);
1326c1330
< quote_identifier(rte->relname));
---
> quote_identifier(rte->u.rel.relname));
1376a1381
> Assert(rte->rtetype == RTE_RELATION);
1379c1384
< quote_identifier(rte->relname));
---
> quote_identifier(rte->u.rel.relname));
2428c2433
< if (rte->relname)
---
> if (rte->rtetype == RTE_RELATION)
2433c2438
< quote_identifier(rte->relname));
---
> quote_identifier( rte->u.rel.relname));
2435c2440
< else
---
> else if (rte->rtetype == RTE_SUBSELECT)
2438d2442
< Assert(rte->subquery != NULL);
2440c2444
< get_query_def(rte->subquery, buf, context->namespaces);
---
> get_query_def( rte->u.sub.subquery, buf, context->namespaces);
2442c2446,2453
< }
---
> } else if (rte->rtetype == RTE_PORTAL)
> {
> appendStringInfo(buf, " CURSOR %s",
> rte->u.portal.portalname);
> } else
> elog(ERROR, "get_from_clause_item: unknown RTE type");
>
>
Index: src/backend/utils/mmgr/portalmem.c
===================================================================
RCS file: /cvs/pgsql/pgsql/src/backend/utils/mmgr/portalmem.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -r1.41 -r1.42
38a39,40
> #include "executor/execdefs.h"
> #include "executor/executor.h"
152a155,174
> * GetPortalTupleDescByName
> * Returns a TupleDesc for portal given a portal name.
> * elog(ERROR) if it doesn't exist
> */
> TupleDesc
> GetPortalTupleDescByName(char *name)
> {
> Portal portal;
>
> Assert( PointerIsValid(name) );
> PortalHashTableLookup(name, portal);
>
> if ( !PointerIsValid( portal ))
> elog( ERROR,
> "GetPortalTupleDescByName: portal %s does not exist", name);
>
> return portal->attinfo;
> }
>
> /*
227a250,344
> }
>
> /* Run the portal's underlying query for number of records, into dest
> * properly setting context and atStart/atEnd flags after execution.
> *
> * If tts!=NULL, will put result of ExecutorRun into variable pointed by TTS
> *
> * Returns number of records processed.
> */
> int
> PortalRun(Portal portal, bool forward, long count, CommandDest dest, TupleTableSlot **tts)
> {
> QueryDesc *queryDesc;
> EState *estate;
> TupleTableSlot *tts_exec;
> bool faked_desc = false;
> bool did_fetch = false; /* did we actually try to run executor? */
> MemoryContext oldcontext;
>
> if (tts) *tts=NULL;
>
> /*
> * switch into the portal context
> */
> oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
>
> /*
> * tell the destination to prepare to receive some tuples.
> *
> * If passed CommandDest is not the same as portal's CommandDest,
> * make a temporary QueryDesc with the new destination.
> */
> queryDesc = PortalGetQueryDesc(portal);
> estate = PortalGetState(portal);
>
> if (dest != queryDesc->dest)
> {
> QueryDesc *qdesc = (QueryDesc *) palloc(sizeof(QueryDesc));
>
> memcpy(qdesc, queryDesc, sizeof(QueryDesc));
> qdesc->dest = dest;
> queryDesc = qdesc;
> faked_desc = true;
> }
>
> /*
> * Determine which direction to go in, and check to see if we're
> * already at the end of the available tuples in that direction. If
> * so, do nothing. (This check exists because not all plan node types
> * are robust about being called again if they've already returned
> * NULL once.) If it's OK to do the fetch, call the executor. Then,
> * update the atStart/atEnd state depending on the number of tuples
> * that were retrieved.
> */
> if (forward)
> {
> if (!portal->atEnd)
> {
> tts_exec=ExecutorRun(queryDesc, estate, EXEC_FOR, (long) count);
> if (estate->es_processed > 0)
> portal->atStart = false; /* OK to back up now */
> if (count <= 0 || (int) estate->es_processed < count)
> portal->atEnd = true; /* we retrieved 'em all */
> did_fetch = true;
> }
> }
> else
> {
> if (!portal->atStart)
> {
> tts_exec=ExecutorRun(queryDesc, estate, EXEC_BACK, (long) count);
> if (estate->es_processed > 0)
> portal->atEnd = false; /* OK to go forward now */
> if (count <= 0 || (int) estate->es_processed < count)
> portal->atStart = true; /* we retrieved 'em all */
> did_fetch = true;
> }
> }
>
> /*
> * Clean up and switch back to old context.
> */
> if (faked_desc) /* MOVE */
> pfree(queryDesc);
>
> MemoryContextSwitchTo(oldcontext);
>
> /* store what we got from Executor */
> if (tts && did_fetch)
> *tts=tts_exec;
>
> /* check whether we actually retrieved records */
> if (did_fetch)
> return estate->es_processed;
> return 0;
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.62
retrieving revision 1.63
diff -r1.62 -r1.63
483a484,496
> /* ----------------
> * PortalScanState information
> *
> * PortalScanState is used for scanning a portal.
> *
> * ----------------
> */
> typedef struct PortalScanState
> {
> CommonScanState csstate; /* its first field is NodeTag */
> struct PortalData * portal;
> } PortalScanState;
>
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.93
retrieving revision 1.94
diff -r1.93 -r1.94
51a52
> T_PortalScan,
122a124
> T_PortalScanState,
224a227,228
> /* T_FuncRangeVar, */
> T_PortalRangeVar,
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.143
retrieving revision 1.144
diff -r1.143 -r1.144
17a18,19
> #include "access/tupdesc.h"
>
891a894
> bool isFunc; /* select * from func(args) */
1183a1187,1208
> * FuncRangeVar - range variable, used in FROM clauses
> * select x,y from foo(1) as bar(x,y)
> */
> typedef struct FuncRangeVar
> {
> NodeTag type;
> Node *func;
> Attr *name; /* optional table alias & column aliases */
> } FuncRangeVar;
>
> /*
> * PortalRangeVar - range variable, used in FROM clauses
> * select x,y from cursor foo
> */
> typedef struct PortalRangeVar
> {
> NodeTag type;
> char *portal;
> Attr *name; /* optional table alias & column aliases */
> } PortalRangeVar;
>
> /*
1289a1315,1320
> typedef enum RTEType {
> RTE_RELATION,
> RTE_SUBSELECT,
> RTE_PORTAL
> } RTEType;
>
1293,1304c1324
<
< /*
< * Fields valid for a plain relation RTE (else NULL/zero):
< */
< char *relname; /* real name of the relation */
< Oid relid; /* OID of the relation */
<
< /*
< * Fields valid for a subquery RTE (else NULL):
< */
< Query *subquery; /* the sub-query */
<
---
> RTEType rtetype;
1314a1335,1350
>
> union {
> struct {
> /* Fields for a plain relation RTE (rtetype=RTE_RELATION) */
> char *relname; /* real name of the relation */
> Oid relid; /* OID of the relation */
> } rel;
> struct {
> /* Fields for a subquery RTE (rtetype=RTE_SUBSELECT) */
> Query *subquery; /* the sub-query */
> } sub;
> struct {
> /* fields for portal RTE (rtetype=RTE_PORTAL) */
> char *portalname; /* portal's name */
> } portal;
> } u;
Index: src/include/nodes/plannodes.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/nodes/plannodes.h,v
retrieving revision 1.49
retrieving revision 1.50
diff -r1.49 -r1.50
232a233,243
> /* ----------------
> * portal scan node
> *
> * PortalScan is for scanning the existing portal. Will need additional
> * fields, but currently, its just the Scan.
> */
> typedef struct PortalScan
> {
> Scan scan;
> } PortalScan;
>
Index: src/include/nodes/relation.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/nodes/relation.h,v
retrieving revision 1.58
retrieving revision 1.59
diff -r1.58 -r1.59
131a132,138
> typedef enum RelOptInfoType {
> REL_PLAIN,
> REL_SUBQUERY,
> REL_JOIN,
> REL_PORTAL
> } RelOptInfoType;
>
135a143,144
> RelOptInfoType reltype;
>
151,152c160
< /* information about a base rel (not set for join rels!) */
< bool issubquery;
---
> /* Following fields are only for REL_PLAIN */
155a164,165
>
> /* following field is only for REL_SUBQUERY */
Index: src/include/optimizer/pathnode.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/optimizer/pathnode.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -r1.38 -r1.39
17a18
> #include "utils/portal.h"
37a39
> extern Path *create_portalscan_path(RelOptInfo *rel, Portal portal);
Index: src/include/parser/parse_relation.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/parser/parse_relation.h,v
retrieving revision 1.24
retrieving revision 1.25
diff -r1.24 -r1.25
38a39,42
> extern RangeTblEntry * addRangeTableEntryForPortal(ParseState *pstate,
> char *portalname,
> Attr *alias
> );
Index: src/include/parser/parsetree.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/parser/parsetree.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -r1.13 -r1.14
39,47c39,40
< /*
< * getrelid
< *
< * Given the range index of a relation, return the corresponding
< * relation OID. Note that InvalidOid will be returned if the
< * RTE is for a sub-select rather than a relation.
< */
< #define getrelid(rangeindex,rangetable) \
< (rt_fetch(rangeindex, rangetable)->relid)
---
> /* getrelid is no longer a #define */
> extern Oid getrelid (int rangeindex, List * rangetable);
Index: src/include/utils/portal.h
===================================================================
RCS file: /cvs/pgsql/pgsql/src/include/utils/portal.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -r1.28 -r1.29
65a66
> extern TupleDesc GetPortalTupleDescByName(char *name);
69c70,71
<
---
> extern int PortalRun(Portal portal, bool forward,
> long count, CommandDest dest, TupleTableSlot **tts);
Index: src/include/executor/nodePortalscan.h
===================================================================
RCS file: nodePortalscan.h
diff -N nodePortalscan.h
0a1,27
> /*-------------------------------------------------------------------------
> *
> * nodePortalscan.h
> *
> *
> *
> * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
> * Portions Copyright (c) 1994, Regents of the University of California
> *
> * $Id$
> *
> *-------------------------------------------------------------------------
> */
> #ifndef NODEPORTALSCAN_H
> #define NODEPORTALSCAN_H
>
> #include "nodes/plannodes.h"
>
> extern TupleTableSlot *ExecPortalScan(PortalScan *node);
> extern bool ExecInitPortalScan(PortalScan *node, EState *estate, Plan *parent);
> extern int ExecCountSlotsPortalScan(PortalScan *node);
> extern void ExecEndPortalScan(PortalScan *node);
> extern void ExecPortalReScan(PortalScan *node, ExprContext *exprCtxt, Plan *parent);
> extern void ExecPortalMarkPos(PortalScan *node);
> extern void ExecPortalRestrPos(PortalScan *node);
>
> #endif /* NODESEQSCAN_H */