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