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