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