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