PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pquery.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pquery.c
4  * POSTGRES process query command code
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/tcop/pquery.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include <limits.h>
19 
20 #include "access/xact.h"
21 #include "commands/prepare.h"
23 #include "miscadmin.h"
24 #include "pg_trace.h"
25 #include "tcop/pquery.h"
26 #include "tcop/utility.h"
27 #include "utils/memutils.h"
28 #include "utils/snapmgr.h"
29 
30 
31 /*
32  * ActivePortal is the currently executing Portal (the most closely nested,
33  * if there are several).
34  */
36 
37 
38 static void ProcessQuery(PlannedStmt *plan,
39  const char *sourceText,
40  ParamListInfo params,
41  DestReceiver *dest,
42  char *completionTag);
43 static void FillPortalStore(Portal portal, bool isTopLevel);
44 static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count,
45  DestReceiver *dest);
46 static uint64 PortalRunSelect(Portal portal, bool forward, long count,
47  DestReceiver *dest);
48 static void PortalRunUtility(Portal portal, PlannedStmt *pstmt,
49  bool isTopLevel, bool setHoldSnapshot,
50  DestReceiver *dest, char *completionTag);
51 static void PortalRunMulti(Portal portal,
52  bool isTopLevel, bool setHoldSnapshot,
53  DestReceiver *dest, DestReceiver *altdest,
54  char *completionTag);
55 static uint64 DoPortalRunFetch(Portal portal,
56  FetchDirection fdirection,
57  long count,
58  DestReceiver *dest);
59 static void DoPortalRewind(Portal portal);
60 
61 
62 /*
63  * CreateQueryDesc
64  */
65 QueryDesc *
67  const char *sourceText,
68  Snapshot snapshot,
69  Snapshot crosscheck_snapshot,
70  DestReceiver *dest,
71  ParamListInfo params,
72  int instrument_options)
73 {
74  QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
75 
76  qd->operation = plannedstmt->commandType; /* operation */
77  qd->plannedstmt = plannedstmt; /* plan */
78  qd->sourceText = sourceText; /* query text */
79  qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */
80  /* RI check snapshot */
81  qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot);
82  qd->dest = dest; /* output dest */
83  qd->params = params; /* parameter values passed into query */
84  qd->instrument_options = instrument_options; /* instrumentation
85  * wanted? */
86 
87  /* null these fields until set by ExecutorStart */
88  qd->tupDesc = NULL;
89  qd->estate = NULL;
90  qd->planstate = NULL;
91  qd->totaltime = NULL;
92 
93  return qd;
94 }
95 
96 /*
97  * FreeQueryDesc
98  */
99 void
101 {
102  /* Can't be a live query */
103  Assert(qdesc->estate == NULL);
104 
105  /* forget our snapshots */
108 
109  /* Only the QueryDesc itself need be freed */
110  pfree(qdesc);
111 }
112 
113 
114 /*
115  * ProcessQuery
116  * Execute a single plannable query within a PORTAL_MULTI_QUERY,
117  * PORTAL_ONE_RETURNING, or PORTAL_ONE_MOD_WITH portal
118  *
119  * plan: the plan tree for the query
120  * sourceText: the source text of the query
121  * params: any parameters needed
122  * dest: where to send results
123  * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
124  * in which to store a command completion status string.
125  *
126  * completionTag may be NULL if caller doesn't want a status string.
127  *
128  * Must be called in a memory context that will be reset or deleted on
129  * error; otherwise the executor's memory usage will be leaked.
130  */
131 static void
133  const char *sourceText,
134  ParamListInfo params,
135  DestReceiver *dest,
136  char *completionTag)
137 {
138  QueryDesc *queryDesc;
139 
140  /*
141  * Create the QueryDesc object
142  */
143  queryDesc = CreateQueryDesc(plan, sourceText,
145  dest, params, 0);
146 
147  /*
148  * Call ExecutorStart to prepare the plan for execution
149  */
150  ExecutorStart(queryDesc, 0);
151 
152  /*
153  * Run the plan to completion.
154  */
155  ExecutorRun(queryDesc, ForwardScanDirection, 0L);
156 
157  /*
158  * Build command completion status string, if caller wants one.
159  */
160  if (completionTag)
161  {
162  Oid lastOid;
163 
164  switch (queryDesc->operation)
165  {
166  case CMD_SELECT:
167  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
168  "SELECT " UINT64_FORMAT,
169  queryDesc->estate->es_processed);
170  break;
171  case CMD_INSERT:
172  if (queryDesc->estate->es_processed == 1)
173  lastOid = queryDesc->estate->es_lastoid;
174  else
175  lastOid = InvalidOid;
176  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
177  "INSERT %u " UINT64_FORMAT,
178  lastOid, queryDesc->estate->es_processed);
179  break;
180  case CMD_UPDATE:
181  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
182  "UPDATE " UINT64_FORMAT,
183  queryDesc->estate->es_processed);
184  break;
185  case CMD_DELETE:
186  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
187  "DELETE " UINT64_FORMAT,
188  queryDesc->estate->es_processed);
189  break;
190  default:
191  strcpy(completionTag, "???");
192  break;
193  }
194  }
195 
196  /*
197  * Now, we close down all the scans and free allocated resources.
198  */
199  ExecutorFinish(queryDesc);
200  ExecutorEnd(queryDesc);
201 
202  FreeQueryDesc(queryDesc);
203 }
204 
205 /*
206  * ChoosePortalStrategy
207  * Select portal execution strategy given the intended statement list.
208  *
209  * The list elements can be Querys or PlannedStmts.
210  * That's more general than portals need, but plancache.c uses this too.
211  *
212  * See the comments in portal.h.
213  */
216 {
217  int nSetTag;
218  ListCell *lc;
219 
220  /*
221  * PORTAL_ONE_SELECT and PORTAL_UTIL_SELECT need only consider the
222  * single-statement case, since there are no rewrite rules that can add
223  * auxiliary queries to a SELECT or a utility command. PORTAL_ONE_MOD_WITH
224  * likewise allows only one top-level statement.
225  */
226  if (list_length(stmts) == 1)
227  {
228  Node *stmt = (Node *) linitial(stmts);
229 
230  if (IsA(stmt, Query))
231  {
232  Query *query = (Query *) stmt;
233 
234  if (query->canSetTag)
235  {
236  if (query->commandType == CMD_SELECT)
237  {
238  if (query->hasModifyingCTE)
239  return PORTAL_ONE_MOD_WITH;
240  else
241  return PORTAL_ONE_SELECT;
242  }
243  if (query->commandType == CMD_UTILITY)
244  {
245  if (UtilityReturnsTuples(query->utilityStmt))
246  return PORTAL_UTIL_SELECT;
247  /* it can't be ONE_RETURNING, so give up */
248  return PORTAL_MULTI_QUERY;
249  }
250  }
251  }
252  else if (IsA(stmt, PlannedStmt))
253  {
254  PlannedStmt *pstmt = (PlannedStmt *) stmt;
255 
256  if (pstmt->canSetTag)
257  {
258  if (pstmt->commandType == CMD_SELECT)
259  {
260  if (pstmt->hasModifyingCTE)
261  return PORTAL_ONE_MOD_WITH;
262  else
263  return PORTAL_ONE_SELECT;
264  }
265  if (pstmt->commandType == CMD_UTILITY)
266  {
267  if (UtilityReturnsTuples(pstmt->utilityStmt))
268  return PORTAL_UTIL_SELECT;
269  /* it can't be ONE_RETURNING, so give up */
270  return PORTAL_MULTI_QUERY;
271  }
272  }
273  }
274  else
275  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
276  }
277 
278  /*
279  * PORTAL_ONE_RETURNING has to allow auxiliary queries added by rewrite.
280  * Choose PORTAL_ONE_RETURNING if there is exactly one canSetTag query and
281  * it has a RETURNING list.
282  */
283  nSetTag = 0;
284  foreach(lc, stmts)
285  {
286  Node *stmt = (Node *) lfirst(lc);
287 
288  if (IsA(stmt, Query))
289  {
290  Query *query = (Query *) stmt;
291 
292  if (query->canSetTag)
293  {
294  if (++nSetTag > 1)
295  return PORTAL_MULTI_QUERY; /* no need to look further */
296  if (query->commandType == CMD_UTILITY ||
297  query->returningList == NIL)
298  return PORTAL_MULTI_QUERY; /* no need to look further */
299  }
300  }
301  else if (IsA(stmt, PlannedStmt))
302  {
303  PlannedStmt *pstmt = (PlannedStmt *) stmt;
304 
305  if (pstmt->canSetTag)
306  {
307  if (++nSetTag > 1)
308  return PORTAL_MULTI_QUERY; /* no need to look further */
309  if (pstmt->commandType == CMD_UTILITY ||
310  !pstmt->hasReturning)
311  return PORTAL_MULTI_QUERY; /* no need to look further */
312  }
313  }
314  else
315  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
316  }
317  if (nSetTag == 1)
318  return PORTAL_ONE_RETURNING;
319 
320  /* Else, it's the general case... */
321  return PORTAL_MULTI_QUERY;
322 }
323 
324 /*
325  * FetchPortalTargetList
326  * Given a portal that returns tuples, extract the query targetlist.
327  * Returns NIL if the portal doesn't have a determinable targetlist.
328  *
329  * Note: do not modify the result.
330  */
331 List *
333 {
334  /* no point in looking if we determined it doesn't return tuples */
335  if (portal->strategy == PORTAL_MULTI_QUERY)
336  return NIL;
337  /* get the primary statement and find out what it returns */
339 }
340 
341 /*
342  * FetchStatementTargetList
343  * Given a statement that returns tuples, extract the query targetlist.
344  * Returns NIL if the statement doesn't have a determinable targetlist.
345  *
346  * This can be applied to a Query or a PlannedStmt.
347  * That's more general than portals need, but plancache.c uses this too.
348  *
349  * Note: do not modify the result.
350  *
351  * XXX be careful to keep this in sync with UtilityReturnsTuples.
352  */
353 List *
355 {
356  if (stmt == NULL)
357  return NIL;
358  if (IsA(stmt, Query))
359  {
360  Query *query = (Query *) stmt;
361 
362  if (query->commandType == CMD_UTILITY)
363  {
364  /* transfer attention to utility statement */
365  stmt = query->utilityStmt;
366  }
367  else
368  {
369  if (query->commandType == CMD_SELECT)
370  return query->targetList;
371  if (query->returningList)
372  return query->returningList;
373  return NIL;
374  }
375  }
376  if (IsA(stmt, PlannedStmt))
377  {
378  PlannedStmt *pstmt = (PlannedStmt *) stmt;
379 
380  if (pstmt->commandType == CMD_UTILITY)
381  {
382  /* transfer attention to utility statement */
383  stmt = pstmt->utilityStmt;
384  }
385  else
386  {
387  if (pstmt->commandType == CMD_SELECT)
388  return pstmt->planTree->targetlist;
389  if (pstmt->hasReturning)
390  return pstmt->planTree->targetlist;
391  return NIL;
392  }
393  }
394  if (IsA(stmt, FetchStmt))
395  {
396  FetchStmt *fstmt = (FetchStmt *) stmt;
397  Portal subportal;
398 
399  Assert(!fstmt->ismove);
400  subportal = GetPortalByName(fstmt->portalname);
401  Assert(PortalIsValid(subportal));
402  return FetchPortalTargetList(subportal);
403  }
404  if (IsA(stmt, ExecuteStmt))
405  {
406  ExecuteStmt *estmt = (ExecuteStmt *) stmt;
407  PreparedStatement *entry;
408 
409  entry = FetchPreparedStatement(estmt->name, true);
410  return FetchPreparedStatementTargetList(entry);
411  }
412  return NIL;
413 }
414 
415 /*
416  * PortalStart
417  * Prepare a portal for execution.
418  *
419  * Caller must already have created the portal, done PortalDefineQuery(),
420  * and adjusted portal options if needed.
421  *
422  * If parameters are needed by the query, they must be passed in "params"
423  * (caller is responsible for giving them appropriate lifetime).
424  *
425  * The caller can also provide an initial set of "eflags" to be passed to
426  * ExecutorStart (but note these can be modified internally, and they are
427  * currently only honored for PORTAL_ONE_SELECT portals). Most callers
428  * should simply pass zero.
429  *
430  * The caller can optionally pass a snapshot to be used; pass InvalidSnapshot
431  * for the normal behavior of setting a new snapshot. This parameter is
432  * presently ignored for non-PORTAL_ONE_SELECT portals (it's only intended
433  * to be used for cursors).
434  *
435  * On return, portal is ready to accept PortalRun() calls, and the result
436  * tupdesc (if any) is known.
437  */
438 void
440  int eflags, Snapshot snapshot)
441 {
442  Portal saveActivePortal;
443  ResourceOwner saveResourceOwner;
444  MemoryContext savePortalContext;
445  MemoryContext oldContext;
446  QueryDesc *queryDesc;
447  int myeflags;
448 
449  AssertArg(PortalIsValid(portal));
450  AssertState(portal->status == PORTAL_DEFINED);
451 
452  /*
453  * Set up global portal context pointers.
454  */
455  saveActivePortal = ActivePortal;
456  saveResourceOwner = CurrentResourceOwner;
457  savePortalContext = PortalContext;
458  PG_TRY();
459  {
460  ActivePortal = portal;
461  if (portal->resowner)
462  CurrentResourceOwner = portal->resowner;
464 
465  oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
466 
467  /* Must remember portal param list, if any */
468  portal->portalParams = params;
469 
470  /*
471  * Determine the portal execution strategy
472  */
473  portal->strategy = ChoosePortalStrategy(portal->stmts);
474 
475  /*
476  * Fire her up according to the strategy
477  */
478  switch (portal->strategy)
479  {
480  case PORTAL_ONE_SELECT:
481 
482  /* Must set snapshot before starting executor. */
483  if (snapshot)
484  PushActiveSnapshot(snapshot);
485  else
487 
488  /*
489  * Create QueryDesc in portal's context; for the moment, set
490  * the destination to DestNone.
491  */
492  queryDesc = CreateQueryDesc(castNode(PlannedStmt, linitial(portal->stmts)),
493  portal->sourceText,
497  params,
498  0);
499 
500  /*
501  * If it's a scrollable cursor, executor needs to support
502  * REWIND and backwards scan, as well as whatever the caller
503  * might've asked for.
504  */
505  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
506  myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
507  else
508  myeflags = eflags;
509 
510  /*
511  * Call ExecutorStart to prepare the plan for execution
512  */
513  ExecutorStart(queryDesc, myeflags);
514 
515  /*
516  * This tells PortalCleanup to shut down the executor
517  */
518  portal->queryDesc = queryDesc;
519 
520  /*
521  * Remember tuple descriptor (computed by ExecutorStart)
522  */
523  portal->tupDesc = queryDesc->tupDesc;
524 
525  /*
526  * Reset cursor position data to "start of query"
527  */
528  portal->atStart = true;
529  portal->atEnd = false; /* allow fetches */
530  portal->portalPos = 0;
531 
533  break;
534 
536  case PORTAL_ONE_MOD_WITH:
537 
538  /*
539  * We don't start the executor until we are told to run the
540  * portal. We do need to set up the result tupdesc.
541  */
542  {
543  PlannedStmt *pstmt;
544 
545  pstmt = PortalGetPrimaryStmt(portal);
546  portal->tupDesc =
548  false);
549  }
550 
551  /*
552  * Reset cursor position data to "start of query"
553  */
554  portal->atStart = true;
555  portal->atEnd = false; /* allow fetches */
556  portal->portalPos = 0;
557  break;
558 
559  case PORTAL_UTIL_SELECT:
560 
561  /*
562  * We don't set snapshot here, because PortalRunUtility will
563  * take care of it if needed.
564  */
565  {
566  PlannedStmt *pstmt = PortalGetPrimaryStmt(portal);
567 
568  Assert(pstmt->commandType == CMD_UTILITY);
569  portal->tupDesc = UtilityTupleDescriptor(pstmt->utilityStmt);
570  }
571 
572  /*
573  * Reset cursor position data to "start of query"
574  */
575  portal->atStart = true;
576  portal->atEnd = false; /* allow fetches */
577  portal->portalPos = 0;
578  break;
579 
580  case PORTAL_MULTI_QUERY:
581  /* Need do nothing now */
582  portal->tupDesc = NULL;
583  break;
584  }
585  }
586  PG_CATCH();
587  {
588  /* Uncaught error while executing portal: mark it dead */
589  MarkPortalFailed(portal);
590 
591  /* Restore global vars and propagate error */
592  ActivePortal = saveActivePortal;
593  CurrentResourceOwner = saveResourceOwner;
594  PortalContext = savePortalContext;
595 
596  PG_RE_THROW();
597  }
598  PG_END_TRY();
599 
600  MemoryContextSwitchTo(oldContext);
601 
602  ActivePortal = saveActivePortal;
603  CurrentResourceOwner = saveResourceOwner;
604  PortalContext = savePortalContext;
605 
606  portal->status = PORTAL_READY;
607 }
608 
609 /*
610  * PortalSetResultFormat
611  * Select the format codes for a portal's output.
612  *
613  * This must be run after PortalStart for a portal that will be read by
614  * a DestRemote or DestRemoteExecute destination. It is not presently needed
615  * for other destination types.
616  *
617  * formats[] is the client format request, as per Bind message conventions.
618  */
619 void
620 PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
621 {
622  int natts;
623  int i;
624 
625  /* Do nothing if portal won't return tuples */
626  if (portal->tupDesc == NULL)
627  return;
628  natts = portal->tupDesc->natts;
629  portal->formats = (int16 *)
631  natts * sizeof(int16));
632  if (nFormats > 1)
633  {
634  /* format specified for each column */
635  if (nFormats != natts)
636  ereport(ERROR,
637  (errcode(ERRCODE_PROTOCOL_VIOLATION),
638  errmsg("bind message has %d result formats but query has %d columns",
639  nFormats, natts)));
640  memcpy(portal->formats, formats, natts * sizeof(int16));
641  }
642  else if (nFormats > 0)
643  {
644  /* single format specified, use for all columns */
645  int16 format1 = formats[0];
646 
647  for (i = 0; i < natts; i++)
648  portal->formats[i] = format1;
649  }
650  else
651  {
652  /* use default format for all columns */
653  for (i = 0; i < natts; i++)
654  portal->formats[i] = 0;
655  }
656 }
657 
658 /*
659  * PortalRun
660  * Run a portal's query or queries.
661  *
662  * count <= 0 is interpreted as a no-op: the destination gets started up
663  * and shut down, but nothing else happens. Also, count == FETCH_ALL is
664  * interpreted as "all rows". Note that count is ignored in multi-query
665  * situations, where we always run the portal to completion.
666  *
667  * isTopLevel: true if query is being executed at backend "top level"
668  * (that is, directly from a client command message)
669  *
670  * dest: where to send output of primary (canSetTag) query
671  *
672  * altdest: where to send output of non-primary queries
673  *
674  * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
675  * in which to store a command completion status string.
676  * May be NULL if caller doesn't want a status string.
677  *
678  * Returns TRUE if the portal's execution is complete, FALSE if it was
679  * suspended due to exhaustion of the count parameter.
680  */
681 bool
682 PortalRun(Portal portal, long count, bool isTopLevel,
683  DestReceiver *dest, DestReceiver *altdest,
684  char *completionTag)
685 {
686  bool result;
687  uint64 nprocessed;
688  ResourceOwner saveTopTransactionResourceOwner;
689  MemoryContext saveTopTransactionContext;
690  Portal saveActivePortal;
691  ResourceOwner saveResourceOwner;
692  MemoryContext savePortalContext;
693  MemoryContext saveMemoryContext;
694 
695  AssertArg(PortalIsValid(portal));
696 
697  TRACE_POSTGRESQL_QUERY_EXECUTE_START();
698 
699  /* Initialize completion tag to empty string */
700  if (completionTag)
701  completionTag[0] = '\0';
702 
704  {
705  elog(DEBUG3, "PortalRun");
706  /* PORTAL_MULTI_QUERY logs its own stats per query */
707  ResetUsage();
708  }
709 
710  /*
711  * Check for improper portal use, and mark portal active.
712  */
713  MarkPortalActive(portal);
714 
715  /*
716  * Set up global portal context pointers.
717  *
718  * We have to play a special game here to support utility commands like
719  * VACUUM and CLUSTER, which internally start and commit transactions.
720  * When we are called to execute such a command, CurrentResourceOwner will
721  * be pointing to the TopTransactionResourceOwner --- which will be
722  * destroyed and replaced in the course of the internal commit and
723  * restart. So we need to be prepared to restore it as pointing to the
724  * exit-time TopTransactionResourceOwner. (Ain't that ugly? This idea of
725  * internally starting whole new transactions is not good.)
726  * CurrentMemoryContext has a similar problem, but the other pointers we
727  * save here will be NULL or pointing to longer-lived objects.
728  */
729  saveTopTransactionResourceOwner = TopTransactionResourceOwner;
730  saveTopTransactionContext = TopTransactionContext;
731  saveActivePortal = ActivePortal;
732  saveResourceOwner = CurrentResourceOwner;
733  savePortalContext = PortalContext;
734  saveMemoryContext = CurrentMemoryContext;
735  PG_TRY();
736  {
737  ActivePortal = portal;
738  if (portal->resowner)
739  CurrentResourceOwner = portal->resowner;
741 
743 
744  switch (portal->strategy)
745  {
746  case PORTAL_ONE_SELECT:
748  case PORTAL_ONE_MOD_WITH:
749  case PORTAL_UTIL_SELECT:
750 
751  /*
752  * If we have not yet run the command, do so, storing its
753  * results in the portal's tuplestore. But we don't do that
754  * for the PORTAL_ONE_SELECT case.
755  */
756  if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
757  FillPortalStore(portal, isTopLevel);
758 
759  /*
760  * Now fetch desired portion of results.
761  */
762  nprocessed = PortalRunSelect(portal, true, count, dest);
763 
764  /*
765  * If the portal result contains a command tag and the caller
766  * gave us a pointer to store it, copy it. Patch the "SELECT"
767  * tag to also provide the rowcount.
768  */
769  if (completionTag && portal->commandTag)
770  {
771  if (strcmp(portal->commandTag, "SELECT") == 0)
772  snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
773  "SELECT " UINT64_FORMAT, nprocessed);
774  else
775  strcpy(completionTag, portal->commandTag);
776  }
777 
778  /* Mark portal not active */
779  portal->status = PORTAL_READY;
780 
781  /*
782  * Since it's a forward fetch, say DONE iff atEnd is now true.
783  */
784  result = portal->atEnd;
785  break;
786 
787  case PORTAL_MULTI_QUERY:
788  PortalRunMulti(portal, isTopLevel, false,
789  dest, altdest, completionTag);
790 
791  /* Prevent portal's commands from being re-executed */
792  MarkPortalDone(portal);
793 
794  /* Always complete at end of RunMulti */
795  result = true;
796  break;
797 
798  default:
799  elog(ERROR, "unrecognized portal strategy: %d",
800  (int) portal->strategy);
801  result = false; /* keep compiler quiet */
802  break;
803  }
804  }
805  PG_CATCH();
806  {
807  /* Uncaught error while executing portal: mark it dead */
808  MarkPortalFailed(portal);
809 
810  /* Restore global vars and propagate error */
811  if (saveMemoryContext == saveTopTransactionContext)
813  else
814  MemoryContextSwitchTo(saveMemoryContext);
815  ActivePortal = saveActivePortal;
816  if (saveResourceOwner == saveTopTransactionResourceOwner)
818  else
819  CurrentResourceOwner = saveResourceOwner;
820  PortalContext = savePortalContext;
821 
822  PG_RE_THROW();
823  }
824  PG_END_TRY();
825 
826  if (saveMemoryContext == saveTopTransactionContext)
828  else
829  MemoryContextSwitchTo(saveMemoryContext);
830  ActivePortal = saveActivePortal;
831  if (saveResourceOwner == saveTopTransactionResourceOwner)
833  else
834  CurrentResourceOwner = saveResourceOwner;
835  PortalContext = savePortalContext;
836 
838  ShowUsage("EXECUTOR STATISTICS");
839 
840  TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
841 
842  return result;
843 }
844 
845 /*
846  * PortalRunSelect
847  * Execute a portal's query in PORTAL_ONE_SELECT mode, and also
848  * when fetching from a completed holdStore in PORTAL_ONE_RETURNING,
849  * PORTAL_ONE_MOD_WITH, and PORTAL_UTIL_SELECT cases.
850  *
851  * This handles simple N-rows-forward-or-backward cases. For more complex
852  * nonsequential access to a portal, see PortalRunFetch.
853  *
854  * count <= 0 is interpreted as a no-op: the destination gets started up
855  * and shut down, but nothing else happens. Also, count == FETCH_ALL is
856  * interpreted as "all rows". (cf FetchStmt.howMany)
857  *
858  * Caller must already have validated the Portal and done appropriate
859  * setup (cf. PortalRun).
860  *
861  * Returns number of rows processed (suitable for use in result tag)
862  */
863 static uint64
865  bool forward,
866  long count,
867  DestReceiver *dest)
868 {
869  QueryDesc *queryDesc;
870  ScanDirection direction;
871  uint64 nprocessed;
872 
873  /*
874  * NB: queryDesc will be NULL if we are fetching from a held cursor or a
875  * completed utility query; can't use it in that path.
876  */
877  queryDesc = PortalGetQueryDesc(portal);
878 
879  /* Caller messed up if we have neither a ready query nor held data. */
880  Assert(queryDesc || portal->holdStore);
881 
882  /*
883  * Force the queryDesc destination to the right thing. This supports
884  * MOVE, for example, which will pass in dest = DestNone. This is okay to
885  * change as long as we do it on every fetch. (The Executor must not
886  * assume that dest never changes.)
887  */
888  if (queryDesc)
889  queryDesc->dest = dest;
890 
891  /*
892  * Determine which direction to go in, and check to see if we're already
893  * at the end of the available tuples in that direction. If so, set the
894  * direction to NoMovement to avoid trying to fetch any tuples. (This
895  * check exists because not all plan node types are robust about being
896  * called again if they've already returned NULL once.) Then call the
897  * executor (we must not skip this, because the destination needs to see a
898  * setup and shutdown even if no tuples are available). Finally, update
899  * the portal position state depending on the number of tuples that were
900  * retrieved.
901  */
902  if (forward)
903  {
904  if (portal->atEnd || count <= 0)
905  {
906  direction = NoMovementScanDirection;
907  count = 0; /* don't pass negative count to executor */
908  }
909  else
910  direction = ForwardScanDirection;
911 
912  /* In the executor, zero count processes all rows */
913  if (count == FETCH_ALL)
914  count = 0;
915 
916  if (portal->holdStore)
917  nprocessed = RunFromStore(portal, direction, (uint64) count, dest);
918  else
919  {
920  PushActiveSnapshot(queryDesc->snapshot);
921  ExecutorRun(queryDesc, direction, (uint64) count);
922  nprocessed = queryDesc->estate->es_processed;
924  }
925 
926  if (!ScanDirectionIsNoMovement(direction))
927  {
928  if (nprocessed > 0)
929  portal->atStart = false; /* OK to go backward now */
930  if (count == 0 || nprocessed < (uint64) count)
931  portal->atEnd = true; /* we retrieved 'em all */
932  portal->portalPos += nprocessed;
933  }
934  }
935  else
936  {
937  if (portal->cursorOptions & CURSOR_OPT_NO_SCROLL)
938  ereport(ERROR,
939  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
940  errmsg("cursor can only scan forward"),
941  errhint("Declare it with SCROLL option to enable backward scan.")));
942 
943  if (portal->atStart || count <= 0)
944  {
945  direction = NoMovementScanDirection;
946  count = 0; /* don't pass negative count to executor */
947  }
948  else
949  direction = BackwardScanDirection;
950 
951  /* In the executor, zero count processes all rows */
952  if (count == FETCH_ALL)
953  count = 0;
954 
955  if (portal->holdStore)
956  nprocessed = RunFromStore(portal, direction, (uint64) count, dest);
957  else
958  {
959  PushActiveSnapshot(queryDesc->snapshot);
960  ExecutorRun(queryDesc, direction, (uint64) count);
961  nprocessed = queryDesc->estate->es_processed;
963  }
964 
965  if (!ScanDirectionIsNoMovement(direction))
966  {
967  if (nprocessed > 0 && portal->atEnd)
968  {
969  portal->atEnd = false; /* OK to go forward now */
970  portal->portalPos++; /* adjust for endpoint case */
971  }
972  if (count == 0 || nprocessed < (uint64) count)
973  {
974  portal->atStart = true; /* we retrieved 'em all */
975  portal->portalPos = 0;
976  }
977  else
978  {
979  portal->portalPos -= nprocessed;
980  }
981  }
982  }
983 
984  return nprocessed;
985 }
986 
987 /*
988  * FillPortalStore
989  * Run the query and load result tuples into the portal's tuple store.
990  *
991  * This is used for PORTAL_ONE_RETURNING, PORTAL_ONE_MOD_WITH, and
992  * PORTAL_UTIL_SELECT cases only.
993  */
994 static void
995 FillPortalStore(Portal portal, bool isTopLevel)
996 {
997  DestReceiver *treceiver;
998  char completionTag[COMPLETION_TAG_BUFSIZE];
999 
1000  PortalCreateHoldStore(portal);
1001  treceiver = CreateDestReceiver(DestTuplestore);
1003  portal->holdStore,
1004  portal->holdContext,
1005  false);
1006 
1007  completionTag[0] = '\0';
1008 
1009  switch (portal->strategy)
1010  {
1011  case PORTAL_ONE_RETURNING:
1012  case PORTAL_ONE_MOD_WITH:
1013 
1014  /*
1015  * Run the portal to completion just as for the default
1016  * MULTI_QUERY case, but send the primary query's output to the
1017  * tuplestore. Auxiliary query outputs are discarded. Set the
1018  * portal's holdSnapshot to the snapshot used (or a copy of it).
1019  */
1020  PortalRunMulti(portal, isTopLevel, true,
1021  treceiver, None_Receiver, completionTag);
1022  break;
1023 
1024  case PORTAL_UTIL_SELECT:
1025  PortalRunUtility(portal, castNode(PlannedStmt, linitial(portal->stmts)),
1026  isTopLevel, true, treceiver, completionTag);
1027  break;
1028 
1029  default:
1030  elog(ERROR, "unsupported portal strategy: %d",
1031  (int) portal->strategy);
1032  break;
1033  }
1034 
1035  /* Override default completion tag with actual command result */
1036  if (completionTag[0] != '\0')
1037  portal->commandTag = pstrdup(completionTag);
1038 
1039  (*treceiver->rDestroy) (treceiver);
1040 }
1041 
1042 /*
1043  * RunFromStore
1044  * Fetch tuples from the portal's tuple store.
1045  *
1046  * Calling conventions are similar to ExecutorRun, except that we
1047  * do not depend on having a queryDesc or estate. Therefore we return the
1048  * number of tuples processed as the result, not in estate->es_processed.
1049  *
1050  * One difference from ExecutorRun is that the destination receiver functions
1051  * are run in the caller's memory context (since we have no estate). Watch
1052  * out for memory leaks.
1053  */
1054 static uint64
1055 RunFromStore(Portal portal, ScanDirection direction, uint64 count,
1056  DestReceiver *dest)
1057 {
1058  uint64 current_tuple_count = 0;
1059  TupleTableSlot *slot;
1060 
1061  slot = MakeSingleTupleTableSlot(portal->tupDesc);
1062 
1063  (*dest->rStartup) (dest, CMD_SELECT, portal->tupDesc);
1064 
1065  if (ScanDirectionIsNoMovement(direction))
1066  {
1067  /* do nothing except start/stop the destination */
1068  }
1069  else
1070  {
1071  bool forward = ScanDirectionIsForward(direction);
1072 
1073  for (;;)
1074  {
1075  MemoryContext oldcontext;
1076  bool ok;
1077 
1078  oldcontext = MemoryContextSwitchTo(portal->holdContext);
1079 
1080  ok = tuplestore_gettupleslot(portal->holdStore, forward, false,
1081  slot);
1082 
1083  MemoryContextSwitchTo(oldcontext);
1084 
1085  if (!ok)
1086  break;
1087 
1088  /*
1089  * If we are not able to send the tuple, we assume the destination
1090  * has closed and no more tuples can be sent. If that's the case,
1091  * end the loop.
1092  */
1093  if (!((*dest->receiveSlot) (slot, dest)))
1094  break;
1095 
1096  ExecClearTuple(slot);
1097 
1098  /*
1099  * check our tuple count.. if we've processed the proper number
1100  * then quit, else loop again and process more tuples. Zero count
1101  * means no limit.
1102  */
1103  current_tuple_count++;
1104  if (count && count == current_tuple_count)
1105  break;
1106  }
1107  }
1108 
1109  (*dest->rShutdown) (dest);
1110 
1112 
1113  return current_tuple_count;
1114 }
1115 
1116 /*
1117  * PortalRunUtility
1118  * Execute a utility statement inside a portal.
1119  */
1120 static void
1122  bool isTopLevel, bool setHoldSnapshot,
1123  DestReceiver *dest, char *completionTag)
1124 {
1125  Node *utilityStmt = pstmt->utilityStmt;
1126  Snapshot snapshot;
1127 
1128  /*
1129  * Set snapshot if utility stmt needs one. Most reliable way to do this
1130  * seems to be to enumerate those that do not need one; this is a short
1131  * list. Transaction control, LOCK, and SET must *not* set a snapshot
1132  * since they need to be executable at the start of a transaction-snapshot
1133  * mode transaction without freezing a snapshot. By extension we allow
1134  * SHOW not to set a snapshot. The other stmts listed are just efficiency
1135  * hacks. Beware of listing anything that can modify the database --- if,
1136  * say, it has to update an index with expressions that invoke
1137  * user-defined functions, then it had better have a snapshot.
1138  */
1139  if (!(IsA(utilityStmt, TransactionStmt) ||
1140  IsA(utilityStmt, LockStmt) ||
1141  IsA(utilityStmt, VariableSetStmt) ||
1142  IsA(utilityStmt, VariableShowStmt) ||
1143  IsA(utilityStmt, ConstraintsSetStmt) ||
1144  /* efficiency hacks from here down */
1145  IsA(utilityStmt, FetchStmt) ||
1146  IsA(utilityStmt, ListenStmt) ||
1147  IsA(utilityStmt, NotifyStmt) ||
1148  IsA(utilityStmt, UnlistenStmt) ||
1149  IsA(utilityStmt, CheckPointStmt)))
1150  {
1151  snapshot = GetTransactionSnapshot();
1152  /* If told to, register the snapshot we're using and save in portal */
1153  if (setHoldSnapshot)
1154  {
1155  snapshot = RegisterSnapshot(snapshot);
1156  portal->holdSnapshot = snapshot;
1157  }
1158  PushActiveSnapshot(snapshot);
1159  /* PushActiveSnapshot might have copied the snapshot */
1160  snapshot = GetActiveSnapshot();
1161  }
1162  else
1163  snapshot = NULL;
1164 
1165  ProcessUtility(pstmt,
1166  portal->sourceText,
1168  portal->portalParams,
1169  dest,
1170  completionTag);
1171 
1172  /* Some utility statements may change context on us */
1174 
1175  /*
1176  * Some utility commands may pop the ActiveSnapshot stack from under us,
1177  * so be careful to only pop the stack if our snapshot is still at the
1178  * top.
1179  */
1180  if (snapshot != NULL && ActiveSnapshotSet() &&
1181  snapshot == GetActiveSnapshot())
1183 }
1184 
1185 /*
1186  * PortalRunMulti
1187  * Execute a portal's queries in the general case (multi queries
1188  * or non-SELECT-like queries)
1189  */
1190 static void
1192  bool isTopLevel, bool setHoldSnapshot,
1193  DestReceiver *dest, DestReceiver *altdest,
1194  char *completionTag)
1195 {
1196  bool active_snapshot_set = false;
1197  ListCell *stmtlist_item;
1198 
1199  /*
1200  * If the destination is DestRemoteExecute, change to DestNone. The
1201  * reason is that the client won't be expecting any tuples, and indeed has
1202  * no way to know what they are, since there is no provision for Describe
1203  * to send a RowDescription message when this portal execution strategy is
1204  * in effect. This presently will only affect SELECT commands added to
1205  * non-SELECT queries by rewrite rules: such commands will be executed,
1206  * but the results will be discarded unless you use "simple Query"
1207  * protocol.
1208  */
1209  if (dest->mydest == DestRemoteExecute)
1210  dest = None_Receiver;
1211  if (altdest->mydest == DestRemoteExecute)
1212  altdest = None_Receiver;
1213 
1214  /*
1215  * Loop to handle the individual queries generated from a single parsetree
1216  * by analysis and rewrite.
1217  */
1218  foreach(stmtlist_item, portal->stmts)
1219  {
1220  PlannedStmt *pstmt = castNode(PlannedStmt, lfirst(stmtlist_item));
1221 
1222  /*
1223  * If we got a cancel signal in prior command, quit
1224  */
1226 
1227  if (pstmt->utilityStmt == NULL)
1228  {
1229  /*
1230  * process a plannable query.
1231  */
1232  TRACE_POSTGRESQL_QUERY_EXECUTE_START();
1233 
1234  if (log_executor_stats)
1235  ResetUsage();
1236 
1237  /*
1238  * Must always have a snapshot for plannable queries. First time
1239  * through, take a new snapshot; for subsequent queries in the
1240  * same portal, just update the snapshot's copy of the command
1241  * counter.
1242  */
1243  if (!active_snapshot_set)
1244  {
1245  Snapshot snapshot = GetTransactionSnapshot();
1246 
1247  /* If told to, register the snapshot and save in portal */
1248  if (setHoldSnapshot)
1249  {
1250  snapshot = RegisterSnapshot(snapshot);
1251  portal->holdSnapshot = snapshot;
1252  }
1253 
1254  /*
1255  * We can't have the holdSnapshot also be the active one,
1256  * because UpdateActiveSnapshotCommandId would complain. So
1257  * force an extra snapshot copy. Plain PushActiveSnapshot
1258  * would have copied the transaction snapshot anyway, so this
1259  * only adds a copy step when setHoldSnapshot is true. (It's
1260  * okay for the command ID of the active snapshot to diverge
1261  * from what holdSnapshot has.)
1262  */
1263  PushCopiedSnapshot(snapshot);
1264  active_snapshot_set = true;
1265  }
1266  else
1268 
1269  if (pstmt->canSetTag)
1270  {
1271  /* statement can set tag string */
1272  ProcessQuery(pstmt,
1273  portal->sourceText,
1274  portal->portalParams,
1275  dest, completionTag);
1276  }
1277  else
1278  {
1279  /* stmt added by rewrite cannot set tag */
1280  ProcessQuery(pstmt,
1281  portal->sourceText,
1282  portal->portalParams,
1283  altdest, NULL);
1284  }
1285 
1286  if (log_executor_stats)
1287  ShowUsage("EXECUTOR STATISTICS");
1288 
1289  TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
1290  }
1291  else
1292  {
1293  /*
1294  * process utility functions (create, destroy, etc..)
1295  *
1296  * We must not set a snapshot here for utility commands (if one is
1297  * needed, PortalRunUtility will do it). If a utility command is
1298  * alone in a portal then everything's fine. The only case where
1299  * a utility command can be part of a longer list is that rules
1300  * are allowed to include NotifyStmt. NotifyStmt doesn't care
1301  * whether it has a snapshot or not, so we just leave the current
1302  * snapshot alone if we have one.
1303  */
1304  if (pstmt->canSetTag)
1305  {
1306  Assert(!active_snapshot_set);
1307  /* statement can set tag string */
1308  PortalRunUtility(portal, pstmt, isTopLevel, false,
1309  dest, completionTag);
1310  }
1311  else
1312  {
1313  Assert(IsA(pstmt->utilityStmt, NotifyStmt));
1314  /* stmt added by rewrite cannot set tag */
1315  PortalRunUtility(portal, pstmt, isTopLevel, false,
1316  altdest, NULL);
1317  }
1318  }
1319 
1320  /*
1321  * Increment command counter between queries, but not after the last
1322  * one.
1323  */
1324  if (lnext(stmtlist_item) != NULL)
1326 
1327  /*
1328  * Clear subsidiary contexts to recover temporary memory.
1329  */
1331 
1333  }
1334 
1335  /* Pop the snapshot if we pushed one. */
1336  if (active_snapshot_set)
1338 
1339  /*
1340  * If a command completion tag was supplied, use it. Otherwise use the
1341  * portal's commandTag as the default completion tag.
1342  *
1343  * Exception: Clients expect INSERT/UPDATE/DELETE tags to have counts, so
1344  * fake them with zeros. This can happen with DO INSTEAD rules if there
1345  * is no replacement query of the same type as the original. We print "0
1346  * 0" here because technically there is no query of the matching tag type,
1347  * and printing a non-zero count for a different query type seems wrong,
1348  * e.g. an INSERT that does an UPDATE instead should not print "0 1" if
1349  * one row was updated. See QueryRewrite(), step 3, for details.
1350  */
1351  if (completionTag && completionTag[0] == '\0')
1352  {
1353  if (portal->commandTag)
1354  strcpy(completionTag, portal->commandTag);
1355  if (strcmp(completionTag, "SELECT") == 0)
1356  sprintf(completionTag, "SELECT 0 0");
1357  else if (strcmp(completionTag, "INSERT") == 0)
1358  strcpy(completionTag, "INSERT 0 0");
1359  else if (strcmp(completionTag, "UPDATE") == 0)
1360  strcpy(completionTag, "UPDATE 0");
1361  else if (strcmp(completionTag, "DELETE") == 0)
1362  strcpy(completionTag, "DELETE 0");
1363  }
1364 }
1365 
1366 /*
1367  * PortalRunFetch
1368  * Variant form of PortalRun that supports SQL FETCH directions.
1369  *
1370  * Note: we presently assume that no callers of this want isTopLevel = true.
1371  *
1372  * count <= 0 is interpreted as a no-op: the destination gets started up
1373  * and shut down, but nothing else happens. Also, count == FETCH_ALL is
1374  * interpreted as "all rows". (cf FetchStmt.howMany)
1375  *
1376  * Returns number of rows processed (suitable for use in result tag)
1377  */
1378 uint64
1380  FetchDirection fdirection,
1381  long count,
1382  DestReceiver *dest)
1383 {
1384  uint64 result;
1385  Portal saveActivePortal;
1386  ResourceOwner saveResourceOwner;
1387  MemoryContext savePortalContext;
1388  MemoryContext oldContext;
1389 
1390  AssertArg(PortalIsValid(portal));
1391 
1392  /*
1393  * Check for improper portal use, and mark portal active.
1394  */
1395  MarkPortalActive(portal);
1396 
1397  /*
1398  * Set up global portal context pointers.
1399  */
1400  saveActivePortal = ActivePortal;
1401  saveResourceOwner = CurrentResourceOwner;
1402  savePortalContext = PortalContext;
1403  PG_TRY();
1404  {
1405  ActivePortal = portal;
1406  if (portal->resowner)
1407  CurrentResourceOwner = portal->resowner;
1409 
1410  oldContext = MemoryContextSwitchTo(PortalContext);
1411 
1412  switch (portal->strategy)
1413  {
1414  case PORTAL_ONE_SELECT:
1415  result = DoPortalRunFetch(portal, fdirection, count, dest);
1416  break;
1417 
1418  case PORTAL_ONE_RETURNING:
1419  case PORTAL_ONE_MOD_WITH:
1420  case PORTAL_UTIL_SELECT:
1421 
1422  /*
1423  * If we have not yet run the command, do so, storing its
1424  * results in the portal's tuplestore.
1425  */
1426  if (!portal->holdStore)
1427  FillPortalStore(portal, false /* isTopLevel */ );
1428 
1429  /*
1430  * Now fetch desired portion of results.
1431  */
1432  result = DoPortalRunFetch(portal, fdirection, count, dest);
1433  break;
1434 
1435  default:
1436  elog(ERROR, "unsupported portal strategy");
1437  result = 0; /* keep compiler quiet */
1438  break;
1439  }
1440  }
1441  PG_CATCH();
1442  {
1443  /* Uncaught error while executing portal: mark it dead */
1444  MarkPortalFailed(portal);
1445 
1446  /* Restore global vars and propagate error */
1447  ActivePortal = saveActivePortal;
1448  CurrentResourceOwner = saveResourceOwner;
1449  PortalContext = savePortalContext;
1450 
1451  PG_RE_THROW();
1452  }
1453  PG_END_TRY();
1454 
1455  MemoryContextSwitchTo(oldContext);
1456 
1457  /* Mark portal not active */
1458  portal->status = PORTAL_READY;
1459 
1460  ActivePortal = saveActivePortal;
1461  CurrentResourceOwner = saveResourceOwner;
1462  PortalContext = savePortalContext;
1463 
1464  return result;
1465 }
1466 
1467 /*
1468  * DoPortalRunFetch
1469  * Guts of PortalRunFetch --- the portal context is already set up
1470  *
1471  * count <= 0 is interpreted as a no-op: the destination gets started up
1472  * and shut down, but nothing else happens. Also, count == FETCH_ALL is
1473  * interpreted as "all rows". (cf FetchStmt.howMany)
1474  *
1475  * Returns number of rows processed (suitable for use in result tag)
1476  */
1477 static uint64
1479  FetchDirection fdirection,
1480  long count,
1481  DestReceiver *dest)
1482 {
1483  bool forward;
1484 
1485  Assert(portal->strategy == PORTAL_ONE_SELECT ||
1486  portal->strategy == PORTAL_ONE_RETURNING ||
1487  portal->strategy == PORTAL_ONE_MOD_WITH ||
1488  portal->strategy == PORTAL_UTIL_SELECT);
1489 
1490  switch (fdirection)
1491  {
1492  case FETCH_FORWARD:
1493  if (count < 0)
1494  {
1495  fdirection = FETCH_BACKWARD;
1496  count = -count;
1497  }
1498  /* fall out of switch to share code with FETCH_BACKWARD */
1499  break;
1500  case FETCH_BACKWARD:
1501  if (count < 0)
1502  {
1503  fdirection = FETCH_FORWARD;
1504  count = -count;
1505  }
1506  /* fall out of switch to share code with FETCH_FORWARD */
1507  break;
1508  case FETCH_ABSOLUTE:
1509  if (count > 0)
1510  {
1511  /*
1512  * Definition: Rewind to start, advance count-1 rows, return
1513  * next row (if any).
1514  *
1515  * In practice, if the goal is less than halfway back to the
1516  * start, it's better to scan from where we are.
1517  *
1518  * Also, if current portalPos is outside the range of "long",
1519  * do it the hard way to avoid possible overflow of the count
1520  * argument to PortalRunSelect. We must exclude exactly
1521  * LONG_MAX, as well, lest the count look like FETCH_ALL.
1522  *
1523  * In any case, we arrange to fetch the target row going
1524  * forwards.
1525  */
1526  if ((uint64) (count - 1) <= portal->portalPos / 2 ||
1527  portal->portalPos >= (uint64) LONG_MAX)
1528  {
1529  DoPortalRewind(portal);
1530  if (count > 1)
1531  PortalRunSelect(portal, true, count - 1,
1532  None_Receiver);
1533  }
1534  else
1535  {
1536  long pos = (long) portal->portalPos;
1537 
1538  if (portal->atEnd)
1539  pos++; /* need one extra fetch if off end */
1540  if (count <= pos)
1541  PortalRunSelect(portal, false, pos - count + 1,
1542  None_Receiver);
1543  else if (count > pos + 1)
1544  PortalRunSelect(portal, true, count - pos - 1,
1545  None_Receiver);
1546  }
1547  return PortalRunSelect(portal, true, 1L, dest);
1548  }
1549  else if (count < 0)
1550  {
1551  /*
1552  * Definition: Advance to end, back up abs(count)-1 rows,
1553  * return prior row (if any). We could optimize this if we
1554  * knew in advance where the end was, but typically we won't.
1555  * (Is it worth considering case where count > half of size of
1556  * query? We could rewind once we know the size ...)
1557  */
1558  PortalRunSelect(portal, true, FETCH_ALL, None_Receiver);
1559  if (count < -1)
1560  PortalRunSelect(portal, false, -count - 1, None_Receiver);
1561  return PortalRunSelect(portal, false, 1L, dest);
1562  }
1563  else
1564  {
1565  /* count == 0 */
1566  /* Rewind to start, return zero rows */
1567  DoPortalRewind(portal);
1568  return PortalRunSelect(portal, true, 0L, dest);
1569  }
1570  break;
1571  case FETCH_RELATIVE:
1572  if (count > 0)
1573  {
1574  /*
1575  * Definition: advance count-1 rows, return next row (if any).
1576  */
1577  if (count > 1)
1578  PortalRunSelect(portal, true, count - 1, None_Receiver);
1579  return PortalRunSelect(portal, true, 1L, dest);
1580  }
1581  else if (count < 0)
1582  {
1583  /*
1584  * Definition: back up abs(count)-1 rows, return prior row (if
1585  * any).
1586  */
1587  if (count < -1)
1588  PortalRunSelect(portal, false, -count - 1, None_Receiver);
1589  return PortalRunSelect(portal, false, 1L, dest);
1590  }
1591  else
1592  {
1593  /* count == 0 */
1594  /* Same as FETCH FORWARD 0, so fall out of switch */
1595  fdirection = FETCH_FORWARD;
1596  }
1597  break;
1598  default:
1599  elog(ERROR, "bogus direction");
1600  break;
1601  }
1602 
1603  /*
1604  * Get here with fdirection == FETCH_FORWARD or FETCH_BACKWARD, and count
1605  * >= 0.
1606  */
1607  forward = (fdirection == FETCH_FORWARD);
1608 
1609  /*
1610  * Zero count means to re-fetch the current row, if any (per SQL)
1611  */
1612  if (count == 0)
1613  {
1614  bool on_row;
1615 
1616  /* Are we sitting on a row? */
1617  on_row = (!portal->atStart && !portal->atEnd);
1618 
1619  if (dest->mydest == DestNone)
1620  {
1621  /* MOVE 0 returns 0/1 based on if FETCH 0 would return a row */
1622  return on_row ? 1 : 0;
1623  }
1624  else
1625  {
1626  /*
1627  * If we are sitting on a row, back up one so we can re-fetch it.
1628  * If we are not sitting on a row, we still have to start up and
1629  * shut down the executor so that the destination is initialized
1630  * and shut down correctly; so keep going. To PortalRunSelect,
1631  * count == 0 means we will retrieve no row.
1632  */
1633  if (on_row)
1634  {
1635  PortalRunSelect(portal, false, 1L, None_Receiver);
1636  /* Set up to fetch one row forward */
1637  count = 1;
1638  forward = true;
1639  }
1640  }
1641  }
1642 
1643  /*
1644  * Optimize MOVE BACKWARD ALL into a Rewind.
1645  */
1646  if (!forward && count == FETCH_ALL && dest->mydest == DestNone)
1647  {
1648  uint64 result = portal->portalPos;
1649 
1650  if (result > 0 && !portal->atEnd)
1651  result--;
1652  DoPortalRewind(portal);
1653  return result;
1654  }
1655 
1656  return PortalRunSelect(portal, forward, count, dest);
1657 }
1658 
1659 /*
1660  * DoPortalRewind - rewind a Portal to starting point
1661  */
1662 static void
1664 {
1665  QueryDesc *queryDesc;
1666 
1667  /* Rewind holdStore, if we have one */
1668  if (portal->holdStore)
1669  {
1670  MemoryContext oldcontext;
1671 
1672  oldcontext = MemoryContextSwitchTo(portal->holdContext);
1673  tuplestore_rescan(portal->holdStore);
1674  MemoryContextSwitchTo(oldcontext);
1675  }
1676 
1677  /* Rewind executor, if active */
1678  queryDesc = PortalGetQueryDesc(portal);
1679  if (queryDesc)
1680  {
1681  PushActiveSnapshot(queryDesc->snapshot);
1682  ExecutorRewind(queryDesc);
1684  }
1685 
1686  portal->atStart = true;
1687  portal->atEnd = false;
1688  portal->portalPos = 0;
1689 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1216
signed short int16
Definition: c.h:252
#define NIL
Definition: pg_list.h:69
static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count, DestReceiver *dest)
Definition: pquery.c:1055
void(* rShutdown)(DestReceiver *self)
Definition: dest.h:124
void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: dest.h:121
void(* rDestroy)(DestReceiver *self)
Definition: dest.h:126
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:776
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
int errhint(const char *fmt,...)
Definition: elog.c:987
void PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
Definition: pquery.c:620
#define AssertState(condition)
Definition: c.h:674
bool atEnd
Definition: portal.h:185
FetchDirection
Definition: parsenodes.h:2553
EState * estate
Definition: execdesc.h:47
MemoryContext TopTransactionContext
Definition: mcxt.c:48
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:439
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:858
#define DEBUG3
Definition: elog.h:23
Oid es_lastoid
Definition: execnodes.h:404
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:100
Portal ActivePortal
Definition: pquery.c:35
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:140
void ShowUsage(const char *title)
Definition: postgres.c:4383
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
CommandDest mydest
Definition: dest.h:128
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
char * pstrdup(const char *in)
Definition: mcxt.c:1165
void MarkPortalActive(Portal portal)
Definition: portalmem.c:388
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1379
void SetTuplestoreDestReceiverParams(DestReceiver *self, Tuplestorestate *tStore, MemoryContext tContext, bool detoast)
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:138
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
Definition: nodes.h:508
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:285
int errcode(int sqlerrcode)
Definition: elog.c:575
MemoryContext holdContext
Definition: portal.h:163
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, int instrument_options)
Definition: pquery.c:66
unsigned int Oid
Definition: postgres_ext.h:31
Node * utilityStmt
Definition: parsenodes.h:111
List * stmts
Definition: portal.h:136
#define ScanDirectionIsNoMovement(direction)
Definition: sdir.h:48
DestReceiver * None_Receiver
Definition: dest.c:91
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
int natts
Definition: tupdesc.h:73
static uint64 PortalRunSelect(Portal portal, bool forward, long count, DestReceiver *dest)
Definition: pquery.c:864
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2521
static uint64 DoPortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1478
struct Plan * planTree
Definition: plannodes.h:61
List * targetList
Definition: parsenodes.h:131
Snapshot snapshot
Definition: execdesc.h:39
int instrument_options
Definition: execdesc.h:43
MemoryContext PortalContext
Definition: mcxt.c:52
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:439
void ResetUsage(void)
Definition: postgres.c:4376
void pfree(void *pointer)
Definition: mcxt.c:992
ParamListInfo portalParams
Definition: portal.h:139
PlannedStmt * PortalGetPrimaryStmt(Portal portal)
Definition: portalmem.c:150
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
PlanState * planstate
Definition: execdesc.h:48
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:354
static void FillPortalStore(Portal portal, bool isTopLevel)
Definition: pquery.c:995
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:764
const char * commandTag
Definition: portal.h:135
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
void MarkPortalDone(Portal portal)
Definition: portalmem.c:407
static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, char *completionTag)
Definition: pquery.c:1121
Definition: dest.h:88
PortalStrategy
Definition: portal.h:88
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
Definition: execTuples.c:216
bool hasReturning
Definition: plannodes.h:49
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
ScanDirection
Definition: sdir.h:22
ParamListInfo params
Definition: execdesc.h:42
Node * utilityStmt
Definition: plannodes.h:80
bool UtilityReturnsTuples(Node *parsetree)
Definition: utility.c:1694
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:846
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
PortalStrategy strategy
Definition: portal.h:142
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc)
Definition: execTuples.c:199
List * returningList
Definition: parsenodes.h:135
char * portalname
Definition: parsenodes.h:2570
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define lnext(lc)
Definition: pg_list.h:105
#define ereport(elevel, rest)
Definition: elog.h:122
#define AssertArg(condition)
Definition: c.h:673
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:379
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:900
QueryDesc * queryDesc
Definition: portal.h:150
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, DestReceiver *dest, char *completionTag)
Definition: utility.c:332
TupleDesc tupDesc
Definition: execdesc.h:46
CmdType operation
Definition: execdesc.h:36
#define InvalidSnapshot
Definition: snapshot.h:25
void MemoryContextDeleteChildren(MemoryContext context)
Definition: mcxt.c:236
#define PortalIsValid(p)
Definition: portal.h:197
void ExecutorRewind(QueryDesc *queryDesc)
Definition: execMain.c:505
bool canSetTag
Definition: plannodes.h:53
bool ismove
Definition: parsenodes.h:2571
int16 * formats
Definition: portal.h:155
void CommandCounterIncrement(void)
Definition: xact.c:921
CmdType commandType
Definition: plannodes.h:45
Snapshot crosscheck_snapshot
Definition: execdesc.h:40
const char * sourceText
Definition: portal.h:134
TupleDesc tupDesc
Definition: portal.h:153
#define InvalidOid
Definition: postgres_ext.h:36
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:549
CmdType commandType
Definition: parsenodes.h:103
#define PG_CATCH()
Definition: elog.h:293
struct Instrumentation * totaltime
Definition: execdesc.h:51
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1061
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
#define NULL
Definition: c.h:226
bool PortalRun(Portal portal, long count, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
Definition: pquery.c:682
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
bool hasModifyingCTE
Definition: plannodes.h:51
static void PortalRunMulti(Portal portal, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
Definition: pquery.c:1191
uint64 es_processed
Definition: execnodes.h:403
bool canSetTag
Definition: parsenodes.h:109
static int list_length(const List *l)
Definition: pg_list.h:89
#define PortalGetHeapMemory(portal)
Definition: portal.h:203
Snapshot holdSnapshot
Definition: portal.h:173
void MarkPortalFailed(Portal portal)
Definition: portalmem.c:435
PortalStatus status
Definition: portal.h:146
#define PG_RE_THROW()
Definition: elog.h:314
void PortalCreateHoldStore(Portal portal)
Definition: portalmem.c:324
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:215
#define nodeTag(nodeptr)
Definition: nodes.h:513
List * targetlist
Definition: plannodes.h:129
#define PortalGetQueryDesc(portal)
Definition: portal.h:202
const char * sourceText
Definition: execdesc.h:38
DestReceiver * dest
Definition: execdesc.h:41
ResourceOwner resowner
Definition: portal.h:120
bool atStart
Definition: portal.h:184
void * palloc(Size size)
Definition: mcxt.c:891
Tuplestorestate * holdStore
Definition: portal.h:162
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2520
bool log_executor_stats
Definition: guc.c:442
char * name
Definition: parsenodes.h:3180
bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)
Definition: dest.h:118
bool hasModifyingCTE
Definition: parsenodes.h:122
TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:900
static void ProcessQuery(PlannedStmt *plan, const char *sourceText, ParamListInfo params, DestReceiver *dest, char *completionTag)
Definition: pquery.c:132
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
#define elog
Definition: elog.h:219
int cursorOptions
Definition: portal.h:143
PlannedStmt * plannedstmt
Definition: execdesc.h:37
static void DoPortalRewind(Portal portal)
Definition: pquery.c:1663
List * FetchPortalTargetList(Portal portal)
Definition: pquery.c:332
#define PG_TRY()
Definition: elog.h:284
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:494
Definition: pg_list.h:45
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:1744
#define UINT64_FORMAT
Definition: c.h:313
#define PG_END_TRY()
Definition: elog.h:300
uint64 portalPos
Definition: portal.h:186
#define FETCH_ALL
Definition: parsenodes.h:2563