1 /*-------------------------------------------------------------------------
4 * Server Programming Interface
6 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.215 2010/02/26 02:00:42 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "access/printtup.h"
18 #include "access/sysattr.h"
19 #include "access/xact.h"
20 #include "catalog/heap.h"
21 #include "catalog/pg_type.h"
22 #include "commands/trigger.h"
23 #include "executor/executor.h"
24 #include "executor/spi_priv.h"
25 #include "tcop/pquery.h"
26 #include "tcop/utility.h"
27 #include "utils/builtins.h"
28 #include "utils/datum.h"
29 #include "utils/lsyscache.h"
30 #include "utils/memutils.h"
31 #include "utils/snapmgr.h"
32 #include "utils/syscache.h"
33 #include "utils/typcache.h"
36 uint32 SPI_processed = 0;
37 Oid SPI_lastoid = InvalidOid;
38 SPITupleTable *SPI_tuptable = NULL;
41 static _SPI_connection *_SPI_stack = NULL;
42 static _SPI_connection *_SPI_current = NULL;
43 static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
44 static int _SPI_connected = -1;
45 static int _SPI_curid = -1;
47 static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
48 ParamListInfo paramLI, bool read_only);
50 static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan,
51 ParamListInfo boundParams);
53 static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
54 Snapshot snapshot, Snapshot crosscheck_snapshot,
55 bool read_only, bool fire_triggers, long tcount);
57 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
58 Datum *Values, const char *Nulls,
61 static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, long tcount);
63 static void _SPI_error_callback(void *arg);
65 static void _SPI_cursor_operation(Portal portal,
66 FetchDirection direction, long count,
69 static SPIPlanPtr _SPI_copy_plan(SPIPlanPtr plan, MemoryContext parentcxt);
70 static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan);
72 static int _SPI_begin_call(bool execmem);
73 static int _SPI_end_call(bool procmem);
74 static MemoryContext _SPI_execmem(void);
75 static MemoryContext _SPI_procmem(void);
76 static bool _SPI_checktuples(void);
79 /* =================== interface functions =================== */
87 * When procedure called by Executor _SPI_curid expected to be equal to
90 if (_SPI_curid != _SPI_connected)
91 return SPI_ERROR_CONNECT;
93 if (_SPI_stack == NULL)
95 if (_SPI_connected != -1 || _SPI_stack_depth != 0)
96 elog(ERROR, "SPI stack corrupted");
98 _SPI_stack = (_SPI_connection *)
99 MemoryContextAlloc(TopTransactionContext,
100 newdepth * sizeof(_SPI_connection));
101 _SPI_stack_depth = newdepth;
105 if (_SPI_stack_depth <= 0 || _SPI_stack_depth <= _SPI_connected)
106 elog(ERROR, "SPI stack corrupted");
107 if (_SPI_stack_depth == _SPI_connected + 1)
109 newdepth = _SPI_stack_depth * 2;
110 _SPI_stack = (_SPI_connection *)
112 newdepth * sizeof(_SPI_connection));
113 _SPI_stack_depth = newdepth;
118 * We're entering procedure where _SPI_curid == _SPI_connected - 1
121 Assert(_SPI_connected >= 0 && _SPI_connected < _SPI_stack_depth);
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->procCxt = NULL; /* in case we fail to create 'em */
128 _SPI_current->execCxt = NULL;
129 _SPI_current->connectSubid = GetCurrentSubTransactionId();
132 * Create memory contexts for this procedure
134 * XXX it would be better to use PortalContext as the parent context, but
135 * we may not be inside a portal (consider deferred-trigger execution).
136 * Perhaps CurTransactionContext would do? For now it doesn't matter
137 * because we clean up explicitly in AtEOSubXact_SPI().
139 _SPI_current->procCxt = AllocSetContextCreate(TopTransactionContext,
141 ALLOCSET_DEFAULT_MINSIZE,
142 ALLOCSET_DEFAULT_INITSIZE,
143 ALLOCSET_DEFAULT_MAXSIZE);
144 _SPI_current->execCxt = AllocSetContextCreate(TopTransactionContext,
146 ALLOCSET_DEFAULT_MINSIZE,
147 ALLOCSET_DEFAULT_INITSIZE,
148 ALLOCSET_DEFAULT_MAXSIZE);
149 /* ... and switch to procedure's context */
150 _SPI_current->savedcxt = MemoryContextSwitchTo(_SPI_current->procCxt);
152 return SPI_OK_CONNECT;
160 res = _SPI_begin_call(false); /* live in procedure memory */
164 /* Restore memory context as it was before procedure call */
165 MemoryContextSwitchTo(_SPI_current->savedcxt);
167 /* Release memory used in procedure call */
168 MemoryContextDelete(_SPI_current->execCxt);
169 _SPI_current->execCxt = NULL;
170 MemoryContextDelete(_SPI_current->procCxt);
171 _SPI_current->procCxt = NULL;
174 * Reset result variables, especially SPI_tuptable which is probably
175 * pointing at a just-deleted tuptable
178 SPI_lastoid = InvalidOid;
182 * After _SPI_begin_call _SPI_connected == _SPI_curid. Now we are closing
183 * connection to SPI and returning to upper Executor and so _SPI_connected
184 * must be equal to _SPI_curid.
188 if (_SPI_connected == -1)
191 _SPI_current = &(_SPI_stack[_SPI_connected]);
193 return SPI_OK_FINISH;
197 * Clean up SPI state at transaction commit or abort.
200 AtEOXact_SPI(bool isCommit)
203 * Note that memory contexts belonging to SPI stack entries will be freed
204 * automatically, so we can ignore them here. We just need to restore our
205 * static variables to initial state.
207 if (isCommit && _SPI_connected != -1)
209 (errcode(ERRCODE_WARNING),
210 errmsg("transaction left non-empty SPI stack"),
211 errhint("Check for missing \"SPI_finish\" calls.")));
213 _SPI_current = _SPI_stack = NULL;
214 _SPI_stack_depth = 0;
215 _SPI_connected = _SPI_curid = -1;
217 SPI_lastoid = InvalidOid;
222 * Clean up SPI state at subtransaction commit or abort.
224 * During commit, there shouldn't be any unclosed entries remaining from
225 * the current subtransaction; we emit a warning if any are found.
228 AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
232 while (_SPI_connected >= 0)
234 _SPI_connection *connection = &(_SPI_stack[_SPI_connected]);
236 if (connection->connectSubid != mySubid)
237 break; /* couldn't be any underneath it either */
242 * Release procedure memory explicitly (see note in SPI_connect)
244 if (connection->execCxt)
246 MemoryContextDelete(connection->execCxt);
247 connection->execCxt = NULL;
249 if (connection->procCxt)
251 MemoryContextDelete(connection->procCxt);
252 connection->procCxt = NULL;
256 * Pop the stack entry and reset global variables. Unlike
257 * SPI_finish(), we don't risk switching to memory contexts that might
261 _SPI_curid = _SPI_connected;
262 if (_SPI_connected == -1)
265 _SPI_current = &(_SPI_stack[_SPI_connected]);
267 SPI_lastoid = InvalidOid;
271 if (found && isCommit)
273 (errcode(ERRCODE_WARNING),
274 errmsg("subtransaction left non-empty SPI stack"),
275 errhint("Check for missing \"SPI_finish\" calls.")));
278 * If we are aborting a subtransaction and there is an open SPI context
279 * surrounding the subxact, clean up to prevent memory leakage.
281 if (_SPI_current && !isCommit)
283 /* free Executor memory the same as _SPI_end_call would do */
284 MemoryContextResetAndDeleteChildren(_SPI_current->execCxt);
285 /* throw away any partially created tuple-table */
286 SPI_freetuptable(_SPI_current->tuptable);
287 _SPI_current->tuptable = NULL;
292 /* Pushes SPI stack to allow recursive SPI calls */
299 /* Pops SPI stack to allow recursive SPI calls */
306 /* Conditional push: push only if we're inside a SPI procedure */
308 SPI_push_conditional(void)
310 bool pushed = (_SPI_curid != _SPI_connected);
315 /* We should now be in a state where SPI_connect would succeed */
316 Assert(_SPI_curid == _SPI_connected);
321 /* Conditional pop: pop only if SPI_push_conditional pushed */
323 SPI_pop_conditional(bool pushed)
325 /* We should be in a state where SPI_connect would succeed */
326 Assert(_SPI_curid == _SPI_connected);
331 /* Restore state of SPI stack after aborting a subtransaction */
333 SPI_restore_connection(void)
335 Assert(_SPI_connected >= 0);
336 _SPI_curid = _SPI_connected - 1;
339 /* Parse, plan, and execute a query string */
341 SPI_execute(const char *src, bool read_only, long tcount)
346 if (src == NULL || tcount < 0)
347 return SPI_ERROR_ARGUMENT;
349 res = _SPI_begin_call(true);
353 memset(&plan, 0, sizeof(_SPI_plan));
354 plan.magic = _SPI_PLAN_MAGIC;
355 plan.cursor_options = 0;
357 _SPI_prepare_plan(src, &plan, NULL);
359 res = _SPI_execute_plan(&plan, NULL,
360 InvalidSnapshot, InvalidSnapshot,
361 read_only, true, tcount);
367 /* Obsolete version of SPI_execute */
369 SPI_exec(const char *src, long tcount)
371 return SPI_execute(src, false, tcount);
374 /* Execute a previously prepared plan */
376 SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
377 bool read_only, long tcount)
381 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
382 return SPI_ERROR_ARGUMENT;
384 if (plan->nargs > 0 && Values == NULL)
385 return SPI_ERROR_PARAM;
387 res = _SPI_begin_call(true);
391 res = _SPI_execute_plan(plan,
392 _SPI_convert_params(plan->nargs, plan->argtypes,
395 InvalidSnapshot, InvalidSnapshot,
396 read_only, true, tcount);
402 /* Obsolete version of SPI_execute_plan */
404 SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
406 return SPI_execute_plan(plan, Values, Nulls, false, tcount);
409 /* Execute a previously prepared plan */
411 SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params,
412 bool read_only, long tcount)
416 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
417 return SPI_ERROR_ARGUMENT;
419 res = _SPI_begin_call(true);
423 res = _SPI_execute_plan(plan, params,
424 InvalidSnapshot, InvalidSnapshot,
425 read_only, true, tcount);
432 * SPI_execute_snapshot -- identical to SPI_execute_plan, except that we allow
433 * the caller to specify exactly which snapshots to use, which will be
434 * registered here. Also, the caller may specify that AFTER triggers should be
435 * queued as part of the outer query rather than being fired immediately at the
436 * end of the command.
438 * This is currently not documented in spi.sgml because it is only intended
439 * for use by RI triggers.
441 * Passing snapshot == InvalidSnapshot will select the normal behavior of
442 * fetching a new snapshot for each query.
445 SPI_execute_snapshot(SPIPlanPtr plan,
446 Datum *Values, const char *Nulls,
447 Snapshot snapshot, Snapshot crosscheck_snapshot,
448 bool read_only, bool fire_triggers, long tcount)
452 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
453 return SPI_ERROR_ARGUMENT;
455 if (plan->nargs > 0 && Values == NULL)
456 return SPI_ERROR_PARAM;
458 res = _SPI_begin_call(true);
462 res = _SPI_execute_plan(plan,
463 _SPI_convert_params(plan->nargs, plan->argtypes,
466 snapshot, crosscheck_snapshot,
467 read_only, fire_triggers, tcount);
474 * SPI_execute_with_args -- plan and execute a query with supplied arguments
476 * This is functionally comparable to SPI_prepare followed by
477 * SPI_execute_plan, except that since we know the plan will be used only
478 * once, we can tell the planner to rely on the parameter values as constants.
479 * This eliminates potential performance disadvantages compared to
480 * inserting the parameter values directly into the query text.
483 SPI_execute_with_args(const char *src,
484 int nargs, Oid *argtypes,
485 Datum *Values, const char *Nulls,
486 bool read_only, long tcount)
490 ParamListInfo paramLI;
492 if (src == NULL || nargs < 0 || tcount < 0)
493 return SPI_ERROR_ARGUMENT;
495 if (nargs > 0 && (argtypes == NULL || Values == NULL))
496 return SPI_ERROR_PARAM;
498 res = _SPI_begin_call(true);
502 memset(&plan, 0, sizeof(_SPI_plan));
503 plan.magic = _SPI_PLAN_MAGIC;
504 plan.cursor_options = 0;
506 plan.argtypes = argtypes;
507 plan.parserSetup = NULL;
508 plan.parserSetupArg = NULL;
510 paramLI = _SPI_convert_params(nargs, argtypes,
514 _SPI_prepare_plan(src, &plan, paramLI);
516 /* We don't need to copy the plan since it will be thrown away anyway */
518 res = _SPI_execute_plan(&plan, paramLI,
519 InvalidSnapshot, InvalidSnapshot,
520 read_only, true, tcount);
527 SPI_prepare(const char *src, int nargs, Oid *argtypes)
529 return SPI_prepare_cursor(src, nargs, argtypes, 0);
533 SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
539 if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
541 SPI_result = SPI_ERROR_ARGUMENT;
545 SPI_result = _SPI_begin_call(true);
549 memset(&plan, 0, sizeof(_SPI_plan));
550 plan.magic = _SPI_PLAN_MAGIC;
551 plan.cursor_options = cursorOptions;
553 plan.argtypes = argtypes;
554 plan.parserSetup = NULL;
555 plan.parserSetupArg = NULL;
557 _SPI_prepare_plan(src, &plan, NULL);
559 /* copy plan to procedure context */
560 result = _SPI_copy_plan(&plan, _SPI_current->procCxt);
568 SPI_prepare_params(const char *src,
569 ParserSetupHook parserSetup,
570 void *parserSetupArg,
578 SPI_result = SPI_ERROR_ARGUMENT;
582 SPI_result = _SPI_begin_call(true);
586 memset(&plan, 0, sizeof(_SPI_plan));
587 plan.magic = _SPI_PLAN_MAGIC;
588 plan.cursor_options = cursorOptions;
590 plan.argtypes = NULL;
591 plan.parserSetup = parserSetup;
592 plan.parserSetupArg = parserSetupArg;
594 _SPI_prepare_plan(src, &plan, NULL);
596 /* copy plan to procedure context */
597 result = _SPI_copy_plan(&plan, _SPI_current->procCxt);
605 SPI_saveplan(SPIPlanPtr plan)
609 /* We don't currently support copying an already-saved plan */
610 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || plan->saved)
612 SPI_result = SPI_ERROR_ARGUMENT;
616 SPI_result = _SPI_begin_call(false); /* don't change context */
620 newplan = _SPI_save_plan(plan);
629 SPI_freeplan(SPIPlanPtr plan)
631 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
632 return SPI_ERROR_ARGUMENT;
634 /* If plancache.c owns the plancache entries, we must release them */
639 foreach(lc, plan->plancache_list)
641 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
643 DropCachedPlan(plansource);
647 /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
648 MemoryContextDelete(plan->plancxt);
654 SPI_copytuple(HeapTuple tuple)
656 MemoryContext oldcxt = NULL;
661 SPI_result = SPI_ERROR_ARGUMENT;
665 if (_SPI_curid + 1 == _SPI_connected) /* connected */
667 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
668 elog(ERROR, "SPI stack corrupted");
669 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
672 ctuple = heap_copytuple(tuple);
675 MemoryContextSwitchTo(oldcxt);
681 SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)
683 MemoryContext oldcxt = NULL;
684 HeapTupleHeader dtup;
686 if (tuple == NULL || tupdesc == NULL)
688 SPI_result = SPI_ERROR_ARGUMENT;
692 /* For RECORD results, make sure a typmod has been assigned */
693 if (tupdesc->tdtypeid == RECORDOID &&
694 tupdesc->tdtypmod < 0)
695 assign_record_type_typmod(tupdesc);
697 if (_SPI_curid + 1 == _SPI_connected) /* connected */
699 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
700 elog(ERROR, "SPI stack corrupted");
701 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
704 dtup = (HeapTupleHeader) palloc(tuple->t_len);
705 memcpy((char *) dtup, (char *) tuple->t_data, tuple->t_len);
707 HeapTupleHeaderSetDatumLength(dtup, tuple->t_len);
708 HeapTupleHeaderSetTypeId(dtup, tupdesc->tdtypeid);
709 HeapTupleHeaderSetTypMod(dtup, tupdesc->tdtypmod);
712 MemoryContextSwitchTo(oldcxt);
718 SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
719 Datum *Values, const char *Nulls)
721 MemoryContext oldcxt = NULL;
723 int numberOfAttributes;
728 if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
730 SPI_result = SPI_ERROR_ARGUMENT;
734 if (_SPI_curid + 1 == _SPI_connected) /* connected */
736 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
737 elog(ERROR, "SPI stack corrupted");
738 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
741 numberOfAttributes = rel->rd_att->natts;
742 v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
743 n = (bool *) palloc(numberOfAttributes * sizeof(bool));
745 /* fetch old values and nulls */
746 heap_deform_tuple(tuple, rel->rd_att, v, n);
748 /* replace values and nulls */
749 for (i = 0; i < natts; i++)
751 if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
753 v[attnum[i] - 1] = Values[i];
754 n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n') ? true : false;
757 if (i == natts) /* no errors in *attnum */
759 mtuple = heap_form_tuple(rel->rd_att, v, n);
762 * copy the identification info of the old tuple: t_ctid, t_self, and
765 mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
766 mtuple->t_self = tuple->t_self;
767 mtuple->t_tableOid = tuple->t_tableOid;
768 if (rel->rd_att->tdhasoid)
769 HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
774 SPI_result = SPI_ERROR_NOATTRIBUTE;
781 MemoryContextSwitchTo(oldcxt);
787 SPI_fnumber(TupleDesc tupdesc, const char *fname)
790 Form_pg_attribute sysatt;
792 for (res = 0; res < tupdesc->natts; res++)
794 if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0)
798 sysatt = SystemAttributeByName(fname, true /* "oid" will be accepted */ );
800 return sysatt->attnum;
802 /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
803 return SPI_ERROR_NOATTRIBUTE;
807 SPI_fname(TupleDesc tupdesc, int fnumber)
809 Form_pg_attribute att;
813 if (fnumber > tupdesc->natts || fnumber == 0 ||
814 fnumber <= FirstLowInvalidHeapAttributeNumber)
816 SPI_result = SPI_ERROR_NOATTRIBUTE;
821 att = tupdesc->attrs[fnumber - 1];
823 att = SystemAttributeDefinition(fnumber, true);
825 return pstrdup(NameStr(att->attname));
829 SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
841 if (fnumber > tupdesc->natts || fnumber == 0 ||
842 fnumber <= FirstLowInvalidHeapAttributeNumber)
844 SPI_result = SPI_ERROR_NOATTRIBUTE;
848 origval = heap_getattr(tuple, fnumber, tupdesc, &isnull);
853 typoid = tupdesc->attrs[fnumber - 1]->atttypid;
855 typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
857 getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
860 * If we have a toasted datum, forcibly detoast it here to avoid memory
861 * leakage inside the type's output routine.
864 val = PointerGetDatum(PG_DETOAST_DATUM(origval));
868 result = OidOutputFunctionCall(foutoid, val);
870 /* Clean up detoasted copy, if any */
872 pfree(DatumGetPointer(val));
878 SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
882 if (fnumber > tupdesc->natts || fnumber == 0 ||
883 fnumber <= FirstLowInvalidHeapAttributeNumber)
885 SPI_result = SPI_ERROR_NOATTRIBUTE;
890 return heap_getattr(tuple, fnumber, tupdesc, isnull);
894 SPI_gettype(TupleDesc tupdesc, int fnumber)
902 if (fnumber > tupdesc->natts || fnumber == 0 ||
903 fnumber <= FirstLowInvalidHeapAttributeNumber)
905 SPI_result = SPI_ERROR_NOATTRIBUTE;
910 typoid = tupdesc->attrs[fnumber - 1]->atttypid;
912 typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
914 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
916 if (!HeapTupleIsValid(typeTuple))
918 SPI_result = SPI_ERROR_TYPUNKNOWN;
922 result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
923 ReleaseSysCache(typeTuple);
928 SPI_gettypeid(TupleDesc tupdesc, int fnumber)
932 if (fnumber > tupdesc->natts || fnumber == 0 ||
933 fnumber <= FirstLowInvalidHeapAttributeNumber)
935 SPI_result = SPI_ERROR_NOATTRIBUTE;
940 return tupdesc->attrs[fnumber - 1]->atttypid;
942 return (SystemAttributeDefinition(fnumber, true))->atttypid;
946 SPI_getrelname(Relation rel)
948 return pstrdup(RelationGetRelationName(rel));
952 SPI_getnspname(Relation rel)
954 return get_namespace_name(RelationGetNamespace(rel));
958 SPI_palloc(Size size)
960 MemoryContext oldcxt = NULL;
963 if (_SPI_curid + 1 == _SPI_connected) /* connected */
965 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
966 elog(ERROR, "SPI stack corrupted");
967 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
970 pointer = palloc(size);
973 MemoryContextSwitchTo(oldcxt);
979 SPI_repalloc(void *pointer, Size size)
981 /* No longer need to worry which context chunk was in... */
982 return repalloc(pointer, size);
986 SPI_pfree(void *pointer)
988 /* No longer need to worry which context chunk was in... */
993 SPI_freetuple(HeapTuple tuple)
995 /* No longer need to worry which context tuple was in... */
996 heap_freetuple(tuple);
1000 SPI_freetuptable(SPITupleTable *tuptable)
1002 if (tuptable != NULL)
1003 MemoryContextDelete(tuptable->tuptabcxt);
1010 * Open a prepared SPI plan as a portal
1013 SPI_cursor_open(const char *name, SPIPlanPtr plan,
1014 Datum *Values, const char *Nulls,
1018 ParamListInfo paramLI;
1020 /* build transient ParamListInfo in caller's context */
1021 paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1025 portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1027 /* done with the transient ParamListInfo */
1036 * SPI_cursor_open_with_args()
1038 * Parse and plan a query and open it as a portal. Like SPI_execute_with_args,
1039 * we can tell the planner to rely on the parameter values as constants,
1040 * because the plan will only be used once.
1043 SPI_cursor_open_with_args(const char *name,
1045 int nargs, Oid *argtypes,
1046 Datum *Values, const char *Nulls,
1047 bool read_only, int cursorOptions)
1051 ParamListInfo paramLI;
1053 if (src == NULL || nargs < 0)
1054 elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1056 if (nargs > 0 && (argtypes == NULL || Values == NULL))
1057 elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1059 SPI_result = _SPI_begin_call(true);
1061 elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1063 memset(&plan, 0, sizeof(_SPI_plan));
1064 plan.magic = _SPI_PLAN_MAGIC;
1065 plan.cursor_options = cursorOptions;
1067 plan.argtypes = argtypes;
1068 plan.parserSetup = NULL;
1069 plan.parserSetupArg = NULL;
1071 /* build transient ParamListInfo in executor context */
1072 paramLI = _SPI_convert_params(nargs, argtypes,
1076 _SPI_prepare_plan(src, &plan, paramLI);
1078 /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1080 /* Adjust stack so that SPI_cursor_open_internal doesn't complain */
1083 /* SPI_cursor_open_internal must be called in procedure memory context */
1086 result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
1090 _SPI_end_call(true);
1097 * SPI_cursor_open_with_paramlist()
1099 * Same as SPI_cursor_open except that parameters (if any) are passed
1100 * as a ParamListInfo, which supports dynamic parameter set determination
1103 SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan,
1104 ParamListInfo params, bool read_only)
1106 return SPI_cursor_open_internal(name, plan, params, read_only);
1111 * SPI_cursor_open_internal()
1113 * Common code for SPI_cursor_open variants
1116 SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
1117 ParamListInfo paramLI, bool read_only)
1119 CachedPlanSource *plansource;
1124 MemoryContext oldcontext;
1128 * Check that the plan is something the Portal code will special-case as
1129 * returning one tupleset.
1131 if (!SPI_is_cursor_plan(plan))
1133 /* try to give a good error message */
1134 if (list_length(plan->plancache_list) != 1)
1136 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1137 errmsg("cannot open multi-query plan as cursor")));
1138 plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1140 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1141 /* translator: %s is name of a SQL command, eg INSERT */
1142 errmsg("cannot open %s query as cursor",
1143 plansource->commandTag)));
1146 Assert(list_length(plan->plancache_list) == 1);
1147 plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1149 /* Push the SPI stack */
1150 if (_SPI_begin_call(false) < 0)
1151 elog(ERROR, "SPI_cursor_open called while not connected");
1153 /* Reset SPI result (note we deliberately don't touch lastoid) */
1155 SPI_tuptable = NULL;
1156 _SPI_current->processed = 0;
1157 _SPI_current->tuptable = NULL;
1159 /* Create the portal */
1160 if (name == NULL || name[0] == '\0')
1162 /* Use a random nonconflicting name */
1163 portal = CreateNewPortal();
1167 /* In this path, error if portal of same name already exists */
1168 portal = CreatePortal(name, false, false);
1171 /* Copy the plan's query string into the portal */
1172 query_string = MemoryContextStrdup(PortalGetHeapMemory(portal),
1173 plansource->query_string);
1176 * Note: we mustn't have any failure occur between RevalidateCachedPlan
1177 * and PortalDefineQuery; that would result in leaking our plancache
1182 /* Replan if needed, and increment plan refcount for portal */
1183 cplan = RevalidateCachedPlan(plansource, false);
1184 stmt_list = cplan->stmt_list;
1188 /* No replan, but copy the plan into the portal's context */
1189 oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
1190 stmt_list = copyObject(plansource->plan->stmt_list);
1191 MemoryContextSwitchTo(oldcontext);
1192 cplan = NULL; /* portal shouldn't depend on cplan */
1196 * Set up the portal.
1198 PortalDefineQuery(portal,
1199 NULL, /* no statement name */
1201 plansource->commandTag,
1206 * Set up options for portal. Default SCROLL type is chosen the same way
1207 * as PerformCursorOpen does it.
1209 portal->cursorOptions = plan->cursor_options;
1210 if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
1212 if (list_length(stmt_list) == 1 &&
1213 IsA((Node *) linitial(stmt_list), PlannedStmt) &&
1214 ((PlannedStmt *) linitial(stmt_list))->rowMarks == NIL &&
1215 ExecSupportsBackwardScan(((PlannedStmt *) linitial(stmt_list))->planTree))
1216 portal->cursorOptions |= CURSOR_OPT_SCROLL;
1218 portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
1222 * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with the
1223 * check in transformDeclareCursorStmt because the cursor options might
1224 * not have come through there.
1226 if (portal->cursorOptions & CURSOR_OPT_SCROLL)
1228 if (list_length(stmt_list) == 1 &&
1229 IsA((Node *) linitial(stmt_list), PlannedStmt) &&
1230 ((PlannedStmt *) linitial(stmt_list))->rowMarks != NIL)
1232 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1233 errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1234 errdetail("Scrollable cursors must be READ ONLY.")));
1238 * If told to be read-only, we'd better check for read-only queries. This
1239 * can't be done earlier because we need to look at the finished, planned
1240 * queries. (In particular, we don't want to do it between
1241 * RevalidateCachedPlan and PortalDefineQuery, because throwing an error
1242 * between those steps would result in leaking our plancache refcount.)
1248 foreach(lc, stmt_list)
1250 Node *pstmt = (Node *) lfirst(lc);
1252 if (!CommandIsReadOnly(pstmt))
1254 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1255 /* translator: %s is a SQL statement name */
1256 errmsg("%s is not allowed in a non-volatile function",
1257 CreateCommandTag(pstmt))));
1261 /* Set up the snapshot to use. */
1263 snapshot = GetActiveSnapshot();
1266 CommandCounterIncrement();
1267 snapshot = GetTransactionSnapshot();
1271 * If the plan has parameters, copy them into the portal. Note that this
1272 * must be done after revalidating the plan, because in dynamic parameter
1273 * cases the set of parameters could have changed during re-parsing.
1277 oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
1278 paramLI = copyParamList(paramLI);
1279 MemoryContextSwitchTo(oldcontext);
1283 * Start portal execution.
1285 PortalStart(portal, paramLI, snapshot);
1287 Assert(portal->strategy != PORTAL_MULTI_QUERY);
1289 /* Pop the SPI stack */
1290 _SPI_end_call(false);
1292 /* Return the created portal */
1300 * Find the portal of an existing open cursor
1303 SPI_cursor_find(const char *name)
1305 return GetPortalByName(name);
1310 * SPI_cursor_fetch()
1312 * Fetch rows in a cursor
1315 SPI_cursor_fetch(Portal portal, bool forward, long count)
1317 _SPI_cursor_operation(portal,
1318 forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1319 CreateDestReceiver(DestSPI));
1320 /* we know that the DestSPI receiver doesn't need a destroy call */
1330 SPI_cursor_move(Portal portal, bool forward, long count)
1332 _SPI_cursor_operation(portal,
1333 forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1339 * SPI_scroll_cursor_fetch()
1341 * Fetch rows in a scrollable cursor
1344 SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
1346 _SPI_cursor_operation(portal,
1348 CreateDestReceiver(DestSPI));
1349 /* we know that the DestSPI receiver doesn't need a destroy call */
1354 * SPI_scroll_cursor_move()
1356 * Move in a scrollable cursor
1359 SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
1361 _SPI_cursor_operation(portal, direction, count, None_Receiver);
1366 * SPI_cursor_close()
1371 SPI_cursor_close(Portal portal)
1373 if (!PortalIsValid(portal))
1374 elog(ERROR, "invalid portal in SPI cursor operation");
1376 PortalDrop(portal, false);
1380 * Returns the Oid representing the type id for argument at argIndex. First
1381 * parameter is at index zero.
1384 SPI_getargtypeid(SPIPlanPtr plan, int argIndex)
1386 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1387 argIndex < 0 || argIndex >= plan->nargs)
1389 SPI_result = SPI_ERROR_ARGUMENT;
1392 return plan->argtypes[argIndex];
1396 * Returns the number of arguments for the prepared plan.
1399 SPI_getargcount(SPIPlanPtr plan)
1401 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1403 SPI_result = SPI_ERROR_ARGUMENT;
1410 * Returns true if the plan contains exactly one command
1411 * and that command returns tuples to the caller (eg, SELECT or
1412 * INSERT ... RETURNING, but not SELECT ... INTO). In essence,
1413 * the result indicates if the command can be used with SPI_cursor_open
1416 * plan: A plan previously prepared using SPI_prepare
1419 SPI_is_cursor_plan(SPIPlanPtr plan)
1421 CachedPlanSource *plansource;
1424 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1426 SPI_result = SPI_ERROR_ARGUMENT;
1430 if (list_length(plan->plancache_list) != 1)
1433 return false; /* not exactly 1 pre-rewrite command */
1435 plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1437 /* Need _SPI_begin_call in case replanning invokes SPI-using functions */
1438 SPI_result = _SPI_begin_call(false);
1444 /* Make sure the plan is up to date */
1445 cplan = RevalidateCachedPlan(plansource, true);
1446 ReleaseCachedPlan(cplan, true);
1449 _SPI_end_call(false);
1452 /* Does it return tuples? */
1453 if (plansource->resultDesc)
1460 * SPI_plan_is_valid --- test whether a SPI plan is currently valid
1461 * (that is, not marked as being in need of revalidation).
1463 * See notes for CachedPlanIsValid before using this.
1466 SPI_plan_is_valid(SPIPlanPtr plan)
1468 Assert(plan->magic == _SPI_PLAN_MAGIC);
1473 foreach(lc, plan->plancache_list)
1475 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1477 if (!CachedPlanIsValid(plansource))
1484 /* An unsaved plan is assumed valid for its (short) lifetime */
1490 * SPI_result_code_string --- convert any SPI return code to a string
1492 * This is often useful in error messages. Most callers will probably
1493 * only pass negative (error-case) codes, but for generality we recognize
1494 * the success codes too.
1497 SPI_result_code_string(int code)
1499 static char buf[64];
1503 case SPI_ERROR_CONNECT:
1504 return "SPI_ERROR_CONNECT";
1505 case SPI_ERROR_COPY:
1506 return "SPI_ERROR_COPY";
1507 case SPI_ERROR_OPUNKNOWN:
1508 return "SPI_ERROR_OPUNKNOWN";
1509 case SPI_ERROR_UNCONNECTED:
1510 return "SPI_ERROR_UNCONNECTED";
1511 case SPI_ERROR_ARGUMENT:
1512 return "SPI_ERROR_ARGUMENT";
1513 case SPI_ERROR_PARAM:
1514 return "SPI_ERROR_PARAM";
1515 case SPI_ERROR_TRANSACTION:
1516 return "SPI_ERROR_TRANSACTION";
1517 case SPI_ERROR_NOATTRIBUTE:
1518 return "SPI_ERROR_NOATTRIBUTE";
1519 case SPI_ERROR_NOOUTFUNC:
1520 return "SPI_ERROR_NOOUTFUNC";
1521 case SPI_ERROR_TYPUNKNOWN:
1522 return "SPI_ERROR_TYPUNKNOWN";
1523 case SPI_OK_CONNECT:
1524 return "SPI_OK_CONNECT";
1526 return "SPI_OK_FINISH";
1528 return "SPI_OK_FETCH";
1529 case SPI_OK_UTILITY:
1530 return "SPI_OK_UTILITY";
1532 return "SPI_OK_SELECT";
1533 case SPI_OK_SELINTO:
1534 return "SPI_OK_SELINTO";
1536 return "SPI_OK_INSERT";
1538 return "SPI_OK_DELETE";
1540 return "SPI_OK_UPDATE";
1542 return "SPI_OK_CURSOR";
1543 case SPI_OK_INSERT_RETURNING:
1544 return "SPI_OK_INSERT_RETURNING";
1545 case SPI_OK_DELETE_RETURNING:
1546 return "SPI_OK_DELETE_RETURNING";
1547 case SPI_OK_UPDATE_RETURNING:
1548 return "SPI_OK_UPDATE_RETURNING";
1549 case SPI_OK_REWRITTEN:
1550 return "SPI_OK_REWRITTEN";
1552 /* Unrecognized code ... return something useful ... */
1553 sprintf(buf, "Unrecognized SPI code %d", code);
1557 /* =================== private functions =================== */
1561 * Initialize to receive tuples from Executor into SPITupleTable
1562 * of current SPI procedure
1565 spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
1567 SPITupleTable *tuptable;
1568 MemoryContext oldcxt;
1569 MemoryContext tuptabcxt;
1572 * When called by Executor _SPI_curid expected to be equal to
1575 if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
1576 elog(ERROR, "improper call to spi_dest_startup");
1577 if (_SPI_current != &(_SPI_stack[_SPI_curid]))
1578 elog(ERROR, "SPI stack corrupted");
1580 if (_SPI_current->tuptable != NULL)
1581 elog(ERROR, "improper call to spi_dest_startup");
1583 oldcxt = _SPI_procmem(); /* switch to procedure memory context */
1585 tuptabcxt = AllocSetContextCreate(CurrentMemoryContext,
1587 ALLOCSET_DEFAULT_MINSIZE,
1588 ALLOCSET_DEFAULT_INITSIZE,
1589 ALLOCSET_DEFAULT_MAXSIZE);
1590 MemoryContextSwitchTo(tuptabcxt);
1592 _SPI_current->tuptable = tuptable = (SPITupleTable *)
1593 palloc(sizeof(SPITupleTable));
1594 tuptable->tuptabcxt = tuptabcxt;
1595 tuptable->alloced = tuptable->free = 128;
1596 tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
1597 tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
1599 MemoryContextSwitchTo(oldcxt);
1604 * store tuple retrieved by Executor into SPITupleTable
1605 * of current SPI procedure
1608 spi_printtup(TupleTableSlot *slot, DestReceiver *self)
1610 SPITupleTable *tuptable;
1611 MemoryContext oldcxt;
1614 * When called by Executor _SPI_curid expected to be equal to
1617 if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
1618 elog(ERROR, "improper call to spi_printtup");
1619 if (_SPI_current != &(_SPI_stack[_SPI_curid]))
1620 elog(ERROR, "SPI stack corrupted");
1622 tuptable = _SPI_current->tuptable;
1623 if (tuptable == NULL)
1624 elog(ERROR, "improper call to spi_printtup");
1626 oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
1628 if (tuptable->free == 0)
1630 tuptable->free = 256;
1631 tuptable->alloced += tuptable->free;
1632 tuptable->vals = (HeapTuple *) repalloc(tuptable->vals,
1633 tuptable->alloced * sizeof(HeapTuple));
1636 tuptable->vals[tuptable->alloced - tuptable->free] =
1637 ExecCopySlotTuple(slot);
1640 MemoryContextSwitchTo(oldcxt);
1648 * Parse and plan a querystring.
1650 * At entry, plan->argtypes and plan->nargs (or alternatively plan->parserSetup
1651 * and plan->parserSetupArg) must be valid, as must plan->cursor_options.
1652 * If boundParams isn't NULL then it represents parameter values that are made
1653 * available to the planner (as either estimates or hard values depending on
1654 * their PARAM_FLAG_CONST marking). The boundParams had better match the
1655 * param type information embedded in the plan!
1657 * Results are stored into *plan (specifically, plan->plancache_list).
1658 * Note however that the result trees are all in CurrentMemoryContext
1659 * and need to be copied somewhere to survive.
1662 _SPI_prepare_plan(const char *src, SPIPlanPtr plan, ParamListInfo boundParams)
1664 List *raw_parsetree_list;
1665 List *plancache_list;
1666 ListCell *list_item;
1667 ErrorContextCallback spierrcontext;
1668 int cursor_options = plan->cursor_options;
1671 * Setup error traceback support for ereport()
1673 spierrcontext.callback = _SPI_error_callback;
1674 spierrcontext.arg = (void *) src;
1675 spierrcontext.previous = error_context_stack;
1676 error_context_stack = &spierrcontext;
1679 * Parse the request string into a list of raw parse trees.
1681 raw_parsetree_list = pg_parse_query(src);
1684 * Do parse analysis, rule rewrite, and planning for each raw parsetree,
1685 * then cons up a phony plancache entry for each one.
1687 plancache_list = NIL;
1689 foreach(list_item, raw_parsetree_list)
1691 Node *parsetree = (Node *) lfirst(list_item);
1693 CachedPlanSource *plansource;
1697 * Parameter datatypes are driven by parserSetup hook if provided,
1698 * otherwise we use the fixed parameter list.
1700 if (plan->parserSetup != NULL)
1702 Assert(plan->nargs == 0);
1703 /* Need a copyObject here to keep parser from modifying raw tree */
1704 stmt_list = pg_analyze_and_rewrite_params(copyObject(parsetree),
1707 plan->parserSetupArg);
1711 /* Need a copyObject here to keep parser from modifying raw tree */
1712 stmt_list = pg_analyze_and_rewrite(copyObject(parsetree),
1717 stmt_list = pg_plan_queries(stmt_list, cursor_options, boundParams);
1719 plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1720 cplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
1722 plansource->raw_parse_tree = parsetree;
1723 /* cast-away-const here is a bit ugly, but there's no reason to copy */
1724 plansource->query_string = (char *) src;
1725 plansource->commandTag = CreateCommandTag(parsetree);
1726 plansource->param_types = plan->argtypes;
1727 plansource->num_params = plan->nargs;
1728 plansource->parserSetup = plan->parserSetup;
1729 plansource->parserSetupArg = plan->parserSetupArg;
1730 plansource->fully_planned = true;
1731 plansource->fixed_result = false;
1732 /* no need to set search_path, generation or saved_xmin */
1733 plansource->resultDesc = PlanCacheComputeResultDesc(stmt_list);
1734 plansource->plan = cplan;
1736 cplan->stmt_list = stmt_list;
1737 cplan->fully_planned = true;
1739 plancache_list = lappend(plancache_list, plansource);
1742 plan->plancache_list = plancache_list;
1745 * Pop the error context stack
1747 error_context_stack = spierrcontext.previous;
1751 * Execute the given plan with the given parameter values
1753 * snapshot: query snapshot to use, or InvalidSnapshot for the normal
1754 * behavior of taking a new snapshot for each query.
1755 * crosscheck_snapshot: for RI use, all others pass InvalidSnapshot
1756 * read_only: TRUE for read-only execution (no CommandCounterIncrement)
1757 * fire_triggers: TRUE to fire AFTER triggers at end of query (normal case);
1758 * FALSE means any AFTER triggers are postponed to end of outer query
1759 * tcount: execution tuple-count limit, or 0 for none
1762 _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
1763 Snapshot snapshot, Snapshot crosscheck_snapshot,
1764 bool read_only, bool fire_triggers, long tcount)
1767 uint32 my_processed = 0;
1768 Oid my_lastoid = InvalidOid;
1769 SPITupleTable *my_tuptable = NULL;
1771 bool have_active_snap = ActiveSnapshotSet();
1772 ErrorContextCallback spierrcontext;
1773 CachedPlan *cplan = NULL;
1777 * Setup error traceback support for ereport()
1779 spierrcontext.callback = _SPI_error_callback;
1780 spierrcontext.arg = NULL;
1781 spierrcontext.previous = error_context_stack;
1782 error_context_stack = &spierrcontext;
1784 foreach(lc1, plan->plancache_list)
1786 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
1790 spierrcontext.arg = (void *) plansource->query_string;
1794 /* Replan if needed, and increment plan refcount locally */
1795 cplan = RevalidateCachedPlan(plansource, true);
1796 stmt_list = cplan->stmt_list;
1800 /* No replan here */
1802 stmt_list = plansource->plan->stmt_list;
1805 foreach(lc2, stmt_list)
1807 Node *stmt = (Node *) lfirst(lc2);
1810 bool pushed_active_snap = false;
1812 _SPI_current->processed = 0;
1813 _SPI_current->lastoid = InvalidOid;
1814 _SPI_current->tuptable = NULL;
1816 if (IsA(stmt, PlannedStmt))
1818 canSetTag = ((PlannedStmt *) stmt)->canSetTag;
1822 /* utilities are canSetTag if only thing in list */
1823 canSetTag = (list_length(stmt_list) == 1);
1825 if (IsA(stmt, CopyStmt))
1827 CopyStmt *cstmt = (CopyStmt *) stmt;
1829 if (cstmt->filename == NULL)
1831 my_res = SPI_ERROR_COPY;
1835 else if (IsA(stmt, TransactionStmt))
1837 my_res = SPI_ERROR_TRANSACTION;
1842 if (read_only && !CommandIsReadOnly(stmt))
1844 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1845 /* translator: %s is a SQL statement name */
1846 errmsg("%s is not allowed in a non-volatile function",
1847 CreateCommandTag(stmt))));
1850 * If not read-only mode, advance the command counter before each
1854 CommandCounterIncrement();
1856 dest = CreateDestReceiver(canSetTag ? DestSPI : DestNone);
1858 if (snapshot == InvalidSnapshot)
1861 * Default read_only behavior is to use the entry-time
1862 * ActiveSnapshot, if any; if read-write, grab a full new
1867 if (have_active_snap)
1869 PushActiveSnapshot(GetActiveSnapshot());
1870 pushed_active_snap = true;
1875 PushActiveSnapshot(GetTransactionSnapshot());
1876 pushed_active_snap = true;
1882 * We interpret read_only with a specified snapshot to be
1883 * exactly that snapshot, but read-write means use the snap
1884 * with advancing of command ID.
1887 PushActiveSnapshot(snapshot);
1889 PushUpdatedSnapshot(snapshot);
1890 pushed_active_snap = true;
1893 if (IsA(stmt, PlannedStmt) &&
1894 ((PlannedStmt *) stmt)->utilityStmt == NULL)
1899 if (ActiveSnapshotSet())
1900 snap = GetActiveSnapshot();
1902 snap = InvalidSnapshot;
1904 qdesc = CreateQueryDesc((PlannedStmt *) stmt,
1905 plansource->query_string,
1906 snap, crosscheck_snapshot,
1909 res = _SPI_pquery(qdesc, fire_triggers,
1910 canSetTag ? tcount : 0);
1911 FreeQueryDesc(qdesc);
1915 ProcessUtility(stmt,
1916 plansource->query_string,
1918 false, /* not top level */
1921 /* Update "processed" if stmt returned tuples */
1922 if (_SPI_current->tuptable)
1923 _SPI_current->processed = _SPI_current->tuptable->alloced -
1924 _SPI_current->tuptable->free;
1925 res = SPI_OK_UTILITY;
1928 if (pushed_active_snap)
1929 PopActiveSnapshot();
1932 * The last canSetTag query sets the status values returned to the
1933 * caller. Be careful to free any tuptables not returned, to
1934 * avoid intratransaction memory leak.
1938 my_processed = _SPI_current->processed;
1939 my_lastoid = _SPI_current->lastoid;
1940 SPI_freetuptable(my_tuptable);
1941 my_tuptable = _SPI_current->tuptable;
1946 SPI_freetuptable(_SPI_current->tuptable);
1947 _SPI_current->tuptable = NULL;
1949 /* we know that the receiver doesn't need a destroy call */
1957 /* Done with this plan, so release refcount */
1959 ReleaseCachedPlan(cplan, true);
1963 * If not read-only mode, advance the command counter after the last
1964 * command. This ensures that its effects are visible, in case it was
1965 * DDL that would affect the next CachedPlanSource.
1968 CommandCounterIncrement();
1973 /* We no longer need the cached plan refcount, if any */
1975 ReleaseCachedPlan(cplan, true);
1978 * Pop the error context stack
1980 error_context_stack = spierrcontext.previous;
1982 /* Save results for caller */
1983 SPI_processed = my_processed;
1984 SPI_lastoid = my_lastoid;
1985 SPI_tuptable = my_tuptable;
1987 /* tuptable now is caller's responsibility, not SPI's */
1988 _SPI_current->tuptable = NULL;
1991 * If none of the queries had canSetTag, return SPI_OK_REWRITTEN. Prior to
1992 * 8.4, we used return the last query's result code, but not its auxiliary
1993 * results, but that's confusing.
1996 my_res = SPI_OK_REWRITTEN;
2002 * Convert arrays of query parameters to form wanted by planner and executor
2004 static ParamListInfo
2005 _SPI_convert_params(int nargs, Oid *argtypes,
2006 Datum *Values, const char *Nulls,
2009 ParamListInfo paramLI;
2015 /* sizeof(ParamListInfoData) includes the first array element */
2016 paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
2017 (nargs - 1) *sizeof(ParamExternData));
2018 /* we have static list of params, so no hooks needed */
2019 paramLI->paramFetch = NULL;
2020 paramLI->paramFetchArg = NULL;
2021 paramLI->parserSetup = NULL;
2022 paramLI->parserSetupArg = NULL;
2023 paramLI->numParams = nargs;
2025 for (i = 0; i < nargs; i++)
2027 ParamExternData *prm = ¶mLI->params[i];
2029 prm->value = Values[i];
2030 prm->isnull = (Nulls && Nulls[i] == 'n');
2031 prm->pflags = pflags;
2032 prm->ptype = argtypes[i];
2041 _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, long tcount)
2043 int operation = queryDesc->operation;
2049 Assert(queryDesc->plannedstmt->utilityStmt == NULL);
2050 if (queryDesc->plannedstmt->intoClause) /* select into table? */
2051 res = SPI_OK_SELINTO;
2052 else if (queryDesc->dest->mydest != DestSPI)
2054 /* Don't return SPI_OK_SELECT if we're discarding result */
2055 res = SPI_OK_UTILITY;
2058 res = SPI_OK_SELECT;
2061 if (queryDesc->plannedstmt->hasReturning)
2062 res = SPI_OK_INSERT_RETURNING;
2064 res = SPI_OK_INSERT;
2067 if (queryDesc->plannedstmt->hasReturning)
2068 res = SPI_OK_DELETE_RETURNING;
2070 res = SPI_OK_DELETE;
2073 if (queryDesc->plannedstmt->hasReturning)
2074 res = SPI_OK_UPDATE_RETURNING;
2076 res = SPI_OK_UPDATE;
2079 return SPI_ERROR_OPUNKNOWN;
2082 #ifdef SPI_EXECUTOR_STATS
2083 if (ShowExecutorStats)
2088 AfterTriggerBeginQuery();
2090 ExecutorStart(queryDesc, 0);
2092 ExecutorRun(queryDesc, ForwardScanDirection, tcount);
2094 _SPI_current->processed = queryDesc->estate->es_processed;
2095 _SPI_current->lastoid = queryDesc->estate->es_lastoid;
2097 if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->hasReturning) &&
2098 queryDesc->dest->mydest == DestSPI)
2100 if (_SPI_checktuples())
2101 elog(ERROR, "consistency check on SPI tuple count failed");
2104 /* Take care of any queued AFTER triggers */
2106 AfterTriggerEndQuery(queryDesc->estate);
2108 ExecutorEnd(queryDesc);
2109 /* FreeQueryDesc is done by the caller */
2111 #ifdef SPI_EXECUTOR_STATS
2112 if (ShowExecutorStats)
2113 ShowUsage("SPI EXECUTOR STATS");
2120 * _SPI_error_callback
2122 * Add context information when a query invoked via SPI fails
2125 _SPI_error_callback(void *arg)
2127 const char *query = (const char *) arg;
2128 int syntaxerrposition;
2131 * If there is a syntax error position, convert to internal syntax error;
2132 * otherwise treat the query as an item of context stack
2134 syntaxerrposition = geterrposition();
2135 if (syntaxerrposition > 0)
2138 internalerrposition(syntaxerrposition);
2139 internalerrquery(query);
2142 errcontext("SQL statement \"%s\"", query);
2146 * _SPI_cursor_operation()
2148 * Do a FETCH or MOVE in a cursor
2151 _SPI_cursor_operation(Portal portal, FetchDirection direction, long count,
2156 /* Check that the portal is valid */
2157 if (!PortalIsValid(portal))
2158 elog(ERROR, "invalid portal in SPI cursor operation");
2160 /* Push the SPI stack */
2161 if (_SPI_begin_call(true) < 0)
2162 elog(ERROR, "SPI cursor operation called while not connected");
2164 /* Reset the SPI result (note we deliberately don't touch lastoid) */
2166 SPI_tuptable = NULL;
2167 _SPI_current->processed = 0;
2168 _SPI_current->tuptable = NULL;
2170 /* Run the cursor */
2171 nfetched = PortalRunFetch(portal,
2177 * Think not to combine this store with the preceding function call. If
2178 * the portal contains calls to functions that use SPI, then SPI_stack is
2179 * likely to move around while the portal runs. When control returns,
2180 * _SPI_current will point to the correct stack entry... but the pointer
2181 * may be different than it was beforehand. So we must be sure to re-fetch
2182 * the pointer after the function call completes.
2184 _SPI_current->processed = nfetched;
2186 if (dest->mydest == DestSPI && _SPI_checktuples())
2187 elog(ERROR, "consistency check on SPI tuple count failed");
2189 /* Put the result into place for access by caller */
2190 SPI_processed = _SPI_current->processed;
2191 SPI_tuptable = _SPI_current->tuptable;
2193 /* tuptable now is caller's responsibility, not SPI's */
2194 _SPI_current->tuptable = NULL;
2196 /* Pop the SPI stack */
2197 _SPI_end_call(true);
2201 static MemoryContext
2204 return MemoryContextSwitchTo(_SPI_current->execCxt);
2207 static MemoryContext
2210 return MemoryContextSwitchTo(_SPI_current->procCxt);
2214 * _SPI_begin_call: begin a SPI operation within a connected procedure
2217 _SPI_begin_call(bool execmem)
2219 if (_SPI_curid + 1 != _SPI_connected)
2220 return SPI_ERROR_UNCONNECTED;
2222 if (_SPI_current != &(_SPI_stack[_SPI_curid]))
2223 elog(ERROR, "SPI stack corrupted");
2225 if (execmem) /* switch to the Executor memory context */
2232 * _SPI_end_call: end a SPI operation within a connected procedure
2234 * Note: this currently has no failure return cases, so callers don't check
2237 _SPI_end_call(bool procmem)
2240 * We're returning to procedure where _SPI_curid == _SPI_connected - 1
2244 if (procmem) /* switch to the procedure memory context */
2247 /* and free Executor memory */
2248 MemoryContextResetAndDeleteChildren(_SPI_current->execCxt);
2255 _SPI_checktuples(void)
2257 uint32 processed = _SPI_current->processed;
2258 SPITupleTable *tuptable = _SPI_current->tuptable;
2259 bool failed = false;
2261 if (tuptable == NULL) /* spi_dest_startup was not called */
2263 else if (processed != (tuptable->alloced - tuptable->free))
2270 * Make an "unsaved" copy of the given plan, in a child context of parentcxt.
2273 _SPI_copy_plan(SPIPlanPtr plan, MemoryContext parentcxt)
2276 MemoryContext plancxt;
2277 MemoryContext oldcxt;
2280 Assert(!plan->saved); /* not currently supported */
2283 * Create a memory context for the plan. We don't expect the plan to be
2284 * very large, so use smaller-than-default alloc parameters.
2286 plancxt = AllocSetContextCreate(parentcxt,
2288 ALLOCSET_SMALL_MINSIZE,
2289 ALLOCSET_SMALL_INITSIZE,
2290 ALLOCSET_SMALL_MAXSIZE);
2291 oldcxt = MemoryContextSwitchTo(plancxt);
2293 /* Copy the SPI plan into its own context */
2294 newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2295 newplan->magic = _SPI_PLAN_MAGIC;
2296 newplan->saved = false;
2297 newplan->plancache_list = NIL;
2298 newplan->plancxt = plancxt;
2299 newplan->cursor_options = plan->cursor_options;
2300 newplan->nargs = plan->nargs;
2301 if (plan->nargs > 0)
2303 newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2304 memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2307 newplan->argtypes = NULL;
2308 newplan->parserSetup = plan->parserSetup;
2309 newplan->parserSetupArg = plan->parserSetupArg;
2311 foreach(lc, plan->plancache_list)
2313 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2314 CachedPlanSource *newsource;
2316 CachedPlan *newcplan;
2318 /* Note: we assume we don't need to revalidate the plan */
2319 cplan = plansource->plan;
2321 newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
2322 newcplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
2324 newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
2325 newsource->query_string = pstrdup(plansource->query_string);
2326 newsource->commandTag = plansource->commandTag;
2327 newsource->param_types = newplan->argtypes;
2328 newsource->num_params = newplan->nargs;
2329 newsource->parserSetup = newplan->parserSetup;
2330 newsource->parserSetupArg = newplan->parserSetupArg;
2331 newsource->fully_planned = plansource->fully_planned;
2332 newsource->fixed_result = plansource->fixed_result;
2333 /* no need to worry about seach_path, generation or saved_xmin */
2334 if (plansource->resultDesc)
2335 newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
2336 newsource->plan = newcplan;
2338 newcplan->stmt_list = copyObject(cplan->stmt_list);
2339 newcplan->fully_planned = cplan->fully_planned;
2341 newplan->plancache_list = lappend(newplan->plancache_list, newsource);
2344 MemoryContextSwitchTo(oldcxt);
2350 * Make a "saved" copy of the given plan, entrusting everything to plancache.c
2353 _SPI_save_plan(SPIPlanPtr plan)
2356 MemoryContext plancxt;
2357 MemoryContext oldcxt;
2360 Assert(!plan->saved); /* not currently supported */
2363 * Create a memory context for the plan. We don't expect the plan to be
2364 * very large, so use smaller-than-default alloc parameters.
2366 plancxt = AllocSetContextCreate(CacheMemoryContext,
2368 ALLOCSET_SMALL_MINSIZE,
2369 ALLOCSET_SMALL_INITSIZE,
2370 ALLOCSET_SMALL_MAXSIZE);
2371 oldcxt = MemoryContextSwitchTo(plancxt);
2373 /* Copy the SPI plan into its own context */
2374 newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2375 newplan->magic = _SPI_PLAN_MAGIC;
2376 newplan->saved = true;
2377 newplan->plancache_list = NIL;
2378 newplan->plancxt = plancxt;
2379 newplan->cursor_options = plan->cursor_options;
2380 newplan->nargs = plan->nargs;
2381 if (plan->nargs > 0)
2383 newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2384 memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2387 newplan->argtypes = NULL;
2388 newplan->parserSetup = plan->parserSetup;
2389 newplan->parserSetupArg = plan->parserSetupArg;
2391 foreach(lc, plan->plancache_list)
2393 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2394 CachedPlanSource *newsource;
2397 /* Note: we assume we don't need to revalidate the plan */
2398 cplan = plansource->plan;
2400 newsource = CreateCachedPlan(plansource->raw_parse_tree,
2401 plansource->query_string,
2402 plansource->commandTag,
2405 newplan->cursor_options,
2409 if (newplan->parserSetup != NULL)
2410 CachedPlanSetParserHook(newsource,
2411 newplan->parserSetup,
2412 newplan->parserSetupArg);
2414 newplan->plancache_list = lappend(newplan->plancache_list, newsource);
2417 MemoryContextSwitchTo(oldcxt);