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