1 /*-------------------------------------------------------------------------
4 * Server Programming Interface
6 * Portions Copyright (c) 1996-2009, 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.203 2009/01/01 17:23:42 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "access/printtup.h"
18 #include "access/sysattr.h"
19 #include "catalog/heap.h"
20 #include "commands/trigger.h"
21 #include "executor/spi_priv.h"
22 #include "utils/lsyscache.h"
23 #include "utils/memutils.h"
24 #include "utils/snapmgr.h"
25 #include "utils/typcache.h"
28 uint32 SPI_processed = 0;
29 Oid SPI_lastoid = InvalidOid;
30 SPITupleTable *SPI_tuptable = NULL;
33 static _SPI_connection *_SPI_stack = NULL;
34 static _SPI_connection *_SPI_current = NULL;
35 static int _SPI_stack_depth = 0; /* allocated size of _SPI_stack */
36 static int _SPI_connected = -1;
37 static int _SPI_curid = -1;
39 static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
40 Datum *Values, const char *Nulls,
41 bool read_only, int pflags);
43 static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan,
44 ParamListInfo boundParams);
46 static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
47 Snapshot snapshot, Snapshot crosscheck_snapshot,
48 bool read_only, bool fire_triggers, long tcount);
50 static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes,
51 Datum *Values, const char *Nulls,
54 static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, long tcount);
56 static void _SPI_error_callback(void *arg);
58 static void _SPI_cursor_operation(Portal portal,
59 FetchDirection direction, long count,
62 static SPIPlanPtr _SPI_copy_plan(SPIPlanPtr plan, MemoryContext parentcxt);
63 static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan);
65 static int _SPI_begin_call(bool execmem);
66 static int _SPI_end_call(bool procmem);
67 static MemoryContext _SPI_execmem(void);
68 static MemoryContext _SPI_procmem(void);
69 static bool _SPI_checktuples(void);
72 /* =================== interface functions =================== */
80 * When procedure called by Executor _SPI_curid expected to be equal to
83 if (_SPI_curid != _SPI_connected)
84 return SPI_ERROR_CONNECT;
86 if (_SPI_stack == NULL)
88 if (_SPI_connected != -1 || _SPI_stack_depth != 0)
89 elog(ERROR, "SPI stack corrupted");
91 _SPI_stack = (_SPI_connection *)
92 MemoryContextAlloc(TopTransactionContext,
93 newdepth * sizeof(_SPI_connection));
94 _SPI_stack_depth = newdepth;
98 if (_SPI_stack_depth <= 0 || _SPI_stack_depth <= _SPI_connected)
99 elog(ERROR, "SPI stack corrupted");
100 if (_SPI_stack_depth == _SPI_connected + 1)
102 newdepth = _SPI_stack_depth * 2;
103 _SPI_stack = (_SPI_connection *)
105 newdepth * sizeof(_SPI_connection));
106 _SPI_stack_depth = newdepth;
111 * We're entering procedure where _SPI_curid == _SPI_connected - 1
114 Assert(_SPI_connected >= 0 && _SPI_connected < _SPI_stack_depth);
116 _SPI_current = &(_SPI_stack[_SPI_connected]);
117 _SPI_current->processed = 0;
118 _SPI_current->lastoid = InvalidOid;
119 _SPI_current->tuptable = NULL;
120 _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
121 _SPI_current->execCxt = NULL;
122 _SPI_current->connectSubid = GetCurrentSubTransactionId();
125 * Create memory contexts for this procedure
127 * XXX it would be better to use PortalContext as the parent context, but
128 * we may not be inside a portal (consider deferred-trigger execution).
129 * Perhaps CurTransactionContext would do? For now it doesn't matter
130 * because we clean up explicitly in AtEOSubXact_SPI().
132 _SPI_current->procCxt = AllocSetContextCreate(TopTransactionContext,
134 ALLOCSET_DEFAULT_MINSIZE,
135 ALLOCSET_DEFAULT_INITSIZE,
136 ALLOCSET_DEFAULT_MAXSIZE);
137 _SPI_current->execCxt = AllocSetContextCreate(TopTransactionContext,
139 ALLOCSET_DEFAULT_MINSIZE,
140 ALLOCSET_DEFAULT_INITSIZE,
141 ALLOCSET_DEFAULT_MAXSIZE);
142 /* ... and switch to procedure's context */
143 _SPI_current->savedcxt = MemoryContextSwitchTo(_SPI_current->procCxt);
145 return SPI_OK_CONNECT;
153 res = _SPI_begin_call(false); /* live in procedure memory */
157 /* Restore memory context as it was before procedure call */
158 MemoryContextSwitchTo(_SPI_current->savedcxt);
160 /* Release memory used in procedure call */
161 MemoryContextDelete(_SPI_current->execCxt);
162 _SPI_current->execCxt = NULL;
163 MemoryContextDelete(_SPI_current->procCxt);
164 _SPI_current->procCxt = NULL;
167 * Reset result variables, especially SPI_tuptable which is probably
168 * pointing at a just-deleted tuptable
171 SPI_lastoid = InvalidOid;
175 * After _SPI_begin_call _SPI_connected == _SPI_curid. Now we are closing
176 * connection to SPI and returning to upper Executor and so _SPI_connected
177 * must be equal to _SPI_curid.
181 if (_SPI_connected == -1)
184 _SPI_current = &(_SPI_stack[_SPI_connected]);
186 return SPI_OK_FINISH;
190 * Clean up SPI state at transaction commit or abort.
193 AtEOXact_SPI(bool isCommit)
196 * Note that memory contexts belonging to SPI stack entries will be freed
197 * automatically, so we can ignore them here. We just need to restore our
198 * static variables to initial state.
200 if (isCommit && _SPI_connected != -1)
202 (errcode(ERRCODE_WARNING),
203 errmsg("transaction left non-empty SPI stack"),
204 errhint("Check for missing \"SPI_finish\" calls.")));
206 _SPI_current = _SPI_stack = NULL;
207 _SPI_stack_depth = 0;
208 _SPI_connected = _SPI_curid = -1;
210 SPI_lastoid = InvalidOid;
215 * Clean up SPI state at subtransaction commit or abort.
217 * During commit, there shouldn't be any unclosed entries remaining from
218 * the current subtransaction; we emit a warning if any are found.
221 AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
225 while (_SPI_connected >= 0)
227 _SPI_connection *connection = &(_SPI_stack[_SPI_connected]);
229 if (connection->connectSubid != mySubid)
230 break; /* couldn't be any underneath it either */
235 * Release procedure memory explicitly (see note in SPI_connect)
237 if (connection->execCxt)
239 MemoryContextDelete(connection->execCxt);
240 connection->execCxt = NULL;
242 if (connection->procCxt)
244 MemoryContextDelete(connection->procCxt);
245 connection->procCxt = NULL;
249 * Pop the stack entry and reset global variables. Unlike
250 * SPI_finish(), we don't risk switching to memory contexts that might
254 _SPI_curid = _SPI_connected;
255 if (_SPI_connected == -1)
258 _SPI_current = &(_SPI_stack[_SPI_connected]);
260 SPI_lastoid = InvalidOid;
264 if (found && isCommit)
266 (errcode(ERRCODE_WARNING),
267 errmsg("subtransaction left non-empty SPI stack"),
268 errhint("Check for missing \"SPI_finish\" calls.")));
271 * If we are aborting a subtransaction and there is an open SPI context
272 * surrounding the subxact, clean up to prevent memory leakage.
274 if (_SPI_current && !isCommit)
276 /* free Executor memory the same as _SPI_end_call would do */
277 MemoryContextResetAndDeleteChildren(_SPI_current->execCxt);
278 /* throw away any partially created tuple-table */
279 SPI_freetuptable(_SPI_current->tuptable);
280 _SPI_current->tuptable = NULL;
285 /* Pushes SPI stack to allow recursive SPI calls */
292 /* Pops SPI stack to allow recursive SPI calls */
299 /* Restore state of SPI stack after aborting a subtransaction */
301 SPI_restore_connection(void)
303 Assert(_SPI_connected >= 0);
304 _SPI_curid = _SPI_connected - 1;
307 /* Parse, plan, and execute a query string */
309 SPI_execute(const char *src, bool read_only, long tcount)
314 if (src == NULL || tcount < 0)
315 return SPI_ERROR_ARGUMENT;
317 res = _SPI_begin_call(true);
321 memset(&plan, 0, sizeof(_SPI_plan));
322 plan.magic = _SPI_PLAN_MAGIC;
323 plan.cursor_options = 0;
325 _SPI_prepare_plan(src, &plan, NULL);
327 res = _SPI_execute_plan(&plan, NULL,
328 InvalidSnapshot, InvalidSnapshot,
329 read_only, true, tcount);
335 /* Obsolete version of SPI_execute */
337 SPI_exec(const char *src, long tcount)
339 return SPI_execute(src, false, tcount);
342 /* Execute a previously prepared plan */
344 SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
345 bool read_only, long tcount)
349 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
350 return SPI_ERROR_ARGUMENT;
352 if (plan->nargs > 0 && Values == NULL)
353 return SPI_ERROR_PARAM;
355 res = _SPI_begin_call(true);
359 res = _SPI_execute_plan(plan,
360 _SPI_convert_params(plan->nargs, plan->argtypes,
363 InvalidSnapshot, InvalidSnapshot,
364 read_only, true, tcount);
370 /* Obsolete version of SPI_execute_plan */
372 SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
374 return SPI_execute_plan(plan, Values, Nulls, false, tcount);
378 * SPI_execute_snapshot -- identical to SPI_execute_plan, except that we allow
379 * the caller to specify exactly which snapshots to use, which will be
380 * registered here. Also, the caller may specify that AFTER triggers should be
381 * queued as part of the outer query rather than being fired immediately at the
382 * end of the command.
384 * This is currently not documented in spi.sgml because it is only intended
385 * for use by RI triggers.
387 * Passing snapshot == InvalidSnapshot will select the normal behavior of
388 * fetching a new snapshot for each query.
391 SPI_execute_snapshot(SPIPlanPtr plan,
392 Datum *Values, const char *Nulls,
393 Snapshot snapshot, Snapshot crosscheck_snapshot,
394 bool read_only, bool fire_triggers, long tcount)
398 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
399 return SPI_ERROR_ARGUMENT;
401 if (plan->nargs > 0 && Values == NULL)
402 return SPI_ERROR_PARAM;
404 res = _SPI_begin_call(true);
408 res = _SPI_execute_plan(plan,
409 _SPI_convert_params(plan->nargs, plan->argtypes,
412 snapshot, crosscheck_snapshot,
413 read_only, fire_triggers, tcount);
420 * SPI_execute_with_args -- plan and execute a query with supplied arguments
422 * This is functionally comparable to SPI_prepare followed by
423 * SPI_execute_plan, except that since we know the plan will be used only
424 * once, we can tell the planner to rely on the parameter values as constants.
425 * This eliminates potential performance disadvantages compared to
426 * inserting the parameter values directly into the query text.
429 SPI_execute_with_args(const char *src,
430 int nargs, Oid *argtypes,
431 Datum *Values, const char *Nulls,
432 bool read_only, long tcount)
436 ParamListInfo paramLI;
438 if (src == NULL || nargs < 0 || tcount < 0)
439 return SPI_ERROR_ARGUMENT;
441 if (nargs > 0 && (argtypes == NULL || Values == NULL))
442 return SPI_ERROR_PARAM;
444 res = _SPI_begin_call(true);
448 memset(&plan, 0, sizeof(_SPI_plan));
449 plan.magic = _SPI_PLAN_MAGIC;
450 plan.cursor_options = 0;
452 plan.argtypes = argtypes;
454 paramLI = _SPI_convert_params(nargs, argtypes,
458 _SPI_prepare_plan(src, &plan, paramLI);
460 /* We don't need to copy the plan since it will be thrown away anyway */
462 res = _SPI_execute_plan(&plan, paramLI,
463 InvalidSnapshot, InvalidSnapshot,
464 read_only, true, tcount);
471 SPI_prepare(const char *src, int nargs, Oid *argtypes)
473 return SPI_prepare_cursor(src, nargs, argtypes, 0);
477 SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
483 if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
485 SPI_result = SPI_ERROR_ARGUMENT;
489 SPI_result = _SPI_begin_call(true);
493 memset(&plan, 0, sizeof(_SPI_plan));
494 plan.magic = _SPI_PLAN_MAGIC;
495 plan.cursor_options = cursorOptions;
497 plan.argtypes = argtypes;
499 _SPI_prepare_plan(src, &plan, NULL);
501 /* copy plan to procedure context */
502 result = _SPI_copy_plan(&plan, _SPI_current->procCxt);
510 SPI_saveplan(SPIPlanPtr plan)
514 /* We don't currently support copying an already-saved plan */
515 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || plan->saved)
517 SPI_result = SPI_ERROR_ARGUMENT;
521 SPI_result = _SPI_begin_call(false); /* don't change context */
525 newplan = _SPI_save_plan(plan);
534 SPI_freeplan(SPIPlanPtr plan)
536 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
537 return SPI_ERROR_ARGUMENT;
539 /* If plancache.c owns the plancache entries, we must release them */
544 foreach(lc, plan->plancache_list)
546 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
548 DropCachedPlan(plansource);
552 /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
553 MemoryContextDelete(plan->plancxt);
559 SPI_copytuple(HeapTuple tuple)
561 MemoryContext oldcxt = NULL;
566 SPI_result = SPI_ERROR_ARGUMENT;
570 if (_SPI_curid + 1 == _SPI_connected) /* connected */
572 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
573 elog(ERROR, "SPI stack corrupted");
574 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
577 ctuple = heap_copytuple(tuple);
580 MemoryContextSwitchTo(oldcxt);
586 SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)
588 MemoryContext oldcxt = NULL;
589 HeapTupleHeader dtup;
591 if (tuple == NULL || tupdesc == NULL)
593 SPI_result = SPI_ERROR_ARGUMENT;
597 /* For RECORD results, make sure a typmod has been assigned */
598 if (tupdesc->tdtypeid == RECORDOID &&
599 tupdesc->tdtypmod < 0)
600 assign_record_type_typmod(tupdesc);
602 if (_SPI_curid + 1 == _SPI_connected) /* connected */
604 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
605 elog(ERROR, "SPI stack corrupted");
606 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
609 dtup = (HeapTupleHeader) palloc(tuple->t_len);
610 memcpy((char *) dtup, (char *) tuple->t_data, tuple->t_len);
612 HeapTupleHeaderSetDatumLength(dtup, tuple->t_len);
613 HeapTupleHeaderSetTypeId(dtup, tupdesc->tdtypeid);
614 HeapTupleHeaderSetTypMod(dtup, tupdesc->tdtypmod);
617 MemoryContextSwitchTo(oldcxt);
623 SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
624 Datum *Values, const char *Nulls)
626 MemoryContext oldcxt = NULL;
628 int numberOfAttributes;
633 if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
635 SPI_result = SPI_ERROR_ARGUMENT;
639 if (_SPI_curid + 1 == _SPI_connected) /* connected */
641 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
642 elog(ERROR, "SPI stack corrupted");
643 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
646 numberOfAttributes = rel->rd_att->natts;
647 v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
648 n = (bool *) palloc(numberOfAttributes * sizeof(bool));
650 /* fetch old values and nulls */
651 heap_deform_tuple(tuple, rel->rd_att, v, n);
653 /* replace values and nulls */
654 for (i = 0; i < natts; i++)
656 if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
658 v[attnum[i] - 1] = Values[i];
659 n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n') ? true : false;
662 if (i == natts) /* no errors in *attnum */
664 mtuple = heap_form_tuple(rel->rd_att, v, n);
667 * copy the identification info of the old tuple: t_ctid, t_self, and
670 mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
671 mtuple->t_self = tuple->t_self;
672 mtuple->t_tableOid = tuple->t_tableOid;
673 if (rel->rd_att->tdhasoid)
674 HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
679 SPI_result = SPI_ERROR_NOATTRIBUTE;
686 MemoryContextSwitchTo(oldcxt);
692 SPI_fnumber(TupleDesc tupdesc, const char *fname)
695 Form_pg_attribute sysatt;
697 for (res = 0; res < tupdesc->natts; res++)
699 if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0)
703 sysatt = SystemAttributeByName(fname, true /* "oid" will be accepted */ );
705 return sysatt->attnum;
707 /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
708 return SPI_ERROR_NOATTRIBUTE;
712 SPI_fname(TupleDesc tupdesc, int fnumber)
714 Form_pg_attribute att;
718 if (fnumber > tupdesc->natts || fnumber == 0 ||
719 fnumber <= FirstLowInvalidHeapAttributeNumber)
721 SPI_result = SPI_ERROR_NOATTRIBUTE;
726 att = tupdesc->attrs[fnumber - 1];
728 att = SystemAttributeDefinition(fnumber, true);
730 return pstrdup(NameStr(att->attname));
734 SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
746 if (fnumber > tupdesc->natts || fnumber == 0 ||
747 fnumber <= FirstLowInvalidHeapAttributeNumber)
749 SPI_result = SPI_ERROR_NOATTRIBUTE;
753 origval = heap_getattr(tuple, fnumber, tupdesc, &isnull);
758 typoid = tupdesc->attrs[fnumber - 1]->atttypid;
760 typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
762 getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
765 * If we have a toasted datum, forcibly detoast it here to avoid memory
766 * leakage inside the type's output routine.
769 val = PointerGetDatum(PG_DETOAST_DATUM(origval));
773 result = OidOutputFunctionCall(foutoid, val);
775 /* Clean up detoasted copy, if any */
777 pfree(DatumGetPointer(val));
783 SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
787 if (fnumber > tupdesc->natts || fnumber == 0 ||
788 fnumber <= FirstLowInvalidHeapAttributeNumber)
790 SPI_result = SPI_ERROR_NOATTRIBUTE;
795 return heap_getattr(tuple, fnumber, tupdesc, isnull);
799 SPI_gettype(TupleDesc tupdesc, int fnumber)
807 if (fnumber > tupdesc->natts || fnumber == 0 ||
808 fnumber <= FirstLowInvalidHeapAttributeNumber)
810 SPI_result = SPI_ERROR_NOATTRIBUTE;
815 typoid = tupdesc->attrs[fnumber - 1]->atttypid;
817 typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
819 typeTuple = SearchSysCache(TYPEOID,
820 ObjectIdGetDatum(typoid),
823 if (!HeapTupleIsValid(typeTuple))
825 SPI_result = SPI_ERROR_TYPUNKNOWN;
829 result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
830 ReleaseSysCache(typeTuple);
835 SPI_gettypeid(TupleDesc tupdesc, int fnumber)
839 if (fnumber > tupdesc->natts || fnumber == 0 ||
840 fnumber <= FirstLowInvalidHeapAttributeNumber)
842 SPI_result = SPI_ERROR_NOATTRIBUTE;
847 return tupdesc->attrs[fnumber - 1]->atttypid;
849 return (SystemAttributeDefinition(fnumber, true))->atttypid;
853 SPI_getrelname(Relation rel)
855 return pstrdup(RelationGetRelationName(rel));
859 SPI_getnspname(Relation rel)
861 return get_namespace_name(RelationGetNamespace(rel));
865 SPI_palloc(Size size)
867 MemoryContext oldcxt = NULL;
870 if (_SPI_curid + 1 == _SPI_connected) /* connected */
872 if (_SPI_current != &(_SPI_stack[_SPI_curid + 1]))
873 elog(ERROR, "SPI stack corrupted");
874 oldcxt = MemoryContextSwitchTo(_SPI_current->savedcxt);
877 pointer = palloc(size);
880 MemoryContextSwitchTo(oldcxt);
886 SPI_repalloc(void *pointer, Size size)
888 /* No longer need to worry which context chunk was in... */
889 return repalloc(pointer, size);
893 SPI_pfree(void *pointer)
895 /* No longer need to worry which context chunk was in... */
900 SPI_freetuple(HeapTuple tuple)
902 /* No longer need to worry which context tuple was in... */
903 heap_freetuple(tuple);
907 SPI_freetuptable(SPITupleTable *tuptable)
909 if (tuptable != NULL)
910 MemoryContextDelete(tuptable->tuptabcxt);
917 * Open a prepared SPI plan as a portal
920 SPI_cursor_open(const char *name, SPIPlanPtr plan,
921 Datum *Values, const char *Nulls,
924 return SPI_cursor_open_internal(name, plan, Values, Nulls,
930 * SPI_cursor_open_with_args()
932 * Parse and plan a query and open it as a portal. Like SPI_execute_with_args,
933 * we can tell the planner to rely on the parameter values as constants,
934 * because the plan will only be used once.
937 SPI_cursor_open_with_args(const char *name,
939 int nargs, Oid *argtypes,
940 Datum *Values, const char *Nulls,
941 bool read_only, int cursorOptions)
945 ParamListInfo paramLI;
947 if (src == NULL || nargs < 0)
948 elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
950 if (nargs > 0 && (argtypes == NULL || Values == NULL))
951 elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
953 SPI_result = _SPI_begin_call(true);
955 elog(ERROR, "SPI_cursor_open_with_args called while not connected");
957 memset(&plan, 0, sizeof(_SPI_plan));
958 plan.magic = _SPI_PLAN_MAGIC;
959 plan.cursor_options = cursorOptions;
961 plan.argtypes = argtypes;
963 paramLI = _SPI_convert_params(nargs, argtypes,
967 _SPI_prepare_plan(src, &plan, paramLI);
969 /* We needn't copy the plan; SPI_cursor_open_internal will do so */
971 /* Adjust stack so that SPI_cursor_open_internal doesn't complain */
974 /* SPI_cursor_open_internal must be called in procedure memory context */
977 result = SPI_cursor_open_internal(name, &plan, Values, Nulls,
978 read_only, PARAM_FLAG_CONST);
989 * SPI_cursor_open_internal()
991 * Common code for SPI_cursor_open and SPI_cursor_open_with_args
994 SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
995 Datum *Values, const char *Nulls,
996 bool read_only, int pflags)
998 CachedPlanSource *plansource;
1002 ParamListInfo paramLI;
1004 MemoryContext oldcontext;
1009 * Check that the plan is something the Portal code will special-case as
1010 * returning one tupleset.
1012 if (!SPI_is_cursor_plan(plan))
1014 /* try to give a good error message */
1015 if (list_length(plan->plancache_list) != 1)
1017 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1018 errmsg("cannot open multi-query plan as cursor")));
1019 plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1021 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1022 /* translator: %s is name of a SQL command, eg INSERT */
1023 errmsg("cannot open %s query as cursor",
1024 plansource->commandTag)));
1027 Assert(list_length(plan->plancache_list) == 1);
1028 plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1030 /* Push the SPI stack */
1031 if (_SPI_begin_call(false) < 0)
1032 elog(ERROR, "SPI_cursor_open called while not connected");
1034 /* Reset SPI result (note we deliberately don't touch lastoid) */
1036 SPI_tuptable = NULL;
1037 _SPI_current->processed = 0;
1038 _SPI_current->tuptable = NULL;
1040 /* Create the portal */
1041 if (name == NULL || name[0] == '\0')
1043 /* Use a random nonconflicting name */
1044 portal = CreateNewPortal();
1048 /* In this path, error if portal of same name already exists */
1049 portal = CreatePortal(name, false, false);
1053 * Prepare to copy stuff into the portal's memory context. We do all this
1054 * copying first, because it could possibly fail (out-of-memory) and we
1055 * don't want a failure to occur between RevalidateCachedPlan and
1056 * PortalDefineQuery; that would result in leaking our plancache refcount.
1058 oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
1060 /* Copy the plan's query string into the portal */
1061 query_string = pstrdup(plansource->query_string);
1063 /* If the plan has parameters, copy them into the portal */
1064 if (plan->nargs > 0)
1066 /* sizeof(ParamListInfoData) includes the first array element */
1067 paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
1068 (plan->nargs - 1) *sizeof(ParamExternData));
1069 paramLI->numParams = plan->nargs;
1071 for (k = 0; k < plan->nargs; k++)
1073 ParamExternData *prm = ¶mLI->params[k];
1075 prm->ptype = plan->argtypes[k];
1076 prm->pflags = pflags;
1077 prm->isnull = (Nulls && Nulls[k] == 'n');
1080 /* nulls just copy */
1081 prm->value = Values[k];
1085 /* pass-by-ref values must be copied into portal context */
1089 get_typlenbyval(prm->ptype, ¶mTypLen, ¶mTypByVal);
1090 prm->value = datumCopy(Values[k],
1091 paramTypByVal, paramTypLen);
1098 MemoryContextSwitchTo(oldcontext);
1102 /* Replan if needed, and increment plan refcount for portal */
1103 cplan = RevalidateCachedPlan(plansource, false);
1104 stmt_list = cplan->stmt_list;
1108 /* No replan, but copy the plan into the portal's context */
1109 oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
1110 stmt_list = copyObject(plansource->plan->stmt_list);
1111 MemoryContextSwitchTo(oldcontext);
1112 cplan = NULL; /* portal shouldn't depend on cplan */
1116 * Set up the portal.
1118 PortalDefineQuery(portal,
1119 NULL, /* no statement name */
1121 plansource->commandTag,
1126 * Set up options for portal. Default SCROLL type is chosen the same way
1127 * as PerformCursorOpen does it.
1129 portal->cursorOptions = plan->cursor_options;
1130 if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
1132 if (list_length(stmt_list) == 1 &&
1133 IsA((Node *) linitial(stmt_list), PlannedStmt) &&
1134 ((PlannedStmt *) linitial(stmt_list))->rowMarks == NIL &&
1135 ExecSupportsBackwardScan(((PlannedStmt *) linitial(stmt_list))->planTree))
1136 portal->cursorOptions |= CURSOR_OPT_SCROLL;
1138 portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
1142 * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with the
1143 * check in transformDeclareCursorStmt because the cursor options might
1144 * not have come through there.
1146 if (portal->cursorOptions & CURSOR_OPT_SCROLL)
1148 if (list_length(stmt_list) == 1 &&
1149 IsA((Node *) linitial(stmt_list), PlannedStmt) &&
1150 ((PlannedStmt *) linitial(stmt_list))->rowMarks != NIL)
1152 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1153 errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1154 errdetail("Scrollable cursors must be READ ONLY.")));
1158 * If told to be read-only, we'd better check for read-only queries. This
1159 * can't be done earlier because we need to look at the finished, planned
1160 * queries. (In particular, we don't want to do it between
1161 * RevalidateCachedPlan and PortalDefineQuery, because throwing an error
1162 * between those steps would result in leaking our plancache refcount.)
1168 foreach(lc, stmt_list)
1170 Node *pstmt = (Node *) lfirst(lc);
1172 if (!CommandIsReadOnly(pstmt))
1174 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1175 /* translator: %s is a SQL statement name */
1176 errmsg("%s is not allowed in a non-volatile function",
1177 CreateCommandTag(pstmt))));
1182 * Set up the snapshot to use. (PortalStart will do PushActiveSnapshot, so
1183 * we skip that here.)
1186 snapshot = GetActiveSnapshot();
1189 CommandCounterIncrement();
1190 snapshot = GetTransactionSnapshot();
1194 * Start portal execution.
1196 PortalStart(portal, paramLI, snapshot);
1198 Assert(portal->strategy != PORTAL_MULTI_QUERY);
1200 /* Pop the SPI stack */
1201 _SPI_end_call(false);
1203 /* Return the created portal */
1211 * Find the portal of an existing open cursor
1214 SPI_cursor_find(const char *name)
1216 return GetPortalByName(name);
1221 * SPI_cursor_fetch()
1223 * Fetch rows in a cursor
1226 SPI_cursor_fetch(Portal portal, bool forward, long count)
1228 _SPI_cursor_operation(portal,
1229 forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1230 CreateDestReceiver(DestSPI));
1231 /* we know that the DestSPI receiver doesn't need a destroy call */
1241 SPI_cursor_move(Portal portal, bool forward, long count)
1243 _SPI_cursor_operation(portal,
1244 forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1250 * SPI_scroll_cursor_fetch()
1252 * Fetch rows in a scrollable cursor
1255 SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
1257 _SPI_cursor_operation(portal,
1259 CreateDestReceiver(DestSPI));
1260 /* we know that the DestSPI receiver doesn't need a destroy call */
1265 * SPI_scroll_cursor_move()
1267 * Move in a scrollable cursor
1270 SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
1272 _SPI_cursor_operation(portal, direction, count, None_Receiver);
1277 * SPI_cursor_close()
1282 SPI_cursor_close(Portal portal)
1284 if (!PortalIsValid(portal))
1285 elog(ERROR, "invalid portal in SPI cursor operation");
1287 PortalDrop(portal, false);
1291 * Returns the Oid representing the type id for argument at argIndex. First
1292 * parameter is at index zero.
1295 SPI_getargtypeid(SPIPlanPtr plan, int argIndex)
1297 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1298 argIndex < 0 || argIndex >= plan->nargs)
1300 SPI_result = SPI_ERROR_ARGUMENT;
1303 return plan->argtypes[argIndex];
1307 * Returns the number of arguments for the prepared plan.
1310 SPI_getargcount(SPIPlanPtr plan)
1312 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1314 SPI_result = SPI_ERROR_ARGUMENT;
1321 * Returns true if the plan contains exactly one command
1322 * and that command returns tuples to the caller (eg, SELECT or
1323 * INSERT ... RETURNING, but not SELECT ... INTO). In essence,
1324 * the result indicates if the command can be used with SPI_cursor_open
1327 * plan: A plan previously prepared using SPI_prepare
1330 SPI_is_cursor_plan(SPIPlanPtr plan)
1332 CachedPlanSource *plansource;
1335 if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1337 SPI_result = SPI_ERROR_ARGUMENT;
1341 if (list_length(plan->plancache_list) != 1)
1344 return false; /* not exactly 1 pre-rewrite command */
1346 plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1348 /* Need _SPI_begin_call in case replanning invokes SPI-using functions */
1349 SPI_result = _SPI_begin_call(false);
1355 /* Make sure the plan is up to date */
1356 cplan = RevalidateCachedPlan(plansource, true);
1357 ReleaseCachedPlan(cplan, true);
1360 _SPI_end_call(false);
1363 /* Does it return tuples? */
1364 if (plansource->resultDesc)
1371 * SPI_plan_is_valid --- test whether a SPI plan is currently valid
1372 * (that is, not marked as being in need of revalidation).
1374 * See notes for CachedPlanIsValid before using this.
1377 SPI_plan_is_valid(SPIPlanPtr plan)
1379 Assert(plan->magic == _SPI_PLAN_MAGIC);
1384 foreach(lc, plan->plancache_list)
1386 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1388 if (!CachedPlanIsValid(plansource))
1395 /* An unsaved plan is assumed valid for its (short) lifetime */
1401 * SPI_result_code_string --- convert any SPI return code to a string
1403 * This is often useful in error messages. Most callers will probably
1404 * only pass negative (error-case) codes, but for generality we recognize
1405 * the success codes too.
1408 SPI_result_code_string(int code)
1410 static char buf[64];
1414 case SPI_ERROR_CONNECT:
1415 return "SPI_ERROR_CONNECT";
1416 case SPI_ERROR_COPY:
1417 return "SPI_ERROR_COPY";
1418 case SPI_ERROR_OPUNKNOWN:
1419 return "SPI_ERROR_OPUNKNOWN";
1420 case SPI_ERROR_UNCONNECTED:
1421 return "SPI_ERROR_UNCONNECTED";
1422 case SPI_ERROR_ARGUMENT:
1423 return "SPI_ERROR_ARGUMENT";
1424 case SPI_ERROR_PARAM:
1425 return "SPI_ERROR_PARAM";
1426 case SPI_ERROR_TRANSACTION:
1427 return "SPI_ERROR_TRANSACTION";
1428 case SPI_ERROR_NOATTRIBUTE:
1429 return "SPI_ERROR_NOATTRIBUTE";
1430 case SPI_ERROR_NOOUTFUNC:
1431 return "SPI_ERROR_NOOUTFUNC";
1432 case SPI_ERROR_TYPUNKNOWN:
1433 return "SPI_ERROR_TYPUNKNOWN";
1434 case SPI_OK_CONNECT:
1435 return "SPI_OK_CONNECT";
1437 return "SPI_OK_FINISH";
1439 return "SPI_OK_FETCH";
1440 case SPI_OK_UTILITY:
1441 return "SPI_OK_UTILITY";
1443 return "SPI_OK_SELECT";
1444 case SPI_OK_SELINTO:
1445 return "SPI_OK_SELINTO";
1447 return "SPI_OK_INSERT";
1449 return "SPI_OK_DELETE";
1451 return "SPI_OK_UPDATE";
1453 return "SPI_OK_CURSOR";
1454 case SPI_OK_INSERT_RETURNING:
1455 return "SPI_OK_INSERT_RETURNING";
1456 case SPI_OK_DELETE_RETURNING:
1457 return "SPI_OK_DELETE_RETURNING";
1458 case SPI_OK_UPDATE_RETURNING:
1459 return "SPI_OK_UPDATE_RETURNING";
1461 /* Unrecognized code ... return something useful ... */
1462 sprintf(buf, "Unrecognized SPI code %d", code);
1466 /* =================== private functions =================== */
1470 * Initialize to receive tuples from Executor into SPITupleTable
1471 * of current SPI procedure
1474 spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
1476 SPITupleTable *tuptable;
1477 MemoryContext oldcxt;
1478 MemoryContext tuptabcxt;
1481 * When called by Executor _SPI_curid expected to be equal to
1484 if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
1485 elog(ERROR, "improper call to spi_dest_startup");
1486 if (_SPI_current != &(_SPI_stack[_SPI_curid]))
1487 elog(ERROR, "SPI stack corrupted");
1489 if (_SPI_current->tuptable != NULL)
1490 elog(ERROR, "improper call to spi_dest_startup");
1492 oldcxt = _SPI_procmem(); /* switch to procedure memory context */
1494 tuptabcxt = AllocSetContextCreate(CurrentMemoryContext,
1496 ALLOCSET_DEFAULT_MINSIZE,
1497 ALLOCSET_DEFAULT_INITSIZE,
1498 ALLOCSET_DEFAULT_MAXSIZE);
1499 MemoryContextSwitchTo(tuptabcxt);
1501 _SPI_current->tuptable = tuptable = (SPITupleTable *)
1502 palloc(sizeof(SPITupleTable));
1503 tuptable->tuptabcxt = tuptabcxt;
1504 tuptable->alloced = tuptable->free = 128;
1505 tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
1506 tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
1508 MemoryContextSwitchTo(oldcxt);
1513 * store tuple retrieved by Executor into SPITupleTable
1514 * of current SPI procedure
1517 spi_printtup(TupleTableSlot *slot, DestReceiver *self)
1519 SPITupleTable *tuptable;
1520 MemoryContext oldcxt;
1523 * When called by Executor _SPI_curid expected to be equal to
1526 if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
1527 elog(ERROR, "improper call to spi_printtup");
1528 if (_SPI_current != &(_SPI_stack[_SPI_curid]))
1529 elog(ERROR, "SPI stack corrupted");
1531 tuptable = _SPI_current->tuptable;
1532 if (tuptable == NULL)
1533 elog(ERROR, "improper call to spi_printtup");
1535 oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
1537 if (tuptable->free == 0)
1539 tuptable->free = 256;
1540 tuptable->alloced += tuptable->free;
1541 tuptable->vals = (HeapTuple *) repalloc(tuptable->vals,
1542 tuptable->alloced * sizeof(HeapTuple));
1545 tuptable->vals[tuptable->alloced - tuptable->free] =
1546 ExecCopySlotTuple(slot);
1549 MemoryContextSwitchTo(oldcxt);
1557 * Parse and plan a querystring.
1559 * At entry, plan->argtypes, plan->nargs, and plan->cursor_options must be
1560 * valid. If boundParams isn't NULL then it represents parameter values
1561 * that are made available to the planner (as either estimates or hard values
1562 * depending on their PARAM_FLAG_CONST marking). The boundParams had better
1563 * match the param types embedded in the plan!
1565 * Results are stored into *plan (specifically, plan->plancache_list).
1566 * Note however that the result trees are all in CurrentMemoryContext
1567 * and need to be copied somewhere to survive.
1570 _SPI_prepare_plan(const char *src, SPIPlanPtr plan, ParamListInfo boundParams)
1572 List *raw_parsetree_list;
1573 List *plancache_list;
1574 ListCell *list_item;
1575 ErrorContextCallback spierrcontext;
1576 Oid *argtypes = plan->argtypes;
1577 int nargs = plan->nargs;
1578 int cursor_options = plan->cursor_options;
1581 * Setup error traceback support for ereport()
1583 spierrcontext.callback = _SPI_error_callback;
1584 spierrcontext.arg = (void *) src;
1585 spierrcontext.previous = error_context_stack;
1586 error_context_stack = &spierrcontext;
1589 * Parse the request string into a list of raw parse trees.
1591 raw_parsetree_list = pg_parse_query(src);
1594 * Do parse analysis and rule rewrite for each raw parsetree, then cons up
1595 * a phony plancache entry for each one.
1597 plancache_list = NIL;
1599 foreach(list_item, raw_parsetree_list)
1601 Node *parsetree = (Node *) lfirst(list_item);
1603 CachedPlanSource *plansource;
1606 /* Need a copyObject here to keep parser from modifying raw tree */
1607 stmt_list = pg_analyze_and_rewrite(copyObject(parsetree),
1608 src, argtypes, nargs);
1609 stmt_list = pg_plan_queries(stmt_list, cursor_options, boundParams);
1611 plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1612 cplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
1614 plansource->raw_parse_tree = parsetree;
1615 /* cast-away-const here is a bit ugly, but there's no reason to copy */
1616 plansource->query_string = (char *) src;
1617 plansource->commandTag = CreateCommandTag(parsetree);
1618 plansource->param_types = argtypes;
1619 plansource->num_params = nargs;
1620 plansource->fully_planned = true;
1621 plansource->fixed_result = false;
1622 /* no need to set search_path, generation or saved_xmin */
1623 plansource->resultDesc = PlanCacheComputeResultDesc(stmt_list);
1624 plansource->plan = cplan;
1626 cplan->stmt_list = stmt_list;
1627 cplan->fully_planned = true;
1629 plancache_list = lappend(plancache_list, plansource);
1632 plan->plancache_list = plancache_list;
1635 * Pop the error context stack
1637 error_context_stack = spierrcontext.previous;
1641 * Execute the given plan with the given parameter values
1643 * snapshot: query snapshot to use, or InvalidSnapshot for the normal
1644 * behavior of taking a new snapshot for each query.
1645 * crosscheck_snapshot: for RI use, all others pass InvalidSnapshot
1646 * read_only: TRUE for read-only execution (no CommandCounterIncrement)
1647 * fire_triggers: TRUE to fire AFTER triggers at end of query (normal case);
1648 * FALSE means any AFTER triggers are postponed to end of outer query
1649 * tcount: execution tuple-count limit, or 0 for none
1652 _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
1653 Snapshot snapshot, Snapshot crosscheck_snapshot,
1654 bool read_only, bool fire_triggers, long tcount)
1657 uint32 my_processed = 0;
1658 Oid my_lastoid = InvalidOid;
1659 SPITupleTable *my_tuptable = NULL;
1661 bool have_active_snap = ActiveSnapshotSet();
1662 ErrorContextCallback spierrcontext;
1663 CachedPlan *cplan = NULL;
1667 * Setup error traceback support for ereport()
1669 spierrcontext.callback = _SPI_error_callback;
1670 spierrcontext.arg = NULL;
1671 spierrcontext.previous = error_context_stack;
1672 error_context_stack = &spierrcontext;
1674 foreach(lc1, plan->plancache_list)
1676 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
1680 spierrcontext.arg = (void *) plansource->query_string;
1684 /* Replan if needed, and increment plan refcount locally */
1685 cplan = RevalidateCachedPlan(plansource, true);
1686 stmt_list = cplan->stmt_list;
1690 /* No replan here */
1692 stmt_list = plansource->plan->stmt_list;
1695 foreach(lc2, stmt_list)
1697 Node *stmt = (Node *) lfirst(lc2);
1700 bool pushed_active_snap = false;
1702 _SPI_current->processed = 0;
1703 _SPI_current->lastoid = InvalidOid;
1704 _SPI_current->tuptable = NULL;
1706 if (IsA(stmt, PlannedStmt))
1708 canSetTag = ((PlannedStmt *) stmt)->canSetTag;
1712 /* utilities are canSetTag if only thing in list */
1713 canSetTag = (list_length(stmt_list) == 1);
1715 if (IsA(stmt, CopyStmt))
1717 CopyStmt *cstmt = (CopyStmt *) stmt;
1719 if (cstmt->filename == NULL)
1721 my_res = SPI_ERROR_COPY;
1725 else if (IsA(stmt, TransactionStmt))
1727 my_res = SPI_ERROR_TRANSACTION;
1732 if (read_only && !CommandIsReadOnly(stmt))
1734 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1735 /* translator: %s is a SQL statement name */
1736 errmsg("%s is not allowed in a non-volatile function",
1737 CreateCommandTag(stmt))));
1740 * If not read-only mode, advance the command counter before
1744 CommandCounterIncrement();
1746 dest = CreateDestReceiver(canSetTag ? DestSPI : DestNone);
1748 if (snapshot == InvalidSnapshot)
1751 * Default read_only behavior is to use the entry-time
1752 * ActiveSnapshot, if any; if read-write, grab a full new snap.
1756 if (have_active_snap)
1758 PushActiveSnapshot(GetActiveSnapshot());
1759 pushed_active_snap = true;
1764 PushActiveSnapshot(GetTransactionSnapshot());
1765 pushed_active_snap = true;
1771 * We interpret read_only with a specified snapshot to be
1772 * exactly that snapshot, but read-write means use the
1773 * snap with advancing of command ID.
1776 PushActiveSnapshot(snapshot);
1778 PushUpdatedSnapshot(snapshot);
1779 pushed_active_snap = true;
1782 if (IsA(stmt, PlannedStmt) &&
1783 ((PlannedStmt *) stmt)->utilityStmt == NULL)
1788 if (ActiveSnapshotSet())
1789 snap = GetActiveSnapshot();
1791 snap = InvalidSnapshot;
1793 qdesc = CreateQueryDesc((PlannedStmt *) stmt,
1794 snap, crosscheck_snapshot,
1797 res = _SPI_pquery(qdesc, fire_triggers,
1798 canSetTag ? tcount : 0);
1799 FreeQueryDesc(qdesc);
1803 ProcessUtility(stmt,
1804 plansource->query_string,
1806 false, /* not top level */
1809 /* Update "processed" if stmt returned tuples */
1810 if (_SPI_current->tuptable)
1811 _SPI_current->processed = _SPI_current->tuptable->alloced -
1812 _SPI_current->tuptable->free;
1813 res = SPI_OK_UTILITY;
1816 if (pushed_active_snap)
1817 PopActiveSnapshot();
1820 * The last canSetTag query sets the status values returned to
1821 * the caller. Be careful to free any tuptables not returned,
1822 * to avoid intratransaction memory leak.
1826 my_processed = _SPI_current->processed;
1827 my_lastoid = _SPI_current->lastoid;
1828 SPI_freetuptable(my_tuptable);
1829 my_tuptable = _SPI_current->tuptable;
1834 SPI_freetuptable(_SPI_current->tuptable);
1835 _SPI_current->tuptable = NULL;
1837 /* we know that the receiver doesn't need a destroy call */
1845 /* Done with this plan, so release refcount */
1847 ReleaseCachedPlan(cplan, true);
1851 * If not read-only mode, advance the command counter after the
1852 * last command. This ensures that its effects are visible, in
1853 * case it was DDL that would affect the next CachedPlanSource.
1856 CommandCounterIncrement();
1861 /* We no longer need the cached plan refcount, if any */
1863 ReleaseCachedPlan(cplan, true);
1866 * Pop the error context stack
1868 error_context_stack = spierrcontext.previous;
1870 /* Save results for caller */
1871 SPI_processed = my_processed;
1872 SPI_lastoid = my_lastoid;
1873 SPI_tuptable = my_tuptable;
1875 /* tuptable now is caller's responsibility, not SPI's */
1876 _SPI_current->tuptable = NULL;
1879 * If none of the queries had canSetTag, we return the last query's result
1880 * code, but not its auxiliary results (for backwards compatibility).
1889 * Convert query parameters to form wanted by planner and executor
1891 static ParamListInfo
1892 _SPI_convert_params(int nargs, Oid *argtypes,
1893 Datum *Values, const char *Nulls,
1896 ParamListInfo paramLI;
1902 /* sizeof(ParamListInfoData) includes the first array element */
1903 paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
1904 (nargs - 1) *sizeof(ParamExternData));
1905 paramLI->numParams = nargs;
1907 for (i = 0; i < nargs; i++)
1909 ParamExternData *prm = ¶mLI->params[i];
1911 prm->value = Values[i];
1912 prm->isnull = (Nulls && Nulls[i] == 'n');
1913 prm->pflags = pflags;
1914 prm->ptype = argtypes[i];
1923 _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, long tcount)
1925 int operation = queryDesc->operation;
1931 Assert(queryDesc->plannedstmt->utilityStmt == NULL);
1932 if (queryDesc->plannedstmt->intoClause) /* select into table? */
1933 res = SPI_OK_SELINTO;
1934 else if (queryDesc->dest->mydest != DestSPI)
1936 /* Don't return SPI_OK_SELECT if we're discarding result */
1937 res = SPI_OK_UTILITY;
1940 res = SPI_OK_SELECT;
1943 if (queryDesc->plannedstmt->returningLists)
1944 res = SPI_OK_INSERT_RETURNING;
1946 res = SPI_OK_INSERT;
1949 if (queryDesc->plannedstmt->returningLists)
1950 res = SPI_OK_DELETE_RETURNING;
1952 res = SPI_OK_DELETE;
1955 if (queryDesc->plannedstmt->returningLists)
1956 res = SPI_OK_UPDATE_RETURNING;
1958 res = SPI_OK_UPDATE;
1961 return SPI_ERROR_OPUNKNOWN;
1964 #ifdef SPI_EXECUTOR_STATS
1965 if (ShowExecutorStats)
1970 AfterTriggerBeginQuery();
1972 ExecutorStart(queryDesc, 0);
1974 ExecutorRun(queryDesc, ForwardScanDirection, tcount);
1976 _SPI_current->processed = queryDesc->estate->es_processed;
1977 _SPI_current->lastoid = queryDesc->estate->es_lastoid;
1979 if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->returningLists) &&
1980 queryDesc->dest->mydest == DestSPI)
1982 if (_SPI_checktuples())
1983 elog(ERROR, "consistency check on SPI tuple count failed");
1986 /* Take care of any queued AFTER triggers */
1988 AfterTriggerEndQuery(queryDesc->estate);
1990 ExecutorEnd(queryDesc);
1991 /* FreeQueryDesc is done by the caller */
1993 #ifdef SPI_EXECUTOR_STATS
1994 if (ShowExecutorStats)
1995 ShowUsage("SPI EXECUTOR STATS");
2002 * _SPI_error_callback
2004 * Add context information when a query invoked via SPI fails
2007 _SPI_error_callback(void *arg)
2009 const char *query = (const char *) arg;
2010 int syntaxerrposition;
2013 * If there is a syntax error position, convert to internal syntax error;
2014 * otherwise treat the query as an item of context stack
2016 syntaxerrposition = geterrposition();
2017 if (syntaxerrposition > 0)
2020 internalerrposition(syntaxerrposition);
2021 internalerrquery(query);
2024 errcontext("SQL statement \"%s\"", query);
2028 * _SPI_cursor_operation()
2030 * Do a FETCH or MOVE in a cursor
2033 _SPI_cursor_operation(Portal portal, FetchDirection direction, long count,
2038 /* Check that the portal is valid */
2039 if (!PortalIsValid(portal))
2040 elog(ERROR, "invalid portal in SPI cursor operation");
2042 /* Push the SPI stack */
2043 if (_SPI_begin_call(true) < 0)
2044 elog(ERROR, "SPI cursor operation called while not connected");
2046 /* Reset the SPI result (note we deliberately don't touch lastoid) */
2048 SPI_tuptable = NULL;
2049 _SPI_current->processed = 0;
2050 _SPI_current->tuptable = NULL;
2052 /* Run the cursor */
2053 nfetched = PortalRunFetch(portal,
2059 * Think not to combine this store with the preceding function call. If
2060 * the portal contains calls to functions that use SPI, then SPI_stack is
2061 * likely to move around while the portal runs. When control returns,
2062 * _SPI_current will point to the correct stack entry... but the pointer
2063 * may be different than it was beforehand. So we must be sure to re-fetch
2064 * the pointer after the function call completes.
2066 _SPI_current->processed = nfetched;
2068 if (dest->mydest == DestSPI && _SPI_checktuples())
2069 elog(ERROR, "consistency check on SPI tuple count failed");
2071 /* Put the result into place for access by caller */
2072 SPI_processed = _SPI_current->processed;
2073 SPI_tuptable = _SPI_current->tuptable;
2075 /* tuptable now is caller's responsibility, not SPI's */
2076 _SPI_current->tuptable = NULL;
2078 /* Pop the SPI stack */
2079 _SPI_end_call(true);
2083 static MemoryContext
2086 return MemoryContextSwitchTo(_SPI_current->execCxt);
2089 static MemoryContext
2092 return MemoryContextSwitchTo(_SPI_current->procCxt);
2096 * _SPI_begin_call: begin a SPI operation within a connected procedure
2099 _SPI_begin_call(bool execmem)
2101 if (_SPI_curid + 1 != _SPI_connected)
2102 return SPI_ERROR_UNCONNECTED;
2104 if (_SPI_current != &(_SPI_stack[_SPI_curid]))
2105 elog(ERROR, "SPI stack corrupted");
2107 if (execmem) /* switch to the Executor memory context */
2114 * _SPI_end_call: end a SPI operation within a connected procedure
2116 * Note: this currently has no failure return cases, so callers don't check
2119 _SPI_end_call(bool procmem)
2122 * We're returning to procedure where _SPI_curid == _SPI_connected - 1
2126 if (procmem) /* switch to the procedure memory context */
2129 /* and free Executor memory */
2130 MemoryContextResetAndDeleteChildren(_SPI_current->execCxt);
2137 _SPI_checktuples(void)
2139 uint32 processed = _SPI_current->processed;
2140 SPITupleTable *tuptable = _SPI_current->tuptable;
2141 bool failed = false;
2143 if (tuptable == NULL) /* spi_dest_startup was not called */
2145 else if (processed != (tuptable->alloced - tuptable->free))
2152 * Make an "unsaved" copy of the given plan, in a child context of parentcxt.
2155 _SPI_copy_plan(SPIPlanPtr plan, MemoryContext parentcxt)
2158 MemoryContext plancxt;
2159 MemoryContext oldcxt;
2162 Assert(!plan->saved); /* not currently supported */
2165 * Create a memory context for the plan. We don't expect the plan to be
2166 * very large, so use smaller-than-default alloc parameters.
2168 plancxt = AllocSetContextCreate(parentcxt,
2170 ALLOCSET_SMALL_MINSIZE,
2171 ALLOCSET_SMALL_INITSIZE,
2172 ALLOCSET_SMALL_MAXSIZE);
2173 oldcxt = MemoryContextSwitchTo(plancxt);
2175 /* Copy the SPI plan into its own context */
2176 newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2177 newplan->magic = _SPI_PLAN_MAGIC;
2178 newplan->saved = false;
2179 newplan->plancache_list = NIL;
2180 newplan->plancxt = plancxt;
2181 newplan->cursor_options = plan->cursor_options;
2182 newplan->nargs = plan->nargs;
2183 if (plan->nargs > 0)
2185 newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2186 memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2189 newplan->argtypes = NULL;
2191 foreach(lc, plan->plancache_list)
2193 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2194 CachedPlanSource *newsource;
2196 CachedPlan *newcplan;
2198 /* Note: we assume we don't need to revalidate the plan */
2199 cplan = plansource->plan;
2201 newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
2202 newcplan = (CachedPlan *) palloc0(sizeof(CachedPlan));
2204 newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
2205 newsource->query_string = pstrdup(plansource->query_string);
2206 newsource->commandTag = plansource->commandTag;
2207 newsource->param_types = newplan->argtypes;
2208 newsource->num_params = newplan->nargs;
2209 newsource->fully_planned = plansource->fully_planned;
2210 newsource->fixed_result = plansource->fixed_result;
2211 /* no need to worry about seach_path, generation or saved_xmin */
2212 if (plansource->resultDesc)
2213 newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
2214 newsource->plan = newcplan;
2216 newcplan->stmt_list = copyObject(cplan->stmt_list);
2217 newcplan->fully_planned = cplan->fully_planned;
2219 newplan->plancache_list = lappend(newplan->plancache_list, newsource);
2222 MemoryContextSwitchTo(oldcxt);
2228 * Make a "saved" copy of the given plan, entrusting everything to plancache.c
2231 _SPI_save_plan(SPIPlanPtr plan)
2234 MemoryContext plancxt;
2235 MemoryContext oldcxt;
2238 Assert(!plan->saved); /* not currently supported */
2241 * Create a memory context for the plan. We don't expect the plan to be
2242 * very large, so use smaller-than-default alloc parameters.
2244 plancxt = AllocSetContextCreate(CacheMemoryContext,
2246 ALLOCSET_SMALL_MINSIZE,
2247 ALLOCSET_SMALL_INITSIZE,
2248 ALLOCSET_SMALL_MAXSIZE);
2249 oldcxt = MemoryContextSwitchTo(plancxt);
2251 /* Copy the SPI plan into its own context */
2252 newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2253 newplan->magic = _SPI_PLAN_MAGIC;
2254 newplan->saved = true;
2255 newplan->plancache_list = NIL;
2256 newplan->plancxt = plancxt;
2257 newplan->cursor_options = plan->cursor_options;
2258 newplan->nargs = plan->nargs;
2259 if (plan->nargs > 0)
2261 newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2262 memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2265 newplan->argtypes = NULL;
2267 foreach(lc, plan->plancache_list)
2269 CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2270 CachedPlanSource *newsource;
2273 /* Note: we assume we don't need to revalidate the plan */
2274 cplan = plansource->plan;
2276 newsource = CreateCachedPlan(plansource->raw_parse_tree,
2277 plansource->query_string,
2278 plansource->commandTag,
2281 newplan->cursor_options,
2286 newplan->plancache_list = lappend(newplan->plancache_list, newsource);
2289 MemoryContextSwitchTo(oldcxt);