]> granicus.if.org Git - postgresql/blob - src/backend/tcop/pquery.c
Rename the members of CommandDest enum so they don't collide with other uses of
[postgresql] / src / backend / tcop / pquery.c
1 /*-------------------------------------------------------------------------
2  *
3  * pquery.c
4  *        POSTGRES process query command code
5  *
6  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.96 2005/11/03 17:11:38 alvherre Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include "postgres.h"
17
18 #include "commands/prepare.h"
19 #include "commands/trigger.h"
20 #include "executor/executor.h"
21 #include "miscadmin.h"
22 #include "tcop/tcopprot.h"
23 #include "tcop/pquery.h"
24 #include "tcop/utility.h"
25 #include "utils/guc.h"
26 #include "utils/memutils.h"
27
28
29 /*
30  * ActivePortal is the currently executing Portal (the most closely nested,
31  * if there are several).
32  */
33 Portal          ActivePortal = NULL;
34
35
36 static void ProcessQuery(Query *parsetree,
37                          Plan *plan,
38                          ParamListInfo params,
39                          DestReceiver *dest,
40                          char *completionTag);
41 static uint32 RunFromStore(Portal portal, ScanDirection direction, long count,
42                          DestReceiver *dest);
43 static long PortalRunSelect(Portal portal, bool forward, long count,
44                                 DestReceiver *dest);
45 static void PortalRunUtility(Portal portal, Query *query,
46                                  DestReceiver *dest, char *completionTag);
47 static void PortalRunMulti(Portal portal,
48                            DestReceiver *dest, DestReceiver *altdest,
49                            char *completionTag);
50 static long DoPortalRunFetch(Portal portal,
51                                  FetchDirection fdirection,
52                                  long count,
53                                  DestReceiver *dest);
54 static void DoPortalRewind(Portal portal);
55
56
57 /*
58  * CreateQueryDesc
59  */
60 QueryDesc *
61 CreateQueryDesc(Query *parsetree,
62                                 Plan *plantree,
63                                 Snapshot snapshot,
64                                 Snapshot crosscheck_snapshot,
65                                 DestReceiver *dest,
66                                 ParamListInfo params,
67                                 bool doInstrument)
68 {
69         QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
70
71         qd->operation = parsetree->commandType;         /* operation */
72         qd->parsetree = parsetree;      /* parse tree */
73         qd->plantree = plantree;        /* plan */
74         qd->snapshot = snapshot;        /* snapshot */
75         qd->crosscheck_snapshot = crosscheck_snapshot;          /* RI check snapshot */
76         qd->dest = dest;                        /* output dest */
77         qd->params = params;            /* parameter values passed into query */
78         qd->doInstrument = doInstrument;        /* instrumentation wanted? */
79
80         /* null these fields until set by ExecutorStart */
81         qd->tupDesc = NULL;
82         qd->estate = NULL;
83         qd->planstate = NULL;
84
85         return qd;
86 }
87
88 /*
89  * FreeQueryDesc
90  */
91 void
92 FreeQueryDesc(QueryDesc *qdesc)
93 {
94         /* Can't be a live query */
95         Assert(qdesc->estate == NULL);
96         /* Only the QueryDesc itself need be freed */
97         pfree(qdesc);
98 }
99
100
101 /*
102  * ProcessQuery
103  *              Execute a single plannable query within a PORTAL_MULTI_QUERY portal
104  *
105  *      parsetree: the query tree
106  *      plan: the plan tree for the query
107  *      params: any parameters needed
108  *      dest: where to send results
109  *      completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
110  *              in which to store a command completion status string.
111  *
112  * completionTag may be NULL if caller doesn't want a status string.
113  *
114  * Must be called in a memory context that will be reset or deleted on
115  * error; otherwise the executor's memory usage will be leaked.
116  */
117 static void
118 ProcessQuery(Query *parsetree,
119                          Plan *plan,
120                          ParamListInfo params,
121                          DestReceiver *dest,
122                          char *completionTag)
123 {
124         int                     operation = parsetree->commandType;
125         QueryDesc  *queryDesc;
126
127         ereport(DEBUG3,
128                         (errmsg_internal("ProcessQuery")));
129
130         /*
131          * Check for special-case destinations
132          */
133         if (operation == CMD_SELECT)
134         {
135                 if (parsetree->into != NULL)
136                 {
137                         /*
138                          * SELECT INTO table (a/k/a CREATE AS ... SELECT).
139                          *
140                          * Override the normal communication destination; execMain.c
141                          * special-cases this case.  (Perhaps would be cleaner to have an
142                          * additional destination type?)
143                          */
144                         dest = None_Receiver;
145                 }
146         }
147
148         /*
149          * Must always set snapshot for plannable queries.      Note we assume that
150          * caller will take care of restoring ActiveSnapshot on exit/error.
151          */
152         ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
153
154         /*
155          * Create the QueryDesc object
156          */
157         queryDesc = CreateQueryDesc(parsetree, plan,
158                                                                 ActiveSnapshot, InvalidSnapshot,
159                                                                 dest, params, false);
160
161         /*
162          * Set up to collect AFTER triggers
163          */
164         AfterTriggerBeginQuery();
165
166         /*
167          * Call ExecStart to prepare the plan for execution
168          */
169         ExecutorStart(queryDesc, false);
170
171         /*
172          * Run the plan to completion.
173          */
174         ExecutorRun(queryDesc, ForwardScanDirection, 0L);
175
176         /*
177          * Build command completion status string, if caller wants one.
178          */
179         if (completionTag)
180         {
181                 Oid                     lastOid;
182
183                 switch (operation)
184                 {
185                         case CMD_SELECT:
186                                 strcpy(completionTag, "SELECT");
187                                 break;
188                         case CMD_INSERT:
189                                 if (queryDesc->estate->es_processed == 1)
190                                         lastOid = queryDesc->estate->es_lastoid;
191                                 else
192                                         lastOid = InvalidOid;
193                                 snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
194                                    "INSERT %u %u", lastOid, queryDesc->estate->es_processed);
195                                 break;
196                         case CMD_UPDATE:
197                                 snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
198                                                  "UPDATE %u", queryDesc->estate->es_processed);
199                                 break;
200                         case CMD_DELETE:
201                                 snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
202                                                  "DELETE %u", queryDesc->estate->es_processed);
203                                 break;
204                         default:
205                                 strcpy(completionTag, "???");
206                                 break;
207                 }
208         }
209
210         /* Now take care of any queued AFTER triggers */
211         AfterTriggerEndQuery(queryDesc->estate);
212
213         /*
214          * Now, we close down all the scans and free allocated resources.
215          */
216         ExecutorEnd(queryDesc);
217
218         FreeQueryDesc(queryDesc);
219
220         FreeSnapshot(ActiveSnapshot);
221         ActiveSnapshot = NULL;
222 }
223
224 /*
225  * ChoosePortalStrategy
226  *              Select portal execution strategy given the intended query list.
227  *
228  * See the comments in portal.h.
229  */
230 PortalStrategy
231 ChoosePortalStrategy(List *parseTrees)
232 {
233         PortalStrategy strategy;
234
235         strategy = PORTAL_MULTI_QUERY;          /* default assumption */
236
237         if (list_length(parseTrees) == 1)
238         {
239                 Query      *query = (Query *) linitial(parseTrees);
240
241                 if (query->commandType == CMD_SELECT &&
242                         query->canSetTag &&
243                         query->into == NULL)
244                         strategy = PORTAL_ONE_SELECT;
245                 else if (query->commandType == CMD_UTILITY &&
246                                  query->canSetTag &&
247                                  query->utilityStmt != NULL)
248                 {
249                         if (UtilityReturnsTuples(query->utilityStmt))
250                                 strategy = PORTAL_UTIL_SELECT;
251                 }
252         }
253         return strategy;
254 }
255
256 /*
257  * FetchPortalTargetList
258  *              Given a portal that returns tuples, extract the query targetlist.
259  *              Returns NIL if the portal doesn't have a determinable targetlist.
260  *
261  * Note: do not modify the result.
262  *
263  * XXX be careful to keep this in sync with FetchPreparedStatementTargetList,
264  * and with UtilityReturnsTuples.
265  */
266 List *
267 FetchPortalTargetList(Portal portal)
268 {
269         if (portal->strategy == PORTAL_ONE_SELECT)
270                 return ((Query *) linitial(portal->parseTrees))->targetList;
271         if (portal->strategy == PORTAL_UTIL_SELECT)
272         {
273                 Node       *utilityStmt;
274
275                 utilityStmt = ((Query *) linitial(portal->parseTrees))->utilityStmt;
276                 switch (nodeTag(utilityStmt))
277                 {
278                         case T_FetchStmt:
279                                 {
280                                         FetchStmt  *substmt = (FetchStmt *) utilityStmt;
281                                         Portal          subportal;
282
283                                         Assert(!substmt->ismove);
284                                         subportal = GetPortalByName(substmt->portalname);
285                                         Assert(PortalIsValid(subportal));
286                                         return FetchPortalTargetList(subportal);
287                                 }
288
289                         case T_ExecuteStmt:
290                                 {
291                                         ExecuteStmt *substmt = (ExecuteStmt *) utilityStmt;
292                                         PreparedStatement *entry;
293
294                                         Assert(!substmt->into);
295                                         entry = FetchPreparedStatement(substmt->name, true);
296                                         return FetchPreparedStatementTargetList(entry);
297                                 }
298
299                         default:
300                                 break;
301                 }
302         }
303         return NIL;
304 }
305
306 /*
307  * PortalStart
308  *              Prepare a portal for execution.
309  *
310  * Caller must already have created the portal, done PortalDefineQuery(),
311  * and adjusted portal options if needed.  If parameters are needed by
312  * the query, they must be passed in here (caller is responsible for
313  * giving them appropriate lifetime).
314  *
315  * The caller can optionally pass a snapshot to be used; pass InvalidSnapshot
316  * for the normal behavior of setting a new snapshot.  This parameter is
317  * presently ignored for non-PORTAL_ONE_SELECT portals (it's only intended
318  * to be used for cursors).
319  *
320  * On return, portal is ready to accept PortalRun() calls, and the result
321  * tupdesc (if any) is known.
322  */
323 void
324 PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot)
325 {
326         Portal          saveActivePortal;
327         Snapshot        saveActiveSnapshot;
328         ResourceOwner saveResourceOwner;
329         MemoryContext savePortalContext;
330         MemoryContext oldContext;
331         QueryDesc  *queryDesc;
332
333         AssertArg(PortalIsValid(portal));
334         AssertState(portal->queryContext != NULL);      /* query defined? */
335         AssertState(portal->status == PORTAL_NEW);      /* else extra PortalStart */
336
337         /*
338          * Set up global portal context pointers.  (Should we set QueryContext?)
339          */
340         saveActivePortal = ActivePortal;
341         saveActiveSnapshot = ActiveSnapshot;
342         saveResourceOwner = CurrentResourceOwner;
343         savePortalContext = PortalContext;
344         PG_TRY();
345         {
346                 ActivePortal = portal;
347                 ActiveSnapshot = NULL;  /* will be set later */
348                 CurrentResourceOwner = portal->resowner;
349                 PortalContext = PortalGetHeapMemory(portal);
350
351                 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
352
353                 /* Must remember portal param list, if any */
354                 portal->portalParams = params;
355
356                 /*
357                  * Determine the portal execution strategy
358                  */
359                 portal->strategy = ChoosePortalStrategy(portal->parseTrees);
360
361                 /*
362                  * Fire her up according to the strategy
363                  */
364                 switch (portal->strategy)
365                 {
366                         case PORTAL_ONE_SELECT:
367
368                                 /*
369                                  * Must set snapshot before starting executor.  Be sure to
370                                  * copy it into the portal's context.
371                                  */
372                                 if (snapshot)
373                                         ActiveSnapshot = CopySnapshot(snapshot);
374                                 else
375                                         ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
376
377                                 /*
378                                  * Create QueryDesc in portal's context; for the moment, set
379                                  * the destination to None.
380                                  */
381                                 queryDesc = CreateQueryDesc((Query *) linitial(portal->parseTrees),
382                                                                                 (Plan *) linitial(portal->planTrees),
383                                                                                         ActiveSnapshot,
384                                                                                         InvalidSnapshot,
385                                                                                         None_Receiver,
386                                                                                         params,
387                                                                                         false);
388
389                                 /*
390                                  * We do *not* call AfterTriggerBeginQuery() here.      We assume
391                                  * that a SELECT cannot queue any triggers.  It would be messy
392                                  * to support triggers since the execution of the portal may
393                                  * be interleaved with other queries.
394                                  */
395
396                                 /*
397                                  * Call ExecStart to prepare the plan for execution
398                                  */
399                                 ExecutorStart(queryDesc, false);
400
401                                 /*
402                                  * This tells PortalCleanup to shut down the executor
403                                  */
404                                 portal->queryDesc = queryDesc;
405
406                                 /*
407                                  * Remember tuple descriptor (computed by ExecutorStart)
408                                  */
409                                 portal->tupDesc = queryDesc->tupDesc;
410
411                                 /*
412                                  * Reset cursor position data to "start of query"
413                                  */
414                                 portal->atStart = true;
415                                 portal->atEnd = false;  /* allow fetches */
416                                 portal->portalPos = 0;
417                                 portal->posOverflow = false;
418                                 break;
419
420                         case PORTAL_UTIL_SELECT:
421
422                                 /*
423                                  * We don't set snapshot here, because PortalRunUtility will
424                                  * take care of it if needed.
425                                  */
426                                 portal->tupDesc =
427                                         UtilityTupleDescriptor(((Query *) linitial(portal->parseTrees))->utilityStmt);
428
429                                 /*
430                                  * Reset cursor position data to "start of query"
431                                  */
432                                 portal->atStart = true;
433                                 portal->atEnd = false;  /* allow fetches */
434                                 portal->portalPos = 0;
435                                 portal->posOverflow = false;
436                                 break;
437
438                         case PORTAL_MULTI_QUERY:
439                                 /* Need do nothing now */
440                                 portal->tupDesc = NULL;
441                                 break;
442                 }
443         }
444         PG_CATCH();
445         {
446                 /* Uncaught error while executing portal: mark it dead */
447                 portal->status = PORTAL_FAILED;
448
449                 /* Restore global vars and propagate error */
450                 ActivePortal = saveActivePortal;
451                 ActiveSnapshot = saveActiveSnapshot;
452                 CurrentResourceOwner = saveResourceOwner;
453                 PortalContext = savePortalContext;
454
455                 PG_RE_THROW();
456         }
457         PG_END_TRY();
458
459         MemoryContextSwitchTo(oldContext);
460
461         ActivePortal = saveActivePortal;
462         ActiveSnapshot = saveActiveSnapshot;
463         CurrentResourceOwner = saveResourceOwner;
464         PortalContext = savePortalContext;
465
466         portal->status = PORTAL_READY;
467 }
468
469 /*
470  * PortalSetResultFormat
471  *              Select the format codes for a portal's output.
472  *
473  * This must be run after PortalStart for a portal that will be read by
474  * a DestRemote or DestRemoteExecute destination.  It is not presently needed
475  * for other destination types.
476  *
477  * formats[] is the client format request, as per Bind message conventions.
478  */
479 void
480 PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
481 {
482         int                     natts;
483         int                     i;
484
485         /* Do nothing if portal won't return tuples */
486         if (portal->tupDesc == NULL)
487                 return;
488         natts = portal->tupDesc->natts;
489         portal->formats = (int16 *)
490                 MemoryContextAlloc(PortalGetHeapMemory(portal),
491                                                    natts * sizeof(int16));
492         if (nFormats > 1)
493         {
494                 /* format specified for each column */
495                 if (nFormats != natts)
496                         ereport(ERROR,
497                                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
498                                          errmsg("bind message has %d result formats but query has %d columns",
499                                                         nFormats, natts)));
500                 memcpy(portal->formats, formats, natts * sizeof(int16));
501         }
502         else if (nFormats > 0)
503         {
504                 /* single format specified, use for all columns */
505                 int16           format1 = formats[0];
506
507                 for (i = 0; i < natts; i++)
508                         portal->formats[i] = format1;
509         }
510         else
511         {
512                 /* use default format for all columns */
513                 for (i = 0; i < natts; i++)
514                         portal->formats[i] = 0;
515         }
516 }
517
518 /*
519  * PortalRun
520  *              Run a portal's query or queries.
521  *
522  * count <= 0 is interpreted as a no-op: the destination gets started up
523  * and shut down, but nothing else happens.  Also, count == FETCH_ALL is
524  * interpreted as "all rows".  Note that count is ignored in multi-query
525  * situations, where we always run the portal to completion.
526  *
527  * dest: where to send output of primary (canSetTag) query
528  *
529  * altdest: where to send output of non-primary queries
530  *
531  * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
532  *              in which to store a command completion status string.
533  *              May be NULL if caller doesn't want a status string.
534  *
535  * Returns TRUE if the portal's execution is complete, FALSE if it was
536  * suspended due to exhaustion of the count parameter.
537  */
538 bool
539 PortalRun(Portal portal, long count,
540                   DestReceiver *dest, DestReceiver *altdest,
541                   char *completionTag)
542 {
543         bool            result;
544         ResourceOwner saveTopTransactionResourceOwner;
545         MemoryContext saveTopTransactionContext;
546         Portal          saveActivePortal;
547         Snapshot        saveActiveSnapshot;
548         ResourceOwner saveResourceOwner;
549         MemoryContext savePortalContext;
550         MemoryContext saveQueryContext;
551         MemoryContext saveMemoryContext;
552
553         AssertArg(PortalIsValid(portal));
554
555         /* Initialize completion tag to empty string */
556         if (completionTag)
557                 completionTag[0] = '\0';
558
559         if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
560         {
561                 ereport(DEBUG3,
562                                 (errmsg_internal("PortalRun")));
563                 /* PORTAL_MULTI_QUERY logs its own stats per query */
564                 ResetUsage();
565         }
566
567         /*
568          * Check for improper portal use, and mark portal active.
569          */
570         if (portal->status != PORTAL_READY)
571                 ereport(ERROR,
572                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
573                                  errmsg("portal \"%s\" cannot be run", portal->name)));
574         portal->status = PORTAL_ACTIVE;
575
576         /*
577          * Set up global portal context pointers.
578          *
579          * We have to play a special game here to support utility commands like
580          * VACUUM and CLUSTER, which internally start and commit transactions.
581          * When we are called to execute such a command, CurrentResourceOwner will
582          * be pointing to the TopTransactionResourceOwner --- which will be
583          * destroyed and replaced in the course of the internal commit and
584          * restart.  So we need to be prepared to restore it as pointing to the
585          * exit-time TopTransactionResourceOwner.  (Ain't that ugly?  This idea of
586          * internally starting whole new transactions is not good.)
587          * CurrentMemoryContext has a similar problem, but the other pointers we
588          * save here will be NULL or pointing to longer-lived objects.
589          */
590         saveTopTransactionResourceOwner = TopTransactionResourceOwner;
591         saveTopTransactionContext = TopTransactionContext;
592         saveActivePortal = ActivePortal;
593         saveActiveSnapshot = ActiveSnapshot;
594         saveResourceOwner = CurrentResourceOwner;
595         savePortalContext = PortalContext;
596         saveQueryContext = QueryContext;
597         saveMemoryContext = CurrentMemoryContext;
598         PG_TRY();
599         {
600                 ActivePortal = portal;
601                 ActiveSnapshot = NULL;  /* will be set later */
602                 CurrentResourceOwner = portal->resowner;
603                 PortalContext = PortalGetHeapMemory(portal);
604                 QueryContext = portal->queryContext;
605
606                 MemoryContextSwitchTo(PortalContext);
607
608                 switch (portal->strategy)
609                 {
610                         case PORTAL_ONE_SELECT:
611                                 (void) PortalRunSelect(portal, true, count, dest);
612                                 /* we know the query is supposed to set the tag */
613                                 if (completionTag && portal->commandTag)
614                                         strcpy(completionTag, portal->commandTag);
615
616                                 /* Mark portal not active */
617                                 portal->status = PORTAL_READY;
618
619                                 /*
620                                  * Since it's a forward fetch, say DONE iff atEnd is now true.
621                                  */
622                                 result = portal->atEnd;
623                                 break;
624
625                         case PORTAL_UTIL_SELECT:
626
627                                 /*
628                                  * If we have not yet run the utility statement, do so,
629                                  * storing its results in the portal's tuplestore.
630                                  */
631                                 if (!portal->portalUtilReady)
632                                 {
633                                         DestReceiver *treceiver;
634
635                                         PortalCreateHoldStore(portal);
636                                         treceiver = CreateDestReceiver(DestTuplestore, portal);
637                                         PortalRunUtility(portal, linitial(portal->parseTrees),
638                                                                          treceiver, NULL);
639                                         (*treceiver->rDestroy) (treceiver);
640                                         portal->portalUtilReady = true;
641                                 }
642
643                                 /*
644                                  * Now fetch desired portion of results.
645                                  */
646                                 (void) PortalRunSelect(portal, true, count, dest);
647
648                                 /*
649                                  * We know the query is supposed to set the tag; we assume
650                                  * only the default tag is needed.
651                                  */
652                                 if (completionTag && portal->commandTag)
653                                         strcpy(completionTag, portal->commandTag);
654
655                                 /* Mark portal not active */
656                                 portal->status = PORTAL_READY;
657
658                                 /*
659                                  * Since it's a forward fetch, say DONE iff atEnd is now true.
660                                  */
661                                 result = portal->atEnd;
662                                 break;
663
664                         case PORTAL_MULTI_QUERY:
665                                 PortalRunMulti(portal, dest, altdest, completionTag);
666
667                                 /* Prevent portal's commands from being re-executed */
668                                 portal->status = PORTAL_DONE;
669
670                                 /* Always complete at end of RunMulti */
671                                 result = true;
672                                 break;
673
674                         default:
675                                 elog(ERROR, "unrecognized portal strategy: %d",
676                                          (int) portal->strategy);
677                                 result = false; /* keep compiler quiet */
678                                 break;
679                 }
680         }
681         PG_CATCH();
682         {
683                 /* Uncaught error while executing portal: mark it dead */
684                 portal->status = PORTAL_FAILED;
685
686                 /* Restore global vars and propagate error */
687                 if (saveMemoryContext == saveTopTransactionContext)
688                         MemoryContextSwitchTo(TopTransactionContext);
689                 else
690                         MemoryContextSwitchTo(saveMemoryContext);
691                 ActivePortal = saveActivePortal;
692                 ActiveSnapshot = saveActiveSnapshot;
693                 if (saveResourceOwner == saveTopTransactionResourceOwner)
694                         CurrentResourceOwner = TopTransactionResourceOwner;
695                 else
696                         CurrentResourceOwner = saveResourceOwner;
697                 PortalContext = savePortalContext;
698                 QueryContext = saveQueryContext;
699
700                 PG_RE_THROW();
701         }
702         PG_END_TRY();
703
704         if (saveMemoryContext == saveTopTransactionContext)
705                 MemoryContextSwitchTo(TopTransactionContext);
706         else
707                 MemoryContextSwitchTo(saveMemoryContext);
708         ActivePortal = saveActivePortal;
709         ActiveSnapshot = saveActiveSnapshot;
710         if (saveResourceOwner == saveTopTransactionResourceOwner)
711                 CurrentResourceOwner = TopTransactionResourceOwner;
712         else
713                 CurrentResourceOwner = saveResourceOwner;
714         PortalContext = savePortalContext;
715         QueryContext = saveQueryContext;
716
717         if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
718                 ShowUsage("EXECUTOR STATISTICS");
719
720         return result;
721 }
722
723 /*
724  * PortalRunSelect
725  *              Execute a portal's query in SELECT cases (also UTIL_SELECT).
726  *
727  * This handles simple N-rows-forward-or-backward cases.  For more complex
728  * nonsequential access to a portal, see PortalRunFetch.
729  *
730  * count <= 0 is interpreted as a no-op: the destination gets started up
731  * and shut down, but nothing else happens.  Also, count == FETCH_ALL is
732  * interpreted as "all rows".
733  *
734  * Caller must already have validated the Portal and done appropriate
735  * setup (cf. PortalRun).
736  *
737  * Returns number of rows processed (suitable for use in result tag)
738  */
739 static long
740 PortalRunSelect(Portal portal,
741                                 bool forward,
742                                 long count,
743                                 DestReceiver *dest)
744 {
745         QueryDesc  *queryDesc;
746         ScanDirection direction;
747         uint32          nprocessed;
748
749         /*
750          * NB: queryDesc will be NULL if we are fetching from a held cursor or a
751          * completed utility query; can't use it in that path.
752          */
753         queryDesc = PortalGetQueryDesc(portal);
754
755         /* Caller messed up if we have neither a ready query nor held data. */
756         Assert(queryDesc || portal->holdStore);
757
758         /*
759          * Force the queryDesc destination to the right thing.  This supports
760          * MOVE, for example, which will pass in dest = None.  This is okay to
761          * change as long as we do it on every fetch.  (The Executor must not
762          * assume that dest never changes.)
763          */
764         if (queryDesc)
765                 queryDesc->dest = dest;
766
767         /*
768          * Determine which direction to go in, and check to see if we're already
769          * at the end of the available tuples in that direction.  If so, set the
770          * direction to NoMovement to avoid trying to fetch any tuples.  (This
771          * check exists because not all plan node types are robust about being
772          * called again if they've already returned NULL once.)  Then call the
773          * executor (we must not skip this, because the destination needs to see a
774          * setup and shutdown even if no tuples are available).  Finally, update
775          * the portal position state depending on the number of tuples that were
776          * retrieved.
777          */
778         if (forward)
779         {
780                 if (portal->atEnd || count <= 0)
781                         direction = NoMovementScanDirection;
782                 else
783                         direction = ForwardScanDirection;
784
785                 /* In the executor, zero count processes all rows */
786                 if (count == FETCH_ALL)
787                         count = 0;
788
789                 if (portal->holdStore)
790                         nprocessed = RunFromStore(portal, direction, count, dest);
791                 else
792                 {
793                         ActiveSnapshot = queryDesc->snapshot;
794                         ExecutorRun(queryDesc, direction, count);
795                         nprocessed = queryDesc->estate->es_processed;
796                 }
797
798                 if (direction != NoMovementScanDirection)
799                 {
800                         long            oldPos;
801
802                         if (nprocessed > 0)
803                                 portal->atStart = false;                /* OK to go backward now */
804                         if (count == 0 ||
805                                 (unsigned long) nprocessed < (unsigned long) count)
806                                 portal->atEnd = true;   /* we retrieved 'em all */
807                         oldPos = portal->portalPos;
808                         portal->portalPos += nprocessed;
809                         /* portalPos doesn't advance when we fall off the end */
810                         if (portal->portalPos < oldPos)
811                                 portal->posOverflow = true;
812                 }
813         }
814         else
815         {
816                 if (portal->cursorOptions & CURSOR_OPT_NO_SCROLL)
817                         ereport(ERROR,
818                                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
819                                          errmsg("cursor can only scan forward"),
820                                          errhint("Declare it with SCROLL option to enable backward scan.")));
821
822                 if (portal->atStart || count <= 0)
823                         direction = NoMovementScanDirection;
824                 else
825                         direction = BackwardScanDirection;
826
827                 /* In the executor, zero count processes all rows */
828                 if (count == FETCH_ALL)
829                         count = 0;
830
831                 if (portal->holdStore)
832                         nprocessed = RunFromStore(portal, direction, count, dest);
833                 else
834                 {
835                         ActiveSnapshot = queryDesc->snapshot;
836                         ExecutorRun(queryDesc, direction, count);
837                         nprocessed = queryDesc->estate->es_processed;
838                 }
839
840                 if (direction != NoMovementScanDirection)
841                 {
842                         if (nprocessed > 0 && portal->atEnd)
843                         {
844                                 portal->atEnd = false;  /* OK to go forward now */
845                                 portal->portalPos++;    /* adjust for endpoint case */
846                         }
847                         if (count == 0 ||
848                                 (unsigned long) nprocessed < (unsigned long) count)
849                         {
850                                 portal->atStart = true; /* we retrieved 'em all */
851                                 portal->portalPos = 0;
852                                 portal->posOverflow = false;
853                         }
854                         else
855                         {
856                                 long            oldPos;
857
858                                 oldPos = portal->portalPos;
859                                 portal->portalPos -= nprocessed;
860                                 if (portal->portalPos > oldPos ||
861                                         portal->portalPos <= 0)
862                                         portal->posOverflow = true;
863                         }
864                 }
865         }
866
867         return nprocessed;
868 }
869
870 /*
871  * RunFromStore
872  *              Fetch tuples from the portal's tuple store.
873  *
874  * Calling conventions are similar to ExecutorRun, except that we
875  * do not depend on having a queryDesc or estate.  Therefore we return the
876  * number of tuples processed as the result, not in estate->es_processed.
877  *
878  * One difference from ExecutorRun is that the destination receiver functions
879  * are run in the caller's memory context (since we have no estate).  Watch
880  * out for memory leaks.
881  */
882 static uint32
883 RunFromStore(Portal portal, ScanDirection direction, long count,
884                          DestReceiver *dest)
885 {
886         long            current_tuple_count = 0;
887         TupleTableSlot *slot;
888
889         slot = MakeSingleTupleTableSlot(portal->tupDesc);
890
891         (*dest->rStartup) (dest, CMD_SELECT, portal->tupDesc);
892
893         if (direction == NoMovementScanDirection)
894         {
895                 /* do nothing except start/stop the destination */
896         }
897         else
898         {
899                 bool            forward = (direction == ForwardScanDirection);
900
901                 for (;;)
902                 {
903                         MemoryContext oldcontext;
904                         HeapTuple       tup;
905                         bool            should_free;
906
907                         oldcontext = MemoryContextSwitchTo(portal->holdContext);
908
909                         tup = tuplestore_getheaptuple(portal->holdStore, forward,
910                                                                                   &should_free);
911
912                         MemoryContextSwitchTo(oldcontext);
913
914                         if (tup == NULL)
915                                 break;
916
917                         ExecStoreTuple(tup, slot, InvalidBuffer, should_free);
918
919                         (*dest->receiveSlot) (slot, dest);
920
921                         ExecClearTuple(slot);
922
923                         /*
924                          * check our tuple count.. if we've processed the proper number
925                          * then quit, else loop again and process more tuples. Zero count
926                          * means no limit.
927                          */
928                         current_tuple_count++;
929                         if (count && count == current_tuple_count)
930                                 break;
931                 }
932         }
933
934         (*dest->rShutdown) (dest);
935
936         ExecDropSingleTupleTableSlot(slot);
937
938         return (uint32) current_tuple_count;
939 }
940
941 /*
942  * PortalRunUtility
943  *              Execute a utility statement inside a portal.
944  */
945 static void
946 PortalRunUtility(Portal portal, Query *query,
947                                  DestReceiver *dest, char *completionTag)
948 {
949         Node       *utilityStmt = query->utilityStmt;
950
951         ereport(DEBUG3,
952                         (errmsg_internal("ProcessUtility")));
953
954         /*
955          * Set snapshot if utility stmt needs one.      Most reliable way to do this
956          * seems to be to enumerate those that do not need one; this is a short
957          * list.  Transaction control, LOCK, and SET must *not* set a snapshot
958          * since they need to be executable at the start of a serializable
959          * transaction without freezing a snapshot.  By extension we allow SHOW
960          * not to set a snapshot.  The other stmts listed are just efficiency
961          * hacks.  Beware of listing anything that can modify the database --- if,
962          * say, it has to update an index with expressions that invoke
963          * user-defined functions, then it had better have a snapshot.
964          *
965          * Note we assume that caller will take care of restoring ActiveSnapshot on
966          * exit/error.
967          */
968         if (!(IsA(utilityStmt, TransactionStmt) ||
969                   IsA(utilityStmt, LockStmt) ||
970                   IsA(utilityStmt, VariableSetStmt) ||
971                   IsA(utilityStmt, VariableShowStmt) ||
972                   IsA(utilityStmt, VariableResetStmt) ||
973                   IsA(utilityStmt, ConstraintsSetStmt) ||
974         /* efficiency hacks from here down */
975                   IsA(utilityStmt, FetchStmt) ||
976                   IsA(utilityStmt, ListenStmt) ||
977                   IsA(utilityStmt, NotifyStmt) ||
978                   IsA(utilityStmt, UnlistenStmt) ||
979                   IsA(utilityStmt, CheckPointStmt)))
980                 ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
981         else
982                 ActiveSnapshot = NULL;
983
984         if (query->canSetTag)
985         {
986                 /* utility statement can override default tag string */
987                 ProcessUtility(utilityStmt, portal->portalParams, dest, completionTag);
988                 if (completionTag && completionTag[0] == '\0' && portal->commandTag)
989                         strcpy(completionTag, portal->commandTag);      /* use the default */
990         }
991         else
992         {
993                 /* utility added by rewrite cannot set tag */
994                 ProcessUtility(utilityStmt, portal->portalParams, dest, NULL);
995         }
996
997         /* Some utility statements may change context on us */
998         MemoryContextSwitchTo(PortalGetHeapMemory(portal));
999
1000         if (ActiveSnapshot)
1001                 FreeSnapshot(ActiveSnapshot);
1002         ActiveSnapshot = NULL;
1003 }
1004
1005 /*
1006  * PortalRunMulti
1007  *              Execute a portal's queries in the general case (multi queries).
1008  */
1009 static void
1010 PortalRunMulti(Portal portal,
1011                            DestReceiver *dest, DestReceiver *altdest,
1012                            char *completionTag)
1013 {
1014         ListCell   *querylist_item;
1015         ListCell   *planlist_item;
1016
1017         /*
1018          * If the destination is DestRemoteExecute, change to DestNone.  The reason
1019          * is that the client won't be expecting any tuples, and indeed has no way
1020          * to know what they are, since there is no provision for Describe to send
1021          * a RowDescription message when this portal execution strategy is in
1022          * effect.      This presently will only affect SELECT commands added to
1023          * non-SELECT queries by rewrite rules: such commands will be executed,
1024          * but the results will be discarded unless you use "simple Query"
1025          * protocol.
1026          */
1027         if (dest->mydest == DestRemoteExecute)
1028                 dest = None_Receiver;
1029         if (altdest->mydest == DestRemoteExecute)
1030                 altdest = None_Receiver;
1031
1032         /*
1033          * Loop to handle the individual queries generated from a single parsetree
1034          * by analysis and rewrite.
1035          */
1036         forboth(querylist_item, portal->parseTrees,
1037                         planlist_item, portal->planTrees)
1038         {
1039                 Query      *query = (Query *) lfirst(querylist_item);
1040                 Plan       *plan = (Plan *) lfirst(planlist_item);
1041
1042                 /*
1043                  * If we got a cancel signal in prior command, quit
1044                  */
1045                 CHECK_FOR_INTERRUPTS();
1046
1047                 if (query->commandType == CMD_UTILITY)
1048                 {
1049                         /*
1050                          * process utility functions (create, destroy, etc..)
1051                          */
1052                         Assert(plan == NULL);
1053
1054                         PortalRunUtility(portal, query,
1055                                                          query->canSetTag ? dest : altdest,
1056                                                          completionTag);
1057                 }
1058                 else
1059                 {
1060                         /*
1061                          * process a plannable query.
1062                          */
1063                         if (log_executor_stats)
1064                                 ResetUsage();
1065
1066                         if (query->canSetTag)
1067                         {
1068                                 /* statement can set tag string */
1069                                 ProcessQuery(query, plan,
1070                                                          portal->portalParams,
1071                                                          dest, completionTag);
1072                         }
1073                         else
1074                         {
1075                                 /* stmt added by rewrite cannot set tag */
1076                                 ProcessQuery(query, plan,
1077                                                          portal->portalParams,
1078                                                          altdest, NULL);
1079                         }
1080
1081                         if (log_executor_stats)
1082                                 ShowUsage("EXECUTOR STATISTICS");
1083                 }
1084
1085                 /*
1086                  * Increment command counter between queries, but not after the last
1087                  * one.
1088                  */
1089                 if (lnext(planlist_item) != NULL)
1090                         CommandCounterIncrement();
1091
1092                 /*
1093                  * Clear subsidiary contexts to recover temporary memory.
1094                  */
1095                 Assert(PortalGetHeapMemory(portal) == CurrentMemoryContext);
1096
1097                 MemoryContextDeleteChildren(PortalGetHeapMemory(portal));
1098         }
1099
1100         /*
1101          * If a command completion tag was supplied, use it.  Otherwise use the
1102          * portal's commandTag as the default completion tag.
1103          *
1104          * Exception: clients will expect INSERT/UPDATE/DELETE tags to have counts,
1105          * so fake something up if necessary.  (This could happen if the original
1106          * query was replaced by a DO INSTEAD rule.)
1107          */
1108         if (completionTag && completionTag[0] == '\0')
1109         {
1110                 if (portal->commandTag)
1111                         strcpy(completionTag, portal->commandTag);
1112                 if (strcmp(completionTag, "INSERT") == 0)
1113                         strcpy(completionTag, "INSERT 0 0");
1114                 else if (strcmp(completionTag, "UPDATE") == 0)
1115                         strcpy(completionTag, "UPDATE 0");
1116                 else if (strcmp(completionTag, "DELETE") == 0)
1117                         strcpy(completionTag, "DELETE 0");
1118         }
1119 }
1120
1121 /*
1122  * PortalRunFetch
1123  *              Variant form of PortalRun that supports SQL FETCH directions.
1124  *
1125  * Returns number of rows processed (suitable for use in result tag)
1126  */
1127 long
1128 PortalRunFetch(Portal portal,
1129                            FetchDirection fdirection,
1130                            long count,
1131                            DestReceiver *dest)
1132 {
1133         long            result;
1134         Portal          saveActivePortal;
1135         Snapshot        saveActiveSnapshot;
1136         ResourceOwner saveResourceOwner;
1137         MemoryContext savePortalContext;
1138         MemoryContext saveQueryContext;
1139         MemoryContext oldContext;
1140
1141         AssertArg(PortalIsValid(portal));
1142
1143         /*
1144          * Check for improper portal use, and mark portal active.
1145          */
1146         if (portal->status != PORTAL_READY)
1147                 ereport(ERROR,
1148                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1149                                  errmsg("portal \"%s\" cannot be run", portal->name)));
1150         portal->status = PORTAL_ACTIVE;
1151
1152         /*
1153          * Set up global portal context pointers.
1154          */
1155         saveActivePortal = ActivePortal;
1156         saveActiveSnapshot = ActiveSnapshot;
1157         saveResourceOwner = CurrentResourceOwner;
1158         savePortalContext = PortalContext;
1159         saveQueryContext = QueryContext;
1160         PG_TRY();
1161         {
1162                 ActivePortal = portal;
1163                 ActiveSnapshot = NULL;  /* will be set later */
1164                 CurrentResourceOwner = portal->resowner;
1165                 PortalContext = PortalGetHeapMemory(portal);
1166                 QueryContext = portal->queryContext;
1167
1168                 oldContext = MemoryContextSwitchTo(PortalContext);
1169
1170                 switch (portal->strategy)
1171                 {
1172                         case PORTAL_ONE_SELECT:
1173                                 result = DoPortalRunFetch(portal, fdirection, count, dest);
1174                                 break;
1175
1176                         case PORTAL_UTIL_SELECT:
1177
1178                                 /*
1179                                  * If we have not yet run the utility statement, do so,
1180                                  * storing its results in the portal's tuplestore.
1181                                  */
1182                                 if (!portal->portalUtilReady)
1183                                 {
1184                                         DestReceiver *treceiver;
1185
1186                                         PortalCreateHoldStore(portal);
1187                                         treceiver = CreateDestReceiver(DestTuplestore, portal);
1188                                         PortalRunUtility(portal, linitial(portal->parseTrees),
1189                                                                          treceiver, NULL);
1190                                         (*treceiver->rDestroy) (treceiver);
1191                                         portal->portalUtilReady = true;
1192                                 }
1193
1194                                 /*
1195                                  * Now fetch desired portion of results.
1196                                  */
1197                                 result = DoPortalRunFetch(portal, fdirection, count, dest);
1198                                 break;
1199
1200                         default:
1201                                 elog(ERROR, "unsupported portal strategy");
1202                                 result = 0;             /* keep compiler quiet */
1203                                 break;
1204                 }
1205         }
1206         PG_CATCH();
1207         {
1208                 /* Uncaught error while executing portal: mark it dead */
1209                 portal->status = PORTAL_FAILED;
1210
1211                 /* Restore global vars and propagate error */
1212                 ActivePortal = saveActivePortal;
1213                 ActiveSnapshot = saveActiveSnapshot;
1214                 CurrentResourceOwner = saveResourceOwner;
1215                 PortalContext = savePortalContext;
1216                 QueryContext = saveQueryContext;
1217
1218                 PG_RE_THROW();
1219         }
1220         PG_END_TRY();
1221
1222         MemoryContextSwitchTo(oldContext);
1223
1224         /* Mark portal not active */
1225         portal->status = PORTAL_READY;
1226
1227         ActivePortal = saveActivePortal;
1228         ActiveSnapshot = saveActiveSnapshot;
1229         CurrentResourceOwner = saveResourceOwner;
1230         PortalContext = savePortalContext;
1231         QueryContext = saveQueryContext;
1232
1233         return result;
1234 }
1235
1236 /*
1237  * DoPortalRunFetch
1238  *              Guts of PortalRunFetch --- the portal context is already set up
1239  *
1240  * Returns number of rows processed (suitable for use in result tag)
1241  */
1242 static long
1243 DoPortalRunFetch(Portal portal,
1244                                  FetchDirection fdirection,
1245                                  long count,
1246                                  DestReceiver *dest)
1247 {
1248         bool            forward;
1249
1250         Assert(portal->strategy == PORTAL_ONE_SELECT ||
1251                    portal->strategy == PORTAL_UTIL_SELECT);
1252
1253         switch (fdirection)
1254         {
1255                 case FETCH_FORWARD:
1256                         if (count < 0)
1257                         {
1258                                 fdirection = FETCH_BACKWARD;
1259                                 count = -count;
1260                         }
1261                         /* fall out of switch to share code with FETCH_BACKWARD */
1262                         break;
1263                 case FETCH_BACKWARD:
1264                         if (count < 0)
1265                         {
1266                                 fdirection = FETCH_FORWARD;
1267                                 count = -count;
1268                         }
1269                         /* fall out of switch to share code with FETCH_FORWARD */
1270                         break;
1271                 case FETCH_ABSOLUTE:
1272                         if (count > 0)
1273                         {
1274                                 /*
1275                                  * Definition: Rewind to start, advance count-1 rows, return
1276                                  * next row (if any).  In practice, if the goal is less than
1277                                  * halfway back to the start, it's better to scan from where
1278                                  * we are.      In any case, we arrange to fetch the target row
1279                                  * going forwards.
1280                                  */
1281                                 if (portal->posOverflow || portal->portalPos == LONG_MAX ||
1282                                         count - 1 <= portal->portalPos / 2)
1283                                 {
1284                                         DoPortalRewind(portal);
1285                                         if (count > 1)
1286                                                 PortalRunSelect(portal, true, count - 1,
1287                                                                                 None_Receiver);
1288                                 }
1289                                 else
1290                                 {
1291                                         long            pos = portal->portalPos;
1292
1293                                         if (portal->atEnd)
1294                                                 pos++;  /* need one extra fetch if off end */
1295                                         if (count <= pos)
1296                                                 PortalRunSelect(portal, false, pos - count + 1,
1297                                                                                 None_Receiver);
1298                                         else if (count > pos + 1)
1299                                                 PortalRunSelect(portal, true, count - pos - 1,
1300                                                                                 None_Receiver);
1301                                 }
1302                                 return PortalRunSelect(portal, true, 1L, dest);
1303                         }
1304                         else if (count < 0)
1305                         {
1306                                 /*
1307                                  * Definition: Advance to end, back up abs(count)-1 rows,
1308                                  * return prior row (if any).  We could optimize this if we
1309                                  * knew in advance where the end was, but typically we won't.
1310                                  * (Is it worth considering case where count > half of size of
1311                                  * query?  We could rewind once we know the size ...)
1312                                  */
1313                                 PortalRunSelect(portal, true, FETCH_ALL, None_Receiver);
1314                                 if (count < -1)
1315                                         PortalRunSelect(portal, false, -count - 1, None_Receiver);
1316                                 return PortalRunSelect(portal, false, 1L, dest);
1317                         }
1318                         else
1319                         {
1320                                 /* count == 0 */
1321                                 /* Rewind to start, return zero rows */
1322                                 DoPortalRewind(portal);
1323                                 return PortalRunSelect(portal, true, 0L, dest);
1324                         }
1325                         break;
1326                 case FETCH_RELATIVE:
1327                         if (count > 0)
1328                         {
1329                                 /*
1330                                  * Definition: advance count-1 rows, return next row (if any).
1331                                  */
1332                                 if (count > 1)
1333                                         PortalRunSelect(portal, true, count - 1, None_Receiver);
1334                                 return PortalRunSelect(portal, true, 1L, dest);
1335                         }
1336                         else if (count < 0)
1337                         {
1338                                 /*
1339                                  * Definition: back up abs(count)-1 rows, return prior row (if
1340                                  * any).
1341                                  */
1342                                 if (count < -1)
1343                                         PortalRunSelect(portal, false, -count - 1, None_Receiver);
1344                                 return PortalRunSelect(portal, false, 1L, dest);
1345                         }
1346                         else
1347                         {
1348                                 /* count == 0 */
1349                                 /* Same as FETCH FORWARD 0, so fall out of switch */
1350                                 fdirection = FETCH_FORWARD;
1351                         }
1352                         break;
1353                 default:
1354                         elog(ERROR, "bogus direction");
1355                         break;
1356         }
1357
1358         /*
1359          * Get here with fdirection == FETCH_FORWARD or FETCH_BACKWARD, and count
1360          * >= 0.
1361          */
1362         forward = (fdirection == FETCH_FORWARD);
1363
1364         /*
1365          * Zero count means to re-fetch the current row, if any (per SQL92)
1366          */
1367         if (count == 0)
1368         {
1369                 bool            on_row;
1370
1371                 /* Are we sitting on a row? */
1372                 on_row = (!portal->atStart && !portal->atEnd);
1373
1374                 if (dest->mydest == DestNone)
1375                 {
1376                         /* MOVE 0 returns 0/1 based on if FETCH 0 would return a row */
1377                         return on_row ? 1L : 0L;
1378                 }
1379                 else
1380                 {
1381                         /*
1382                          * If we are sitting on a row, back up one so we can re-fetch it.
1383                          * If we are not sitting on a row, we still have to start up and
1384                          * shut down the executor so that the destination is initialized
1385                          * and shut down correctly; so keep going.      To PortalRunSelect,
1386                          * count == 0 means we will retrieve no row.
1387                          */
1388                         if (on_row)
1389                         {
1390                                 PortalRunSelect(portal, false, 1L, None_Receiver);
1391                                 /* Set up to fetch one row forward */
1392                                 count = 1;
1393                                 forward = true;
1394                         }
1395                 }
1396         }
1397
1398         /*
1399          * Optimize MOVE BACKWARD ALL into a Rewind.
1400          */
1401         if (!forward && count == FETCH_ALL && dest->mydest == DestNone)
1402         {
1403                 long            result = portal->portalPos;
1404
1405                 if (result > 0 && !portal->atEnd)
1406                         result--;
1407                 DoPortalRewind(portal);
1408                 /* result is bogus if pos had overflowed, but it's best we can do */
1409                 return result;
1410         }
1411
1412         return PortalRunSelect(portal, forward, count, dest);
1413 }
1414
1415 /*
1416  * DoPortalRewind - rewind a Portal to starting point
1417  */
1418 static void
1419 DoPortalRewind(Portal portal)
1420 {
1421         if (portal->holdStore)
1422         {
1423                 MemoryContext oldcontext;
1424
1425                 oldcontext = MemoryContextSwitchTo(portal->holdContext);
1426                 tuplestore_rescan(portal->holdStore);
1427                 MemoryContextSwitchTo(oldcontext);
1428         }
1429         if (PortalGetQueryDesc(portal))
1430                 ExecutorRewind(PortalGetQueryDesc(portal));
1431
1432         portal->atStart = true;
1433         portal->atEnd = false;
1434         portal->portalPos = 0;
1435         portal->posOverflow = false;
1436 }