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