PostgreSQL Source Code  git master
spi.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * spi.c
4  * Server Programming Interface
5  *
6  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/executor/spi.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/htup_details.h"
18 #include "access/printtup.h"
19 #include "access/sysattr.h"
20 #include "access/xact.h"
21 #include "catalog/heap.h"
22 #include "catalog/pg_type.h"
23 #include "commands/trigger.h"
24 #include "executor/executor.h"
25 #include "executor/spi_priv.h"
26 #include "miscadmin.h"
27 #include "tcop/pquery.h"
28 #include "tcop/utility.h"
29 #include "utils/builtins.h"
30 #include "utils/datum.h"
31 #include "utils/lsyscache.h"
32 #include "utils/memutils.h"
33 #include "utils/rel.h"
34 #include "utils/snapmgr.h"
35 #include "utils/syscache.h"
36 #include "utils/typcache.h"
37 
38 
39 /*
40  * These global variables are part of the API for various SPI functions
41  * (a horrible API choice, but it's too late now). To reduce the risk of
42  * interference between different SPI callers, we save and restore them
43  * when entering/exiting a SPI nesting level.
44  */
45 uint64 SPI_processed = 0;
47 int SPI_result = 0;
48 
49 static _SPI_connection *_SPI_stack = NULL;
51 static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
52 static int _SPI_connected = -1; /* current stack index */
53 
54 typedef struct SPICallbackArg
55 {
56  const char *query;
59 
60 static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
61  ParamListInfo paramLI, bool read_only);
62 
63 static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan);
64 
65 static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan);
66 
68  Snapshot snapshot, Snapshot crosscheck_snapshot,
69  bool fire_triggers);
70 
71 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
72  Datum *Values, const char *Nulls);
73 
74 static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount);
75 
76 static void _SPI_error_callback(void *arg);
77 
78 static void _SPI_cursor_operation(Portal portal,
79  FetchDirection direction, long count,
81 
84 
85 static int _SPI_begin_call(bool use_exec);
86 static int _SPI_end_call(bool use_exec);
87 static MemoryContext _SPI_execmem(void);
88 static MemoryContext _SPI_procmem(void);
89 static bool _SPI_checktuples(void);
90 
91 
92 /* =================== interface functions =================== */
93 
94 int
96 {
97  return SPI_connect_ext(0);
98 }
99 
100 int
102 {
103  int newdepth;
104 
105  /* Enlarge stack if necessary */
106  if (_SPI_stack == NULL)
107  {
108  if (_SPI_connected != -1 || _SPI_stack_depth != 0)
109  elog(ERROR, "SPI stack corrupted");
110  newdepth = 16;
113  newdepth * sizeof(_SPI_connection));
114  _SPI_stack_depth = newdepth;
115  }
116  else
117  {
119  elog(ERROR, "SPI stack corrupted");
120  if (_SPI_stack_depth == _SPI_connected + 1)
121  {
122  newdepth = _SPI_stack_depth * 2;
125  newdepth * sizeof(_SPI_connection));
126  _SPI_stack_depth = newdepth;
127  }
128  }
129 
130  /* Enter new stack level */
131  _SPI_connected++;
133 
135  _SPI_current->processed = 0;
136  _SPI_current->tuptable = NULL;
139  _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
140  _SPI_current->execCxt = NULL;
142  _SPI_current->queryEnv = NULL;
144  _SPI_current->internal_xact = false;
148 
149  /*
150  * Create memory contexts for this procedure
151  *
152  * In atomic contexts (the normal case), we use TopTransactionContext,
153  * otherwise PortalContext, so that it lives across transaction
154  * boundaries.
155  *
156  * XXX It could be better to use PortalContext as the parent context in
157  * all cases, but we may not be inside a portal (consider deferred-trigger
158  * execution). Perhaps CurTransactionContext could be an option? For now
159  * it doesn't matter because we clean up explicitly in AtEOSubXact_SPI();
160  * but see also AtEOXact_SPI().
161  */
163  "SPI Proc",
166  "SPI Exec",
168  /* ... and switch to procedure's context */
170 
171  /*
172  * Reset API global variables so that current caller cannot accidentally
173  * depend on state of an outer caller.
174  */
175  SPI_processed = 0;
176  SPI_tuptable = NULL;
177  SPI_result = 0;
178 
179  return SPI_OK_CONNECT;
180 }
181 
182 int
184 {
185  int res;
186 
187  res = _SPI_begin_call(false); /* just check we're connected */
188  if (res < 0)
189  return res;
190 
191  /* Restore memory context as it was before procedure call */
193 
194  /* Release memory used in procedure call (including tuptables) */
196  _SPI_current->execCxt = NULL;
198  _SPI_current->procCxt = NULL;
199 
200  /*
201  * Restore outer API variables, especially SPI_tuptable which is probably
202  * pointing at a just-deleted tuptable
203  */
207 
208  /* Exit stack level */
209  _SPI_connected--;
210  if (_SPI_connected < 0)
211  _SPI_current = NULL;
212  else
214 
215  return SPI_OK_FINISH;
216 }
217 
218 /*
219  * SPI_start_transaction is a no-op, kept for backwards compatibility.
220  * SPI callers are *always* inside a transaction.
221  */
222 void
224 {
225 }
226 
227 static void
228 _SPI_commit(bool chain)
229 {
230  MemoryContext oldcontext = CurrentMemoryContext;
232 
233  /*
234  * Complain if we are in a context that doesn't permit transaction
235  * termination. (Note: here and _SPI_rollback should be the only places
236  * that throw ERRCODE_INVALID_TRANSACTION_TERMINATION, so that callers can
237  * test for that with security that they know what happened.)
238  */
239  if (_SPI_current->atomic)
240  ereport(ERROR,
241  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
242  errmsg("invalid transaction termination")));
243 
244  /*
245  * This restriction is required by PLs implemented on top of SPI. They
246  * use subtransactions to establish exception blocks that are supposed to
247  * be rolled back together if there is an error. Terminating the
248  * top-level transaction in such a block violates that idea. A future PL
249  * implementation might have different ideas about this, in which case
250  * this restriction would have to be refined or the check possibly be
251  * moved out of SPI into the PLs. Note however that the code below relies
252  * on not being within a subtransaction.
253  */
254  if (IsSubTransaction())
255  ereport(ERROR,
256  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
257  errmsg("cannot commit while a subtransaction is active")));
258 
259  if (chain)
261 
262  /* Catch any error occurring during the COMMIT */
263  PG_TRY();
264  {
265  /* Protect current SPI stack entry against deletion */
266  _SPI_current->internal_xact = true;
267 
268  /*
269  * Hold any pinned portals that any PLs might be using. We have to do
270  * this before changing transaction state, since this will run
271  * user-defined code that might throw an error.
272  */
274 
275  /* Release snapshots associated with portals */
277 
278  /* Do the deed */
280 
281  /* Immediately start a new transaction */
283  if (chain)
285 
286  MemoryContextSwitchTo(oldcontext);
287 
288  _SPI_current->internal_xact = false;
289  }
290  PG_CATCH();
291  {
292  ErrorData *edata;
293 
294  /* Save error info in caller's context */
295  MemoryContextSwitchTo(oldcontext);
296  edata = CopyErrorData();
297  FlushErrorState();
298 
299  /*
300  * Abort the failed transaction. If this fails too, we'll just
301  * propagate the error out ... there's not that much we can do.
302  */
304 
305  /* ... and start a new one */
307  if (chain)
309 
310  MemoryContextSwitchTo(oldcontext);
311 
312  _SPI_current->internal_xact = false;
313 
314  /* Now that we've cleaned up the transaction, re-throw the error */
315  ReThrowError(edata);
316  }
317  PG_END_TRY();
318 }
319 
320 void
322 {
323  _SPI_commit(false);
324 }
325 
326 void
328 {
329  _SPI_commit(true);
330 }
331 
332 static void
333 _SPI_rollback(bool chain)
334 {
335  MemoryContext oldcontext = CurrentMemoryContext;
337 
338  /* see under SPI_commit() */
339  if (_SPI_current->atomic)
340  ereport(ERROR,
341  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
342  errmsg("invalid transaction termination")));
343 
344  /* see under SPI_commit() */
345  if (IsSubTransaction())
346  ereport(ERROR,
347  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
348  errmsg("cannot roll back while a subtransaction is active")));
349 
350  if (chain)
352 
353  /* Catch any error occurring during the ROLLBACK */
354  PG_TRY();
355  {
356  /* Protect current SPI stack entry against deletion */
357  _SPI_current->internal_xact = true;
358 
359  /*
360  * Hold any pinned portals that any PLs might be using. We have to do
361  * this before changing transaction state, since this will run
362  * user-defined code that might throw an error, and in any case
363  * couldn't be run in an already-aborted transaction.
364  */
366 
367  /* Release snapshots associated with portals */
369 
370  /* Do the deed */
372 
373  /* Immediately start a new transaction */
375  if (chain)
377 
378  MemoryContextSwitchTo(oldcontext);
379 
380  _SPI_current->internal_xact = false;
381  }
382  PG_CATCH();
383  {
384  ErrorData *edata;
385 
386  /* Save error info in caller's context */
387  MemoryContextSwitchTo(oldcontext);
388  edata = CopyErrorData();
389  FlushErrorState();
390 
391  /*
392  * Try again to abort the failed transaction. If this fails too,
393  * we'll just propagate the error out ... there's not that much we can
394  * do.
395  */
397 
398  /* ... and start a new one */
400  if (chain)
402 
403  MemoryContextSwitchTo(oldcontext);
404 
405  _SPI_current->internal_xact = false;
406 
407  /* Now that we've cleaned up the transaction, re-throw the error */
408  ReThrowError(edata);
409  }
410  PG_END_TRY();
411 }
412 
413 void
415 {
416  _SPI_rollback(false);
417 }
418 
419 void
421 {
422  _SPI_rollback(true);
423 }
424 
425 /*
426  * Clean up SPI state at transaction commit or abort.
427  */
428 void
429 AtEOXact_SPI(bool isCommit)
430 {
431  bool found = false;
432 
433  /*
434  * Pop stack entries, stopping if we find one marked internal_xact (that
435  * one belongs to the caller of SPI_commit or SPI_abort).
436  */
437  while (_SPI_connected >= 0)
438  {
440 
441  if (connection->internal_xact)
442  break;
443 
444  found = true;
445 
446  /*
447  * We need not release the procedure's memory contexts explicitly, as
448  * they'll go away automatically when their parent context does; see
449  * notes in SPI_connect_ext.
450  */
451 
452  /*
453  * Restore outer global variables and pop the stack entry. Unlike
454  * SPI_finish(), we don't risk switching to memory contexts that might
455  * be already gone.
456  */
457  SPI_processed = connection->outer_processed;
458  SPI_tuptable = connection->outer_tuptable;
459  SPI_result = connection->outer_result;
460 
461  _SPI_connected--;
462  if (_SPI_connected < 0)
463  _SPI_current = NULL;
464  else
466  }
467 
468  /* We should only find entries to pop during an ABORT. */
469  if (found && isCommit)
471  (errcode(ERRCODE_WARNING),
472  errmsg("transaction left non-empty SPI stack"),
473  errhint("Check for missing \"SPI_finish\" calls.")));
474 }
475 
476 /*
477  * Clean up SPI state at subtransaction commit or abort.
478  *
479  * During commit, there shouldn't be any unclosed entries remaining from
480  * the current subtransaction; we emit a warning if any are found.
481  */
482 void
483 AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
484 {
485  bool found = false;
486 
487  while (_SPI_connected >= 0)
488  {
490 
491  if (connection->connectSubid != mySubid)
492  break; /* couldn't be any underneath it either */
493 
494  if (connection->internal_xact)
495  break;
496 
497  found = true;
498 
499  /*
500  * Release procedure memory explicitly (see note in SPI_connect)
501  */
502  if (connection->execCxt)
503  {
505  connection->execCxt = NULL;
506  }
507  if (connection->procCxt)
508  {
510  connection->procCxt = NULL;
511  }
512 
513  /*
514  * Restore outer global variables and pop the stack entry. Unlike
515  * SPI_finish(), we don't risk switching to memory contexts that might
516  * be already gone.
517  */
518  SPI_processed = connection->outer_processed;
519  SPI_tuptable = connection->outer_tuptable;
520  SPI_result = connection->outer_result;
521 
522  _SPI_connected--;
523  if (_SPI_connected < 0)
524  _SPI_current = NULL;
525  else
527  }
528 
529  if (found && isCommit)
531  (errcode(ERRCODE_WARNING),
532  errmsg("subtransaction left non-empty SPI stack"),
533  errhint("Check for missing \"SPI_finish\" calls.")));
534 
535  /*
536  * If we are aborting a subtransaction and there is an open SPI context
537  * surrounding the subxact, clean up to prevent memory leakage.
538  */
539  if (_SPI_current && !isCommit)
540  {
541  slist_mutable_iter siter;
542 
543  /*
544  * Throw away executor state if current executor operation was started
545  * within current subxact (essentially, force a _SPI_end_call(true)).
546  */
547  if (_SPI_current->execSubid >= mySubid)
548  {
551  }
552 
553  /* throw away any tuple tables created within current subxact */
555  {
556  SPITupleTable *tuptable;
557 
558  tuptable = slist_container(SPITupleTable, next, siter.cur);
559  if (tuptable->subid >= mySubid)
560  {
561  /*
562  * If we used SPI_freetuptable() here, its internal search of
563  * the tuptables list would make this operation O(N^2).
564  * Instead, just free the tuptable manually. This should
565  * match what SPI_freetuptable() does.
566  */
567  slist_delete_current(&siter);
568  if (tuptable == _SPI_current->tuptable)
569  _SPI_current->tuptable = NULL;
570  if (tuptable == SPI_tuptable)
571  SPI_tuptable = NULL;
572  MemoryContextDelete(tuptable->tuptabcxt);
573  }
574  }
575  }
576 }
577 
578 /*
579  * Are we executing inside a procedure (that is, a nonatomic SPI context)?
580  */
581 bool
583 {
584  if (_SPI_current == NULL)
585  return false; /* not in any SPI context at all */
586  if (_SPI_current->atomic)
587  return false; /* it's atomic (ie function not procedure) */
588  return true;
589 }
590 
591 
592 /* Parse, plan, and execute a query string */
593 int
594 SPI_execute(const char *src, bool read_only, long tcount)
595 {
596  _SPI_plan plan;
598  int res;
599 
600  if (src == NULL || tcount < 0)
601  return SPI_ERROR_ARGUMENT;
602 
603  res = _SPI_begin_call(true);
604  if (res < 0)
605  return res;
606 
607  memset(&plan, 0, sizeof(_SPI_plan));
608  plan.magic = _SPI_PLAN_MAGIC;
611 
612  _SPI_prepare_oneshot_plan(src, &plan);
613 
614  memset(&options, 0, sizeof(options));
615  options.read_only = read_only;
616  options.tcount = tcount;
617 
618  res = _SPI_execute_plan(&plan, &options,
620  true);
621 
622  _SPI_end_call(true);
623  return res;
624 }
625 
626 /* Obsolete version of SPI_execute */
627 int
628 SPI_exec(const char *src, long tcount)
629 {
630  return SPI_execute(src, false, tcount);
631 }
632 
633 /* Parse, plan, and execute a query string, with extensible options */
634 int
635 SPI_execute_extended(const char *src,
636  const SPIExecuteOptions *options)
637 {
638  int res;
639  _SPI_plan plan;
640 
641  if (src == NULL || options == NULL)
642  return SPI_ERROR_ARGUMENT;
643 
644  res = _SPI_begin_call(true);
645  if (res < 0)
646  return res;
647 
648  memset(&plan, 0, sizeof(_SPI_plan));
649  plan.magic = _SPI_PLAN_MAGIC;
652  if (options->params)
653  {
654  plan.parserSetup = options->params->parserSetup;
655  plan.parserSetupArg = options->params->parserSetupArg;
656  }
657 
658  _SPI_prepare_oneshot_plan(src, &plan);
659 
660  res = _SPI_execute_plan(&plan, options,
662  true);
663 
664  _SPI_end_call(true);
665  return res;
666 }
667 
668 /* Execute a previously prepared plan */
669 int
670 SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
671  bool read_only, long tcount)
672 {
674  int res;
675 
676  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
677  return SPI_ERROR_ARGUMENT;
678 
679  if (plan->nargs > 0 && Values == NULL)
680  return SPI_ERROR_PARAM;
681 
682  res = _SPI_begin_call(true);
683  if (res < 0)
684  return res;
685 
686  memset(&options, 0, sizeof(options));
687  options.params = _SPI_convert_params(plan->nargs, plan->argtypes,
688  Values, Nulls);
689  options.read_only = read_only;
690  options.tcount = tcount;
691 
692  res = _SPI_execute_plan(plan, &options,
694  true);
695 
696  _SPI_end_call(true);
697  return res;
698 }
699 
700 /* Obsolete version of SPI_execute_plan */
701 int
702 SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
703 {
704  return SPI_execute_plan(plan, Values, Nulls, false, tcount);
705 }
706 
707 /* Execute a previously prepared plan */
708 int
710  const SPIExecuteOptions *options)
711 {
712  int res;
713 
714  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || options == NULL)
715  return SPI_ERROR_ARGUMENT;
716 
717  res = _SPI_begin_call(true);
718  if (res < 0)
719  return res;
720 
721  res = _SPI_execute_plan(plan, options,
723  true);
724 
725  _SPI_end_call(true);
726  return res;
727 }
728 
729 /* Execute a previously prepared plan */
730 int
732  bool read_only, long tcount)
733 {
735  int res;
736 
737  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
738  return SPI_ERROR_ARGUMENT;
739 
740  res = _SPI_begin_call(true);
741  if (res < 0)
742  return res;
743 
744  memset(&options, 0, sizeof(options));
745  options.params = params;
746  options.read_only = read_only;
747  options.tcount = tcount;
748 
749  res = _SPI_execute_plan(plan, &options,
751  true);
752 
753  _SPI_end_call(true);
754  return res;
755 }
756 
757 /*
758  * SPI_execute_snapshot -- identical to SPI_execute_plan, except that we allow
759  * the caller to specify exactly which snapshots to use, which will be
760  * registered here. Also, the caller may specify that AFTER triggers should be
761  * queued as part of the outer query rather than being fired immediately at the
762  * end of the command.
763  *
764  * This is currently not documented in spi.sgml because it is only intended
765  * for use by RI triggers.
766  *
767  * Passing snapshot == InvalidSnapshot will select the normal behavior of
768  * fetching a new snapshot for each query.
769  */
770 int
772  Datum *Values, const char *Nulls,
773  Snapshot snapshot, Snapshot crosscheck_snapshot,
774  bool read_only, bool fire_triggers, long tcount)
775 {
777  int res;
778 
779  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
780  return SPI_ERROR_ARGUMENT;
781 
782  if (plan->nargs > 0 && Values == NULL)
783  return SPI_ERROR_PARAM;
784 
785  res = _SPI_begin_call(true);
786  if (res < 0)
787  return res;
788 
789  memset(&options, 0, sizeof(options));
790  options.params = _SPI_convert_params(plan->nargs, plan->argtypes,
791  Values, Nulls);
792  options.read_only = read_only;
793  options.tcount = tcount;
794 
795  res = _SPI_execute_plan(plan, &options,
796  snapshot, crosscheck_snapshot,
797  fire_triggers);
798 
799  _SPI_end_call(true);
800  return res;
801 }
802 
803 /*
804  * SPI_execute_with_args -- plan and execute a query with supplied arguments
805  *
806  * This is functionally equivalent to SPI_prepare followed by
807  * SPI_execute_plan.
808  */
809 int
810 SPI_execute_with_args(const char *src,
811  int nargs, Oid *argtypes,
812  Datum *Values, const char *Nulls,
813  bool read_only, long tcount)
814 {
815  int res;
816  _SPI_plan plan;
817  ParamListInfo paramLI;
819 
820  if (src == NULL || nargs < 0 || tcount < 0)
821  return SPI_ERROR_ARGUMENT;
822 
823  if (nargs > 0 && (argtypes == NULL || Values == NULL))
824  return SPI_ERROR_PARAM;
825 
826  res = _SPI_begin_call(true);
827  if (res < 0)
828  return res;
829 
830  memset(&plan, 0, sizeof(_SPI_plan));
831  plan.magic = _SPI_PLAN_MAGIC;
834  plan.nargs = nargs;
835  plan.argtypes = argtypes;
836  plan.parserSetup = NULL;
837  plan.parserSetupArg = NULL;
838 
839  paramLI = _SPI_convert_params(nargs, argtypes,
840  Values, Nulls);
841 
842  _SPI_prepare_oneshot_plan(src, &plan);
843 
844  memset(&options, 0, sizeof(options));
845  options.params = paramLI;
846  options.read_only = read_only;
847  options.tcount = tcount;
848 
849  res = _SPI_execute_plan(&plan, &options,
851  true);
852 
853  _SPI_end_call(true);
854  return res;
855 }
856 
858 SPI_prepare(const char *src, int nargs, Oid *argtypes)
859 {
860  return SPI_prepare_cursor(src, nargs, argtypes, 0);
861 }
862 
864 SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
865  int cursorOptions)
866 {
867  _SPI_plan plan;
868  SPIPlanPtr result;
869 
870  if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
871  {
873  return NULL;
874  }
875 
876  SPI_result = _SPI_begin_call(true);
877  if (SPI_result < 0)
878  return NULL;
879 
880  memset(&plan, 0, sizeof(_SPI_plan));
881  plan.magic = _SPI_PLAN_MAGIC;
883  plan.cursor_options = cursorOptions;
884  plan.nargs = nargs;
885  plan.argtypes = argtypes;
886  plan.parserSetup = NULL;
887  plan.parserSetupArg = NULL;
888 
889  _SPI_prepare_plan(src, &plan);
890 
891  /* copy plan to procedure context */
892  result = _SPI_make_plan_non_temp(&plan);
893 
894  _SPI_end_call(true);
895 
896  return result;
897 }
898 
900 SPI_prepare_extended(const char *src,
901  const SPIPrepareOptions *options)
902 {
903  _SPI_plan plan;
904  SPIPlanPtr result;
905 
906  if (src == NULL || options == NULL)
907  {
909  return NULL;
910  }
911 
912  SPI_result = _SPI_begin_call(true);
913  if (SPI_result < 0)
914  return NULL;
915 
916  memset(&plan, 0, sizeof(_SPI_plan));
917  plan.magic = _SPI_PLAN_MAGIC;
918  plan.parse_mode = options->parseMode;
919  plan.cursor_options = options->cursorOptions;
920  plan.nargs = 0;
921  plan.argtypes = NULL;
922  plan.parserSetup = options->parserSetup;
923  plan.parserSetupArg = options->parserSetupArg;
924 
925  _SPI_prepare_plan(src, &plan);
926 
927  /* copy plan to procedure context */
928  result = _SPI_make_plan_non_temp(&plan);
929 
930  _SPI_end_call(true);
931 
932  return result;
933 }
934 
936 SPI_prepare_params(const char *src,
937  ParserSetupHook parserSetup,
938  void *parserSetupArg,
939  int cursorOptions)
940 {
941  _SPI_plan plan;
942  SPIPlanPtr result;
943 
944  if (src == NULL)
945  {
947  return NULL;
948  }
949 
950  SPI_result = _SPI_begin_call(true);
951  if (SPI_result < 0)
952  return NULL;
953 
954  memset(&plan, 0, sizeof(_SPI_plan));
955  plan.magic = _SPI_PLAN_MAGIC;
957  plan.cursor_options = cursorOptions;
958  plan.nargs = 0;
959  plan.argtypes = NULL;
960  plan.parserSetup = parserSetup;
961  plan.parserSetupArg = parserSetupArg;
962 
963  _SPI_prepare_plan(src, &plan);
964 
965  /* copy plan to procedure context */
966  result = _SPI_make_plan_non_temp(&plan);
967 
968  _SPI_end_call(true);
969 
970  return result;
971 }
972 
973 int
975 {
976  ListCell *lc;
977 
978  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
979  plan->saved || plan->oneshot)
980  return SPI_ERROR_ARGUMENT;
981 
982  /*
983  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
984  * component CachedPlanSources as saved. This sequence cannot fail
985  * partway through, so there's no risk of long-term memory leakage.
986  */
987  plan->saved = true;
989 
990  foreach(lc, plan->plancache_list)
991  {
992  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
993 
994  SaveCachedPlan(plansource);
995  }
996 
997  return 0;
998 }
999 
1000 SPIPlanPtr
1002 {
1003  SPIPlanPtr newplan;
1004 
1005  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1006  {
1008  return NULL;
1009  }
1010 
1011  SPI_result = _SPI_begin_call(false); /* don't change context */
1012  if (SPI_result < 0)
1013  return NULL;
1014 
1015  newplan = _SPI_save_plan(plan);
1016 
1017  SPI_result = _SPI_end_call(false);
1018 
1019  return newplan;
1020 }
1021 
1022 int
1024 {
1025  ListCell *lc;
1026 
1027  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1028  return SPI_ERROR_ARGUMENT;
1029 
1030  /* Release the plancache entries */
1031  foreach(lc, plan->plancache_list)
1032  {
1033  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1034 
1035  DropCachedPlan(plansource);
1036  }
1037 
1038  /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
1040 
1041  return 0;
1042 }
1043 
1044 HeapTuple
1046 {
1047  MemoryContext oldcxt;
1048  HeapTuple ctuple;
1049 
1050  if (tuple == NULL)
1051  {
1053  return NULL;
1054  }
1055 
1056  if (_SPI_current == NULL)
1057  {
1059  return NULL;
1060  }
1061 
1063 
1064  ctuple = heap_copytuple(tuple);
1065 
1066  MemoryContextSwitchTo(oldcxt);
1067 
1068  return ctuple;
1069 }
1070 
1073 {
1074  MemoryContext oldcxt;
1075  HeapTupleHeader dtup;
1076 
1077  if (tuple == NULL || tupdesc == NULL)
1078  {
1080  return NULL;
1081  }
1082 
1083  if (_SPI_current == NULL)
1084  {
1086  return NULL;
1087  }
1088 
1089  /* For RECORD results, make sure a typmod has been assigned */
1090  if (tupdesc->tdtypeid == RECORDOID &&
1091  tupdesc->tdtypmod < 0)
1092  assign_record_type_typmod(tupdesc);
1093 
1095 
1096  dtup = DatumGetHeapTupleHeader(heap_copy_tuple_as_datum(tuple, tupdesc));
1097 
1098  MemoryContextSwitchTo(oldcxt);
1099 
1100  return dtup;
1101 }
1102 
1103 HeapTuple
1104 SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
1105  Datum *Values, const char *Nulls)
1106 {
1107  MemoryContext oldcxt;
1108  HeapTuple mtuple;
1109  int numberOfAttributes;
1110  Datum *v;
1111  bool *n;
1112  int i;
1113 
1114  if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
1115  {
1117  return NULL;
1118  }
1119 
1120  if (_SPI_current == NULL)
1121  {
1123  return NULL;
1124  }
1125 
1127 
1128  SPI_result = 0;
1129 
1130  numberOfAttributes = rel->rd_att->natts;
1131  v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1132  n = (bool *) palloc(numberOfAttributes * sizeof(bool));
1133 
1134  /* fetch old values and nulls */
1135  heap_deform_tuple(tuple, rel->rd_att, v, n);
1136 
1137  /* replace values and nulls */
1138  for (i = 0; i < natts; i++)
1139  {
1140  if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
1141  break;
1142  v[attnum[i] - 1] = Values[i];
1143  n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n');
1144  }
1145 
1146  if (i == natts) /* no errors in *attnum */
1147  {
1148  mtuple = heap_form_tuple(rel->rd_att, v, n);
1149 
1150  /*
1151  * copy the identification info of the old tuple: t_ctid, t_self, and
1152  * OID (if any)
1153  */
1154  mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
1155  mtuple->t_self = tuple->t_self;
1156  mtuple->t_tableOid = tuple->t_tableOid;
1157  }
1158  else
1159  {
1160  mtuple = NULL;
1162  }
1163 
1164  pfree(v);
1165  pfree(n);
1166 
1167  MemoryContextSwitchTo(oldcxt);
1168 
1169  return mtuple;
1170 }
1171 
1172 int
1173 SPI_fnumber(TupleDesc tupdesc, const char *fname)
1174 {
1175  int res;
1176  const FormData_pg_attribute *sysatt;
1177 
1178  for (res = 0; res < tupdesc->natts; res++)
1179  {
1180  Form_pg_attribute attr = TupleDescAttr(tupdesc, res);
1181 
1182  if (namestrcmp(&attr->attname, fname) == 0 &&
1183  !attr->attisdropped)
1184  return res + 1;
1185  }
1186 
1187  sysatt = SystemAttributeByName(fname);
1188  if (sysatt != NULL)
1189  return sysatt->attnum;
1190 
1191  /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
1192  return SPI_ERROR_NOATTRIBUTE;
1193 }
1194 
1195 char *
1196 SPI_fname(TupleDesc tupdesc, int fnumber)
1197 {
1198  const FormData_pg_attribute *att;
1199 
1200  SPI_result = 0;
1201 
1202  if (fnumber > tupdesc->natts || fnumber == 0 ||
1204  {
1206  return NULL;
1207  }
1208 
1209  if (fnumber > 0)
1210  att = TupleDescAttr(tupdesc, fnumber - 1);
1211  else
1212  att = SystemAttributeDefinition(fnumber);
1213 
1214  return pstrdup(NameStr(att->attname));
1215 }
1216 
1217 char *
1218 SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
1219 {
1220  Datum val;
1221  bool isnull;
1222  Oid typoid,
1223  foutoid;
1224  bool typisvarlena;
1225 
1226  SPI_result = 0;
1227 
1228  if (fnumber > tupdesc->natts || fnumber == 0 ||
1230  {
1232  return NULL;
1233  }
1234 
1235  val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
1236  if (isnull)
1237  return NULL;
1238 
1239  if (fnumber > 0)
1240  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1241  else
1242  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1243 
1244  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
1245 
1246  return OidOutputFunctionCall(foutoid, val);
1247 }
1248 
1249 Datum
1250 SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
1251 {
1252  SPI_result = 0;
1253 
1254  if (fnumber > tupdesc->natts || fnumber == 0 ||
1256  {
1258  *isnull = true;
1259  return (Datum) NULL;
1260  }
1261 
1262  return heap_getattr(tuple, fnumber, tupdesc, isnull);
1263 }
1264 
1265 char *
1266 SPI_gettype(TupleDesc tupdesc, int fnumber)
1267 {
1268  Oid typoid;
1269  HeapTuple typeTuple;
1270  char *result;
1271 
1272  SPI_result = 0;
1273 
1274  if (fnumber > tupdesc->natts || fnumber == 0 ||
1276  {
1278  return NULL;
1279  }
1280 
1281  if (fnumber > 0)
1282  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1283  else
1284  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1285 
1286  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
1287 
1288  if (!HeapTupleIsValid(typeTuple))
1289  {
1291  return NULL;
1292  }
1293 
1294  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
1295  ReleaseSysCache(typeTuple);
1296  return result;
1297 }
1298 
1299 /*
1300  * Get the data type OID for a column.
1301  *
1302  * There's nothing similar for typmod and typcollation. The rare consumers
1303  * thereof should inspect the TupleDesc directly.
1304  */
1305 Oid
1306 SPI_gettypeid(TupleDesc tupdesc, int fnumber)
1307 {
1308  SPI_result = 0;
1309 
1310  if (fnumber > tupdesc->natts || fnumber == 0 ||
1312  {
1314  return InvalidOid;
1315  }
1316 
1317  if (fnumber > 0)
1318  return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1319  else
1320  return (SystemAttributeDefinition(fnumber))->atttypid;
1321 }
1322 
1323 char *
1325 {
1326  return pstrdup(RelationGetRelationName(rel));
1327 }
1328 
1329 char *
1331 {
1333 }
1334 
1335 void *
1337 {
1338  if (_SPI_current == NULL)
1339  elog(ERROR, "SPI_palloc called while not connected to SPI");
1340 
1341  return MemoryContextAlloc(_SPI_current->savedcxt, size);
1342 }
1343 
1344 void *
1345 SPI_repalloc(void *pointer, Size size)
1346 {
1347  /* No longer need to worry which context chunk was in... */
1348  return repalloc(pointer, size);
1349 }
1350 
1351 void
1352 SPI_pfree(void *pointer)
1353 {
1354  /* No longer need to worry which context chunk was in... */
1355  pfree(pointer);
1356 }
1357 
1358 Datum
1359 SPI_datumTransfer(Datum value, bool typByVal, int typLen)
1360 {
1361  MemoryContext oldcxt;
1362  Datum result;
1363 
1364  if (_SPI_current == NULL)
1365  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1366 
1368 
1369  result = datumTransfer(value, typByVal, typLen);
1370 
1371  MemoryContextSwitchTo(oldcxt);
1372 
1373  return result;
1374 }
1375 
1376 void
1378 {
1379  /* No longer need to worry which context tuple was in... */
1380  heap_freetuple(tuple);
1381 }
1382 
1383 void
1385 {
1386  bool found = false;
1387 
1388  /* ignore call if NULL pointer */
1389  if (tuptable == NULL)
1390  return;
1391 
1392  /*
1393  * Search only the topmost SPI context for a matching tuple table.
1394  */
1395  if (_SPI_current != NULL)
1396  {
1397  slist_mutable_iter siter;
1398 
1399  /* find tuptable in active list, then remove it */
1401  {
1402  SPITupleTable *tt;
1403 
1404  tt = slist_container(SPITupleTable, next, siter.cur);
1405  if (tt == tuptable)
1406  {
1407  slist_delete_current(&siter);
1408  found = true;
1409  break;
1410  }
1411  }
1412  }
1413 
1414  /*
1415  * Refuse the deletion if we didn't find it in the topmost SPI context.
1416  * This is primarily a guard against double deletion, but might prevent
1417  * other errors as well. Since the worst consequence of not deleting a
1418  * tuptable would be a transient memory leak, this is just a WARNING.
1419  */
1420  if (!found)
1421  {
1422  elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1423  return;
1424  }
1425 
1426  /* for safety, reset global variables that might point at tuptable */
1427  if (tuptable == _SPI_current->tuptable)
1428  _SPI_current->tuptable = NULL;
1429  if (tuptable == SPI_tuptable)
1430  SPI_tuptable = NULL;
1431 
1432  /* release all memory belonging to tuptable */
1433  MemoryContextDelete(tuptable->tuptabcxt);
1434 }
1435 
1436 
1437 /*
1438  * SPI_cursor_open()
1439  *
1440  * Open a prepared SPI plan as a portal
1441  */
1442 Portal
1443 SPI_cursor_open(const char *name, SPIPlanPtr plan,
1444  Datum *Values, const char *Nulls,
1445  bool read_only)
1446 {
1447  Portal portal;
1448  ParamListInfo paramLI;
1449 
1450  /* build transient ParamListInfo in caller's context */
1451  paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1452  Values, Nulls);
1453 
1454  portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1455 
1456  /* done with the transient ParamListInfo */
1457  if (paramLI)
1458  pfree(paramLI);
1459 
1460  return portal;
1461 }
1462 
1463 
1464 /*
1465  * SPI_cursor_open_with_args()
1466  *
1467  * Parse and plan a query and open it as a portal.
1468  */
1469 Portal
1471  const char *src,
1472  int nargs, Oid *argtypes,
1473  Datum *Values, const char *Nulls,
1474  bool read_only, int cursorOptions)
1475 {
1476  Portal result;
1477  _SPI_plan plan;
1478  ParamListInfo paramLI;
1479 
1480  if (src == NULL || nargs < 0)
1481  elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1482 
1483  if (nargs > 0 && (argtypes == NULL || Values == NULL))
1484  elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1485 
1486  SPI_result = _SPI_begin_call(true);
1487  if (SPI_result < 0)
1488  elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1489 
1490  memset(&plan, 0, sizeof(_SPI_plan));
1491  plan.magic = _SPI_PLAN_MAGIC;
1493  plan.cursor_options = cursorOptions;
1494  plan.nargs = nargs;
1495  plan.argtypes = argtypes;
1496  plan.parserSetup = NULL;
1497  plan.parserSetupArg = NULL;
1498 
1499  /* build transient ParamListInfo in executor context */
1500  paramLI = _SPI_convert_params(nargs, argtypes,
1501  Values, Nulls);
1502 
1503  _SPI_prepare_plan(src, &plan);
1504 
1505  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1506 
1507  result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
1508 
1509  /* And clean up */
1510  _SPI_end_call(true);
1511 
1512  return result;
1513 }
1514 
1515 
1516 /*
1517  * SPI_cursor_open_with_paramlist()
1518  *
1519  * Same as SPI_cursor_open except that parameters (if any) are passed
1520  * as a ParamListInfo, which supports dynamic parameter set determination
1521  */
1522 Portal
1524  ParamListInfo params, bool read_only)
1525 {
1526  return SPI_cursor_open_internal(name, plan, params, read_only);
1527 }
1528 
1529 /* Parse a query and open it as a cursor */
1530 Portal
1532  const char *src,
1534 {
1535  Portal result;
1536  _SPI_plan plan;
1537 
1538  if (src == NULL || options == NULL)
1539  elog(ERROR, "SPI_cursor_parse_open called with invalid arguments");
1540 
1541  SPI_result = _SPI_begin_call(true);
1542  if (SPI_result < 0)
1543  elog(ERROR, "SPI_cursor_parse_open called while not connected");
1544 
1545  memset(&plan, 0, sizeof(_SPI_plan));
1546  plan.magic = _SPI_PLAN_MAGIC;
1548  plan.cursor_options = options->cursorOptions;
1549  if (options->params)
1550  {
1551  plan.parserSetup = options->params->parserSetup;
1552  plan.parserSetupArg = options->params->parserSetupArg;
1553  }
1554 
1555  _SPI_prepare_plan(src, &plan);
1556 
1557  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1558 
1559  result = SPI_cursor_open_internal(name, &plan,
1560  options->params, options->read_only);
1561 
1562  /* And clean up */
1563  _SPI_end_call(true);
1564 
1565  return result;
1566 }
1567 
1568 
1569 /*
1570  * SPI_cursor_open_internal()
1571  *
1572  * Common code for SPI_cursor_open variants
1573  */
1574 static Portal
1576  ParamListInfo paramLI, bool read_only)
1577 {
1578  CachedPlanSource *plansource;
1579  CachedPlan *cplan;
1580  List *stmt_list;
1581  char *query_string;
1582  Snapshot snapshot;
1583  MemoryContext oldcontext;
1584  Portal portal;
1585  SPICallbackArg spicallbackarg;
1586  ErrorContextCallback spierrcontext;
1587 
1588  /*
1589  * Check that the plan is something the Portal code will special-case as
1590  * returning one tupleset.
1591  */
1592  if (!SPI_is_cursor_plan(plan))
1593  {
1594  /* try to give a good error message */
1595  const char *cmdtag;
1596 
1597  if (list_length(plan->plancache_list) != 1)
1598  ereport(ERROR,
1599  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1600  errmsg("cannot open multi-query plan as cursor")));
1601  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1602  /* A SELECT that fails SPI_is_cursor_plan() must be SELECT INTO */
1603  if (plansource->commandTag == CMDTAG_SELECT)
1604  cmdtag = "SELECT INTO";
1605  else
1606  cmdtag = GetCommandTagName(plansource->commandTag);
1607  ereport(ERROR,
1608  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1609  /* translator: %s is name of a SQL command, eg INSERT */
1610  errmsg("cannot open %s query as cursor", cmdtag)));
1611  }
1612 
1613  Assert(list_length(plan->plancache_list) == 1);
1614  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1615 
1616  /* Push the SPI stack */
1617  if (_SPI_begin_call(true) < 0)
1618  elog(ERROR, "SPI_cursor_open called while not connected");
1619 
1620  /* Reset SPI result (note we deliberately don't touch lastoid) */
1621  SPI_processed = 0;
1622  SPI_tuptable = NULL;
1623  _SPI_current->processed = 0;
1624  _SPI_current->tuptable = NULL;
1625 
1626  /* Create the portal */
1627  if (name == NULL || name[0] == '\0')
1628  {
1629  /* Use a random nonconflicting name */
1630  portal = CreateNewPortal();
1631  }
1632  else
1633  {
1634  /* In this path, error if portal of same name already exists */
1635  portal = CreatePortal(name, false, false);
1636  }
1637 
1638  /* Copy the plan's query string into the portal */
1639  query_string = MemoryContextStrdup(portal->portalContext,
1640  plansource->query_string);
1641 
1642  /*
1643  * Setup error traceback support for ereport(), in case GetCachedPlan
1644  * throws an error.
1645  */
1646  spicallbackarg.query = plansource->query_string;
1647  spicallbackarg.mode = plan->parse_mode;
1648  spierrcontext.callback = _SPI_error_callback;
1649  spierrcontext.arg = &spicallbackarg;
1650  spierrcontext.previous = error_context_stack;
1651  error_context_stack = &spierrcontext;
1652 
1653  /*
1654  * Note: for a saved plan, we mustn't have any failure occur between
1655  * GetCachedPlan and PortalDefineQuery; that would result in leaking our
1656  * plancache refcount.
1657  */
1658 
1659  /* Replan if needed, and increment plan refcount for portal */
1660  cplan = GetCachedPlan(plansource, paramLI, NULL, _SPI_current->queryEnv);
1661  stmt_list = cplan->stmt_list;
1662 
1663  if (!plan->saved)
1664  {
1665  /*
1666  * We don't want the portal to depend on an unsaved CachedPlanSource,
1667  * so must copy the plan into the portal's context. An error here
1668  * will result in leaking our refcount on the plan, but it doesn't
1669  * matter because the plan is unsaved and hence transient anyway.
1670  */
1671  oldcontext = MemoryContextSwitchTo(portal->portalContext);
1672  stmt_list = copyObject(stmt_list);
1673  MemoryContextSwitchTo(oldcontext);
1674  ReleaseCachedPlan(cplan, NULL);
1675  cplan = NULL; /* portal shouldn't depend on cplan */
1676  }
1677 
1678  /*
1679  * Set up the portal.
1680  */
1681  PortalDefineQuery(portal,
1682  NULL, /* no statement name */
1683  query_string,
1684  plansource->commandTag,
1685  stmt_list,
1686  cplan);
1687 
1688  /*
1689  * Set up options for portal. Default SCROLL type is chosen the same way
1690  * as PerformCursorOpen does it.
1691  */
1692  portal->cursorOptions = plan->cursor_options;
1694  {
1695  if (list_length(stmt_list) == 1 &&
1696  linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
1697  linitial_node(PlannedStmt, stmt_list)->rowMarks == NIL &&
1698  ExecSupportsBackwardScan(linitial_node(PlannedStmt, stmt_list)->planTree))
1699  portal->cursorOptions |= CURSOR_OPT_SCROLL;
1700  else
1702  }
1703 
1704  /*
1705  * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with the
1706  * check in transformDeclareCursorStmt because the cursor options might
1707  * not have come through there.
1708  */
1709  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
1710  {
1711  if (list_length(stmt_list) == 1 &&
1712  linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
1713  linitial_node(PlannedStmt, stmt_list)->rowMarks != NIL)
1714  ereport(ERROR,
1715  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1716  errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1717  errdetail("Scrollable cursors must be READ ONLY.")));
1718  }
1719 
1720  /* Make current query environment available to portal at execution time. */
1721  portal->queryEnv = _SPI_current->queryEnv;
1722 
1723  /*
1724  * If told to be read-only, we'd better check for read-only queries. This
1725  * can't be done earlier because we need to look at the finished, planned
1726  * queries. (In particular, we don't want to do it between GetCachedPlan
1727  * and PortalDefineQuery, because throwing an error between those steps
1728  * would result in leaking our plancache refcount.)
1729  */
1730  if (read_only)
1731  {
1732  ListCell *lc;
1733 
1734  foreach(lc, stmt_list)
1735  {
1736  PlannedStmt *pstmt = lfirst_node(PlannedStmt, lc);
1737 
1738  if (!CommandIsReadOnly(pstmt))
1739  ereport(ERROR,
1740  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1741  /* translator: %s is a SQL statement name */
1742  errmsg("%s is not allowed in a non-volatile function",
1743  CreateCommandName((Node *) pstmt))));
1744  }
1745  }
1746 
1747  /* Set up the snapshot to use. */
1748  if (read_only)
1749  snapshot = GetActiveSnapshot();
1750  else
1751  {
1753  snapshot = GetTransactionSnapshot();
1754  }
1755 
1756  /*
1757  * If the plan has parameters, copy them into the portal. Note that this
1758  * must be done after revalidating the plan, because in dynamic parameter
1759  * cases the set of parameters could have changed during re-parsing.
1760  */
1761  if (paramLI)
1762  {
1763  oldcontext = MemoryContextSwitchTo(portal->portalContext);
1764  paramLI = copyParamList(paramLI);
1765  MemoryContextSwitchTo(oldcontext);
1766  }
1767 
1768  /*
1769  * Start portal execution.
1770  */
1771  PortalStart(portal, paramLI, 0, snapshot);
1772 
1773  Assert(portal->strategy != PORTAL_MULTI_QUERY);
1774 
1775  /* Pop the error context stack */
1776  error_context_stack = spierrcontext.previous;
1777 
1778  /* Pop the SPI stack */
1779  _SPI_end_call(true);
1780 
1781  /* Return the created portal */
1782  return portal;
1783 }
1784 
1785 
1786 /*
1787  * SPI_cursor_find()
1788  *
1789  * Find the portal of an existing open cursor
1790  */
1791 Portal
1792 SPI_cursor_find(const char *name)
1793 {
1794  return GetPortalByName(name);
1795 }
1796 
1797 
1798 /*
1799  * SPI_cursor_fetch()
1800  *
1801  * Fetch rows in a cursor
1802  */
1803 void
1804 SPI_cursor_fetch(Portal portal, bool forward, long count)
1805 {
1806  _SPI_cursor_operation(portal,
1807  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1809  /* we know that the DestSPI receiver doesn't need a destroy call */
1810 }
1811 
1812 
1813 /*
1814  * SPI_cursor_move()
1815  *
1816  * Move in a cursor
1817  */
1818 void
1819 SPI_cursor_move(Portal portal, bool forward, long count)
1820 {
1821  _SPI_cursor_operation(portal,
1822  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1823  None_Receiver);
1824 }
1825 
1826 
1827 /*
1828  * SPI_scroll_cursor_fetch()
1829  *
1830  * Fetch rows in a scrollable cursor
1831  */
1832 void
1833 SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
1834 {
1835  _SPI_cursor_operation(portal,
1836  direction, count,
1838  /* we know that the DestSPI receiver doesn't need a destroy call */
1839 }
1840 
1841 
1842 /*
1843  * SPI_scroll_cursor_move()
1844  *
1845  * Move in a scrollable cursor
1846  */
1847 void
1848 SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
1849 {
1850  _SPI_cursor_operation(portal, direction, count, None_Receiver);
1851 }
1852 
1853 
1854 /*
1855  * SPI_cursor_close()
1856  *
1857  * Close a cursor
1858  */
1859 void
1861 {
1862  if (!PortalIsValid(portal))
1863  elog(ERROR, "invalid portal in SPI cursor operation");
1864 
1865  PortalDrop(portal, false);
1866 }
1867 
1868 /*
1869  * Returns the Oid representing the type id for argument at argIndex. First
1870  * parameter is at index zero.
1871  */
1872 Oid
1873 SPI_getargtypeid(SPIPlanPtr plan, int argIndex)
1874 {
1875  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1876  argIndex < 0 || argIndex >= plan->nargs)
1877  {
1879  return InvalidOid;
1880  }
1881  return plan->argtypes[argIndex];
1882 }
1883 
1884 /*
1885  * Returns the number of arguments for the prepared plan.
1886  */
1887 int
1889 {
1890  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1891  {
1893  return -1;
1894  }
1895  return plan->nargs;
1896 }
1897 
1898 /*
1899  * Returns true if the plan contains exactly one command
1900  * and that command returns tuples to the caller (eg, SELECT or
1901  * INSERT ... RETURNING, but not SELECT ... INTO). In essence,
1902  * the result indicates if the command can be used with SPI_cursor_open
1903  *
1904  * Parameters
1905  * plan: A plan previously prepared using SPI_prepare
1906  */
1907 bool
1909 {
1910  CachedPlanSource *plansource;
1911 
1912  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1913  {
1915  return false;
1916  }
1917 
1918  if (list_length(plan->plancache_list) != 1)
1919  {
1920  SPI_result = 0;
1921  return false; /* not exactly 1 pre-rewrite command */
1922  }
1923  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1924 
1925  /*
1926  * We used to force revalidation of the cached plan here, but that seems
1927  * unnecessary: invalidation could mean a change in the rowtype of the
1928  * tuples returned by a plan, but not whether it returns tuples at all.
1929  */
1930  SPI_result = 0;
1931 
1932  /* Does it return tuples? */
1933  if (plansource->resultDesc)
1934  return true;
1935 
1936  return false;
1937 }
1938 
1939 /*
1940  * SPI_plan_is_valid --- test whether a SPI plan is currently valid
1941  * (that is, not marked as being in need of revalidation).
1942  *
1943  * See notes for CachedPlanIsValid before using this.
1944  */
1945 bool
1947 {
1948  ListCell *lc;
1949 
1950  Assert(plan->magic == _SPI_PLAN_MAGIC);
1951 
1952  foreach(lc, plan->plancache_list)
1953  {
1954  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1955 
1956  if (!CachedPlanIsValid(plansource))
1957  return false;
1958  }
1959  return true;
1960 }
1961 
1962 /*
1963  * SPI_result_code_string --- convert any SPI return code to a string
1964  *
1965  * This is often useful in error messages. Most callers will probably
1966  * only pass negative (error-case) codes, but for generality we recognize
1967  * the success codes too.
1968  */
1969 const char *
1971 {
1972  static char buf[64];
1973 
1974  switch (code)
1975  {
1976  case SPI_ERROR_CONNECT:
1977  return "SPI_ERROR_CONNECT";
1978  case SPI_ERROR_COPY:
1979  return "SPI_ERROR_COPY";
1980  case SPI_ERROR_OPUNKNOWN:
1981  return "SPI_ERROR_OPUNKNOWN";
1982  case SPI_ERROR_UNCONNECTED:
1983  return "SPI_ERROR_UNCONNECTED";
1984  case SPI_ERROR_ARGUMENT:
1985  return "SPI_ERROR_ARGUMENT";
1986  case SPI_ERROR_PARAM:
1987  return "SPI_ERROR_PARAM";
1988  case SPI_ERROR_TRANSACTION:
1989  return "SPI_ERROR_TRANSACTION";
1990  case SPI_ERROR_NOATTRIBUTE:
1991  return "SPI_ERROR_NOATTRIBUTE";
1992  case SPI_ERROR_NOOUTFUNC:
1993  return "SPI_ERROR_NOOUTFUNC";
1994  case SPI_ERROR_TYPUNKNOWN:
1995  return "SPI_ERROR_TYPUNKNOWN";
1997  return "SPI_ERROR_REL_DUPLICATE";
1999  return "SPI_ERROR_REL_NOT_FOUND";
2000  case SPI_OK_CONNECT:
2001  return "SPI_OK_CONNECT";
2002  case SPI_OK_FINISH:
2003  return "SPI_OK_FINISH";
2004  case SPI_OK_FETCH:
2005  return "SPI_OK_FETCH";
2006  case SPI_OK_UTILITY:
2007  return "SPI_OK_UTILITY";
2008  case SPI_OK_SELECT:
2009  return "SPI_OK_SELECT";
2010  case SPI_OK_SELINTO:
2011  return "SPI_OK_SELINTO";
2012  case SPI_OK_INSERT:
2013  return "SPI_OK_INSERT";
2014  case SPI_OK_DELETE:
2015  return "SPI_OK_DELETE";
2016  case SPI_OK_UPDATE:
2017  return "SPI_OK_UPDATE";
2018  case SPI_OK_CURSOR:
2019  return "SPI_OK_CURSOR";
2021  return "SPI_OK_INSERT_RETURNING";
2023  return "SPI_OK_DELETE_RETURNING";
2025  return "SPI_OK_UPDATE_RETURNING";
2026  case SPI_OK_REWRITTEN:
2027  return "SPI_OK_REWRITTEN";
2028  case SPI_OK_REL_REGISTER:
2029  return "SPI_OK_REL_REGISTER";
2030  case SPI_OK_REL_UNREGISTER:
2031  return "SPI_OK_REL_UNREGISTER";
2032  }
2033  /* Unrecognized code ... return something useful ... */
2034  sprintf(buf, "Unrecognized SPI code %d", code);
2035  return buf;
2036 }
2037 
2038 /*
2039  * SPI_plan_get_plan_sources --- get a SPI plan's underlying list of
2040  * CachedPlanSources.
2041  *
2042  * This is exported so that PL/pgSQL can use it (this beats letting PL/pgSQL
2043  * look directly into the SPIPlan for itself). It's not documented in
2044  * spi.sgml because we'd just as soon not have too many places using this.
2045  */
2046 List *
2048 {
2049  Assert(plan->magic == _SPI_PLAN_MAGIC);
2050  return plan->plancache_list;
2051 }
2052 
2053 /*
2054  * SPI_plan_get_cached_plan --- get a SPI plan's generic CachedPlan,
2055  * if the SPI plan contains exactly one CachedPlanSource. If not,
2056  * return NULL.
2057  *
2058  * The plan's refcount is incremented (and logged in CurrentResourceOwner,
2059  * if it's a saved plan). Caller is responsible for doing ReleaseCachedPlan.
2060  *
2061  * This is exported so that PL/pgSQL can use it (this beats letting PL/pgSQL
2062  * look directly into the SPIPlan for itself). It's not documented in
2063  * spi.sgml because we'd just as soon not have too many places using this.
2064  */
2065 CachedPlan *
2067 {
2068  CachedPlanSource *plansource;
2069  CachedPlan *cplan;
2070  SPICallbackArg spicallbackarg;
2071  ErrorContextCallback spierrcontext;
2072 
2073  Assert(plan->magic == _SPI_PLAN_MAGIC);
2074 
2075  /* Can't support one-shot plans here */
2076  if (plan->oneshot)
2077  return NULL;
2078 
2079  /* Must have exactly one CachedPlanSource */
2080  if (list_length(plan->plancache_list) != 1)
2081  return NULL;
2082  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
2083 
2084  /* Setup error traceback support for ereport() */
2085  spicallbackarg.query = plansource->query_string;
2086  spicallbackarg.mode = plan->parse_mode;
2087  spierrcontext.callback = _SPI_error_callback;
2088  spierrcontext.arg = &spicallbackarg;
2089  spierrcontext.previous = error_context_stack;
2090  error_context_stack = &spierrcontext;
2091 
2092  /* Get the generic plan for the query */
2093  cplan = GetCachedPlan(plansource, NULL,
2094  plan->saved ? CurrentResourceOwner : NULL,
2096  Assert(cplan == plansource->gplan);
2097 
2098  /* Pop the error context stack */
2099  error_context_stack = spierrcontext.previous;
2100 
2101  return cplan;
2102 }
2103 
2104 
2105 /* =================== private functions =================== */
2106 
2107 /*
2108  * spi_dest_startup
2109  * Initialize to receive tuples from Executor into SPITupleTable
2110  * of current SPI procedure
2111  */
2112 void
2113 spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
2114 {
2115  SPITupleTable *tuptable;
2116  MemoryContext oldcxt;
2117  MemoryContext tuptabcxt;
2118 
2119  if (_SPI_current == NULL)
2120  elog(ERROR, "spi_dest_startup called while not connected to SPI");
2121 
2122  if (_SPI_current->tuptable != NULL)
2123  elog(ERROR, "improper call to spi_dest_startup");
2124 
2125  /* We create the tuple table context as a child of procCxt */
2126 
2127  oldcxt = _SPI_procmem(); /* switch to procedure memory context */
2128 
2130  "SPI TupTable",
2132  MemoryContextSwitchTo(tuptabcxt);
2133 
2134  _SPI_current->tuptable = tuptable = (SPITupleTable *)
2135  palloc0(sizeof(SPITupleTable));
2136  tuptable->tuptabcxt = tuptabcxt;
2137  tuptable->subid = GetCurrentSubTransactionId();
2138 
2139  /*
2140  * The tuptable is now valid enough to be freed by AtEOSubXact_SPI, so put
2141  * it onto the SPI context's tuptables list. This will ensure it's not
2142  * leaked even in the unlikely event the following few lines fail.
2143  */
2144  slist_push_head(&_SPI_current->tuptables, &tuptable->next);
2145 
2146  /* set up initial allocations */
2147  tuptable->alloced = 128;
2148  tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
2149  tuptable->numvals = 0;
2150  tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
2151 
2152  MemoryContextSwitchTo(oldcxt);
2153 }
2154 
2155 /*
2156  * spi_printtup
2157  * store tuple retrieved by Executor into SPITupleTable
2158  * of current SPI procedure
2159  */
2160 bool
2162 {
2163  SPITupleTable *tuptable;
2164  MemoryContext oldcxt;
2165 
2166  if (_SPI_current == NULL)
2167  elog(ERROR, "spi_printtup called while not connected to SPI");
2168 
2169  tuptable = _SPI_current->tuptable;
2170  if (tuptable == NULL)
2171  elog(ERROR, "improper call to spi_printtup");
2172 
2173  oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
2174 
2175  if (tuptable->numvals >= tuptable->alloced)
2176  {
2177  /* Double the size of the pointer array */
2178  uint64 newalloced = tuptable->alloced * 2;
2179 
2180  tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals,
2181  newalloced * sizeof(HeapTuple));
2182  tuptable->alloced = newalloced;
2183  }
2184 
2185  tuptable->vals[tuptable->numvals] = ExecCopySlotHeapTuple(slot);
2186  (tuptable->numvals)++;
2187 
2188  MemoryContextSwitchTo(oldcxt);
2189 
2190  return true;
2191 }
2192 
2193 /*
2194  * Static functions
2195  */
2196 
2197 /*
2198  * Parse and analyze a querystring.
2199  *
2200  * At entry, plan->argtypes and plan->nargs (or alternatively plan->parserSetup
2201  * and plan->parserSetupArg) must be valid, as must plan->parse_mode and
2202  * plan->cursor_options.
2203  *
2204  * Results are stored into *plan (specifically, plan->plancache_list).
2205  * Note that the result data is all in CurrentMemoryContext or child contexts
2206  * thereof; in practice this means it is in the SPI executor context, and
2207  * what we are creating is a "temporary" SPIPlan. Cruft generated during
2208  * parsing is also left in CurrentMemoryContext.
2209  */
2210 static void
2211 _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
2212 {
2213  List *raw_parsetree_list;
2214  List *plancache_list;
2215  ListCell *list_item;
2216  SPICallbackArg spicallbackarg;
2217  ErrorContextCallback spierrcontext;
2218 
2219  /*
2220  * Setup error traceback support for ereport()
2221  */
2222  spicallbackarg.query = src;
2223  spicallbackarg.mode = plan->parse_mode;
2224  spierrcontext.callback = _SPI_error_callback;
2225  spierrcontext.arg = &spicallbackarg;
2226  spierrcontext.previous = error_context_stack;
2227  error_context_stack = &spierrcontext;
2228 
2229  /*
2230  * Parse the request string into a list of raw parse trees.
2231  */
2232  raw_parsetree_list = raw_parser(src, plan->parse_mode);
2233 
2234  /*
2235  * Do parse analysis and rule rewrite for each raw parsetree, storing the
2236  * results into unsaved plancache entries.
2237  */
2238  plancache_list = NIL;
2239 
2240  foreach(list_item, raw_parsetree_list)
2241  {
2242  RawStmt *parsetree = lfirst_node(RawStmt, list_item);
2243  List *stmt_list;
2244  CachedPlanSource *plansource;
2245 
2246  /*
2247  * Create the CachedPlanSource before we do parse analysis, since it
2248  * needs to see the unmodified raw parse tree.
2249  */
2250  plansource = CreateCachedPlan(parsetree,
2251  src,
2252  CreateCommandTag(parsetree->stmt));
2253 
2254  /*
2255  * Parameter datatypes are driven by parserSetup hook if provided,
2256  * otherwise we use the fixed parameter list.
2257  */
2258  if (plan->parserSetup != NULL)
2259  {
2260  Assert(plan->nargs == 0);
2261  stmt_list = pg_analyze_and_rewrite_withcb(parsetree,
2262  src,
2263  plan->parserSetup,
2264  plan->parserSetupArg,
2266  }
2267  else
2268  {
2269  stmt_list = pg_analyze_and_rewrite_fixedparams(parsetree,
2270  src,
2271  plan->argtypes,
2272  plan->nargs,
2274  }
2275 
2276  /* Finish filling in the CachedPlanSource */
2277  CompleteCachedPlan(plansource,
2278  stmt_list,
2279  NULL,
2280  plan->argtypes,
2281  plan->nargs,
2282  plan->parserSetup,
2283  plan->parserSetupArg,
2284  plan->cursor_options,
2285  false); /* not fixed result */
2286 
2287  plancache_list = lappend(plancache_list, plansource);
2288  }
2289 
2290  plan->plancache_list = plancache_list;
2291  plan->oneshot = false;
2292 
2293  /*
2294  * Pop the error context stack
2295  */
2296  error_context_stack = spierrcontext.previous;
2297 }
2298 
2299 /*
2300  * Parse, but don't analyze, a querystring.
2301  *
2302  * This is a stripped-down version of _SPI_prepare_plan that only does the
2303  * initial raw parsing. It creates "one shot" CachedPlanSources
2304  * that still require parse analysis before execution is possible.
2305  *
2306  * The advantage of using the "one shot" form of CachedPlanSource is that
2307  * we eliminate data copying and invalidation overhead. Postponing parse
2308  * analysis also prevents issues if some of the raw parsetrees are DDL
2309  * commands that affect validity of later parsetrees. Both of these
2310  * attributes are good things for SPI_execute() and similar cases.
2311  *
2312  * Results are stored into *plan (specifically, plan->plancache_list).
2313  * Note that the result data is all in CurrentMemoryContext or child contexts
2314  * thereof; in practice this means it is in the SPI executor context, and
2315  * what we are creating is a "temporary" SPIPlan. Cruft generated during
2316  * parsing is also left in CurrentMemoryContext.
2317  */
2318 static void
2320 {
2321  List *raw_parsetree_list;
2322  List *plancache_list;
2323  ListCell *list_item;
2324  SPICallbackArg spicallbackarg;
2325  ErrorContextCallback spierrcontext;
2326 
2327  /*
2328  * Setup error traceback support for ereport()
2329  */
2330  spicallbackarg.query = src;
2331  spicallbackarg.mode = plan->parse_mode;
2332  spierrcontext.callback = _SPI_error_callback;
2333  spierrcontext.arg = &spicallbackarg;
2334  spierrcontext.previous = error_context_stack;
2335  error_context_stack = &spierrcontext;
2336 
2337  /*
2338  * Parse the request string into a list of raw parse trees.
2339  */
2340  raw_parsetree_list = raw_parser(src, plan->parse_mode);
2341 
2342  /*
2343  * Construct plancache entries, but don't do parse analysis yet.
2344  */
2345  plancache_list = NIL;
2346 
2347  foreach(list_item, raw_parsetree_list)
2348  {
2349  RawStmt *parsetree = lfirst_node(RawStmt, list_item);
2350  CachedPlanSource *plansource;
2351 
2352  plansource = CreateOneShotCachedPlan(parsetree,
2353  src,
2354  CreateCommandTag(parsetree->stmt));
2355 
2356  plancache_list = lappend(plancache_list, plansource);
2357  }
2358 
2359  plan->plancache_list = plancache_list;
2360  plan->oneshot = true;
2361 
2362  /*
2363  * Pop the error context stack
2364  */
2365  error_context_stack = spierrcontext.previous;
2366 }
2367 
2368 /*
2369  * _SPI_execute_plan: execute the given plan with the given options
2370  *
2371  * options contains options accessible from outside SPI:
2372  * params: parameter values to pass to query
2373  * read_only: true for read-only execution (no CommandCounterIncrement)
2374  * allow_nonatomic: true to allow nonatomic CALL/DO execution
2375  * must_return_tuples: throw error if query doesn't return tuples
2376  * tcount: execution tuple-count limit, or 0 for none
2377  * dest: DestReceiver to receive output, or NULL for normal SPI output
2378  * owner: ResourceOwner that will be used to hold refcount on plan;
2379  * if NULL, CurrentResourceOwner is used (ignored for non-saved plan)
2380  *
2381  * Additional, only-internally-accessible options:
2382  * snapshot: query snapshot to use, or InvalidSnapshot for the normal
2383  * behavior of taking a new snapshot for each query.
2384  * crosscheck_snapshot: for RI use, all others pass InvalidSnapshot
2385  * fire_triggers: true to fire AFTER triggers at end of query (normal case);
2386  * false means any AFTER triggers are postponed to end of outer query
2387  */
2388 static int
2390  Snapshot snapshot, Snapshot crosscheck_snapshot,
2391  bool fire_triggers)
2392 {
2393  int my_res = 0;
2394  uint64 my_processed = 0;
2395  SPITupleTable *my_tuptable = NULL;
2396  int res = 0;
2397  bool pushed_active_snap = false;
2398  ResourceOwner plan_owner = options->owner;
2399  SPICallbackArg spicallbackarg;
2400  ErrorContextCallback spierrcontext;
2401  CachedPlan *cplan = NULL;
2402  ListCell *lc1;
2403 
2404  /*
2405  * Setup error traceback support for ereport()
2406  */
2407  spicallbackarg.query = NULL; /* we'll fill this below */
2408  spicallbackarg.mode = plan->parse_mode;
2409  spierrcontext.callback = _SPI_error_callback;
2410  spierrcontext.arg = &spicallbackarg;
2411  spierrcontext.previous = error_context_stack;
2412  error_context_stack = &spierrcontext;
2413 
2414  /*
2415  * We support four distinct snapshot management behaviors:
2416  *
2417  * snapshot != InvalidSnapshot, read_only = true: use exactly the given
2418  * snapshot.
2419  *
2420  * snapshot != InvalidSnapshot, read_only = false: use the given snapshot,
2421  * modified by advancing its command ID before each querytree.
2422  *
2423  * snapshot == InvalidSnapshot, read_only = true: use the entry-time
2424  * ActiveSnapshot, if any (if there isn't one, we run with no snapshot).
2425  *
2426  * snapshot == InvalidSnapshot, read_only = false: take a full new
2427  * snapshot for each user command, and advance its command ID before each
2428  * querytree within the command.
2429  *
2430  * In the first two cases, we can just push the snap onto the stack once
2431  * for the whole plan list.
2432  *
2433  * Note that snapshot != InvalidSnapshot implies an atomic execution
2434  * context.
2435  */
2436  if (snapshot != InvalidSnapshot)
2437  {
2438  Assert(!options->allow_nonatomic);
2439  if (options->read_only)
2440  {
2441  PushActiveSnapshot(snapshot);
2442  pushed_active_snap = true;
2443  }
2444  else
2445  {
2446  /* Make sure we have a private copy of the snapshot to modify */
2447  PushCopiedSnapshot(snapshot);
2448  pushed_active_snap = true;
2449  }
2450  }
2451 
2452  /*
2453  * Ensure that we have a resource owner if plan is saved, and not if it
2454  * isn't.
2455  */
2456  if (!plan->saved)
2457  plan_owner = NULL;
2458  else if (plan_owner == NULL)
2459  plan_owner = CurrentResourceOwner;
2460 
2461  /*
2462  * We interpret must_return_tuples as "there must be at least one query,
2463  * and all of them must return tuples". This is a bit laxer than
2464  * SPI_is_cursor_plan's check, but there seems no reason to enforce that
2465  * there be only one query.
2466  */
2467  if (options->must_return_tuples && plan->plancache_list == NIL)
2468  ereport(ERROR,
2469  (errcode(ERRCODE_SYNTAX_ERROR),
2470  errmsg("empty query does not return tuples")));
2471 
2472  foreach(lc1, plan->plancache_list)
2473  {
2474  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
2475  List *stmt_list;
2476  ListCell *lc2;
2477 
2478  spicallbackarg.query = plansource->query_string;
2479 
2480  /*
2481  * If this is a one-shot plan, we still need to do parse analysis.
2482  */
2483  if (plan->oneshot)
2484  {
2485  RawStmt *parsetree = plansource->raw_parse_tree;
2486  const char *src = plansource->query_string;
2487  List *querytree_list;
2488 
2489  /*
2490  * Parameter datatypes are driven by parserSetup hook if provided,
2491  * otherwise we use the fixed parameter list.
2492  */
2493  if (parsetree == NULL)
2494  querytree_list = NIL;
2495  else if (plan->parserSetup != NULL)
2496  {
2497  Assert(plan->nargs == 0);
2498  querytree_list = pg_analyze_and_rewrite_withcb(parsetree,
2499  src,
2500  plan->parserSetup,
2501  plan->parserSetupArg,
2503  }
2504  else
2505  {
2506  querytree_list = pg_analyze_and_rewrite_fixedparams(parsetree,
2507  src,
2508  plan->argtypes,
2509  plan->nargs,
2511  }
2512 
2513  /* Finish filling in the CachedPlanSource */
2514  CompleteCachedPlan(plansource,
2515  querytree_list,
2516  NULL,
2517  plan->argtypes,
2518  plan->nargs,
2519  plan->parserSetup,
2520  plan->parserSetupArg,
2521  plan->cursor_options,
2522  false); /* not fixed result */
2523  }
2524 
2525  /*
2526  * If asked to, complain when query does not return tuples.
2527  * (Replanning can't change this, so we can check it before that.
2528  * However, we can't check it till after parse analysis, so in the
2529  * case of a one-shot plan this is the earliest we could check.)
2530  */
2531  if (options->must_return_tuples && !plansource->resultDesc)
2532  {
2533  /* try to give a good error message */
2534  const char *cmdtag;
2535 
2536  /* A SELECT without resultDesc must be SELECT INTO */
2537  if (plansource->commandTag == CMDTAG_SELECT)
2538  cmdtag = "SELECT INTO";
2539  else
2540  cmdtag = GetCommandTagName(plansource->commandTag);
2541  ereport(ERROR,
2542  (errcode(ERRCODE_SYNTAX_ERROR),
2543  /* translator: %s is name of a SQL command, eg INSERT */
2544  errmsg("%s query does not return tuples", cmdtag)));
2545  }
2546 
2547  /*
2548  * Replan if needed, and increment plan refcount. If it's a saved
2549  * plan, the refcount must be backed by the plan_owner.
2550  */
2551  cplan = GetCachedPlan(plansource, options->params,
2552  plan_owner, _SPI_current->queryEnv);
2553 
2554  stmt_list = cplan->stmt_list;
2555 
2556  /*
2557  * If we weren't given a specific snapshot to use, and the statement
2558  * list requires a snapshot, set that up.
2559  */
2560  if (snapshot == InvalidSnapshot &&
2561  (list_length(stmt_list) > 1 ||
2562  (list_length(stmt_list) == 1 &&
2564  stmt_list)))))
2565  {
2566  /*
2567  * First, ensure there's a Portal-level snapshot. This back-fills
2568  * the snapshot stack in case the previous operation was a COMMIT
2569  * or ROLLBACK inside a procedure or DO block. (We can't put back
2570  * the Portal snapshot any sooner, or we'd break cases like doing
2571  * SET or LOCK just after COMMIT.) It's enough to check once per
2572  * statement list, since COMMIT/ROLLBACK/CALL/DO can't appear
2573  * within a multi-statement list.
2574  */
2576 
2577  /*
2578  * In the default non-read-only case, get a new per-statement-list
2579  * snapshot, replacing any that we pushed in a previous cycle.
2580  * Skip it when doing non-atomic execution, though (we rely
2581  * entirely on the Portal snapshot in that case).
2582  */
2583  if (!options->read_only && !options->allow_nonatomic)
2584  {
2585  if (pushed_active_snap)
2588  pushed_active_snap = true;
2589  }
2590  }
2591 
2592  foreach(lc2, stmt_list)
2593  {
2594  PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
2595  bool canSetTag = stmt->canSetTag;
2596  DestReceiver *dest;
2597 
2598  /*
2599  * Reset output state. (Note that if a non-SPI receiver is used,
2600  * _SPI_current->processed will stay zero, and that's what we'll
2601  * report to the caller. It's the receiver's job to count tuples
2602  * in that case.)
2603  */
2604  _SPI_current->processed = 0;
2605  _SPI_current->tuptable = NULL;
2606 
2607  /* Check for unsupported cases. */
2608  if (stmt->utilityStmt)
2609  {
2610  if (IsA(stmt->utilityStmt, CopyStmt))
2611  {
2612  CopyStmt *cstmt = (CopyStmt *) stmt->utilityStmt;
2613 
2614  if (cstmt->filename == NULL)
2615  {
2616  my_res = SPI_ERROR_COPY;
2617  goto fail;
2618  }
2619  }
2620  else if (IsA(stmt->utilityStmt, TransactionStmt))
2621  {
2622  my_res = SPI_ERROR_TRANSACTION;
2623  goto fail;
2624  }
2625  }
2626 
2627  if (options->read_only && !CommandIsReadOnly(stmt))
2628  ereport(ERROR,
2629  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2630  /* translator: %s is a SQL statement name */
2631  errmsg("%s is not allowed in a non-volatile function",
2632  CreateCommandName((Node *) stmt))));
2633 
2634  /*
2635  * If not read-only mode, advance the command counter before each
2636  * command and update the snapshot. (But skip it if the snapshot
2637  * isn't under our control.)
2638  */
2639  if (!options->read_only && pushed_active_snap)
2640  {
2643  }
2644 
2645  /*
2646  * Select appropriate tuple receiver. Output from non-canSetTag
2647  * subqueries always goes to the bit bucket.
2648  */
2649  if (!canSetTag)
2651  else if (options->dest)
2652  dest = options->dest;
2653  else
2655 
2656  if (stmt->utilityStmt == NULL)
2657  {
2658  QueryDesc *qdesc;
2659  Snapshot snap;
2660 
2661  if (ActiveSnapshotSet())
2662  snap = GetActiveSnapshot();
2663  else
2664  snap = InvalidSnapshot;
2665 
2666  qdesc = CreateQueryDesc(stmt,
2667  plansource->query_string,
2668  snap, crosscheck_snapshot,
2669  dest,
2670  options->params,
2672  0);
2673  res = _SPI_pquery(qdesc, fire_triggers,
2674  canSetTag ? options->tcount : 0);
2675  FreeQueryDesc(qdesc);
2676  }
2677  else
2678  {
2679  ProcessUtilityContext context;
2680  QueryCompletion qc;
2681 
2682  /*
2683  * If the SPI context is atomic, or we were not told to allow
2684  * nonatomic operations, tell ProcessUtility this is an atomic
2685  * execution context.
2686  */
2687  if (_SPI_current->atomic || !options->allow_nonatomic)
2688  context = PROCESS_UTILITY_QUERY;
2689  else
2691 
2693  ProcessUtility(stmt,
2694  plansource->query_string,
2695  true, /* protect plancache's node tree */
2696  context,
2697  options->params,
2699  dest,
2700  &qc);
2701 
2702  /* Update "processed" if stmt returned tuples */
2703  if (_SPI_current->tuptable)
2705 
2706  res = SPI_OK_UTILITY;
2707 
2708  /*
2709  * Some utility statements return a row count, even though the
2710  * tuples are not returned to the caller.
2711  */
2712  if (IsA(stmt->utilityStmt, CreateTableAsStmt))
2713  {
2714  CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
2715 
2716  if (qc.commandTag == CMDTAG_SELECT)
2718  else
2719  {
2720  /*
2721  * Must be an IF NOT EXISTS that did nothing, or a
2722  * CREATE ... WITH NO DATA.
2723  */
2724  Assert(ctastmt->if_not_exists ||
2725  ctastmt->into->skipData);
2726  _SPI_current->processed = 0;
2727  }
2728 
2729  /*
2730  * For historical reasons, if CREATE TABLE AS was spelled
2731  * as SELECT INTO, return a special return code.
2732  */
2733  if (ctastmt->is_select_into)
2734  res = SPI_OK_SELINTO;
2735  }
2736  else if (IsA(stmt->utilityStmt, CopyStmt))
2737  {
2738  Assert(qc.commandTag == CMDTAG_COPY);
2740  }
2741  }
2742 
2743  /*
2744  * The last canSetTag query sets the status values returned to the
2745  * caller. Be careful to free any tuptables not returned, to
2746  * avoid intra-transaction memory leak.
2747  */
2748  if (canSetTag)
2749  {
2750  my_processed = _SPI_current->processed;
2751  SPI_freetuptable(my_tuptable);
2752  my_tuptable = _SPI_current->tuptable;
2753  my_res = res;
2754  }
2755  else
2756  {
2758  _SPI_current->tuptable = NULL;
2759  }
2760 
2761  /*
2762  * We don't issue a destroy call to the receiver. The SPI and
2763  * None receivers would ignore it anyway, while if the caller
2764  * supplied a receiver, it's not our job to destroy it.
2765  */
2766 
2767  if (res < 0)
2768  {
2769  my_res = res;
2770  goto fail;
2771  }
2772  }
2773 
2774  /* Done with this plan, so release refcount */
2775  ReleaseCachedPlan(cplan, plan_owner);
2776  cplan = NULL;
2777 
2778  /*
2779  * If not read-only mode, advance the command counter after the last
2780  * command. This ensures that its effects are visible, in case it was
2781  * DDL that would affect the next CachedPlanSource.
2782  */
2783  if (!options->read_only)
2785  }
2786 
2787 fail:
2788 
2789  /* Pop the snapshot off the stack if we pushed one */
2790  if (pushed_active_snap)
2792 
2793  /* We no longer need the cached plan refcount, if any */
2794  if (cplan)
2795  ReleaseCachedPlan(cplan, plan_owner);
2796 
2797  /*
2798  * Pop the error context stack
2799  */
2800  error_context_stack = spierrcontext.previous;
2801 
2802  /* Save results for caller */
2803  SPI_processed = my_processed;
2804  SPI_tuptable = my_tuptable;
2805 
2806  /* tuptable now is caller's responsibility, not SPI's */
2807  _SPI_current->tuptable = NULL;
2808 
2809  /*
2810  * If none of the queries had canSetTag, return SPI_OK_REWRITTEN. Prior to
2811  * 8.4, we used return the last query's result code, but not its auxiliary
2812  * results, but that's confusing.
2813  */
2814  if (my_res == 0)
2815  my_res = SPI_OK_REWRITTEN;
2816 
2817  return my_res;
2818 }
2819 
2820 /*
2821  * Convert arrays of query parameters to form wanted by planner and executor
2822  */
2823 static ParamListInfo
2824 _SPI_convert_params(int nargs, Oid *argtypes,
2825  Datum *Values, const char *Nulls)
2826 {
2827  ParamListInfo paramLI;
2828 
2829  if (nargs > 0)
2830  {
2831  paramLI = makeParamList(nargs);
2832 
2833  for (int i = 0; i < nargs; i++)
2834  {
2835  ParamExternData *prm = &paramLI->params[i];
2836 
2837  prm->value = Values[i];
2838  prm->isnull = (Nulls && Nulls[i] == 'n');
2839  prm->pflags = PARAM_FLAG_CONST;
2840  prm->ptype = argtypes[i];
2841  }
2842  }
2843  else
2844  paramLI = NULL;
2845  return paramLI;
2846 }
2847 
2848 static int
2849 _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
2850 {
2851  int operation = queryDesc->operation;
2852  int eflags;
2853  int res;
2854 
2855  switch (operation)
2856  {
2857  case CMD_SELECT:
2858  if (queryDesc->dest->mydest == DestNone)
2859  {
2860  /* Don't return SPI_OK_SELECT if we're discarding result */
2861  res = SPI_OK_UTILITY;
2862  }
2863  else
2864  res = SPI_OK_SELECT;
2865  break;
2866  case CMD_INSERT:
2867  if (queryDesc->plannedstmt->hasReturning)
2869  else
2870  res = SPI_OK_INSERT;
2871  break;
2872  case CMD_DELETE:
2873  if (queryDesc->plannedstmt->hasReturning)
2875  else
2876  res = SPI_OK_DELETE;
2877  break;
2878  case CMD_UPDATE:
2879  if (queryDesc->plannedstmt->hasReturning)
2881  else
2882  res = SPI_OK_UPDATE;
2883  break;
2884  case CMD_MERGE:
2885  res = SPI_OK_MERGE;
2886  break;
2887  default:
2888  return SPI_ERROR_OPUNKNOWN;
2889  }
2890 
2891 #ifdef SPI_EXECUTOR_STATS
2892  if (ShowExecutorStats)
2893  ResetUsage();
2894 #endif
2895 
2896  /* Select execution options */
2897  if (fire_triggers)
2898  eflags = 0; /* default run-to-completion flags */
2899  else
2900  eflags = EXEC_FLAG_SKIP_TRIGGERS;
2901 
2902  ExecutorStart(queryDesc, eflags);
2903 
2904  ExecutorRun(queryDesc, ForwardScanDirection, tcount, true);
2905 
2906  _SPI_current->processed = queryDesc->estate->es_processed;
2907 
2908  if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->hasReturning) &&
2909  queryDesc->dest->mydest == DestSPI)
2910  {
2911  if (_SPI_checktuples())
2912  elog(ERROR, "consistency check on SPI tuple count failed");
2913  }
2914 
2915  ExecutorFinish(queryDesc);
2916  ExecutorEnd(queryDesc);
2917  /* FreeQueryDesc is done by the caller */
2918 
2919 #ifdef SPI_EXECUTOR_STATS
2920  if (ShowExecutorStats)
2921  ShowUsage("SPI EXECUTOR STATS");
2922 #endif
2923 
2924  return res;
2925 }
2926 
2927 /*
2928  * _SPI_error_callback
2929  *
2930  * Add context information when a query invoked via SPI fails
2931  */
2932 static void
2934 {
2935  SPICallbackArg *carg = (SPICallbackArg *) arg;
2936  const char *query = carg->query;
2937  int syntaxerrposition;
2938 
2939  if (query == NULL) /* in case arg wasn't set yet */
2940  return;
2941 
2942  /*
2943  * If there is a syntax error position, convert to internal syntax error;
2944  * otherwise treat the query as an item of context stack
2945  */
2946  syntaxerrposition = geterrposition();
2947  if (syntaxerrposition > 0)
2948  {
2949  errposition(0);
2950  internalerrposition(syntaxerrposition);
2951  internalerrquery(query);
2952  }
2953  else
2954  {
2955  /* Use the parse mode to decide how to describe the query */
2956  switch (carg->mode)
2957  {
2959  errcontext("SQL expression \"%s\"", query);
2960  break;
2964  errcontext("PL/pgSQL assignment \"%s\"", query);
2965  break;
2966  default:
2967  errcontext("SQL statement \"%s\"", query);
2968  break;
2969  }
2970  }
2971 }
2972 
2973 /*
2974  * _SPI_cursor_operation()
2975  *
2976  * Do a FETCH or MOVE in a cursor
2977  */
2978 static void
2979 _SPI_cursor_operation(Portal portal, FetchDirection direction, long count,
2980  DestReceiver *dest)
2981 {
2982  uint64 nfetched;
2983 
2984  /* Check that the portal is valid */
2985  if (!PortalIsValid(portal))
2986  elog(ERROR, "invalid portal in SPI cursor operation");
2987 
2988  /* Push the SPI stack */
2989  if (_SPI_begin_call(true) < 0)
2990  elog(ERROR, "SPI cursor operation called while not connected");
2991 
2992  /* Reset the SPI result (note we deliberately don't touch lastoid) */
2993  SPI_processed = 0;
2994  SPI_tuptable = NULL;
2995  _SPI_current->processed = 0;
2996  _SPI_current->tuptable = NULL;
2997 
2998  /* Run the cursor */
2999  nfetched = PortalRunFetch(portal,
3000  direction,
3001  count,
3002  dest);
3003 
3004  /*
3005  * Think not to combine this store with the preceding function call. If
3006  * the portal contains calls to functions that use SPI, then _SPI_stack is
3007  * likely to move around while the portal runs. When control returns,
3008  * _SPI_current will point to the correct stack entry... but the pointer
3009  * may be different than it was beforehand. So we must be sure to re-fetch
3010  * the pointer after the function call completes.
3011  */
3012  _SPI_current->processed = nfetched;
3013 
3014  if (dest->mydest == DestSPI && _SPI_checktuples())
3015  elog(ERROR, "consistency check on SPI tuple count failed");
3016 
3017  /* Put the result into place for access by caller */
3020 
3021  /* tuptable now is caller's responsibility, not SPI's */
3022  _SPI_current->tuptable = NULL;
3023 
3024  /* Pop the SPI stack */
3025  _SPI_end_call(true);
3026 }
3027 
3028 
3029 static MemoryContext
3031 {
3033 }
3034 
3035 static MemoryContext
3037 {
3039 }
3040 
3041 /*
3042  * _SPI_begin_call: begin a SPI operation within a connected procedure
3043  *
3044  * use_exec is true if we intend to make use of the procedure's execCxt
3045  * during this SPI operation. We'll switch into that context, and arrange
3046  * for it to be cleaned up at _SPI_end_call or if an error occurs.
3047  */
3048 static int
3049 _SPI_begin_call(bool use_exec)
3050 {
3051  if (_SPI_current == NULL)
3052  return SPI_ERROR_UNCONNECTED;
3053 
3054  if (use_exec)
3055  {
3056  /* remember when the Executor operation started */
3058  /* switch to the Executor memory context */
3059  _SPI_execmem();
3060  }
3061 
3062  return 0;
3063 }
3064 
3065 /*
3066  * _SPI_end_call: end a SPI operation within a connected procedure
3067  *
3068  * use_exec must be the same as in the previous _SPI_begin_call
3069  *
3070  * Note: this currently has no failure return cases, so callers don't check
3071  */
3072 static int
3073 _SPI_end_call(bool use_exec)
3074 {
3075  if (use_exec)
3076  {
3077  /* switch to the procedure memory context */
3078  _SPI_procmem();
3079  /* mark Executor context no longer in use */
3081  /* and free Executor memory */
3083  }
3084 
3085  return 0;
3086 }
3087 
3088 static bool
3090 {
3091  uint64 processed = _SPI_current->processed;
3092  SPITupleTable *tuptable = _SPI_current->tuptable;
3093  bool failed = false;
3094 
3095  if (tuptable == NULL) /* spi_dest_startup was not called */
3096  failed = true;
3097  else if (processed != tuptable->numvals)
3098  failed = true;
3099 
3100  return failed;
3101 }
3102 
3103 /*
3104  * Convert a "temporary" SPIPlan into an "unsaved" plan.
3105  *
3106  * The passed _SPI_plan struct is on the stack, and all its subsidiary data
3107  * is in or under the current SPI executor context. Copy the plan into the
3108  * SPI procedure context so it will survive _SPI_end_call(). To minimize
3109  * data copying, this destructively modifies the input plan, by taking the
3110  * plancache entries away from it and reparenting them to the new SPIPlan.
3111  */
3112 static SPIPlanPtr
3114 {
3115  SPIPlanPtr newplan;
3116  MemoryContext parentcxt = _SPI_current->procCxt;
3117  MemoryContext plancxt;
3118  MemoryContext oldcxt;
3119  ListCell *lc;
3120 
3121  /* Assert the input is a temporary SPIPlan */
3122  Assert(plan->magic == _SPI_PLAN_MAGIC);
3123  Assert(plan->plancxt == NULL);
3124  /* One-shot plans can't be saved */
3125  Assert(!plan->oneshot);
3126 
3127  /*
3128  * Create a memory context for the plan, underneath the procedure context.
3129  * We don't expect the plan to be very large.
3130  */
3131  plancxt = AllocSetContextCreate(parentcxt,
3132  "SPI Plan",
3134  oldcxt = MemoryContextSwitchTo(plancxt);
3135 
3136  /* Copy the _SPI_plan struct and subsidiary data into the new context */
3137  newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
3138  newplan->magic = _SPI_PLAN_MAGIC;
3139  newplan->plancxt = plancxt;
3140  newplan->parse_mode = plan->parse_mode;
3141  newplan->cursor_options = plan->cursor_options;
3142  newplan->nargs = plan->nargs;
3143  if (plan->nargs > 0)
3144  {
3145  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
3146  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
3147  }
3148  else
3149  newplan->argtypes = NULL;
3150  newplan->parserSetup = plan->parserSetup;
3151  newplan->parserSetupArg = plan->parserSetupArg;
3152 
3153  /*
3154  * Reparent all the CachedPlanSources into the procedure context. In
3155  * theory this could fail partway through due to the pallocs, but we don't
3156  * care too much since both the procedure context and the executor context
3157  * would go away on error.
3158  */
3159  foreach(lc, plan->plancache_list)
3160  {
3161  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
3162 
3163  CachedPlanSetParentContext(plansource, parentcxt);
3164 
3165  /* Build new list, with list cells in plancxt */
3166  newplan->plancache_list = lappend(newplan->plancache_list, plansource);
3167  }
3168 
3169  MemoryContextSwitchTo(oldcxt);
3170 
3171  /* For safety, unlink the CachedPlanSources from the temporary plan */
3172  plan->plancache_list = NIL;
3173 
3174  return newplan;
3175 }
3176 
3177 /*
3178  * Make a "saved" copy of the given plan.
3179  */
3180 static SPIPlanPtr
3182 {
3183  SPIPlanPtr newplan;
3184  MemoryContext plancxt;
3185  MemoryContext oldcxt;
3186  ListCell *lc;
3187 
3188  /* One-shot plans can't be saved */
3189  Assert(!plan->oneshot);
3190 
3191  /*
3192  * Create a memory context for the plan. We don't expect the plan to be
3193  * very large, so use smaller-than-default alloc parameters. It's a
3194  * transient context until we finish copying everything.
3195  */
3197  "SPI Plan",
3199  oldcxt = MemoryContextSwitchTo(plancxt);
3200 
3201  /* Copy the SPI plan into its own context */
3202  newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
3203  newplan->magic = _SPI_PLAN_MAGIC;
3204  newplan->plancxt = plancxt;
3205  newplan->parse_mode = plan->parse_mode;
3206  newplan->cursor_options = plan->cursor_options;
3207  newplan->nargs = plan->nargs;
3208  if (plan->nargs > 0)
3209  {
3210  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
3211  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
3212  }
3213  else
3214  newplan->argtypes = NULL;
3215  newplan->parserSetup = plan->parserSetup;
3216  newplan->parserSetupArg = plan->parserSetupArg;
3217 
3218  /* Copy all the plancache entries */
3219  foreach(lc, plan->plancache_list)
3220  {
3221  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
3222  CachedPlanSource *newsource;
3223 
3224  newsource = CopyCachedPlan(plansource);
3225  newplan->plancache_list = lappend(newplan->plancache_list, newsource);
3226  }
3227 
3228  MemoryContextSwitchTo(oldcxt);
3229 
3230  /*
3231  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
3232  * component CachedPlanSources as saved. This sequence cannot fail
3233  * partway through, so there's no risk of long-term memory leakage.
3234  */
3235  newplan->saved = true;
3237 
3238  foreach(lc, newplan->plancache_list)
3239  {
3240  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
3241 
3242  SaveCachedPlan(plansource);
3243  }
3244 
3245  return newplan;
3246 }
3247 
3248 /*
3249  * Internal lookup of ephemeral named relation by name.
3250  */
3253 {
3254  /* internal static function; any error is bug in SPI itself */
3255  Assert(name != NULL);
3256 
3257  /* fast exit if no tuplestores have been added */
3258  if (_SPI_current->queryEnv == NULL)
3259  return NULL;
3260 
3261  return get_ENR(_SPI_current->queryEnv, name);
3262 }
3263 
3264 /*
3265  * Register an ephemeral named relation for use by the planner and executor on
3266  * subsequent calls using this SPI connection.
3267  */
3268 int
3270 {
3271  EphemeralNamedRelation match;
3272  int res;
3273 
3274  if (enr == NULL || enr->md.name == NULL)
3275  return SPI_ERROR_ARGUMENT;
3276 
3277  res = _SPI_begin_call(false); /* keep current memory context */
3278  if (res < 0)
3279  return res;
3280 
3281  match = _SPI_find_ENR_by_name(enr->md.name);
3282  if (match)
3284  else
3285  {
3286  if (_SPI_current->queryEnv == NULL)
3288 
3291  }
3292 
3293  _SPI_end_call(false);
3294 
3295  return res;
3296 }
3297 
3298 /*
3299  * Unregister an ephemeral named relation by name. This will probably be a
3300  * rarely used function, since SPI_finish will clear it automatically.
3301  */
3302 int
3304 {
3305  EphemeralNamedRelation match;
3306  int res;
3307 
3308  if (name == NULL)
3309  return SPI_ERROR_ARGUMENT;
3310 
3311  res = _SPI_begin_call(false); /* keep current memory context */
3312  if (res < 0)
3313  return res;
3314 
3315  match = _SPI_find_ENR_by_name(name);
3316  if (match)
3317  {
3320  }
3321  else
3323 
3324  _SPI_end_call(false);
3325 
3326  return res;
3327 }
3328 
3329 /*
3330  * Register the transient relations from 'tdata' using this SPI connection.
3331  * This should be called by PL implementations' trigger handlers after
3332  * connecting, in order to make transition tables visible to any queries run
3333  * in this connection.
3334  */
3335 int
3337 {
3338  if (tdata == NULL)
3339  return SPI_ERROR_ARGUMENT;
3340 
3341  if (tdata->tg_newtable)
3342  {
3345  int rc;
3346 
3347  enr->md.name = tdata->tg_trigger->tgnewtable;
3348  enr->md.reliddesc = tdata->tg_relation->rd_id;
3349  enr->md.tupdesc = NULL;
3352  enr->reldata = tdata->tg_newtable;
3353  rc = SPI_register_relation(enr);
3354  if (rc != SPI_OK_REL_REGISTER)
3355  return rc;
3356  }
3357 
3358  if (tdata->tg_oldtable)
3359  {
3362  int rc;
3363 
3364  enr->md.name = tdata->tg_trigger->tgoldtable;
3365  enr->md.reliddesc = tdata->tg_relation->rd_id;
3366  enr->md.tupdesc = NULL;
3369  enr->reldata = tdata->tg_oldtable;
3370  rc = SPI_register_relation(enr);
3371  if (rc != SPI_OK_REL_REGISTER)
3372  return rc;
3373  }
3374 
3375  return SPI_OK_TD_REGISTER;
3376 }
List * raw_parser(const char *str, RawParseMode mode)
Definition: parser.c:42
static int32 next
Definition: blutils.c:219
static bool Nulls[MAXATTR]
Definition: bootstrap.c:157
#define NameStr(name)
Definition: c.h:682
uint32 SubTransactionId
Definition: c.h:592
#define InvalidSubTransactionId
Definition: c.h:594
size_t Size
Definition: c.h:541
void InitializeQueryCompletion(QueryCompletion *qc)
Definition: cmdtag.c:38
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:45
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:194
DestReceiver * None_Receiver
Definition: dest.c:96
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestSPI
Definition: dest.h:94
@ DestNone
Definition: dest.h:89
int internalerrquery(const char *query)
Definition: elog.c:1318
int internalerrposition(int cursorpos)
Definition: elog.c:1298
int errdetail(const char *fmt,...)
Definition: elog.c:1039
ErrorContextCallback * error_context_stack
Definition: elog.c:94
void ReThrowError(ErrorData *edata)
Definition: elog.c:1735
void FlushErrorState(void)
Definition: elog.c:1651
int errhint(const char *fmt,...)
Definition: elog.c:1153
int geterrposition(void)
Definition: elog.c:1414
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
int errposition(int cursorpos)
Definition: elog.c:1282
ErrorData * CopyErrorData(void)
Definition: elog.c:1557
#define errcontext
Definition: elog.h:192
#define PG_TRY(...)
Definition: elog.h:309
#define WARNING
Definition: elog.h:32
#define PG_END_TRY(...)
Definition: elog.h:334
#define ERROR
Definition: elog.h:35
#define PG_CATCH(...)
Definition: elog.h:319
#define ereport(elevel,...)
Definition: elog.h:145
const char * name
Definition: encode.c:561
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:512
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:461
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:401
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:131
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:300
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:60
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1639
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:239
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:251
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1249
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:984
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:1021
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:1085
static void slist_init(slist_head *head)
Definition: ilist.h:923
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:943
#define slist_container(type, membername, ptr)
Definition: ilist.h:1043
static struct @143 value
long val
Definition: informix.c:664
return false
Definition: isn.c:131
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3331
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2865
MemoryContext TopTransactionContext
Definition: mcxt.c:135
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:519
char * pstrdup(const char *in)
Definition: mcxt.c:1483
void pfree(void *pointer)
Definition: mcxt.c:1306
MemoryContext TopMemoryContext
Definition: mcxt.c:130
void * palloc0(Size size)
Definition: mcxt.c:1230
MemoryContext CurrentMemoryContext
Definition: mcxt.c:124
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1321
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:994
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1470
MemoryContext CacheMemoryContext
Definition: mcxt.c:133
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:376
void * palloc(Size size)
Definition: mcxt.c:1199
MemoryContext PortalContext
Definition: mcxt.c:139
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1459
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:163
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:70
int namestrcmp(Name name, const char *str)
Definition: name.c:247
#define IsA(nodeptr, _type_)
Definition: nodes.h:162
#define copyObject(obj)
Definition: nodes.h:227
@ CMD_MERGE
Definition: nodes.h:263
@ CMD_UTILITY
Definition: nodes.h:264
@ CMD_INSERT
Definition: nodes.h:261
@ CMD_DELETE
Definition: nodes.h:262
@ CMD_UPDATE
Definition: nodes.h:260
@ CMD_SELECT
Definition: nodes.h:259
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
ParamListInfo makeParamList(int numParams)
Definition: params.c:44
ParamListInfo copyParamList(ParamListInfo from)
Definition: params.c:78
#define PARAM_FLAG_CONST
Definition: params.h:88
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:108
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2897
FetchDirection
Definition: parsenodes.h:2932
@ FETCH_FORWARD
Definition: parsenodes.h:2934
@ FETCH_BACKWARD
Definition: parsenodes.h:2935
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2906
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2898
RawParseMode
Definition: parser.h:38
@ RAW_PARSE_PLPGSQL_EXPR
Definition: parser.h:41
@ RAW_PARSE_PLPGSQL_ASSIGN2
Definition: parser.h:43
@ RAW_PARSE_PLPGSQL_ASSIGN1
Definition: parser.h:42
@ RAW_PARSE_PLPGSQL_ASSIGN3
Definition: parser.h:44
@ RAW_PARSE_DEFAULT
Definition: parser.h:39
FormData_pg_attribute
Definition: pg_attribute.h:191
int16 attnum
Definition: pg_attribute.h:83
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
void * arg
#define lfirst(lc)
Definition: pg_list.h:170
#define lfirst_node(type, lc)
Definition: pg_list.h:174
static int list_length(const List *l)
Definition: pg_list.h:150
#define linitial_node(type, l)
Definition: pg_list.h:179
#define NIL
Definition: pg_list.h:66
#define linitial(l)
Definition: pg_list.h:176
static char ** options
static char * buf
Definition: pg_test_fsync.c:67
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)
Definition: plancache.c:1469
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1598
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:498
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:454
void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
Definition: plancache.c:338
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:164
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1141
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1264
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:248
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:1507
#define sprintf
Definition: port.h:240
@ PORTAL_MULTI_QUERY
Definition: portal.h:95
#define PortalIsValid(p)
Definition: portal.h:212
Portal CreateNewPortal(void)
Definition: portalmem.c:236
void HoldPinnedPortals(void)
Definition: portalmem.c:1205
void PortalDrop(Portal portal, bool isTopCommit)
Definition: portalmem.c:469
Portal GetPortalByName(const char *name)
Definition: portalmem.c:131
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)
Definition: portalmem.c:283
Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)
Definition: portalmem.c:176
void ForgetPortalSnapshots(void)
Definition: portalmem.c:1254
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:731
void ShowUsage(const char *title)
Definition: postgres.c:4856
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:638
void ResetUsage(void)
Definition: postgres.c:4849
uintptr_t Datum
Definition: postgres.h:412
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
bool PlannedStmtRequiresSnapshot(PlannedStmt *pstmt)
Definition: pquery.c:1732
void EnsurePortalSnapshotExists(void)
Definition: pquery.c:1780
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:433
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
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1391
EphemeralNamedRelation get_ENR(QueryEnvironment *queryEnv, const char *name)
void unregister_ENR(QueryEnvironment *queryEnv, const char *name)
QueryEnvironment * create_queryEnv(void)
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
@ ENR_NAMED_TUPLESTORE
#define RelationGetRelationName(relation)
Definition: rel.h:535
#define RelationGetNamespace(relation)
Definition: rel.h:542
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
@ ForwardScanDirection
Definition: sdir.h:26
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:251
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:683
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:747
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:817
void PopActiveSnapshot(void)
Definition: snapmgr.c:778
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:735
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:805
#define InvalidSnapshot
Definition: snapshot.h:123
void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
Definition: spi.c:483
void SPI_commit(void)
Definition: spi.c:321
SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions)
Definition: spi.c:864
static int _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options, Snapshot snapshot, Snapshot crosscheck_snapshot, bool fire_triggers)
Definition: spi.c:2389
int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)
Definition: spi.c:731
bool spi_printtup(TupleTableSlot *slot, DestReceiver *self)
Definition: spi.c:2161
static void _SPI_error_callback(void *arg)
Definition: spi.c:2933
char * SPI_getrelname(Relation rel)
Definition: spi.c:1324
CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)
Definition: spi.c:2066
static int _SPI_connected
Definition: spi.c:52
void SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
Definition: spi.c:1848
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan)
Definition: spi.c:3181
void SPI_cursor_move(Portal portal, bool forward, long count)
Definition: spi.c:1819
void SPI_freetuple(HeapTuple tuple)
Definition: spi.c:1377
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:1173
void spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
Definition: spi.c:2113
static int _SPI_end_call(bool use_exec)
Definition: spi.c:3073
bool SPI_plan_is_valid(SPIPlanPtr plan)
Definition: spi.c:1946
void SPI_commit_and_chain(void)
Definition: spi.c:327
bool SPI_is_cursor_plan(SPIPlanPtr plan)
Definition: spi.c:1908
uint64 SPI_processed
Definition: spi.c:45
SPIPlanPtr SPI_prepare_extended(const char *src, const SPIPrepareOptions *options)
Definition: spi.c:900
Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)
Definition: spi.c:1306
static _SPI_connection * _SPI_stack
Definition: spi.c:49
HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)
Definition: spi.c:1072
int SPI_freeplan(SPIPlanPtr plan)
Definition: spi.c:1023
void SPI_rollback_and_chain(void)
Definition: spi.c:420
SPITupleTable * SPI_tuptable
Definition: spi.c:46
static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
Definition: spi.c:2849
Portal SPI_cursor_find(const char *name)
Definition: spi.c:1792
int SPI_unregister_relation(const char *name)
Definition: spi.c:3303
bool SPI_inside_nonatomic_context(void)
Definition: spi.c:582
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2979
int SPI_connect(void)
Definition: spi.c:95
int SPI_execute_snapshot(SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount)
Definition: spi.c:771
int SPI_execute_plan_extended(SPIPlanPtr plan, const SPIExecuteOptions *options)
Definition: spi.c:709
int SPI_result
Definition: spi.c:47
SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)
Definition: spi.c:936
SPIPlanPtr SPI_saveplan(SPIPlanPtr plan)
Definition: spi.c:1001
const char * SPI_result_code_string(int code)
Definition: spi.c:1970
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Definition: spi.c:1804
Portal SPI_cursor_parse_open(const char *name, const char *src, const SPIParseOpenOptions *options)
Definition: spi.c:1531
int SPI_finish(void)
Definition: spi.c:183
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:670
static _SPI_connection * _SPI_current
Definition: spi.c:50
Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen)
Definition: spi.c:1359
int SPI_register_trigger_data(TriggerData *tdata)
Definition: spi.c:3336
static int _SPI_stack_depth
Definition: spi.c:51
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2211
Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)
Definition: spi.c:1523
Portal SPI_cursor_open_with_args(const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions)
Definition: spi.c:1470
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:1384
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
Definition: spi.c:1443
void * SPI_repalloc(void *pointer, Size size)
Definition: spi.c:1345
int SPI_exec(const char *src, long tcount)
Definition: spi.c:628
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:3049
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2824
int SPI_register_relation(EphemeralNamedRelation enr)
Definition: spi.c:3269
HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls)
Definition: spi.c:1104
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition: spi.c:858
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:974
void SPI_cursor_close(Portal portal)
Definition: spi.c:1860
void SPI_pfree(void *pointer)
Definition: spi.c:1352
char * SPI_getnspname(Relation rel)
Definition: spi.c:1330
int SPI_connect_ext(int options)
Definition: spi.c:101
int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
Definition: spi.c:702
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2319
void SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
Definition: spi.c:1833
char * SPI_gettype(TupleDesc tupdesc, int fnumber)
Definition: spi.c:1266
static void _SPI_commit(bool chain)
Definition: spi.c:228
int SPI_execute_extended(const char *src, const SPIExecuteOptions *options)
Definition: spi.c:635
void SPI_rollback(void)
Definition: spi.c:414
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1575
List * SPI_plan_get_plan_sources(SPIPlanPtr plan)
Definition: spi.c:2047
void * SPI_palloc(Size size)
Definition: spi.c:1336
static bool _SPI_checktuples(void)
Definition: spi.c:3089
char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
Definition: spi.c:1218
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:3252
static MemoryContext _SPI_execmem(void)
Definition: spi.c:3030
static MemoryContext _SPI_procmem(void)
Definition: spi.c:3036
int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:810
char * SPI_fname(TupleDesc tupdesc, int fnumber)
Definition: spi.c:1196
void SPI_start_transaction(void)
Definition: spi.c:223
HeapTuple SPI_copytuple(HeapTuple tuple)
Definition: spi.c:1045
int SPI_getargcount(SPIPlanPtr plan)
Definition: spi.c:1888
struct SPICallbackArg SPICallbackArg
void AtEOXact_SPI(bool isCommit)
Definition: spi.c:429
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:594
Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
Definition: spi.c:1250
static void _SPI_rollback(bool chain)
Definition: spi.c:333
Oid SPI_getargtypeid(SPIPlanPtr plan, int argIndex)
Definition: spi.c:1873
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:3113
#define SPI_ERROR_TRANSACTION
Definition: spi.h:75
#define SPI_ERROR_REL_NOT_FOUND
Definition: spi.h:80
#define SPI_ERROR_REL_DUPLICATE
Definition: spi.h:79
#define SPI_OPT_NONATOMIC
Definition: spi.h:101
#define SPI_OK_TD_REGISTER
Definition: spi.h:98
#define SPI_OK_UTILITY
Definition: spi.h:85
#define SPI_OK_REWRITTEN
Definition: spi.h:95
#define SPI_OK_INSERT
Definition: spi.h:88
#define SPI_OK_UPDATE
Definition: spi.h:90
#define SPI_OK_CURSOR
Definition: spi.h:91
#define SPI_OK_FETCH
Definition: spi.h:84
#define SPI_OK_MERGE
Definition: spi.h:99
#define SPI_OK_SELINTO
Definition: spi.h:87
#define SPI_OK_REL_REGISTER
Definition: spi.h:96
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:70
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:94
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:71
#define SPI_OK_DELETE
Definition: spi.h:89
#define SPI_OK_REL_UNREGISTER
Definition: spi.h:97
#define SPI_ERROR_ARGUMENT
Definition: spi.h:73
#define SPI_ERROR_PARAM
Definition: spi.h:74
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:76
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:92
#define SPI_ERROR_COPY
Definition: spi.h:69
#define SPI_OK_CONNECT
Definition: spi.h:82
#define SPI_ERROR_NOOUTFUNC
Definition: spi.h:77
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:93
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:66
#define SPI_OK_FINISH
Definition: spi.h:83
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:78
#define SPI_ERROR_CONNECT
Definition: spi.h:68
#define SPI_OK_SELECT
Definition: spi.h:86
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
struct CachedPlan * gplan
Definition: plancache.h:121
CommandTag commandTag
Definition: plancache.h:101
const char * query_string
Definition: plancache.h:100
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
TupleDesc resultDesc
Definition: plancache.h:108
List * stmt_list
Definition: plancache.h:150
char * filename
Definition: parsenodes.h:2202
IntoClause * into
Definition: parsenodes.h:3498
uint64 es_processed
Definition: execnodes.h:654
EphemeralNamedRelationMetadataData md
EphemeralNameRelationType enrtype
struct ErrorContextCallback * previous
Definition: elog.h:234
void(* callback)(void *arg)
Definition: elog.h:235
ItemPointerData t_self
Definition: htup.h:65
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
ItemPointerData t_ctid
Definition: htup_details.h:160
bool skipData
Definition: primnodes.h:135
Definition: pg_list.h:52
Definition: nodes.h:112
bool isnull
Definition: params.h:93
uint16 pflags
Definition: params.h:94
Datum value
Definition: params.h:92
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125
bool canSetTag
Definition: plannodes.h:61
bool hasReturning
Definition: plannodes.h:57
Node * utilityStmt
Definition: plannodes.h:93
QueryEnvironment * queryEnv
Definition: portal.h:143
MemoryContext portalContext
Definition: portal.h:120
int cursorOptions
Definition: portal.h:147
PortalStrategy strategy
Definition: portal.h:146
uint64 nprocessed
Definition: cmdtag.h:31
CommandTag commandTag
Definition: cmdtag.h:30
DestReceiver * dest
Definition: execdesc.h:41
EState * estate
Definition: execdesc.h:48
CmdType operation
Definition: execdesc.h:36
PlannedStmt * plannedstmt
Definition: execdesc.h:37
Node * stmt
Definition: parsenodes.h:1629
TupleDesc rd_att
Definition: rel.h:111
Oid rd_id
Definition: rel.h:112
const char * query
Definition: spi.c:56
RawParseMode mode
Definition: spi.c:57
uint64 alloced
Definition: spi.h:30
uint64 numvals
Definition: spi.h:27
TupleDesc tupdesc
Definition: spi.h:25
HeapTuple * vals
Definition: spi.h:26
MemoryContext tuptabcxt
Definition: spi.h:31
slist_node next
Definition: spi.h:32
SubTransactionId subid
Definition: spi.h:33
Tuplestorestate * tg_oldtable
Definition: trigger.h:41
Relation tg_relation
Definition: trigger.h:35
Tuplestorestate * tg_newtable
Definition: trigger.h:42
Trigger * tg_trigger
Definition: trigger.h:38
char * tgoldtable
Definition: reltrigger.h:43
char * tgnewtable
Definition: reltrigger.h:44
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
CommandDest mydest
Definition: dest.h:129
SubTransactionId connectSubid
Definition: spi_priv.h:36
uint64 processed
Definition: spi_priv.h:25
SPITupleTable * outer_tuptable
Definition: spi_priv.h:47
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
int outer_result
Definition: spi_priv.h:48
slist_head tuptables
Definition: spi_priv.h:32
uint64 outer_processed
Definition: spi_priv.h:46
MemoryContext execCxt
Definition: spi_priv.h:34
SubTransactionId execSubid
Definition: spi_priv.h:29
MemoryContext procCxt
Definition: spi_priv.h:33
SPITupleTable * tuptable
Definition: spi_priv.h:26
bool internal_xact
Definition: spi_priv.h:42
MemoryContext savedcxt
Definition: spi_priv.h:35
ParserSetupHook parserSetup
Definition: spi_priv.h:101
List * plancache_list
Definition: spi_priv.h:95
bool oneshot
Definition: spi_priv.h:94
int magic
Definition: spi_priv.h:92
bool saved
Definition: spi_priv.h:93
int cursor_options
Definition: spi_priv.h:98
Oid * argtypes
Definition: spi_priv.h:100
int nargs
Definition: spi_priv.h:99
MemoryContext plancxt
Definition: spi_priv.h:96
RawParseMode parse_mode
Definition: spi_priv.h:97
void * parserSetupArg
Definition: spi_priv.h:102
slist_node * cur
Definition: ilist.h:274
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ TYPEOID
Definition: syscache.h:114
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
int64 tuplestore_tuple_count(Tuplestorestate *state)
Definition: tuplestore.c:546
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
Definition: tuptable.h:460
void assign_record_type_typmod(TupleDesc tupDesc)
Definition: typcache.c:1944
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:506
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:101
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2353
static const char * CreateCommandName(Node *parsetree)
Definition: utility.h:103
ProcessUtilityContext
Definition: utility.h:21
@ PROCESS_UTILITY_QUERY_NONATOMIC
Definition: utility.h:24
@ PROCESS_UTILITY_QUERY
Definition: utility.h:23
void SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)
Definition: xact.c:3002
void RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
Definition: xact.c:3010
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:779
void CommandCounterIncrement(void)
Definition: xact.c:1077
void StartTransactionCommand(void)
Definition: xact.c:2925
bool IsSubTransaction(void)
Definition: xact.c:4869
void CommitTransactionCommand(void)
Definition: xact.c:3022
void AbortCurrentTransaction(void)
Definition: xact.c:3293