LCOV - code coverage report
Current view: top level - src/backend/executor - functions.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 491 568 86.4 %
Date: 2017-09-29 15:12:54 Functions: 21 22 95.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * functions.c
       4             :  *    Execution of SQL-language functions
       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/functions.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/htup_details.h"
      18             : #include "access/xact.h"
      19             : #include "catalog/pg_proc.h"
      20             : #include "catalog/pg_type.h"
      21             : #include "executor/functions.h"
      22             : #include "funcapi.h"
      23             : #include "miscadmin.h"
      24             : #include "nodes/makefuncs.h"
      25             : #include "nodes/nodeFuncs.h"
      26             : #include "parser/parse_coerce.h"
      27             : #include "parser/parse_func.h"
      28             : #include "storage/proc.h"
      29             : #include "tcop/utility.h"
      30             : #include "utils/builtins.h"
      31             : #include "utils/datum.h"
      32             : #include "utils/lsyscache.h"
      33             : #include "utils/memutils.h"
      34             : #include "utils/snapmgr.h"
      35             : #include "utils/syscache.h"
      36             : 
      37             : 
      38             : /*
      39             :  * Specialized DestReceiver for collecting query output in a SQL function
      40             :  */
      41             : typedef struct
      42             : {
      43             :     DestReceiver pub;           /* publicly-known function pointers */
      44             :     Tuplestorestate *tstore;    /* where to put result tuples */
      45             :     MemoryContext cxt;          /* context containing tstore */
      46             :     JunkFilter *filter;         /* filter to convert tuple type */
      47             : } DR_sqlfunction;
      48             : 
      49             : /*
      50             :  * We have an execution_state record for each query in a function.  Each
      51             :  * record contains a plantree for its query.  If the query is currently in
      52             :  * F_EXEC_RUN state then there's a QueryDesc too.
      53             :  *
      54             :  * The "next" fields chain together all the execution_state records generated
      55             :  * from a single original parsetree.  (There will only be more than one in
      56             :  * case of rule expansion of the original parsetree.)
      57             :  */
      58             : typedef enum
      59             : {
      60             :     F_EXEC_START, F_EXEC_RUN, F_EXEC_DONE
      61             : } ExecStatus;
      62             : 
      63             : typedef struct execution_state
      64             : {
      65             :     struct execution_state *next;
      66             :     ExecStatus  status;
      67             :     bool        setsResult;     /* true if this query produces func's result */
      68             :     bool        lazyEval;       /* true if should fetch one row at a time */
      69             :     PlannedStmt *stmt;          /* plan for this query */
      70             :     QueryDesc  *qd;             /* null unless status == RUN */
      71             : } execution_state;
      72             : 
      73             : 
      74             : /*
      75             :  * An SQLFunctionCache record is built during the first call,
      76             :  * and linked to from the fn_extra field of the FmgrInfo struct.
      77             :  *
      78             :  * Note that currently this has only the lifespan of the calling query.
      79             :  * Someday we should rewrite this code to use plancache.c to save parse/plan
      80             :  * results for longer than that.
      81             :  *
      82             :  * Physically, though, the data has the lifespan of the FmgrInfo that's used
      83             :  * to call the function, and there are cases (particularly with indexes)
      84             :  * where the FmgrInfo might survive across transactions.  We cannot assume
      85             :  * that the parse/plan trees are good for longer than the (sub)transaction in
      86             :  * which parsing was done, so we must mark the record with the LXID/subxid of
      87             :  * its creation time, and regenerate everything if that's obsolete.  To avoid
      88             :  * memory leakage when we do have to regenerate things, all the data is kept
      89             :  * in a sub-context of the FmgrInfo's fn_mcxt.
      90             :  */
      91             : typedef struct
      92             : {
      93             :     char       *fname;          /* function name (for error msgs) */
      94             :     char       *src;            /* function body text (for error msgs) */
      95             : 
      96             :     SQLFunctionParseInfoPtr pinfo;  /* data for parser callback hooks */
      97             : 
      98             :     Oid         rettype;        /* actual return type */
      99             :     int16       typlen;         /* length of the return type */
     100             :     bool        typbyval;       /* true if return type is pass by value */
     101             :     bool        returnsSet;     /* true if returning multiple rows */
     102             :     bool        returnsTuple;   /* true if returning whole tuple result */
     103             :     bool        shutdown_reg;   /* true if registered shutdown callback */
     104             :     bool        readonly_func;  /* true to run in "read only" mode */
     105             :     bool        lazyEval;       /* true if using lazyEval for result query */
     106             : 
     107             :     ParamListInfo paramLI;      /* Param list representing current args */
     108             : 
     109             :     Tuplestorestate *tstore;    /* where we accumulate result tuples */
     110             : 
     111             :     JunkFilter *junkFilter;     /* will be NULL if function returns VOID */
     112             : 
     113             :     /*
     114             :      * func_state is a List of execution_state records, each of which is the
     115             :      * first for its original parsetree, with any additional records chained
     116             :      * to it via the "next" fields.  This sublist structure is needed to keep
     117             :      * track of where the original query boundaries are.
     118             :      */
     119             :     List       *func_state;
     120             : 
     121             :     MemoryContext fcontext;     /* memory context holding this struct and all
     122             :                                  * subsidiary data */
     123             : 
     124             :     LocalTransactionId lxid;    /* lxid in which cache was made */
     125             :     SubTransactionId subxid;    /* subxid in which cache was made */
     126             : } SQLFunctionCache;
     127             : 
     128             : typedef SQLFunctionCache *SQLFunctionCachePtr;
     129             : 
     130             : /*
     131             :  * Data structure needed by the parser callback hooks to resolve parameter
     132             :  * references during parsing of a SQL function's body.  This is separate from
     133             :  * SQLFunctionCache since we sometimes do parsing separately from execution.
     134             :  */
     135             : typedef struct SQLFunctionParseInfo
     136             : {
     137             :     char       *fname;          /* function's name */
     138             :     int         nargs;          /* number of input arguments */
     139             :     Oid        *argtypes;       /* resolved types of input arguments */
     140             :     char      **argnames;       /* names of input arguments; NULL if none */
     141             :     /* Note that argnames[i] can be NULL, if some args are unnamed */
     142             :     Oid         collation;      /* function's input collation, if known */
     143             : }           SQLFunctionParseInfo;
     144             : 
     145             : 
     146             : /* non-export function prototypes */
     147             : static Node *sql_fn_param_ref(ParseState *pstate, ParamRef *pref);
     148             : static Node *sql_fn_post_column_ref(ParseState *pstate,
     149             :                        ColumnRef *cref, Node *var);
     150             : static Node *sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
     151             :                   int paramno, int location);
     152             : static Node *sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
     153             :                           const char *paramname, int location);
     154             : static List *init_execution_state(List *queryTree_list,
     155             :                      SQLFunctionCachePtr fcache,
     156             :                      bool lazyEvalOK);
     157             : static void init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK);
     158             : static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
     159             : static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
     160             : static void postquel_end(execution_state *es);
     161             : static void postquel_sub_params(SQLFunctionCachePtr fcache,
     162             :                     FunctionCallInfo fcinfo);
     163             : static Datum postquel_get_single_result(TupleTableSlot *slot,
     164             :                            FunctionCallInfo fcinfo,
     165             :                            SQLFunctionCachePtr fcache,
     166             :                            MemoryContext resultcontext);
     167             : static void sql_exec_error_callback(void *arg);
     168             : static void ShutdownSQLFunction(Datum arg);
     169             : static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo);
     170             : static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self);
     171             : static void sqlfunction_shutdown(DestReceiver *self);
     172             : static void sqlfunction_destroy(DestReceiver *self);
     173             : 
     174             : 
     175             : /*
     176             :  * Prepare the SQLFunctionParseInfo struct for parsing a SQL function body
     177             :  *
     178             :  * This includes resolving actual types of polymorphic arguments.
     179             :  *
     180             :  * call_expr can be passed as NULL, but then we will fail if there are any
     181             :  * polymorphic arguments.
     182             :  */
     183             : SQLFunctionParseInfoPtr
     184        5749 : prepare_sql_fn_parse_info(HeapTuple procedureTuple,
     185             :                           Node *call_expr,
     186             :                           Oid inputCollation)
     187             : {
     188             :     SQLFunctionParseInfoPtr pinfo;
     189        5749 :     Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
     190             :     int         nargs;
     191             : 
     192        5749 :     pinfo = (SQLFunctionParseInfoPtr) palloc0(sizeof(SQLFunctionParseInfo));
     193             : 
     194             :     /* Function's name (only) can be used to qualify argument names */
     195        5749 :     pinfo->fname = pstrdup(NameStr(procedureStruct->proname));
     196             : 
     197             :     /* Save the function's input collation */
     198        5749 :     pinfo->collation = inputCollation;
     199             : 
     200             :     /*
     201             :      * Copy input argument types from the pg_proc entry, then resolve any
     202             :      * polymorphic types.
     203             :      */
     204        5749 :     pinfo->nargs = nargs = procedureStruct->pronargs;
     205        5749 :     if (nargs > 0)
     206             :     {
     207             :         Oid        *argOidVect;
     208             :         int         argnum;
     209             : 
     210        1040 :         argOidVect = (Oid *) palloc(nargs * sizeof(Oid));
     211        2080 :         memcpy(argOidVect,
     212        1040 :                procedureStruct->proargtypes.values,
     213             :                nargs * sizeof(Oid));
     214             : 
     215        2874 :         for (argnum = 0; argnum < nargs; argnum++)
     216             :         {
     217        1834 :             Oid         argtype = argOidVect[argnum];
     218             : 
     219        1834 :             if (IsPolymorphicType(argtype))
     220             :             {
     221         213 :                 argtype = get_call_expr_argtype(call_expr, argnum);
     222         213 :                 if (argtype == InvalidOid)
     223           0 :                     ereport(ERROR,
     224             :                             (errcode(ERRCODE_DATATYPE_MISMATCH),
     225             :                              errmsg("could not determine actual type of argument declared %s",
     226             :                                     format_type_be(argOidVect[argnum]))));
     227         213 :                 argOidVect[argnum] = argtype;
     228             :             }
     229             :         }
     230             : 
     231        1040 :         pinfo->argtypes = argOidVect;
     232             :     }
     233             : 
     234             :     /*
     235             :      * Collect names of arguments, too, if any
     236             :      */
     237        5749 :     if (nargs > 0)
     238             :     {
     239             :         Datum       proargnames;
     240             :         Datum       proargmodes;
     241             :         int         n_arg_names;
     242             :         bool        isNull;
     243             : 
     244        1040 :         proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
     245             :                                       Anum_pg_proc_proargnames,
     246             :                                       &isNull);
     247        1040 :         if (isNull)
     248         845 :             proargnames = PointerGetDatum(NULL);    /* just to be sure */
     249             : 
     250        1040 :         proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,
     251             :                                       Anum_pg_proc_proargmodes,
     252             :                                       &isNull);
     253        1040 :         if (isNull)
     254         946 :             proargmodes = PointerGetDatum(NULL);    /* just to be sure */
     255             : 
     256        1040 :         n_arg_names = get_func_input_arg_names(proargnames, proargmodes,
     257             :                                                &pinfo->argnames);
     258             : 
     259             :         /* Paranoia: ignore the result if too few array entries */
     260        1040 :         if (n_arg_names < nargs)
     261         845 :             pinfo->argnames = NULL;
     262             :     }
     263             :     else
     264        4709 :         pinfo->argnames = NULL;
     265             : 
     266        5749 :     return pinfo;
     267             : }
     268             : 
     269             : /*
     270             :  * Parser setup hook for parsing a SQL function body.
     271             :  */
     272             : void
     273        5749 : sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
     274             : {
     275        5749 :     pstate->p_pre_columnref_hook = NULL;
     276        5749 :     pstate->p_post_columnref_hook = sql_fn_post_column_ref;
     277        5749 :     pstate->p_paramref_hook = sql_fn_param_ref;
     278             :     /* no need to use p_coerce_param_hook */
     279        5749 :     pstate->p_ref_hook_state = (void *) pinfo;
     280        5749 : }
     281             : 
     282             : /*
     283             :  * sql_fn_post_column_ref       parser callback for ColumnRefs
     284             :  */
     285             : static Node *
     286        2054 : sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
     287             : {
     288        2054 :     SQLFunctionParseInfoPtr pinfo = (SQLFunctionParseInfoPtr) pstate->p_ref_hook_state;
     289             :     int         nnames;
     290             :     Node       *field1;
     291        2054 :     Node       *subfield = NULL;
     292             :     const char *name1;
     293        2054 :     const char *name2 = NULL;
     294             :     Node       *param;
     295             : 
     296             :     /*
     297             :      * Never override a table-column reference.  This corresponds to
     298             :      * considering the parameter names to appear in a scope outside the
     299             :      * individual SQL commands, which is what we want.
     300             :      */
     301        2054 :     if (var != NULL)
     302        1985 :         return NULL;
     303             : 
     304             :     /*----------
     305             :      * The allowed syntaxes are:
     306             :      *
     307             :      * A        A = parameter name
     308             :      * A.B      A = function name, B = parameter name
     309             :      *          OR: A = record-typed parameter name, B = field name
     310             :      *          (the first possibility takes precedence)
     311             :      * A.B.C    A = function name, B = record-typed parameter name,
     312             :      *          C = field name
     313             :      * A.*      Whole-row reference to composite parameter A.
     314             :      * A.B.*    Same, with A = function name, B = parameter name
     315             :      *
     316             :      * Here, it's sufficient to ignore the "*" in the last two cases --- the
     317             :      * main parser will take care of expanding the whole-row reference.
     318             :      *----------
     319             :      */
     320          69 :     nnames = list_length(cref->fields);
     321             : 
     322          69 :     if (nnames > 3)
     323           0 :         return NULL;
     324             : 
     325          69 :     if (IsA(llast(cref->fields), A_Star))
     326           9 :         nnames--;
     327             : 
     328          69 :     field1 = (Node *) linitial(cref->fields);
     329          69 :     Assert(IsA(field1, String));
     330          69 :     name1 = strVal(field1);
     331          69 :     if (nnames > 1)
     332             :     {
     333          24 :         subfield = (Node *) lsecond(cref->fields);
     334          24 :         Assert(IsA(subfield, String));
     335          24 :         name2 = strVal(subfield);
     336             :     }
     337             : 
     338          69 :     if (nnames == 3)
     339             :     {
     340             :         /*
     341             :          * Three-part name: if the first part doesn't match the function name,
     342             :          * we can fail immediately. Otherwise, look up the second part, and
     343             :          * take the third part to be a field reference.
     344             :          */
     345           4 :         if (strcmp(name1, pinfo->fname) != 0)
     346           0 :             return NULL;
     347             : 
     348           4 :         param = sql_fn_resolve_param_name(pinfo, name2, cref->location);
     349             : 
     350           4 :         subfield = (Node *) lthird(cref->fields);
     351           4 :         Assert(IsA(subfield, String));
     352             :     }
     353          65 :     else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)
     354             :     {
     355             :         /*
     356             :          * Two-part name with first part matching function name: first see if
     357             :          * second part matches any parameter name.
     358             :          */
     359           4 :         param = sql_fn_resolve_param_name(pinfo, name2, cref->location);
     360             : 
     361           8 :         if (param)
     362             :         {
     363             :             /* Yes, so this is a parameter reference, no subfield */
     364           4 :             subfield = NULL;
     365             :         }
     366             :         else
     367             :         {
     368             :             /* No, so try to match as parameter name and subfield */
     369           0 :             param = sql_fn_resolve_param_name(pinfo, name1, cref->location);
     370             :         }
     371             :     }
     372             :     else
     373             :     {
     374             :         /* Single name, or parameter name followed by subfield */
     375          61 :         param = sql_fn_resolve_param_name(pinfo, name1, cref->location);
     376             :     }
     377             : 
     378          69 :     if (!param)
     379           0 :         return NULL;            /* No match */
     380             : 
     381          69 :     if (subfield)
     382             :     {
     383             :         /*
     384             :          * Must be a reference to a field of a composite parameter; otherwise
     385             :          * ParseFuncOrColumn will return NULL, and we'll fail back at the
     386             :          * caller.
     387             :          */
     388          20 :         param = ParseFuncOrColumn(pstate,
     389             :                                   list_make1(subfield),
     390             :                                   list_make1(param),
     391             :                                   pstate->p_last_srf,
     392             :                                   NULL,
     393             :                                   cref->location);
     394             :     }
     395             : 
     396          69 :     return param;
     397             : }
     398             : 
     399             : /*
     400             :  * sql_fn_param_ref     parser callback for ParamRefs ($n symbols)
     401             :  */
     402             : static Node *
     403        1817 : sql_fn_param_ref(ParseState *pstate, ParamRef *pref)
     404             : {
     405        1817 :     SQLFunctionParseInfoPtr pinfo = (SQLFunctionParseInfoPtr) pstate->p_ref_hook_state;
     406        1817 :     int         paramno = pref->number;
     407             : 
     408             :     /* Check parameter number is valid */
     409        1817 :     if (paramno <= 0 || paramno > pinfo->nargs)
     410           1 :         return NULL;            /* unknown parameter number */
     411             : 
     412        1816 :     return sql_fn_make_param(pinfo, paramno, pref->location);
     413             : }
     414             : 
     415             : /*
     416             :  * sql_fn_make_param        construct a Param node for the given paramno
     417             :  */
     418             : static Node *
     419        1885 : sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
     420             :                   int paramno, int location)
     421             : {
     422             :     Param      *param;
     423             : 
     424        1885 :     param = makeNode(Param);
     425        1885 :     param->paramkind = PARAM_EXTERN;
     426        1885 :     param->paramid = paramno;
     427        1885 :     param->paramtype = pinfo->argtypes[paramno - 1];
     428        1885 :     param->paramtypmod = -1;
     429        1885 :     param->paramcollid = get_typcollation(param->paramtype);
     430        1885 :     param->location = location;
     431             : 
     432             :     /*
     433             :      * If we have a function input collation, allow it to override the
     434             :      * type-derived collation for parameter symbols.  (XXX perhaps this should
     435             :      * not happen if the type collation is not default?)
     436             :      */
     437        1885 :     if (OidIsValid(pinfo->collation) && OidIsValid(param->paramcollid))
     438         325 :         param->paramcollid = pinfo->collation;
     439             : 
     440        1885 :     return (Node *) param;
     441             : }
     442             : 
     443             : /*
     444             :  * Search for a function parameter of the given name; if there is one,
     445             :  * construct and return a Param node for it.  If not, return NULL.
     446             :  * Helper function for sql_fn_post_column_ref.
     447             :  */
     448             : static Node *
     449          69 : sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
     450             :                           const char *paramname, int location)
     451             : {
     452             :     int         i;
     453             : 
     454          69 :     if (pinfo->argnames == NULL)
     455           0 :         return NULL;
     456             : 
     457          80 :     for (i = 0; i < pinfo->nargs; i++)
     458             :     {
     459          80 :         if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)
     460          69 :             return sql_fn_make_param(pinfo, i + 1, location);
     461             :     }
     462             : 
     463           0 :     return NULL;
     464             : }
     465             : 
     466             : /*
     467             :  * Set up the per-query execution_state records for a SQL function.
     468             :  *
     469             :  * The input is a List of Lists of parsed and rewritten, but not planned,
     470             :  * querytrees.  The sublist structure denotes the original query boundaries.
     471             :  */
     472             : static List *
     473        2886 : init_execution_state(List *queryTree_list,
     474             :                      SQLFunctionCachePtr fcache,
     475             :                      bool lazyEvalOK)
     476             : {
     477        2886 :     List       *eslist = NIL;
     478        2886 :     execution_state *lasttages = NULL;
     479             :     ListCell   *lc1;
     480             : 
     481        5771 :     foreach(lc1, queryTree_list)
     482             :     {
     483        2886 :         List       *qtlist = lfirst_node(List, lc1);
     484        2886 :         execution_state *firstes = NULL;
     485        2886 :         execution_state *preves = NULL;
     486             :         ListCell   *lc2;
     487             : 
     488        5772 :         foreach(lc2, qtlist)
     489             :         {
     490        2887 :             Query      *queryTree = lfirst_node(Query, lc2);
     491             :             PlannedStmt *stmt;
     492             :             execution_state *newes;
     493             : 
     494             :             /* Plan the query if needed */
     495        2887 :             if (queryTree->commandType == CMD_UTILITY)
     496             :             {
     497             :                 /* Utility commands require no planning. */
     498           8 :                 stmt = makeNode(PlannedStmt);
     499           8 :                 stmt->commandType = CMD_UTILITY;
     500           8 :                 stmt->canSetTag = queryTree->canSetTag;
     501           8 :                 stmt->utilityStmt = queryTree->utilityStmt;
     502           8 :                 stmt->stmt_location = queryTree->stmt_location;
     503           8 :                 stmt->stmt_len = queryTree->stmt_len;
     504             :             }
     505             :             else
     506        2879 :                 stmt = pg_plan_query(queryTree,
     507             :                                      CURSOR_OPT_PARALLEL_OK,
     508             :                                      NULL);
     509             : 
     510             :             /*
     511             :              * Precheck all commands for validity in a function.  This should
     512             :              * generally match the restrictions spi.c applies.
     513             :              */
     514        2886 :             if (stmt->commandType == CMD_UTILITY)
     515             :             {
     516           8 :                 if (IsA(stmt->utilityStmt, CopyStmt) &&
     517           0 :                     ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
     518           0 :                     ereport(ERROR,
     519             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     520             :                              errmsg("cannot COPY to/from client in a SQL function")));
     521             : 
     522           8 :                 if (IsA(stmt->utilityStmt, TransactionStmt))
     523           0 :                     ereport(ERROR,
     524             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     525             :                     /* translator: %s is a SQL statement name */
     526             :                              errmsg("%s is not allowed in a SQL function",
     527             :                                     CreateCommandTag(stmt->utilityStmt))));
     528             :             }
     529             : 
     530        2886 :             if (fcache->readonly_func && !CommandIsReadOnly(stmt))
     531           0 :                 ereport(ERROR,
     532             :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     533             :                 /* translator: %s is a SQL statement name */
     534             :                          errmsg("%s is not allowed in a non-volatile function",
     535             :                                 CreateCommandTag((Node *) stmt))));
     536             : 
     537        2886 :             if (IsInParallelMode() && !CommandIsReadOnly(stmt))
     538           0 :                 PreventCommandIfParallelMode(CreateCommandTag((Node *) stmt));
     539             : 
     540             :             /* OK, build the execution_state for this query */
     541        2886 :             newes = (execution_state *) palloc(sizeof(execution_state));
     542        2886 :             if (preves)
     543           1 :                 preves->next = newes;
     544             :             else
     545        2885 :                 firstes = newes;
     546             : 
     547        2886 :             newes->next = NULL;
     548        2886 :             newes->status = F_EXEC_START;
     549        2886 :             newes->setsResult = false;   /* might change below */
     550        2886 :             newes->lazyEval = false; /* might change below */
     551        2886 :             newes->stmt = stmt;
     552        2886 :             newes->qd = NULL;
     553             : 
     554        2886 :             if (queryTree->canSetTag)
     555        2885 :                 lasttages = newes;
     556             : 
     557        2886 :             preves = newes;
     558             :         }
     559             : 
     560        2885 :         eslist = lappend(eslist, firstes);
     561             :     }
     562             : 
     563             :     /*
     564             :      * Mark the last canSetTag query as delivering the function result; then,
     565             :      * if it is a plain SELECT, mark it for lazy evaluation. If it's not a
     566             :      * SELECT we must always run it to completion.
     567             :      *
     568             :      * Note: at some point we might add additional criteria for whether to use
     569             :      * lazy eval.  However, we should prefer to use it whenever the function
     570             :      * doesn't return set, since fetching more than one row is useless in that
     571             :      * case.
     572             :      *
     573             :      * Note: don't set setsResult if the function returns VOID, as evidenced
     574             :      * by not having made a junkfilter.  This ensures we'll throw away any
     575             :      * output from a utility statement that check_sql_fn_retval deemed to not
     576             :      * have output.
     577             :      */
     578        2885 :     if (lasttages && fcache->junkFilter)
     579             :     {
     580        2874 :         lasttages->setsResult = true;
     581        5628 :         if (lazyEvalOK &&
     582        5498 :             lasttages->stmt->commandType == CMD_SELECT &&
     583        2744 :             !lasttages->stmt->hasModifyingCTE)
     584        2744 :             fcache->lazyEval = lasttages->lazyEval = true;
     585             :     }
     586             : 
     587        2885 :     return eslist;
     588             : }
     589             : 
     590             : /*
     591             :  * Initialize the SQLFunctionCache for a SQL function
     592             :  */
     593             : static void
     594        2886 : init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
     595             : {
     596        2886 :     Oid         foid = finfo->fn_oid;
     597             :     MemoryContext fcontext;
     598             :     MemoryContext oldcontext;
     599             :     Oid         rettype;
     600             :     HeapTuple   procedureTuple;
     601             :     Form_pg_proc procedureStruct;
     602             :     SQLFunctionCachePtr fcache;
     603             :     List       *raw_parsetree_list;
     604             :     List       *queryTree_list;
     605             :     List       *flat_query_list;
     606             :     ListCell   *lc;
     607             :     Datum       tmp;
     608             :     bool        isNull;
     609             : 
     610             :     /*
     611             :      * Create memory context that holds all the SQLFunctionCache data.  It
     612             :      * must be a child of whatever context holds the FmgrInfo.
     613             :      */
     614        2886 :     fcontext = AllocSetContextCreate(finfo->fn_mcxt,
     615             :                                      "SQL function data",
     616             :                                      ALLOCSET_DEFAULT_SIZES);
     617             : 
     618        2886 :     oldcontext = MemoryContextSwitchTo(fcontext);
     619             : 
     620             :     /*
     621             :      * Create the struct proper, link it to fcontext and fn_extra.  Once this
     622             :      * is done, we'll be able to recover the memory after failure, even if the
     623             :      * FmgrInfo is long-lived.
     624             :      */
     625        2886 :     fcache = (SQLFunctionCachePtr) palloc0(sizeof(SQLFunctionCache));
     626        2886 :     fcache->fcontext = fcontext;
     627        2886 :     finfo->fn_extra = (void *) fcache;
     628             : 
     629             :     /*
     630             :      * get the procedure tuple corresponding to the given function Oid
     631             :      */
     632        2886 :     procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(foid));
     633        2886 :     if (!HeapTupleIsValid(procedureTuple))
     634           0 :         elog(ERROR, "cache lookup failed for function %u", foid);
     635        2886 :     procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
     636             : 
     637             :     /*
     638             :      * copy function name immediately for use by error reporting callback
     639             :      */
     640        2886 :     fcache->fname = pstrdup(NameStr(procedureStruct->proname));
     641             : 
     642             :     /*
     643             :      * get the result type from the procedure tuple, and check for polymorphic
     644             :      * result type; if so, find out the actual result type.
     645             :      */
     646        2886 :     rettype = procedureStruct->prorettype;
     647             : 
     648        2886 :     if (IsPolymorphicType(rettype))
     649             :     {
     650          35 :         rettype = get_fn_expr_rettype(finfo);
     651          35 :         if (rettype == InvalidOid)  /* this probably should not happen */
     652           0 :             ereport(ERROR,
     653             :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
     654             :                      errmsg("could not determine actual result type for function declared to return type %s",
     655             :                             format_type_be(procedureStruct->prorettype))));
     656             :     }
     657             : 
     658        2886 :     fcache->rettype = rettype;
     659             : 
     660             :     /* Fetch the typlen and byval info for the result type */
     661        2886 :     get_typlenbyval(rettype, &fcache->typlen, &fcache->typbyval);
     662             : 
     663             :     /* Remember whether we're returning setof something */
     664        2886 :     fcache->returnsSet = procedureStruct->proretset;
     665             : 
     666             :     /* Remember if function is STABLE/IMMUTABLE */
     667        2886 :     fcache->readonly_func =
     668        2886 :         (procedureStruct->provolatile != PROVOLATILE_VOLATILE);
     669             : 
     670             :     /*
     671             :      * We need the actual argument types to pass to the parser.  Also make
     672             :      * sure that parameter symbols are considered to have the function's
     673             :      * resolved input collation.
     674             :      */
     675        2886 :     fcache->pinfo = prepare_sql_fn_parse_info(procedureTuple,
     676        2886 :                                               finfo->fn_expr,
     677             :                                               collation);
     678             : 
     679             :     /*
     680             :      * And of course we need the function body text.
     681             :      */
     682        2886 :     tmp = SysCacheGetAttr(PROCOID,
     683             :                           procedureTuple,
     684             :                           Anum_pg_proc_prosrc,
     685             :                           &isNull);
     686        2886 :     if (isNull)
     687           0 :         elog(ERROR, "null prosrc for function %u", foid);
     688        2886 :     fcache->src = TextDatumGetCString(tmp);
     689             : 
     690             :     /*
     691             :      * Parse and rewrite the queries in the function text.  Use sublists to
     692             :      * keep track of the original query boundaries.  But we also build a
     693             :      * "flat" list of the rewritten queries to pass to check_sql_fn_retval.
     694             :      * This is because the last canSetTag query determines the result type
     695             :      * independently of query boundaries --- and it might not be in the last
     696             :      * sublist, for example if the last query rewrites to DO INSTEAD NOTHING.
     697             :      * (It might not be unreasonable to throw an error in such a case, but
     698             :      * this is the historical behavior and it doesn't seem worth changing.)
     699             :      *
     700             :      * Note: since parsing and planning is done in fcontext, we will generate
     701             :      * a lot of cruft that lives as long as the fcache does.  This is annoying
     702             :      * but we'll not worry about it until the module is rewritten to use
     703             :      * plancache.c.
     704             :      */
     705        2886 :     raw_parsetree_list = pg_parse_query(fcache->src);
     706             : 
     707        2886 :     queryTree_list = NIL;
     708        2886 :     flat_query_list = NIL;
     709        5772 :     foreach(lc, raw_parsetree_list)
     710             :     {
     711        2886 :         RawStmt    *parsetree = lfirst_node(RawStmt, lc);
     712             :         List       *queryTree_sublist;
     713             : 
     714        2886 :         queryTree_sublist = pg_analyze_and_rewrite_params(parsetree,
     715        2886 :                                                           fcache->src,
     716             :                                                           (ParserSetupHook) sql_fn_parser_setup,
     717        2886 :                                                           fcache->pinfo,
     718             :                                                           NULL);
     719        2886 :         queryTree_list = lappend(queryTree_list, queryTree_sublist);
     720        2886 :         flat_query_list = list_concat(flat_query_list,
     721             :                                       list_copy(queryTree_sublist));
     722             :     }
     723             : 
     724             :     /*
     725             :      * Check that the function returns the type it claims to.  Although in
     726             :      * simple cases this was already done when the function was defined, we
     727             :      * have to recheck because database objects used in the function's queries
     728             :      * might have changed type.  We'd have to do it anyway if the function had
     729             :      * any polymorphic arguments.
     730             :      *
     731             :      * Note: we set fcache->returnsTuple according to whether we are returning
     732             :      * the whole tuple result or just a single column.  In the latter case we
     733             :      * clear returnsTuple because we need not act different from the scalar
     734             :      * result case, even if it's a rowtype column.  (However, we have to force
     735             :      * lazy eval mode in that case; otherwise we'd need extra code to expand
     736             :      * the rowtype column into multiple columns, since we have no way to
     737             :      * notify the caller that it should do that.)
     738             :      *
     739             :      * check_sql_fn_retval will also construct a JunkFilter we can use to
     740             :      * coerce the returned rowtype to the desired form (unless the result type
     741             :      * is VOID, in which case there's nothing to coerce to).
     742             :      */
     743        2886 :     fcache->returnsTuple = check_sql_fn_retval(foid,
     744             :                                                rettype,
     745             :                                                flat_query_list,
     746             :                                                NULL,
     747             :                                                &fcache->junkFilter);
     748             : 
     749        2886 :     if (fcache->returnsTuple)
     750             :     {
     751             :         /* Make sure output rowtype is properly blessed */
     752         183 :         BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tts_tupleDescriptor);
     753             :     }
     754        2703 :     else if (fcache->returnsSet && type_is_rowtype(fcache->rettype))
     755             :     {
     756             :         /*
     757             :          * Returning rowtype as if it were scalar --- materialize won't work.
     758             :          * Right now it's sufficient to override any caller preference for
     759             :          * materialize mode, but to add more smarts in init_execution_state
     760             :          * about this, we'd probably need a three-way flag instead of bool.
     761             :          */
     762           0 :         lazyEvalOK = true;
     763             :     }
     764             : 
     765             :     /* Finally, plan the queries */
     766        2886 :     fcache->func_state = init_execution_state(queryTree_list,
     767             :                                               fcache,
     768             :                                               lazyEvalOK);
     769             : 
     770             :     /* Mark fcache with time of creation to show it's valid */
     771        2885 :     fcache->lxid = MyProc->lxid;
     772        2885 :     fcache->subxid = GetCurrentSubTransactionId();
     773             : 
     774        2885 :     ReleaseSysCache(procedureTuple);
     775             : 
     776        2885 :     MemoryContextSwitchTo(oldcontext);
     777        2885 : }
     778             : 
     779             : /* Start up execution of one execution_state node */
     780             : static void
     781        5211 : postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
     782             : {
     783             :     DestReceiver *dest;
     784             : 
     785        5211 :     Assert(es->qd == NULL);
     786             : 
     787             :     /* Caller should have ensured a suitable snapshot is active */
     788        5211 :     Assert(ActiveSnapshotSet());
     789             : 
     790             :     /*
     791             :      * If this query produces the function result, send its output to the
     792             :      * tuplestore; else discard any output.
     793             :      */
     794        5211 :     if (es->setsResult)
     795             :     {
     796             :         DR_sqlfunction *myState;
     797             : 
     798        5199 :         dest = CreateDestReceiver(DestSQLFunction);
     799             :         /* pass down the needed info to the dest receiver routines */
     800        5199 :         myState = (DR_sqlfunction *) dest;
     801        5199 :         Assert(myState->pub.mydest == DestSQLFunction);
     802        5199 :         myState->tstore = fcache->tstore;
     803        5199 :         myState->cxt = CurrentMemoryContext;
     804        5199 :         myState->filter = fcache->junkFilter;
     805             :     }
     806             :     else
     807          12 :         dest = None_Receiver;
     808             : 
     809       10422 :     es->qd = CreateQueryDesc(es->stmt,
     810        5211 :                              fcache->src,
     811             :                              GetActiveSnapshot(),
     812             :                              InvalidSnapshot,
     813             :                              dest,
     814             :                              fcache->paramLI,
     815        5211 :                              es->qd ? es->qd->queryEnv : NULL,
     816             :                              0);
     817             : 
     818             :     /* Utility commands don't need Executor. */
     819        5211 :     if (es->qd->operation != CMD_UTILITY)
     820             :     {
     821             :         /*
     822             :          * In lazyEval mode, do not let the executor set up an AfterTrigger
     823             :          * context.  This is necessary not just an optimization, because we
     824             :          * mustn't exit from the function execution with a stacked
     825             :          * AfterTrigger level still active.  We are careful not to select
     826             :          * lazyEval mode for any statement that could possibly queue triggers.
     827             :          */
     828             :         int         eflags;
     829             : 
     830        5203 :         if (es->lazyEval)
     831        5041 :             eflags = EXEC_FLAG_SKIP_TRIGGERS;
     832             :         else
     833         162 :             eflags = 0;         /* default run-to-completion flags */
     834        5203 :         ExecutorStart(es->qd, eflags);
     835             :     }
     836             : 
     837        5211 :     es->status = F_EXEC_RUN;
     838        5211 : }
     839             : 
     840             : /* Run one execution_state; either to completion or to first result row */
     841             : /* Returns true if we ran to completion */
     842             : static bool
     843        5349 : postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
     844             : {
     845             :     bool        result;
     846             : 
     847        5349 :     if (es->qd->operation == CMD_UTILITY)
     848             :     {
     849          32 :         ProcessUtility(es->qd->plannedstmt,
     850           8 :                        fcache->src,
     851             :                        PROCESS_UTILITY_QUERY,
     852           8 :                        es->qd->params,
     853           8 :                        es->qd->queryEnv,
     854           8 :                        es->qd->dest,
     855             :                        NULL);
     856           5 :         result = true;          /* never stops early */
     857             :     }
     858             :     else
     859             :     {
     860             :         /* Run regular commands to completion unless lazyEval */
     861        5341 :         uint64      count = (es->lazyEval) ? 1 : 0;
     862             : 
     863        5341 :         ExecutorRun(es->qd, ForwardScanDirection, count, !fcache->returnsSet || !es->lazyEval);
     864             : 
     865             :         /*
     866             :          * If we requested run to completion OR there was no tuple returned,
     867             :          * command must be complete.
     868             :          */
     869        3040 :         result = (count == 0 || es->qd->estate->es_processed == 0);
     870             :     }
     871             : 
     872        3045 :     return result;
     873             : }
     874             : 
     875             : /* Shut down execution of one execution_state node */
     876             : static void
     877        2907 : postquel_end(execution_state *es)
     878             : {
     879             :     /* mark status done to ensure we don't do ExecutorEnd twice */
     880        2907 :     es->status = F_EXEC_DONE;
     881             : 
     882             :     /* Utility commands don't need Executor. */
     883        2907 :     if (es->qd->operation != CMD_UTILITY)
     884             :     {
     885        2902 :         ExecutorFinish(es->qd);
     886        2902 :         ExecutorEnd(es->qd);
     887             :     }
     888             : 
     889        2907 :     (*es->qd->dest->rDestroy) (es->qd->dest);
     890             : 
     891        2907 :     FreeQueryDesc(es->qd);
     892        2907 :     es->qd = NULL;
     893        2907 : }
     894             : 
     895             : /* Build ParamListInfo array representing current arguments */
     896             : static void
     897        5210 : postquel_sub_params(SQLFunctionCachePtr fcache,
     898             :                     FunctionCallInfo fcinfo)
     899             : {
     900        5210 :     int         nargs = fcinfo->nargs;
     901             : 
     902        5210 :     if (nargs > 0)
     903             :     {
     904             :         ParamListInfo paramLI;
     905             :         int         i;
     906             : 
     907        2841 :         if (fcache->paramLI == NULL)
     908             :         {
     909         522 :             paramLI = (ParamListInfo)
     910         522 :                 palloc(offsetof(ParamListInfoData, params) +
     911         522 :                        nargs * sizeof(ParamExternData));
     912             :             /* we have static list of params, so no hooks needed */
     913         522 :             paramLI->paramFetch = NULL;
     914         522 :             paramLI->paramFetchArg = NULL;
     915         522 :             paramLI->parserSetup = NULL;
     916         522 :             paramLI->parserSetupArg = NULL;
     917         522 :             paramLI->numParams = nargs;
     918         522 :             paramLI->paramMask = NULL;
     919         522 :             fcache->paramLI = paramLI;
     920             :         }
     921             :         else
     922             :         {
     923        2319 :             paramLI = fcache->paramLI;
     924        2319 :             Assert(paramLI->numParams == nargs);
     925             :         }
     926             : 
     927        7928 :         for (i = 0; i < nargs; i++)
     928             :         {
     929        5087 :             ParamExternData *prm = &paramLI->params[i];
     930             : 
     931        5087 :             prm->value = fcinfo->arg[i];
     932        5087 :             prm->isnull = fcinfo->argnull[i];
     933        5087 :             prm->pflags = 0;
     934        5087 :             prm->ptype = fcache->pinfo->argtypes[i];
     935             :         }
     936             :     }
     937             :     else
     938        2369 :         fcache->paramLI = NULL;
     939        5210 : }
     940             : 
     941             : /*
     942             :  * Extract the SQL function's value from a single result row.  This is used
     943             :  * both for scalar (non-set) functions and for each row of a lazy-eval set
     944             :  * result.
     945             :  */
     946             : static Datum
     947        1975 : postquel_get_single_result(TupleTableSlot *slot,
     948             :                            FunctionCallInfo fcinfo,
     949             :                            SQLFunctionCachePtr fcache,
     950             :                            MemoryContext resultcontext)
     951             : {
     952             :     Datum       value;
     953             :     MemoryContext oldcontext;
     954             : 
     955             :     /*
     956             :      * Set up to return the function value.  For pass-by-reference datatypes,
     957             :      * be sure to allocate the result in resultcontext, not the current memory
     958             :      * context (which has query lifespan).  We can't leave the data in the
     959             :      * TupleTableSlot because we intend to clear the slot before returning.
     960             :      */
     961        1975 :     oldcontext = MemoryContextSwitchTo(resultcontext);
     962             : 
     963        1975 :     if (fcache->returnsTuple)
     964             :     {
     965             :         /* We must return the whole tuple as a Datum. */
     966         191 :         fcinfo->isnull = false;
     967         191 :         value = ExecFetchSlotTupleDatum(slot);
     968             :     }
     969             :     else
     970             :     {
     971             :         /*
     972             :          * Returning a scalar, which we have to extract from the first column
     973             :          * of the SELECT result, and then copy into result context if needed.
     974             :          */
     975        1784 :         value = slot_getattr(slot, 1, &(fcinfo->isnull));
     976             : 
     977        1784 :         if (!fcinfo->isnull)
     978        1727 :             value = datumCopy(value, fcache->typbyval, fcache->typlen);
     979             :     }
     980             : 
     981        1975 :     MemoryContextSwitchTo(oldcontext);
     982             : 
     983        1975 :     return value;
     984             : }
     985             : 
     986             : /*
     987             :  * fmgr_sql: function call manager for SQL functions
     988             :  */
     989             : Datum
     990        5349 : fmgr_sql(PG_FUNCTION_ARGS)
     991             : {
     992             :     SQLFunctionCachePtr fcache;
     993             :     ErrorContextCallback sqlerrcontext;
     994             :     MemoryContext oldcontext;
     995             :     bool        randomAccess;
     996             :     bool        lazyEvalOK;
     997             :     bool        is_first;
     998             :     bool        pushed_snapshot;
     999             :     execution_state *es;
    1000             :     TupleTableSlot *slot;
    1001             :     Datum       result;
    1002             :     List       *eslist;
    1003             :     ListCell   *eslc;
    1004             : 
    1005             :     /*
    1006             :      * Setup error traceback support for ereport()
    1007             :      */
    1008        5349 :     sqlerrcontext.callback = sql_exec_error_callback;
    1009        5349 :     sqlerrcontext.arg = fcinfo->flinfo;
    1010        5349 :     sqlerrcontext.previous = error_context_stack;
    1011        5349 :     error_context_stack = &sqlerrcontext;
    1012             : 
    1013             :     /* Check call context */
    1014        5349 :     if (fcinfo->flinfo->fn_retset)
    1015             :     {
    1016         800 :         ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    1017             : 
    1018             :         /*
    1019             :          * For simplicity, we require callers to support both set eval modes.
    1020             :          * There are cases where we must use one or must use the other, and
    1021             :          * it's not really worthwhile to postpone the check till we know. But
    1022             :          * note we do not require caller to provide an expectedDesc.
    1023             :          */
    1024        1600 :         if (!rsi || !IsA(rsi, ReturnSetInfo) ||
    1025        1600 :             (rsi->allowedModes & SFRM_ValuePerCall) == 0 ||
    1026         800 :             (rsi->allowedModes & SFRM_Materialize) == 0)
    1027           0 :             ereport(ERROR,
    1028             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1029             :                      errmsg("set-valued function called in context that cannot accept a set")));
    1030         800 :         randomAccess = rsi->allowedModes & SFRM_Materialize_Random;
    1031         800 :         lazyEvalOK = !(rsi->allowedModes & SFRM_Materialize_Preferred);
    1032             :     }
    1033             :     else
    1034             :     {
    1035        4549 :         randomAccess = false;
    1036        4549 :         lazyEvalOK = true;
    1037             :     }
    1038             : 
    1039             :     /*
    1040             :      * Initialize fcache (build plans) if first time through; or re-initialize
    1041             :      * if the cache is stale.
    1042             :      */
    1043        5349 :     fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
    1044             : 
    1045        5349 :     if (fcache != NULL)
    1046             :     {
    1047        4926 :         if (fcache->lxid != MyProc->lxid ||
    1048        2463 :             !SubTransactionIsActive(fcache->subxid))
    1049             :         {
    1050             :             /* It's stale; unlink and delete */
    1051           0 :             fcinfo->flinfo->fn_extra = NULL;
    1052           0 :             MemoryContextDelete(fcache->fcontext);
    1053           0 :             fcache = NULL;
    1054             :         }
    1055             :     }
    1056             : 
    1057        5349 :     if (fcache == NULL)
    1058             :     {
    1059        2886 :         init_sql_fcache(fcinfo->flinfo, PG_GET_COLLATION(), lazyEvalOK);
    1060        2885 :         fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
    1061             :     }
    1062             : 
    1063             :     /*
    1064             :      * Switch to context in which the fcache lives.  This ensures that our
    1065             :      * tuplestore etc will have sufficient lifetime.  The sub-executor is
    1066             :      * responsible for deleting per-tuple information.  (XXX in the case of a
    1067             :      * long-lived FmgrInfo, this policy represents more memory leakage, but
    1068             :      * it's not entirely clear where to keep stuff instead.)
    1069             :      */
    1070        5348 :     oldcontext = MemoryContextSwitchTo(fcache->fcontext);
    1071             : 
    1072             :     /*
    1073             :      * Find first unfinished query in function, and note whether it's the
    1074             :      * first query.
    1075             :      */
    1076        5348 :     eslist = fcache->func_state;
    1077        5348 :     es = NULL;
    1078        5348 :     is_first = true;
    1079        5348 :     foreach(eslc, eslist)
    1080             :     {
    1081        5348 :         es = (execution_state *) lfirst(eslc);
    1082             : 
    1083       10696 :         while (es && es->status == F_EXEC_DONE)
    1084             :         {
    1085           0 :             is_first = false;
    1086           0 :             es = es->next;
    1087             :         }
    1088             : 
    1089        5348 :         if (es)
    1090        5348 :             break;
    1091             :     }
    1092             : 
    1093             :     /*
    1094             :      * Convert params to appropriate format if starting a fresh execution. (If
    1095             :      * continuing execution, we can re-use prior params.)
    1096             :      */
    1097        5348 :     if (is_first && es && es->status == F_EXEC_START)
    1098        5210 :         postquel_sub_params(fcache, fcinfo);
    1099             : 
    1100             :     /*
    1101             :      * Build tuplestore to hold results, if we don't have one already. Note
    1102             :      * it's in the query-lifespan context.
    1103             :      */
    1104        5348 :     if (!fcache->tstore)
    1105        2913 :         fcache->tstore = tuplestore_begin_heap(randomAccess, false, work_mem);
    1106             : 
    1107             :     /*
    1108             :      * Execute each command in the function one after another until we either
    1109             :      * run out of commands or get a result row from a lazily-evaluated SELECT.
    1110             :      *
    1111             :      * Notes about snapshot management:
    1112             :      *
    1113             :      * In a read-only function, we just use the surrounding query's snapshot.
    1114             :      *
    1115             :      * In a non-read-only function, we rely on the fact that we'll never
    1116             :      * suspend execution between queries of the function: the only reason to
    1117             :      * suspend execution before completion is if we are returning a row from a
    1118             :      * lazily-evaluated SELECT.  So, when first entering this loop, we'll
    1119             :      * either start a new query (and push a fresh snapshot) or re-establish
    1120             :      * the active snapshot from the existing query descriptor.  If we need to
    1121             :      * start a new query in a subsequent execution of the loop, either we need
    1122             :      * a fresh snapshot (and pushed_snapshot is false) or the existing
    1123             :      * snapshot is on the active stack and we can just bump its command ID.
    1124             :      */
    1125        5348 :     pushed_snapshot = false;
    1126       13603 :     while (es)
    1127             :     {
    1128             :         bool        completed;
    1129             : 
    1130        5349 :         if (es->status == F_EXEC_START)
    1131             :         {
    1132             :             /*
    1133             :              * If not read-only, be sure to advance the command counter for
    1134             :              * each command, so that all work to date in this transaction is
    1135             :              * visible.  Take a new snapshot if we don't have one yet,
    1136             :              * otherwise just bump the command ID in the existing snapshot.
    1137             :              */
    1138        5211 :             if (!fcache->readonly_func)
    1139             :             {
    1140        3483 :                 CommandCounterIncrement();
    1141        3483 :                 if (!pushed_snapshot)
    1142             :                 {
    1143        3482 :                     PushActiveSnapshot(GetTransactionSnapshot());
    1144        3482 :                     pushed_snapshot = true;
    1145             :                 }
    1146             :                 else
    1147           1 :                     UpdateActiveSnapshotCommandId();
    1148             :             }
    1149             : 
    1150        5211 :             postquel_start(es, fcache);
    1151             :         }
    1152         138 :         else if (!fcache->readonly_func && !pushed_snapshot)
    1153             :         {
    1154             :             /* Re-establish active snapshot when re-entering function */
    1155         101 :             PushActiveSnapshot(es->qd->snapshot);
    1156         101 :             pushed_snapshot = true;
    1157             :         }
    1158             : 
    1159        5349 :         completed = postquel_getnext(es, fcache);
    1160             : 
    1161             :         /*
    1162             :          * If we ran the command to completion, we can shut it down now. Any
    1163             :          * row(s) we need to return are safely stashed in the tuplestore, and
    1164             :          * we want to be sure that, for example, AFTER triggers get fired
    1165             :          * before we return anything.  Also, if the function doesn't return
    1166             :          * set, we can shut it down anyway because it must be a SELECT and we
    1167             :          * don't care about fetching any more result rows.
    1168             :          */
    1169        3045 :         if (completed || !fcache->returnsSet)
    1170        2907 :             postquel_end(es);
    1171             : 
    1172             :         /*
    1173             :          * Break from loop if we didn't shut down (implying we got a
    1174             :          * lazily-evaluated row).  Otherwise we'll press on till the whole
    1175             :          * function is done, relying on the tuplestore to keep hold of the
    1176             :          * data to eventually be returned.  This is necessary since an
    1177             :          * INSERT/UPDATE/DELETE RETURNING that sets the result might be
    1178             :          * followed by additional rule-inserted commands, and we want to
    1179             :          * finish doing all those commands before we return anything.
    1180             :          */
    1181        3045 :         if (es->status != F_EXEC_DONE)
    1182         138 :             break;
    1183             : 
    1184             :         /*
    1185             :          * Advance to next execution_state, which might be in the next list.
    1186             :          */
    1187        2907 :         es = es->next;
    1188        5814 :         while (!es)
    1189             :         {
    1190        2906 :             eslc = lnext(eslc);
    1191        2906 :             if (!eslc)
    1192        2906 :                 break;          /* end of function */
    1193             : 
    1194           0 :             es = (execution_state *) lfirst(eslc);
    1195             : 
    1196             :             /*
    1197             :              * Flush the current snapshot so that we will take a new one for
    1198             :              * the new query list.  This ensures that new snaps are taken at
    1199             :              * original-query boundaries, matching the behavior of interactive
    1200             :              * execution.
    1201             :              */
    1202           0 :             if (pushed_snapshot)
    1203             :             {
    1204           0 :                 PopActiveSnapshot();
    1205           0 :                 pushed_snapshot = false;
    1206             :             }
    1207             :         }
    1208             :     }
    1209             : 
    1210             :     /*
    1211             :      * The tuplestore now contains whatever row(s) we are supposed to return.
    1212             :      */
    1213        3044 :     if (fcache->returnsSet)
    1214             :     {
    1215         800 :         ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    1216             : 
    1217         800 :         if (es)
    1218             :         {
    1219             :             /*
    1220             :              * If we stopped short of being done, we must have a lazy-eval
    1221             :              * row.
    1222             :              */
    1223         138 :             Assert(es->lazyEval);
    1224             :             /* Re-use the junkfilter's output slot to fetch back the tuple */
    1225         138 :             Assert(fcache->junkFilter);
    1226         138 :             slot = fcache->junkFilter->jf_resultSlot;
    1227         138 :             if (!tuplestore_gettupleslot(fcache->tstore, true, false, slot))
    1228           0 :                 elog(ERROR, "failed to fetch lazy-eval tuple");
    1229             :             /* Extract the result as a datum, and copy out from the slot */
    1230         138 :             result = postquel_get_single_result(slot, fcinfo,
    1231             :                                                 fcache, oldcontext);
    1232             :             /* Clear the tuplestore, but keep it for next time */
    1233             :             /* NB: this might delete the slot's content, but we don't care */
    1234         138 :             tuplestore_clear(fcache->tstore);
    1235             : 
    1236             :             /*
    1237             :              * Let caller know we're not finished.
    1238             :              */
    1239         138 :             rsi->isDone = ExprMultipleResult;
    1240             : 
    1241             :             /*
    1242             :              * Ensure we will get shut down cleanly if the exprcontext is not
    1243             :              * run to completion.
    1244             :              */
    1245         138 :             if (!fcache->shutdown_reg)
    1246             :             {
    1247         104 :                 RegisterExprContextCallback(rsi->econtext,
    1248             :                                             ShutdownSQLFunction,
    1249             :                                             PointerGetDatum(fcache));
    1250         104 :                 fcache->shutdown_reg = true;
    1251             :             }
    1252             :         }
    1253         662 :         else if (fcache->lazyEval)
    1254             :         {
    1255             :             /*
    1256             :              * We are done with a lazy evaluation.  Clean up.
    1257             :              */
    1258         509 :             tuplestore_clear(fcache->tstore);
    1259             : 
    1260             :             /*
    1261             :              * Let caller know we're finished.
    1262             :              */
    1263         509 :             rsi->isDone = ExprEndResult;
    1264             : 
    1265         509 :             fcinfo->isnull = true;
    1266         509 :             result = (Datum) 0;
    1267             : 
    1268             :             /* Deregister shutdown callback, if we made one */
    1269         509 :             if (fcache->shutdown_reg)
    1270             :             {
    1271         104 :                 UnregisterExprContextCallback(rsi->econtext,
    1272             :                                               ShutdownSQLFunction,
    1273             :                                               PointerGetDatum(fcache));
    1274         104 :                 fcache->shutdown_reg = false;
    1275             :             }
    1276             :         }
    1277             :         else
    1278             :         {
    1279             :             /*
    1280             :              * We are done with a non-lazy evaluation.  Return whatever is in
    1281             :              * the tuplestore.  (It is now caller's responsibility to free the
    1282             :              * tuplestore when done.)
    1283             :              */
    1284         153 :             rsi->returnMode = SFRM_Materialize;
    1285         153 :             rsi->setResult = fcache->tstore;
    1286         153 :             fcache->tstore = NULL;
    1287             :             /* must copy desc because execSRF.c will free it */
    1288         153 :             if (fcache->junkFilter)
    1289         153 :                 rsi->setDesc = CreateTupleDescCopy(fcache->junkFilter->jf_cleanTupType);
    1290             : 
    1291         153 :             fcinfo->isnull = true;
    1292         153 :             result = (Datum) 0;
    1293             : 
    1294             :             /* Deregister shutdown callback, if we made one */
    1295         153 :             if (fcache->shutdown_reg)
    1296             :             {
    1297           0 :                 UnregisterExprContextCallback(rsi->econtext,
    1298             :                                               ShutdownSQLFunction,
    1299             :                                               PointerGetDatum(fcache));
    1300           0 :                 fcache->shutdown_reg = false;
    1301             :             }
    1302             :         }
    1303             :     }
    1304             :     else
    1305             :     {
    1306             :         /*
    1307             :          * Non-set function.  If we got a row, return it; else return NULL.
    1308             :          */
    1309        2244 :         if (fcache->junkFilter)
    1310             :         {
    1311             :             /* Re-use the junkfilter's output slot to fetch back the tuple */
    1312        2236 :             slot = fcache->junkFilter->jf_resultSlot;
    1313        2236 :             if (tuplestore_gettupleslot(fcache->tstore, true, false, slot))
    1314        1837 :                 result = postquel_get_single_result(slot, fcinfo,
    1315             :                                                     fcache, oldcontext);
    1316             :             else
    1317             :             {
    1318         399 :                 fcinfo->isnull = true;
    1319         399 :                 result = (Datum) 0;
    1320             :             }
    1321             :         }
    1322             :         else
    1323             :         {
    1324             :             /* Should only get here for VOID functions */
    1325           8 :             Assert(fcache->rettype == VOIDOID);
    1326           8 :             fcinfo->isnull = true;
    1327           8 :             result = (Datum) 0;
    1328             :         }
    1329             : 
    1330             :         /* Clear the tuplestore, but keep it for next time */
    1331        2244 :         tuplestore_clear(fcache->tstore);
    1332             :     }
    1333             : 
    1334             :     /* Pop snapshot if we have pushed one */
    1335        3044 :     if (pushed_snapshot)
    1336        1286 :         PopActiveSnapshot();
    1337             : 
    1338             :     /*
    1339             :      * If we've gone through every command in the function, we are done. Reset
    1340             :      * the execution states to start over again on next call.
    1341             :      */
    1342        3044 :     if (es == NULL)
    1343             :     {
    1344        5812 :         foreach(eslc, fcache->func_state)
    1345             :         {
    1346        2906 :             es = (execution_state *) lfirst(eslc);
    1347        8719 :             while (es)
    1348             :             {
    1349        2907 :                 es->status = F_EXEC_START;
    1350        2907 :                 es = es->next;
    1351             :             }
    1352             :         }
    1353             :     }
    1354             : 
    1355        3044 :     error_context_stack = sqlerrcontext.previous;
    1356             : 
    1357        3044 :     MemoryContextSwitchTo(oldcontext);
    1358             : 
    1359        3044 :     return result;
    1360             : }
    1361             : 
    1362             : 
    1363             : /*
    1364             :  * error context callback to let us supply a call-stack traceback
    1365             :  */
    1366             : static void
    1367        2311 : sql_exec_error_callback(void *arg)
    1368             : {
    1369        2311 :     FmgrInfo   *flinfo = (FmgrInfo *) arg;
    1370        2311 :     SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) flinfo->fn_extra;
    1371             :     int         syntaxerrposition;
    1372             : 
    1373             :     /*
    1374             :      * We can do nothing useful if init_sql_fcache() didn't get as far as
    1375             :      * saving the function name
    1376             :      */
    1377        2311 :     if (fcache == NULL || fcache->fname == NULL)
    1378        2311 :         return;
    1379             : 
    1380             :     /*
    1381             :      * If there is a syntax error position, convert to internal syntax error
    1382             :      */
    1383        2311 :     syntaxerrposition = geterrposition();
    1384        2311 :     if (syntaxerrposition > 0 && fcache->src != NULL)
    1385             :     {
    1386           0 :         errposition(0);
    1387           0 :         internalerrposition(syntaxerrposition);
    1388           0 :         internalerrquery(fcache->src);
    1389             :     }
    1390             : 
    1391             :     /*
    1392             :      * Try to determine where in the function we failed.  If there is a query
    1393             :      * with non-null QueryDesc, finger it.  (We check this rather than looking
    1394             :      * for F_EXEC_RUN state, so that errors during ExecutorStart or
    1395             :      * ExecutorEnd are blamed on the appropriate query; see postquel_start and
    1396             :      * postquel_end.)
    1397             :      */
    1398        2311 :     if (fcache->func_state)
    1399             :     {
    1400             :         execution_state *es;
    1401             :         int         query_num;
    1402             :         ListCell   *lc;
    1403             : 
    1404        2310 :         es = NULL;
    1405        2310 :         query_num = 1;
    1406        2310 :         foreach(lc, fcache->func_state)
    1407             :         {
    1408        2310 :             es = (execution_state *) lfirst(lc);
    1409        4620 :             while (es)
    1410             :             {
    1411        2310 :                 if (es->qd)
    1412             :                 {
    1413        2310 :                     errcontext("SQL function \"%s\" statement %d",
    1414             :                                fcache->fname, query_num);
    1415        2310 :                     break;
    1416             :                 }
    1417           0 :                 es = es->next;
    1418             :             }
    1419        2310 :             if (es)
    1420        2310 :                 break;
    1421           0 :             query_num++;
    1422             :         }
    1423        2310 :         if (es == NULL)
    1424             :         {
    1425             :             /*
    1426             :              * couldn't identify a running query; might be function entry,
    1427             :              * function exit, or between queries.
    1428             :              */
    1429           0 :             errcontext("SQL function \"%s\"", fcache->fname);
    1430             :         }
    1431             :     }
    1432             :     else
    1433             :     {
    1434             :         /*
    1435             :          * Assume we failed during init_sql_fcache().  (It's possible that the
    1436             :          * function actually has an empty body, but in that case we may as
    1437             :          * well report all errors as being "during startup".)
    1438             :          */
    1439           1 :         errcontext("SQL function \"%s\" during startup", fcache->fname);
    1440             :     }
    1441             : }
    1442             : 
    1443             : 
    1444             : /*
    1445             :  * callback function in case a function-returning-set needs to be shut down
    1446             :  * before it has been run to completion
    1447             :  */
    1448             : static void
    1449           0 : ShutdownSQLFunction(Datum arg)
    1450             : {
    1451           0 :     SQLFunctionCachePtr fcache = (SQLFunctionCachePtr) DatumGetPointer(arg);
    1452             :     execution_state *es;
    1453             :     ListCell   *lc;
    1454             : 
    1455           0 :     foreach(lc, fcache->func_state)
    1456             :     {
    1457           0 :         es = (execution_state *) lfirst(lc);
    1458           0 :         while (es)
    1459             :         {
    1460             :             /* Shut down anything still running */
    1461           0 :             if (es->status == F_EXEC_RUN)
    1462             :             {
    1463             :                 /* Re-establish active snapshot for any called functions */
    1464           0 :                 if (!fcache->readonly_func)
    1465           0 :                     PushActiveSnapshot(es->qd->snapshot);
    1466             : 
    1467           0 :                 postquel_end(es);
    1468             : 
    1469           0 :                 if (!fcache->readonly_func)
    1470           0 :                     PopActiveSnapshot();
    1471             :             }
    1472             : 
    1473             :             /* Reset states to START in case we're called again */
    1474           0 :             es->status = F_EXEC_START;
    1475           0 :             es = es->next;
    1476             :         }
    1477             :     }
    1478             : 
    1479             :     /* Release tuplestore if we have one */
    1480           0 :     if (fcache->tstore)
    1481           0 :         tuplestore_end(fcache->tstore);
    1482           0 :     fcache->tstore = NULL;
    1483             : 
    1484             :     /* execUtils will deregister the callback... */
    1485           0 :     fcache->shutdown_reg = false;
    1486           0 : }
    1487             : 
    1488             : 
    1489             : /*
    1490             :  * check_sql_fn_retval() -- check return value of a list of sql parse trees.
    1491             :  *
    1492             :  * The return value of a sql function is the value returned by the last
    1493             :  * canSetTag query in the function.  We do some ad-hoc type checking here
    1494             :  * to be sure that the user is returning the type he claims.  There are
    1495             :  * also a couple of strange-looking features to assist callers in dealing
    1496             :  * with allowed special cases, such as binary-compatible result types.
    1497             :  *
    1498             :  * For a polymorphic function the passed rettype must be the actual resolved
    1499             :  * output type of the function; we should never see a polymorphic pseudotype
    1500             :  * such as ANYELEMENT as rettype.  (This means we can't check the type during
    1501             :  * function definition of a polymorphic function.)
    1502             :  *
    1503             :  * This function returns true if the sql function returns the entire tuple
    1504             :  * result of its final statement, or false if it returns just the first column
    1505             :  * result of that statement.  It throws an error if the final statement doesn't
    1506             :  * return the right type at all.
    1507             :  *
    1508             :  * Note that because we allow "SELECT rowtype_expression", the result can be
    1509             :  * false even when the declared function return type is a rowtype.
    1510             :  *
    1511             :  * If modifyTargetList isn't NULL, the function will modify the final
    1512             :  * statement's targetlist in two cases:
    1513             :  * (1) if the tlist returns values that are binary-coercible to the expected
    1514             :  * type rather than being exactly the expected type.  RelabelType nodes will
    1515             :  * be inserted to make the result types match exactly.
    1516             :  * (2) if there are dropped columns in the declared result rowtype.  NULL
    1517             :  * output columns will be inserted in the tlist to match them.
    1518             :  * (Obviously the caller must pass a parsetree that is okay to modify when
    1519             :  * using this flag.)  Note that this flag does not affect whether the tlist is
    1520             :  * considered to be a legal match to the result type, only how we react to
    1521             :  * allowed not-exact-match cases.  *modifyTargetList will be set true iff
    1522             :  * we had to make any "dangerous" changes that could modify the semantics of
    1523             :  * the statement.  If it is set true, the caller should not use the modified
    1524             :  * statement, but for simplicity we apply the changes anyway.
    1525             :  *
    1526             :  * If junkFilter isn't NULL, then *junkFilter is set to a JunkFilter defined
    1527             :  * to convert the function's tuple result to the correct output tuple type.
    1528             :  * Exception: if the function is defined to return VOID then *junkFilter is
    1529             :  * set to NULL.
    1530             :  */
    1531             : bool
    1532        5538 : check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
    1533             :                     bool *modifyTargetList,
    1534             :                     JunkFilter **junkFilter)
    1535             : {
    1536             :     Query      *parse;
    1537             :     List      **tlist_ptr;
    1538             :     List       *tlist;
    1539             :     int         tlistlen;
    1540             :     char        fn_typtype;
    1541             :     Oid         restype;
    1542             :     ListCell   *lc;
    1543             : 
    1544        5538 :     AssertArg(!IsPolymorphicType(rettype));
    1545             : 
    1546        5538 :     if (modifyTargetList)
    1547        2481 :         *modifyTargetList = false;  /* initialize for no change */
    1548        5538 :     if (junkFilter)
    1549        2886 :         *junkFilter = NULL;     /* initialize in case of VOID result */
    1550             : 
    1551             :     /*
    1552             :      * Find the last canSetTag query in the list.  This isn't necessarily the
    1553             :      * last parsetree, because rule rewriting can insert queries after what
    1554             :      * the user wrote.
    1555             :      */
    1556        5538 :     parse = NULL;
    1557       11077 :     foreach(lc, queryTreeList)
    1558             :     {
    1559        5539 :         Query      *q = lfirst_node(Query, lc);
    1560             : 
    1561        5539 :         if (q->canSetTag)
    1562        5538 :             parse = q;
    1563             :     }
    1564             : 
    1565             :     /*
    1566             :      * If it's a plain SELECT, it returns whatever the targetlist says.
    1567             :      * Otherwise, if it's INSERT/UPDATE/DELETE with RETURNING, it returns
    1568             :      * that. Otherwise, the function return type must be VOID.
    1569             :      *
    1570             :      * Note: eventually replace this test with QueryReturnsTuples?  We'd need
    1571             :      * a more general method of determining the output type, though.  Also, it
    1572             :      * seems too dangerous to consider FETCH or EXECUTE as returning a
    1573             :      * determinable rowtype, since they depend on relatively short-lived
    1574             :      * entities.
    1575             :      */
    1576       11076 :     if (parse &&
    1577        5538 :         parse->commandType == CMD_SELECT)
    1578             :     {
    1579        5504 :         tlist_ptr = &parse->targetList;
    1580        5504 :         tlist = parse->targetList;
    1581             :     }
    1582          68 :     else if (parse &&
    1583          47 :              (parse->commandType == CMD_INSERT ||
    1584          26 :               parse->commandType == CMD_UPDATE ||
    1585          34 :               parse->commandType == CMD_DELETE) &&
    1586          21 :              parse->returningList)
    1587             :     {
    1588          17 :         tlist_ptr = &parse->returningList;
    1589          17 :         tlist = parse->returningList;
    1590             :     }
    1591             :     else
    1592             :     {
    1593             :         /* Empty function body, or last statement is a utility command */
    1594          17 :         if (rettype != VOIDOID)
    1595           0 :             ereport(ERROR,
    1596             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1597             :                      errmsg("return type mismatch in function declared to return %s",
    1598             :                             format_type_be(rettype)),
    1599             :                      errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE RETURNING.")));
    1600          17 :         return false;
    1601             :     }
    1602             : 
    1603             :     /*
    1604             :      * OK, check that the targetlist returns something matching the declared
    1605             :      * type.  (We used to insist that the declared type not be VOID in this
    1606             :      * case, but that makes it hard to write a void function that exits after
    1607             :      * calling another void function.  Instead, we insist that the tlist
    1608             :      * return void ... so void is treated as if it were a scalar type below.)
    1609             :      */
    1610             : 
    1611             :     /*
    1612             :      * Count the non-junk entries in the result targetlist.
    1613             :      */
    1614        5521 :     tlistlen = ExecCleanTargetListLength(tlist);
    1615             : 
    1616        5521 :     fn_typtype = get_typtype(rettype);
    1617             : 
    1618        5521 :     if (fn_typtype == TYPTYPE_BASE ||
    1619         234 :         fn_typtype == TYPTYPE_DOMAIN ||
    1620         233 :         fn_typtype == TYPTYPE_ENUM ||
    1621         233 :         fn_typtype == TYPTYPE_RANGE ||
    1622             :         rettype == VOIDOID)
    1623        5291 :     {
    1624             :         /*
    1625             :          * For scalar-type returns, the target list must have exactly one
    1626             :          * non-junk entry, and its type must agree with what the user
    1627             :          * declared; except we allow binary-compatible types too.
    1628             :          */
    1629             :         TargetEntry *tle;
    1630             : 
    1631        5293 :         if (tlistlen != 1)
    1632           1 :             ereport(ERROR,
    1633             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1634             :                      errmsg("return type mismatch in function declared to return %s",
    1635             :                             format_type_be(rettype)),
    1636             :                      errdetail("Final statement must return exactly one column.")));
    1637             : 
    1638             :         /* We assume here that non-junk TLEs must come first in tlists */
    1639        5292 :         tle = (TargetEntry *) linitial(tlist);
    1640        5292 :         Assert(!tle->resjunk);
    1641             : 
    1642        5292 :         restype = exprType((Node *) tle->expr);
    1643        5292 :         if (!IsBinaryCoercible(restype, rettype))
    1644           1 :             ereport(ERROR,
    1645             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1646             :                      errmsg("return type mismatch in function declared to return %s",
    1647             :                             format_type_be(rettype)),
    1648             :                      errdetail("Actual return type is %s.",
    1649             :                                format_type_be(restype))));
    1650        5291 :         if (modifyTargetList && restype != rettype)
    1651             :         {
    1652           1 :             tle->expr = (Expr *) makeRelabelType(tle->expr,
    1653             :                                                  rettype,
    1654             :                                                  -1,
    1655             :                                                  get_typcollation(rettype),
    1656             :                                                  COERCE_IMPLICIT_CAST);
    1657             :             /* Relabel is dangerous if TLE is a sort/group or setop column */
    1658           1 :             if (tle->ressortgroupref != 0 || parse->setOperations)
    1659           1 :                 *modifyTargetList = true;
    1660             :         }
    1661             : 
    1662             :         /* Set up junk filter if needed */
    1663        5291 :         if (junkFilter)
    1664        2689 :             *junkFilter = ExecInitJunkFilter(tlist, false, NULL);
    1665             :     }
    1666         228 :     else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
    1667             :     {
    1668             :         /* Returns a rowtype */
    1669             :         TupleDesc   tupdesc;
    1670             :         int         tupnatts;   /* physical number of columns in tuple */
    1671             :         int         tuplogcols; /* # of nondeleted columns in tuple */
    1672             :         int         colindex;   /* physical column index */
    1673             :         List       *newtlist;   /* new non-junk tlist entries */
    1674             :         List       *junkattrs;  /* new junk tlist entries */
    1675             : 
    1676             :         /*
    1677             :          * If the target list is of length 1, and the type of the varnode in
    1678             :          * the target list matches the declared return type, this is okay.
    1679             :          * This can happen, for example, where the body of the function is
    1680             :          * 'SELECT func2()', where func2 has the same composite return type as
    1681             :          * the function that's calling it.
    1682             :          *
    1683             :          * XXX Note that if rettype is RECORD, the IsBinaryCoercible check
    1684             :          * will succeed for any composite restype.  For the moment we rely on
    1685             :          * runtime type checking to catch any discrepancy, but it'd be nice to
    1686             :          * do better at parse time.
    1687             :          */
    1688         228 :         if (tlistlen == 1)
    1689             :         {
    1690          12 :             TargetEntry *tle = (TargetEntry *) linitial(tlist);
    1691             : 
    1692          12 :             Assert(!tle->resjunk);
    1693          12 :             restype = exprType((Node *) tle->expr);
    1694          12 :             if (IsBinaryCoercible(restype, rettype))
    1695             :             {
    1696           6 :                 if (modifyTargetList && restype != rettype)
    1697             :                 {
    1698           0 :                     tle->expr = (Expr *) makeRelabelType(tle->expr,
    1699             :                                                          rettype,
    1700             :                                                          -1,
    1701             :                                                          get_typcollation(rettype),
    1702             :                                                          COERCE_IMPLICIT_CAST);
    1703             :                     /* Relabel is dangerous if sort/group or setop column */
    1704           0 :                     if (tle->ressortgroupref != 0 || parse->setOperations)
    1705           0 :                         *modifyTargetList = true;
    1706             :                 }
    1707             :                 /* Set up junk filter if needed */
    1708           6 :                 if (junkFilter)
    1709           3 :                     *junkFilter = ExecInitJunkFilter(tlist, false, NULL);
    1710           6 :                 return false;   /* NOT returning whole tuple */
    1711             :             }
    1712             :         }
    1713             : 
    1714             :         /* Is the rowtype fixed, or determined only at runtime? */
    1715         222 :         if (get_func_result_type(func_id, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
    1716             :         {
    1717             :             /*
    1718             :              * Assume we are returning the whole tuple. Crosschecking against
    1719             :              * what the caller expects will happen at runtime.
    1720             :              */
    1721          31 :             if (junkFilter)
    1722          27 :                 *junkFilter = ExecInitJunkFilter(tlist, false, NULL);
    1723          31 :             return true;
    1724             :         }
    1725         191 :         Assert(tupdesc);
    1726             : 
    1727             :         /*
    1728             :          * Verify that the targetlist matches the return tuple type. We scan
    1729             :          * the non-deleted attributes to ensure that they match the datatypes
    1730             :          * of the non-resjunk columns.  For deleted attributes, insert NULL
    1731             :          * result columns if the caller asked for that.
    1732             :          */
    1733         191 :         tupnatts = tupdesc->natts;
    1734         191 :         tuplogcols = 0;         /* we'll count nondeleted cols as we go */
    1735         191 :         colindex = 0;
    1736         191 :         newtlist = NIL;         /* these are only used if modifyTargetList */
    1737         191 :         junkattrs = NIL;
    1738             : 
    1739         733 :         foreach(lc, tlist)
    1740             :         {
    1741         542 :             TargetEntry *tle = (TargetEntry *) lfirst(lc);
    1742             :             Form_pg_attribute attr;
    1743             :             Oid         tletype;
    1744             :             Oid         atttype;
    1745             : 
    1746         542 :             if (tle->resjunk)
    1747             :             {
    1748           0 :                 if (modifyTargetList)
    1749           0 :                     junkattrs = lappend(junkattrs, tle);
    1750           0 :                 continue;
    1751             :             }
    1752             : 
    1753             :             do
    1754             :             {
    1755         556 :                 colindex++;
    1756         556 :                 if (colindex > tupnatts)
    1757           0 :                     ereport(ERROR,
    1758             :                             (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1759             :                              errmsg("return type mismatch in function declared to return %s",
    1760             :                                     format_type_be(rettype)),
    1761             :                              errdetail("Final statement returns too many columns.")));
    1762         556 :                 attr = TupleDescAttr(tupdesc, colindex - 1);
    1763         556 :                 if (attr->attisdropped && modifyTargetList)
    1764             :                 {
    1765             :                     Expr       *null_expr;
    1766             : 
    1767             :                     /* The type of the null we insert isn't important */
    1768           1 :                     null_expr = (Expr *) makeConst(INT4OID,
    1769             :                                                    -1,
    1770             :                                                    InvalidOid,
    1771             :                                                    sizeof(int32),
    1772             :                                                    (Datum) 0,
    1773             :                                                    true,    /* isnull */
    1774             :                                                    true /* byval */ );
    1775           1 :                     newtlist = lappend(newtlist,
    1776           1 :                                        makeTargetEntry(null_expr,
    1777             :                                                        colindex,
    1778             :                                                        NULL,
    1779             :                                                        false));
    1780             :                     /* NULL insertion is dangerous in a setop */
    1781           1 :                     if (parse->setOperations)
    1782           0 :                         *modifyTargetList = true;
    1783             :                 }
    1784         556 :             } while (attr->attisdropped);
    1785         542 :             tuplogcols++;
    1786             : 
    1787         542 :             tletype = exprType((Node *) tle->expr);
    1788         542 :             atttype = attr->atttypid;
    1789         542 :             if (!IsBinaryCoercible(tletype, atttype))
    1790           0 :                 ereport(ERROR,
    1791             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1792             :                          errmsg("return type mismatch in function declared to return %s",
    1793             :                                 format_type_be(rettype)),
    1794             :                          errdetail("Final statement returns %s instead of %s at column %d.",
    1795             :                                    format_type_be(tletype),
    1796             :                                    format_type_be(atttype),
    1797             :                                    tuplogcols)));
    1798         542 :             if (modifyTargetList)
    1799             :             {
    1800           7 :                 if (tletype != atttype)
    1801             :                 {
    1802           0 :                     tle->expr = (Expr *) makeRelabelType(tle->expr,
    1803             :                                                          atttype,
    1804             :                                                          -1,
    1805             :                                                          get_typcollation(atttype),
    1806             :                                                          COERCE_IMPLICIT_CAST);
    1807             :                     /* Relabel is dangerous if sort/group or setop column */
    1808           0 :                     if (tle->ressortgroupref != 0 || parse->setOperations)
    1809           0 :                         *modifyTargetList = true;
    1810             :                 }
    1811           7 :                 tle->resno = colindex;
    1812           7 :                 newtlist = lappend(newtlist, tle);
    1813             :             }
    1814             :         }
    1815             : 
    1816             :         /* remaining columns in tupdesc had better all be dropped */
    1817         191 :         for (colindex++; colindex <= tupnatts; colindex++)
    1818             :         {
    1819           0 :             if (!TupleDescAttr(tupdesc, colindex - 1)->attisdropped)
    1820           0 :                 ereport(ERROR,
    1821             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1822             :                          errmsg("return type mismatch in function declared to return %s",
    1823             :                                 format_type_be(rettype)),
    1824             :                          errdetail("Final statement returns too few columns.")));
    1825           0 :             if (modifyTargetList)
    1826             :             {
    1827             :                 Expr       *null_expr;
    1828             : 
    1829             :                 /* The type of the null we insert isn't important */
    1830           0 :                 null_expr = (Expr *) makeConst(INT4OID,
    1831             :                                                -1,
    1832             :                                                InvalidOid,
    1833             :                                                sizeof(int32),
    1834             :                                                (Datum) 0,
    1835             :                                                true,    /* isnull */
    1836             :                                                true /* byval */ );
    1837           0 :                 newtlist = lappend(newtlist,
    1838           0 :                                    makeTargetEntry(null_expr,
    1839             :                                                    colindex,
    1840             :                                                    NULL,
    1841             :                                                    false));
    1842             :                 /* NULL insertion is dangerous in a setop */
    1843           0 :                 if (parse->setOperations)
    1844           0 :                     *modifyTargetList = true;
    1845             :             }
    1846             :         }
    1847             : 
    1848         191 :         if (modifyTargetList)
    1849             :         {
    1850             :             /* ensure resjunk columns are numbered correctly */
    1851           3 :             foreach(lc, junkattrs)
    1852             :             {
    1853           0 :                 TargetEntry *tle = (TargetEntry *) lfirst(lc);
    1854             : 
    1855           0 :                 tle->resno = colindex++;
    1856             :             }
    1857             :             /* replace the tlist with the modified one */
    1858           3 :             *tlist_ptr = list_concat(newtlist, junkattrs);
    1859             :         }
    1860             : 
    1861             :         /* Set up junk filter if needed */
    1862         191 :         if (junkFilter)
    1863         156 :             *junkFilter = ExecInitJunkFilterConversion(tlist,
    1864             :                                                        CreateTupleDescCopy(tupdesc),
    1865             :                                                        NULL);
    1866             : 
    1867             :         /* Report that we are returning entire tuple result */
    1868         191 :         return true;
    1869             :     }
    1870             :     else
    1871           0 :         ereport(ERROR,
    1872             :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1873             :                  errmsg("return type %s is not supported for SQL functions",
    1874             :                         format_type_be(rettype))));
    1875             : 
    1876        5291 :     return false;
    1877             : }
    1878             : 
    1879             : 
    1880             : /*
    1881             :  * CreateSQLFunctionDestReceiver -- create a suitable DestReceiver object
    1882             :  */
    1883             : DestReceiver *
    1884        5199 : CreateSQLFunctionDestReceiver(void)
    1885             : {
    1886        5199 :     DR_sqlfunction *self = (DR_sqlfunction *) palloc0(sizeof(DR_sqlfunction));
    1887             : 
    1888        5199 :     self->pub.receiveSlot = sqlfunction_receive;
    1889        5199 :     self->pub.rStartup = sqlfunction_startup;
    1890        5199 :     self->pub.rShutdown = sqlfunction_shutdown;
    1891        5199 :     self->pub.rDestroy = sqlfunction_destroy;
    1892        5199 :     self->pub.mydest = DestSQLFunction;
    1893             : 
    1894             :     /* private fields will be set by postquel_start */
    1895             : 
    1896        5199 :     return (DestReceiver *) self;
    1897             : }
    1898             : 
    1899             : /*
    1900             :  * sqlfunction_startup --- executor startup
    1901             :  */
    1902             : static void
    1903        5337 : sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
    1904             : {
    1905             :     /* no-op */
    1906        5337 : }
    1907             : 
    1908             : /*
    1909             :  * sqlfunction_receive --- receive one tuple
    1910             :  */
    1911             : static bool
    1912       22380 : sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)
    1913             : {
    1914       22380 :     DR_sqlfunction *myState = (DR_sqlfunction *) self;
    1915             : 
    1916             :     /* Filter tuple as needed */
    1917       22380 :     slot = ExecFilterJunk(myState->filter, slot);
    1918             : 
    1919             :     /* Store the filtered tuple into the tuplestore */
    1920       22380 :     tuplestore_puttupleslot(myState->tstore, slot);
    1921             : 
    1922       22380 :     return true;
    1923             : }
    1924             : 
    1925             : /*
    1926             :  * sqlfunction_shutdown --- executor end
    1927             :  */
    1928             : static void
    1929        3036 : sqlfunction_shutdown(DestReceiver *self)
    1930             : {
    1931             :     /* no-op */
    1932        3036 : }
    1933             : 
    1934             : /*
    1935             :  * sqlfunction_destroy --- release DestReceiver object
    1936             :  */
    1937             : static void
    1938        2898 : sqlfunction_destroy(DestReceiver *self)
    1939             : {
    1940        2898 :     pfree(self);
    1941        2898 : }

Generated by: LCOV version 1.11