diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/command.c | 60 | ||||
-rw-r--r-- | src/backend/tcop/pquery.c | 4 | ||||
-rw-r--r-- | src/backend/utils/mmgr/portalmem.c | 79 |
3 files changed, 54 insertions, 89 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 8808a03f1ac..8a3be15a052 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.121 2001/02/14 21:35:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.122 2001/02/27 22:07:34 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -107,8 +107,8 @@ PerformPortalFetch(char *name, CommandDest dest) { Portal portal; - int feature; QueryDesc *queryDesc; + EState *estate; MemoryContext oldcontext; /* ---------------- @@ -140,19 +140,14 @@ PerformPortalFetch(char *name, oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); /* ---------------- - * setup "feature" to tell the executor which direction to go in. - * ---------------- - */ - if (forward) - feature = EXEC_FOR; - else - feature = EXEC_BACK; - - /* ---------------- - * tell the destination to prepare to receive some tuples + * tell the destination to prepare to receive some tuples. + * + * If we've been asked for a MOVE, make a temporary QueryDesc + * with the appropriate dummy destination. * ---------------- */ queryDesc = PortalGetQueryDesc(portal); + estate = PortalGetState(portal); if (dest == None) /* MOVE */ { @@ -165,7 +160,7 @@ PerformPortalFetch(char *name, BeginCommand(name, queryDesc->operation, - portal->attinfo, /* QueryDescGetTypeInfo(queryDesc) */ + PortalGetTupleDesc(portal), false, /* portal fetches don't end up in * relations */ false, /* this is a portal fetch, not a "retrieve @@ -174,18 +169,45 @@ PerformPortalFetch(char *name, dest); /* ---------------- - * execute the portal fetch operation + * 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. * ---------------- */ - ExecutorRun(queryDesc, PortalGetState(portal), feature, (long) count); - - if (dest == None) /* MOVE */ - pfree(queryDesc); + if (forward) + { + if (! portal->atEnd) + { + 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 */ + } + } + else + { + if (! portal->atStart) + { + 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 */ + } + } /* ---------------- - * Switch back to old context. + * Clean up and switch back to old context. * ---------------- */ + if (dest == None) /* MOVE */ + pfree(queryDesc); + MemoryContextSwitchTo(oldcontext); /* ---------------- diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 3481bc675ec..b36b9f6510c 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.41 2001/01/24 19:43:09 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.42 2001/02/27 22:07:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -248,7 +248,7 @@ ProcessQuery(Query *parsetree, * ---------------- */ if (isRetrieveIntoRelation) - queryDesc->dest = (int) None; + queryDesc->dest = None; /* ---------------- * create a default executor state. diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 08db60a492c..63d3ed363cb 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -8,44 +8,26 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.39 2001/01/24 19:43:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.40 2001/02/27 22:07:34 tgl Exp $ * *------------------------------------------------------------------------- */ /* * NOTES - * Do not confuse "Portal" with "PortalEntry" (or "PortalBuffer"). - * When a PQexec() routine is run, the resulting tuples - * find their way into a "PortalEntry". The contents of the resulting - * "PortalEntry" can then be inspected by other PQxxx functions. + * A "Portal" is a structure used to keep track of cursor queries. * - * A "Portal" is a structure used to keep track of queries of the - * form: - * retrieve portal FOO ( blah... ) where blah... - * - * When the backend sees a "retrieve portal" query, it allocates - * a "PortalD" structure, plans the query and then stores the query + * When the backend sees a "declare cursor" query, it allocates a + * "PortalData" structure, plans the query and then stores the query * in the portal without executing it. Later, when the backend * sees a - * fetch 1 into FOO - * + * fetch 1 from FOO * the system looks up the portal named "FOO" in the portal table, * gets the planned query and then calls the executor with a feature of * '(EXEC_FOR 1). The executor then runs the query and returns a single * tuple. The problem is that we have to hold onto the state of the - * portal query until we see a "close p". This means we have to be + * portal query until we see a "close". This means we have to be * careful about memory management. * - * Having said all that, here is what a PortalD currently looks like: - * - * struct PortalD { - * char* name; - * classObj(MemoryContext) heap; - * List queryDesc; - * EState state; - * void (*cleanup) ARGS((Portal portal)); - * }; - * * I hope this makes things clearer to whoever reads this -cim 2/22/91 */ @@ -188,44 +170,14 @@ PortalSetQuery(Portal portal, AssertArg(IsA((Node *) state, EState)); portal->queryDesc = queryDesc; - portal->state = state; portal->attinfo = attinfo; + portal->state = state; + portal->atStart = true; /* Allow fetch forward only */ + portal->atEnd = false; portal->cleanup = cleanup; } /* - * PortalGetQueryDesc - * Returns query attached to portal. - * - * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. - */ -QueryDesc * -PortalGetQueryDesc(Portal portal) -{ - AssertArg(PortalIsValid(portal)); - - return portal->queryDesc; -} - -/* - * PortalGetState - * Returns state attached to portal. - * - * Exceptions: - * BadState if called when disabled. - * BadArg if portal is invalid. - */ -EState * -PortalGetState(Portal portal) -{ - AssertArg(PortalIsValid(portal)); - - return portal->state; -} - -/* * CreatePortal * Returns a new portal given a name. * @@ -265,7 +217,8 @@ CreatePortal(char *name) portal->queryDesc = NULL; portal->attinfo = NULL; portal->state = NULL; - + portal->atStart = true; /* disallow fetches until query is set */ + portal->atEnd = true; portal->cleanup = NULL; /* put portal in table */ @@ -315,13 +268,3 @@ AtEOXact_portals(void) { HashTableWalk(PortalHashTable, (HashtFunc) PortalDrop, 0); } - -/* - * PortalGetHeapMemory - * Returns heap memory context for a given portal. - */ -MemoryContext -PortalGetHeapMemory(Portal portal) -{ - return portal->heap; -} |