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