]> granicus.if.org Git - postgresql/blob - src/backend/executor/functions.c
Simplify and standardize conversions between TEXT datums and ordinary C
[postgresql] / src / backend / executor / functions.c
1 /*-------------------------------------------------------------------------
2  *
3  * functions.c
4  *        Execution of SQL-language functions
5  *
6  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.122 2008/03/25 22:42:43 tgl Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/xact.h"
18 #include "catalog/pg_proc.h"
19 #include "catalog/pg_type.h"
20 #include "commands/trigger.h"
21 #include "executor/functions.h"
22 #include "funcapi.h"
23 #include "nodes/makefuncs.h"
24 #include "parser/parse_coerce.h"
25 #include "parser/parse_expr.h"
26 #include "tcop/tcopprot.h"
27 #include "tcop/utility.h"
28 #include "utils/builtins.h"
29 #include "utils/datum.h"
30 #include "utils/lsyscache.h"
31 #include "utils/syscache.h"
32 #include "utils/typcache.h"
33
34
35 /*
36  * We have an execution_state record for each query in a function.      Each
37  * record contains a plantree for its query.  If the query is currently in
38  * F_EXEC_RUN state then there's a QueryDesc too.
39  */
40 typedef enum
41 {
42         F_EXEC_START, F_EXEC_RUN, F_EXEC_DONE
43 } ExecStatus;
44
45 typedef struct local_es
46 {
47         struct local_es *next;
48         ExecStatus      status;
49         Node       *stmt;                       /* PlannedStmt or utility statement */
50         QueryDesc  *qd;                         /* null unless status == RUN */
51 } execution_state;
52
53 #define LAST_POSTQUEL_COMMAND(es) ((es)->next == NULL)
54
55
56 /*
57  * An SQLFunctionCache record is built during the first call,
58  * and linked to from the fn_extra field of the FmgrInfo struct.
59  */
60 typedef struct
61 {
62         char       *src;                        /* function body text (for error msgs) */
63
64         Oid                *argtypes;           /* resolved types of arguments */
65         Oid                     rettype;                /* actual return type */
66         int16           typlen;                 /* length of the return type */
67         bool            typbyval;               /* true if return type is pass by value */
68         bool            returnsTuple;   /* true if returning whole tuple result */
69         bool            shutdown_reg;   /* true if registered shutdown callback */
70         bool            readonly_func;  /* true to run in "read only" mode */
71
72         ParamListInfo paramLI;          /* Param list representing current args */
73
74         JunkFilter *junkFilter;         /* used only if returnsTuple */
75
76         /* head of linked list of execution_state records */
77         execution_state *func_state;
78 } SQLFunctionCache;
79
80 typedef SQLFunctionCache *SQLFunctionCachePtr;
81
82
83 /* non-export function prototypes */
84 static execution_state *init_execution_state(List *queryTree_list,
85                                          bool readonly_func);
86 static void init_sql_fcache(FmgrInfo *finfo);
87 static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
88 static TupleTableSlot *postquel_getnext(execution_state *es,
89                                  SQLFunctionCachePtr fcache);
90 static void postquel_end(execution_state *es);
91 static void postquel_sub_params(SQLFunctionCachePtr fcache,
92                                         FunctionCallInfo fcinfo);
93 static Datum postquel_execute(execution_state *es,
94                                  FunctionCallInfo fcinfo,
95                                  SQLFunctionCachePtr fcache,
96                                  MemoryContext resultcontext);
97 static void sql_exec_error_callback(void *arg);
98 static void ShutdownSQLFunction(Datum arg);
99
100
101 static execution_state *
102 init_execution_state(List *queryTree_list, bool readonly_func)
103 {
104         execution_state *firstes = NULL;
105         execution_state *preves = NULL;
106         ListCell   *qtl_item;
107
108         foreach(qtl_item, queryTree_list)
109         {
110                 Query      *queryTree = lfirst(qtl_item);
111                 Node       *stmt;
112                 execution_state *newes;
113
114                 Assert(IsA(queryTree, Query));
115
116                 if (queryTree->commandType == CMD_UTILITY)
117                         stmt = queryTree->utilityStmt;
118                 else
119                         stmt = (Node *) pg_plan_query(queryTree, 0, NULL);
120
121                 /* Precheck all commands for validity in a function */
122                 if (IsA(stmt, TransactionStmt))
123                         ereport(ERROR,
124                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
125                         /* translator: %s is a SQL statement name */
126                                          errmsg("%s is not allowed in a SQL function",
127                                                         CreateCommandTag(stmt))));
128
129                 if (readonly_func && !CommandIsReadOnly(stmt))
130                         ereport(ERROR,
131                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
132                         /* translator: %s is a SQL statement name */
133                                          errmsg("%s is not allowed in a non-volatile function",
134                                                         CreateCommandTag(stmt))));
135
136                 newes = (execution_state *) palloc(sizeof(execution_state));
137                 if (preves)
138                         preves->next = newes;
139                 else
140                         firstes = newes;
141
142                 newes->next = NULL;
143                 newes->status = F_EXEC_START;
144                 newes->stmt = stmt;
145                 newes->qd = NULL;
146
147                 preves = newes;
148         }
149
150         return firstes;
151 }
152
153
154 static void
155 init_sql_fcache(FmgrInfo *finfo)
156 {
157         Oid                     foid = finfo->fn_oid;
158         Oid                     rettype;
159         HeapTuple       procedureTuple;
160         Form_pg_proc procedureStruct;
161         SQLFunctionCachePtr fcache;
162         Oid                *argOidVect;
163         int                     nargs;
164         List       *queryTree_list;
165         Datum           tmp;
166         bool            isNull;
167
168         fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache));
169
170         /*
171          * get the procedure tuple corresponding to the given function Oid
172          */
173         procedureTuple = SearchSysCache(PROCOID,
174                                                                         ObjectIdGetDatum(foid),
175                                                                         0, 0, 0);
176         if (!HeapTupleIsValid(procedureTuple))
177                 elog(ERROR, "cache lookup failed for function %u", foid);
178         procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
179
180         /*
181          * get the result type from the procedure tuple, and check for polymorphic
182          * result type; if so, find out the actual result type.
183          */
184         rettype = procedureStruct->prorettype;
185
186         if (IsPolymorphicType(rettype))
187         {
188                 rettype = get_fn_expr_rettype(finfo);
189                 if (rettype == InvalidOid)              /* this probably should not happen */
190                         ereport(ERROR,
191                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
192                                          errmsg("could not determine actual result type for function declared to return type %s",
193                                                         format_type_be(procedureStruct->prorettype))));
194         }
195
196         fcache->rettype = rettype;
197
198         /* Fetch the typlen and byval info for the result type */
199         get_typlenbyval(rettype, &fcache->typlen, &fcache->typbyval);
200
201         /* Remember if function is STABLE/IMMUTABLE */
202         fcache->readonly_func =
203                 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
204
205         /*
206          * We need the actual argument types to pass to the parser.
207          */
208         nargs = procedureStruct->pronargs;
209         if (nargs > 0)
210         {
211                 int                     argnum;
212
213                 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
214                 memcpy(argOidVect,
215                            procedureStruct->proargtypes.values,
216                            nargs * sizeof(Oid));
217                 /* Resolve any polymorphic argument types */
218                 for (argnum = 0; argnum < nargs; argnum++)
219                 {
220                         Oid                     argtype = argOidVect[argnum];
221
222                         if (IsPolymorphicType(argtype))
223                         {
224                                 argtype = get_fn_expr_argtype(finfo, argnum);
225                                 if (argtype == InvalidOid)
226                                         ereport(ERROR,
227                                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
228                                                          errmsg("could not determine actual type of argument declared %s",
229                                                                         format_type_be(argOidVect[argnum]))));
230                                 argOidVect[argnum] = argtype;
231                         }
232                 }
233         }
234         else
235                 argOidVect = NULL;
236         fcache->argtypes = argOidVect;
237
238         /*
239          * And of course we need the function body text.
240          */
241         tmp = SysCacheGetAttr(PROCOID,
242                                                   procedureTuple,
243                                                   Anum_pg_proc_prosrc,
244                                                   &isNull);
245         if (isNull)
246                 elog(ERROR, "null prosrc for function %u", foid);
247         fcache->src = TextDatumGetCString(tmp);
248
249         /*
250          * Parse and rewrite the queries in the function text.
251          */
252         queryTree_list = pg_parse_and_rewrite(fcache->src, argOidVect, nargs);
253
254         /*
255          * Check that the function returns the type it claims to.  Although in
256          * simple cases this was already done when the function was defined, we
257          * have to recheck because database objects used in the function's queries
258          * might have changed type.  We'd have to do it anyway if the function had
259          * any polymorphic arguments.
260          *
261          * Note: we set fcache->returnsTuple according to whether we are returning
262          * the whole tuple result or just a single column.      In the latter case we
263          * clear returnsTuple because we need not act different from the scalar
264          * result case, even if it's a rowtype column.
265          *
266          * In the returnsTuple case, check_sql_fn_retval will also construct a
267          * JunkFilter we can use to coerce the returned rowtype to the desired
268          * form.
269          */
270         fcache->returnsTuple = check_sql_fn_retval(foid,
271                                                                                            rettype,
272                                                                                            queryTree_list,
273                                                                                            false,
274                                                                                            &fcache->junkFilter);
275
276         /* Finally, plan the queries */
277         fcache->func_state = init_execution_state(queryTree_list,
278                                                                                           fcache->readonly_func);
279
280         ReleaseSysCache(procedureTuple);
281
282         finfo->fn_extra = (void *) fcache;
283 }
284
285
286 static void
287 postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
288 {
289         Snapshot        snapshot;
290
291         Assert(es->qd == NULL);
292
293         /*
294          * In a read-only function, use the surrounding query's snapshot;
295          * otherwise take a new snapshot for each query.  The snapshot should
296          * include a fresh command ID so that all work to date in this transaction
297          * is visible.  We copy in both cases so that postquel_end can
298          * unconditionally do FreeSnapshot.
299          */
300         if (fcache->readonly_func)
301                 snapshot = CopySnapshot(ActiveSnapshot);
302         else
303         {
304                 CommandCounterIncrement();
305                 snapshot = CopySnapshot(GetTransactionSnapshot());
306         }
307
308         if (IsA(es->stmt, PlannedStmt))
309                 es->qd = CreateQueryDesc((PlannedStmt *) es->stmt,
310                                                                  snapshot, InvalidSnapshot,
311                                                                  None_Receiver,
312                                                                  fcache->paramLI, false);
313         else
314                 es->qd = CreateUtilityQueryDesc(es->stmt,
315                                                                                 snapshot,
316                                                                                 None_Receiver,
317                                                                                 fcache->paramLI);
318
319         /* We assume we don't need to set up ActiveSnapshot for ExecutorStart */
320
321         /* Utility commands don't need Executor. */
322         if (es->qd->utilitystmt == NULL)
323         {
324                 /*
325                  * Only set up to collect queued triggers if it's not a SELECT. This
326                  * isn't just an optimization, but is necessary in case a SELECT
327                  * returns multiple rows to caller --- we mustn't exit from the
328                  * function execution with a stacked AfterTrigger level still active.
329                  */
330                 if (es->qd->operation != CMD_SELECT)
331                         AfterTriggerBeginQuery();
332                 ExecutorStart(es->qd, 0);
333         }
334
335         es->status = F_EXEC_RUN;
336 }
337
338 static TupleTableSlot *
339 postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
340 {
341         TupleTableSlot *result;
342         Snapshot        saveActiveSnapshot;
343         long            count;
344
345         /* Make our snapshot the active one for any called functions */
346         saveActiveSnapshot = ActiveSnapshot;
347         PG_TRY();
348         {
349                 ActiveSnapshot = es->qd->snapshot;
350
351                 if (es->qd->utilitystmt)
352                 {
353                         /* ProcessUtility needs the PlannedStmt for DECLARE CURSOR */
354                         ProcessUtility((es->qd->plannedstmt ?
355                                                         (Node *) es->qd->plannedstmt :
356                                                         es->qd->utilitystmt),
357                                                    fcache->src,
358                                                    es->qd->params,
359                                                    false,               /* not top level */
360                                                    es->qd->dest,
361                                                    NULL);
362                         result = NULL;
363                 }
364                 else
365                 {
366                         /*
367                          * If it's the function's last command, and it's a SELECT, fetch
368                          * one row at a time so we can return the results. Otherwise just
369                          * run it to completion.  (If we run to completion then
370                          * ExecutorRun is guaranteed to return NULL.)
371                          */
372                         if (LAST_POSTQUEL_COMMAND(es) &&
373                                 es->qd->operation == CMD_SELECT &&
374                                 es->qd->plannedstmt->utilityStmt == NULL &&
375                                 es->qd->plannedstmt->intoClause == NULL)
376                                 count = 1L;
377                         else
378                                 count = 0L;
379
380                         result = ExecutorRun(es->qd, ForwardScanDirection, count);
381                 }
382         }
383         PG_CATCH();
384         {
385                 /* Restore global vars and propagate error */
386                 ActiveSnapshot = saveActiveSnapshot;
387                 PG_RE_THROW();
388         }
389         PG_END_TRY();
390
391         ActiveSnapshot = saveActiveSnapshot;
392
393         return result;
394 }
395
396 static void
397 postquel_end(execution_state *es)
398 {
399         Snapshot        saveActiveSnapshot;
400
401         /* mark status done to ensure we don't do ExecutorEnd twice */
402         es->status = F_EXEC_DONE;
403
404         /* Utility commands don't need Executor. */
405         if (es->qd->utilitystmt == NULL)
406         {
407                 /* Make our snapshot the active one for any called functions */
408                 saveActiveSnapshot = ActiveSnapshot;
409                 PG_TRY();
410                 {
411                         ActiveSnapshot = es->qd->snapshot;
412
413                         if (es->qd->operation != CMD_SELECT)
414                                 AfterTriggerEndQuery(es->qd->estate);
415                         ExecutorEnd(es->qd);
416                 }
417                 PG_CATCH();
418                 {
419                         /* Restore global vars and propagate error */
420                         ActiveSnapshot = saveActiveSnapshot;
421                         PG_RE_THROW();
422                 }
423                 PG_END_TRY();
424                 ActiveSnapshot = saveActiveSnapshot;
425         }
426
427         FreeSnapshot(es->qd->snapshot);
428         FreeQueryDesc(es->qd);
429         es->qd = NULL;
430 }
431
432 /* Build ParamListInfo array representing current arguments */
433 static void
434 postquel_sub_params(SQLFunctionCachePtr fcache,
435                                         FunctionCallInfo fcinfo)
436 {
437         ParamListInfo paramLI;
438         int                     nargs = fcinfo->nargs;
439
440         if (nargs > 0)
441         {
442                 int                     i;
443
444                 /* sizeof(ParamListInfoData) includes the first array element */
445                 paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
446                                                                            (nargs - 1) *sizeof(ParamExternData));
447                 paramLI->numParams = nargs;
448
449                 for (i = 0; i < nargs; i++)
450                 {
451                         ParamExternData *prm = &paramLI->params[i];
452
453                         prm->value = fcinfo->arg[i];
454                         prm->isnull = fcinfo->argnull[i];
455                         prm->pflags = 0;
456                         prm->ptype = fcache->argtypes[i];
457                 }
458         }
459         else
460                 paramLI = NULL;
461
462         if (fcache->paramLI)
463                 pfree(fcache->paramLI);
464
465         fcache->paramLI = paramLI;
466 }
467
468 static Datum
469 postquel_execute(execution_state *es,
470                                  FunctionCallInfo fcinfo,
471                                  SQLFunctionCachePtr fcache,
472                                  MemoryContext resultcontext)
473 {
474         TupleTableSlot *slot;
475         Datum           value;
476         MemoryContext oldcontext;
477
478         if (es->status == F_EXEC_START)
479                 postquel_start(es, fcache);
480
481         slot = postquel_getnext(es, fcache);
482
483         if (TupIsNull(slot))
484         {
485                 /*
486                  * We fall out here for all cases except where we have obtained a row
487                  * from a function's final SELECT.
488                  */
489                 postquel_end(es);
490                 fcinfo->isnull = true;
491                 return (Datum) NULL;
492         }
493
494         /*
495          * If we got a row from a command within the function it has to be the
496          * final command.  All others shouldn't be returning anything.
497          */
498         Assert(LAST_POSTQUEL_COMMAND(es));
499
500         /*
501          * Set up to return the function value.  For pass-by-reference datatypes,
502          * be sure to allocate the result in resultcontext, not the current memory
503          * context (which has query lifespan).
504          */
505         oldcontext = MemoryContextSwitchTo(resultcontext);
506
507         if (fcache->returnsTuple)
508         {
509                 /*
510                  * We are returning the whole tuple, so filter it and apply the proper
511                  * labeling to make it a valid Datum.  There are several reasons why
512                  * we do this:
513                  *
514                  * 1. To copy the tuple out of the child execution context and into
515                  * the desired result context.
516                  *
517                  * 2. To remove any junk attributes present in the raw subselect
518                  * result. (This is probably not absolutely necessary, but it seems
519                  * like good policy.)
520                  *
521                  * 3. To insert dummy null columns if the declared result type has any
522                  * attisdropped columns.
523                  */
524                 HeapTuple       newtup;
525                 HeapTupleHeader dtup;
526                 uint32          t_len;
527                 Oid                     dtuptype;
528                 int32           dtuptypmod;
529
530                 newtup = ExecRemoveJunk(fcache->junkFilter, slot);
531
532                 /*
533                  * Compress out the HeapTuple header data.      We assume that
534                  * heap_form_tuple made the tuple with header and body in one palloc'd
535                  * chunk.  We want to return a pointer to the chunk start so that it
536                  * will work if someone tries to free it.
537                  */
538                 t_len = newtup->t_len;
539                 dtup = (HeapTupleHeader) newtup;
540                 memmove((char *) dtup, (char *) newtup->t_data, t_len);
541
542                 /*
543                  * Use the declared return type if it's not RECORD; else take the type
544                  * from the computed result, making sure a typmod has been assigned.
545                  */
546                 if (fcache->rettype != RECORDOID)
547                 {
548                         /* function has a named composite return type */
549                         dtuptype = fcache->rettype;
550                         dtuptypmod = -1;
551                 }
552                 else
553                 {
554                         /* function is declared to return RECORD */
555                         TupleDesc       tupDesc = fcache->junkFilter->jf_cleanTupType;
556
557                         if (tupDesc->tdtypeid == RECORDOID &&
558                                 tupDesc->tdtypmod < 0)
559                                 assign_record_type_typmod(tupDesc);
560                         dtuptype = tupDesc->tdtypeid;
561                         dtuptypmod = tupDesc->tdtypmod;
562                 }
563
564                 HeapTupleHeaderSetDatumLength(dtup, t_len);
565                 HeapTupleHeaderSetTypeId(dtup, dtuptype);
566                 HeapTupleHeaderSetTypMod(dtup, dtuptypmod);
567
568                 value = PointerGetDatum(dtup);
569                 fcinfo->isnull = false;
570         }
571         else
572         {
573                 /*
574                  * Returning a scalar, which we have to extract from the first column
575                  * of the SELECT result, and then copy into result context if needed.
576                  */
577                 value = slot_getattr(slot, 1, &(fcinfo->isnull));
578
579                 if (!fcinfo->isnull)
580                         value = datumCopy(value, fcache->typbyval, fcache->typlen);
581         }
582
583         MemoryContextSwitchTo(oldcontext);
584
585         /*
586          * If this is a single valued function we have to end the function
587          * execution now.
588          */
589         if (!fcinfo->flinfo->fn_retset)
590                 postquel_end(es);
591
592         return value;
593 }
594
595 Datum
596 fmgr_sql(PG_FUNCTION_ARGS)
597 {
598         MemoryContext oldcontext;
599         SQLFunctionCachePtr fcache;
600         ErrorContextCallback sqlerrcontext;
601         execution_state *es;
602         Datum           result = 0;
603
604         /*
605          * Switch to context in which the fcache lives.  This ensures that
606          * parsetrees, plans, etc, will have sufficient lifetime.  The
607          * sub-executor is responsible for deleting per-tuple information.
608          */
609         oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
610
611         /*
612          * Setup error traceback support for ereport()
613          */
614         sqlerrcontext.callback = sql_exec_error_callback;
615         sqlerrcontext.arg = fcinfo->flinfo;
616         sqlerrcontext.previous = error_context_stack;
617         error_context_stack = &sqlerrcontext;
618
619         /*
620          * Initialize fcache (build plans) if first time through.
621          */
622         fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
623         if (fcache == NULL)
624         {
625                 init_sql_fcache(fcinfo->flinfo);
626                 fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
627         }
628         es = fcache->func_state;
629
630         /*
631          * Convert params to appropriate format if starting a fresh execution. (If
632          * continuing execution, we can re-use prior params.)
633          */
634         if (es && es->status == F_EXEC_START)
635                 postquel_sub_params(fcache, fcinfo);
636
637         /*
638          * Find first unfinished query in function.
639          */
640         while (es && es->status == F_EXEC_DONE)
641                 es = es->next;
642
643         /*
644          * Execute each command in the function one after another until we're
645          * executing the final command and get a result or we run out of commands.
646          */
647         while (es)
648         {
649                 result = postquel_execute(es, fcinfo, fcache, oldcontext);
650                 if (es->status != F_EXEC_DONE)
651                         break;
652                 es = es->next;
653         }
654
655         /*
656          * If we've gone through every command in this function, we are done.
657          */
658         if (es == NULL)
659         {
660                 /*
661                  * Reset the execution states to start over again on next call.
662                  */
663                 es = fcache->func_state;
664                 while (es)
665                 {
666                         es->status = F_EXEC_START;
667                         es = es->next;
668                 }
669
670                 /*
671                  * Let caller know we're finished.
672                  */
673                 if (fcinfo->flinfo->fn_retset)
674                 {
675                         ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
676
677                         if (rsi && IsA(rsi, ReturnSetInfo))
678                                 rsi->isDone = ExprEndResult;
679                         else
680                                 ereport(ERROR,
681                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
682                                                  errmsg("set-valued function called in context that cannot accept a set")));
683                         fcinfo->isnull = true;
684                         result = (Datum) 0;
685
686                         /* Deregister shutdown callback, if we made one */
687                         if (fcache->shutdown_reg)
688                         {
689                                 UnregisterExprContextCallback(rsi->econtext,
690                                                                                           ShutdownSQLFunction,
691                                                                                           PointerGetDatum(fcache));
692                                 fcache->shutdown_reg = false;
693                         }
694                 }
695
696                 error_context_stack = sqlerrcontext.previous;
697
698                 MemoryContextSwitchTo(oldcontext);
699
700                 return result;
701         }
702
703         /*
704          * If we got a result from a command within the function it has to be the
705          * final command.  All others shouldn't be returning anything.
706          */
707         Assert(LAST_POSTQUEL_COMMAND(es));
708
709         /*
710          * Let caller know we're not finished.
711          */
712         if (fcinfo->flinfo->fn_retset)
713         {
714                 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
715
716                 if (rsi && IsA(rsi, ReturnSetInfo))
717                         rsi->isDone = ExprMultipleResult;
718                 else
719                         ereport(ERROR,
720                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
721                                          errmsg("set-valued function called in context that cannot accept a set")));
722
723                 /*
724                  * Ensure we will get shut down cleanly if the exprcontext is not run
725                  * to completion.
726                  */
727                 if (!fcache->shutdown_reg)
728                 {
729                         RegisterExprContextCallback(rsi->econtext,
730                                                                                 ShutdownSQLFunction,
731                                                                                 PointerGetDatum(fcache));
732                         fcache->shutdown_reg = true;
733                 }
734         }
735
736         error_context_stack = sqlerrcontext.previous;
737
738         MemoryContextSwitchTo(oldcontext);
739
740         return result;
741 }
742
743
744 /*
745  * error context callback to let us supply a call-stack traceback
746  */
747 static void
748 sql_exec_error_callback(void *arg)
749 {
750         FmgrInfo   *flinfo = (FmgrInfo *) arg;
751         SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) flinfo->fn_extra;
752         HeapTuple       func_tuple;
753         Form_pg_proc functup;
754         char       *fn_name;
755         int                     syntaxerrposition;
756
757         /* Need access to function's pg_proc tuple */
758         func_tuple = SearchSysCache(PROCOID,
759                                                                 ObjectIdGetDatum(flinfo->fn_oid),
760                                                                 0, 0, 0);
761         if (!HeapTupleIsValid(func_tuple))
762                 return;                                 /* shouldn't happen */
763         functup = (Form_pg_proc) GETSTRUCT(func_tuple);
764         fn_name = NameStr(functup->proname);
765
766         /*
767          * If there is a syntax error position, convert to internal syntax error
768          */
769         syntaxerrposition = geterrposition();
770         if (syntaxerrposition > 0)
771         {
772                 bool            isnull;
773                 Datum           tmp;
774                 char       *prosrc;
775
776                 tmp = SysCacheGetAttr(PROCOID, func_tuple, Anum_pg_proc_prosrc,
777                                                           &isnull);
778                 if (isnull)
779                         elog(ERROR, "null prosrc");
780                 prosrc = TextDatumGetCString(tmp);
781                 errposition(0);
782                 internalerrposition(syntaxerrposition);
783                 internalerrquery(prosrc);
784                 pfree(prosrc);
785         }
786
787         /*
788          * Try to determine where in the function we failed.  If there is a query
789          * with non-null QueryDesc, finger it.  (We check this rather than looking
790          * for F_EXEC_RUN state, so that errors during ExecutorStart or
791          * ExecutorEnd are blamed on the appropriate query; see postquel_start and
792          * postquel_end.)
793          */
794         if (fcache)
795         {
796                 execution_state *es;
797                 int                     query_num;
798
799                 es = fcache->func_state;
800                 query_num = 1;
801                 while (es)
802                 {
803                         if (es->qd)
804                         {
805                                 errcontext("SQL function \"%s\" statement %d",
806                                                    fn_name, query_num);
807                                 break;
808                         }
809                         es = es->next;
810                         query_num++;
811                 }
812                 if (es == NULL)
813                 {
814                         /*
815                          * couldn't identify a running query; might be function entry,
816                          * function exit, or between queries.
817                          */
818                         errcontext("SQL function \"%s\"", fn_name);
819                 }
820         }
821         else
822         {
823                 /* must have failed during init_sql_fcache() */
824                 errcontext("SQL function \"%s\" during startup", fn_name);
825         }
826
827         ReleaseSysCache(func_tuple);
828 }
829
830
831 /*
832  * callback function in case a function-returning-set needs to be shut down
833  * before it has been run to completion
834  */
835 static void
836 ShutdownSQLFunction(Datum arg)
837 {
838         SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) DatumGetPointer(arg);
839         execution_state *es = fcache->func_state;
840
841         while (es != NULL)
842         {
843                 /* Shut down anything still running */
844                 if (es->status == F_EXEC_RUN)
845                         postquel_end(es);
846                 /* Reset states to START in case we're called again */
847                 es->status = F_EXEC_START;
848                 es = es->next;
849         }
850
851         /* execUtils will deregister the callback... */
852         fcache->shutdown_reg = false;
853 }
854
855
856 /*
857  * check_sql_fn_retval() -- check return value of a list of sql parse trees.
858  *
859  * The return value of a sql function is the value returned by
860  * the final query in the function.  We do some ad-hoc type checking here
861  * to be sure that the user is returning the type he claims.  There are
862  * also a couple of strange-looking features to assist callers in dealing
863  * with allowed special cases, such as binary-compatible result types.
864  *
865  * For a polymorphic function the passed rettype must be the actual resolved
866  * output type of the function; we should never see a polymorphic pseudotype
867  * such as ANYELEMENT as rettype.  (This means we can't check the type during
868  * function definition of a polymorphic function.)
869  *
870  * This function returns true if the sql function returns the entire tuple
871  * result of its final SELECT, and false otherwise.  Note that because we
872  * allow "SELECT rowtype_expression", this may be false even when the declared
873  * function return type is a rowtype.
874  *
875  * If insertRelabels is true, then binary-compatible cases are dealt with
876  * by actually inserting RelabelType nodes into the final SELECT; obviously
877  * the caller must pass a parsetree that it's okay to modify in this case.
878  *
879  * If junkFilter isn't NULL, then *junkFilter is set to a JunkFilter defined
880  * to convert the function's tuple result to the correct output tuple type.
881  * Whenever the result value is false (ie, the function isn't returning a
882  * tuple result), *junkFilter is set to NULL.
883  */
884 bool
885 check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
886                                         bool insertRelabels,
887                                         JunkFilter **junkFilter)
888 {
889         Query      *parse;
890         List       *tlist;
891         ListCell   *tlistitem;
892         int                     tlistlen;
893         char            fn_typtype;
894         Oid                     restype;
895
896         AssertArg(!IsPolymorphicType(rettype));
897
898         if (junkFilter)
899                 *junkFilter = NULL;             /* default result */
900
901         /* guard against empty function body; OK only if void return type */
902         if (queryTreeList == NIL)
903         {
904                 if (rettype != VOIDOID)
905                         ereport(ERROR,
906                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
907                          errmsg("return type mismatch in function declared to return %s",
908                                         format_type_be(rettype)),
909                                  errdetail("Function's final statement must be a SELECT.")));
910                 return false;
911         }
912
913         /* find the final query */
914         parse = (Query *) lfirst(list_tail(queryTreeList));
915
916         /*
917          * If the last query isn't a SELECT, the return type must be VOID.
918          *
919          * Note: eventually replace this test with QueryReturnsTuples?  We'd need
920          * a more general method of determining the output type, though.
921          */
922         if (!(parse->commandType == CMD_SELECT &&
923                   parse->utilityStmt == NULL &&
924                   parse->intoClause == NULL))
925         {
926                 if (rettype != VOIDOID)
927                         ereport(ERROR,
928                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
929                          errmsg("return type mismatch in function declared to return %s",
930                                         format_type_be(rettype)),
931                                  errdetail("Function's final statement must be a SELECT.")));
932                 return false;
933         }
934
935         /*
936          * OK, it's a SELECT, so it must return something matching the declared
937          * type.  (We used to insist that the declared type not be VOID in this
938          * case, but that makes it hard to write a void function that exits after
939          * calling another void function.  Instead, we insist that the SELECT
940          * return void ... so void is treated as if it were a scalar type below.)
941          */
942
943         /*
944          * Count the non-junk entries in the result targetlist.
945          */
946         tlist = parse->targetList;
947         tlistlen = ExecCleanTargetListLength(tlist);
948
949         fn_typtype = get_typtype(rettype);
950
951         if (fn_typtype == TYPTYPE_BASE ||
952                 fn_typtype == TYPTYPE_DOMAIN ||
953                 fn_typtype == TYPTYPE_ENUM ||
954                 rettype == VOIDOID)
955         {
956                 /*
957                  * For scalar-type returns, the target list must have exactly one
958                  * non-junk entry, and its type must agree with what the user
959                  * declared; except we allow binary-compatible types too.
960                  */
961                 TargetEntry *tle;
962
963                 if (tlistlen != 1)
964                         ereport(ERROR,
965                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
966                          errmsg("return type mismatch in function declared to return %s",
967                                         format_type_be(rettype)),
968                                  errdetail("Final SELECT must return exactly one column.")));
969
970                 /* We assume here that non-junk TLEs must come first in tlists */
971                 tle = (TargetEntry *) linitial(tlist);
972                 Assert(!tle->resjunk);
973
974                 restype = exprType((Node *) tle->expr);
975                 if (!IsBinaryCoercible(restype, rettype))
976                         ereport(ERROR,
977                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
978                          errmsg("return type mismatch in function declared to return %s",
979                                         format_type_be(rettype)),
980                                          errdetail("Actual return type is %s.",
981                                                            format_type_be(restype))));
982                 if (insertRelabels && restype != rettype)
983                         tle->expr = (Expr *) makeRelabelType(tle->expr,
984                                                                                                  rettype,
985                                                                                                  -1,
986                                                                                                  COERCE_DONTCARE);
987         }
988         else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
989         {
990                 /* Returns a rowtype */
991                 TupleDesc       tupdesc;
992                 int                     tupnatts;       /* physical number of columns in tuple */
993                 int                     tuplogcols; /* # of nondeleted columns in tuple */
994                 int                     colindex;       /* physical column index */
995
996                 /*
997                  * If the target list is of length 1, and the type of the varnode in
998                  * the target list matches the declared return type, this is okay.
999                  * This can happen, for example, where the body of the function is
1000                  * 'SELECT func2()', where func2 has the same composite return type
1001                  * as the function that's calling it.
1002                  */
1003                 if (tlistlen == 1)
1004                 {
1005                         TargetEntry *tle = (TargetEntry *) linitial(tlist);
1006
1007                         Assert(!tle->resjunk);
1008                         restype = exprType((Node *) tle->expr);
1009                         if (IsBinaryCoercible(restype, rettype))
1010                         {
1011                                 if (insertRelabels && restype != rettype)
1012                                         tle->expr = (Expr *) makeRelabelType(tle->expr,
1013                                                                                                                  rettype,
1014                                                                                                                  -1,
1015                                                                                                                  COERCE_DONTCARE);
1016                                 return false;   /* NOT returning whole tuple */
1017                         }
1018                 }
1019
1020                 /* Is the rowtype fixed, or determined only at runtime? */
1021                 if (get_func_result_type(func_id, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1022                 {
1023                         /*
1024                          * Assume we are returning the whole tuple. Crosschecking against
1025                          * what the caller expects will happen at runtime.
1026                          */
1027                         if (junkFilter)
1028                                 *junkFilter = ExecInitJunkFilter(tlist, false, NULL);
1029                         return true;
1030                 }
1031                 Assert(tupdesc);
1032
1033                 /*
1034                  * Verify that the targetlist matches the return tuple type. We scan
1035                  * the non-deleted attributes to ensure that they match the datatypes
1036                  * of the non-resjunk columns.
1037                  */
1038                 tupnatts = tupdesc->natts;
1039                 tuplogcols = 0;                 /* we'll count nondeleted cols as we go */
1040                 colindex = 0;
1041
1042                 foreach(tlistitem, tlist)
1043                 {
1044                         TargetEntry *tle = (TargetEntry *) lfirst(tlistitem);
1045                         Form_pg_attribute attr;
1046                         Oid                     tletype;
1047                         Oid                     atttype;
1048
1049                         if (tle->resjunk)
1050                                 continue;
1051
1052                         do
1053                         {
1054                                 colindex++;
1055                                 if (colindex > tupnatts)
1056                                         ereport(ERROR,
1057                                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1058                                                          errmsg("return type mismatch in function declared to return %s",
1059                                                                         format_type_be(rettype)),
1060                                            errdetail("Final SELECT returns too many columns.")));
1061                                 attr = tupdesc->attrs[colindex - 1];
1062                         } while (attr->attisdropped);
1063                         tuplogcols++;
1064
1065                         tletype = exprType((Node *) tle->expr);
1066                         atttype = attr->atttypid;
1067                         if (!IsBinaryCoercible(tletype, atttype))
1068                                 ereport(ERROR,
1069                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1070                                                  errmsg("return type mismatch in function declared to return %s",
1071                                                                 format_type_be(rettype)),
1072                                                  errdetail("Final SELECT returns %s instead of %s at column %d.",
1073                                                                    format_type_be(tletype),
1074                                                                    format_type_be(atttype),
1075                                                                    tuplogcols)));
1076                         if (insertRelabels && tletype != atttype)
1077                                 tle->expr = (Expr *) makeRelabelType(tle->expr,
1078                                                                                                          atttype,
1079                                                                                                          -1,
1080                                                                                                          COERCE_DONTCARE);
1081                 }
1082
1083                 for (;;)
1084                 {
1085                         colindex++;
1086                         if (colindex > tupnatts)
1087                                 break;
1088                         if (!tupdesc->attrs[colindex - 1]->attisdropped)
1089                                 tuplogcols++;
1090                 }
1091
1092                 if (tlistlen != tuplogcols)
1093                         ereport(ERROR,
1094                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1095                          errmsg("return type mismatch in function declared to return %s",
1096                                         format_type_be(rettype)),
1097                                          errdetail("Final SELECT returns too few columns.")));
1098
1099                 /* Set up junk filter if needed */
1100                 if (junkFilter)
1101                         *junkFilter = ExecInitJunkFilterConversion(tlist,
1102                                                                                                 CreateTupleDescCopy(tupdesc),
1103                                                                                                            NULL);
1104
1105                 /* Report that we are returning entire tuple result */
1106                 return true;
1107         }
1108         else
1109                 ereport(ERROR,
1110                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1111                                  errmsg("return type %s is not supported for SQL functions",
1112                                                 format_type_be(rettype))));
1113
1114         return false;
1115 }