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