LCOV - code coverage report
Current view: top level - src/pl/plpgsql/src - pl_comp.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 715 820 87.2 %
Date: 2019-09-19 02:07:14 Functions: 36 38 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pl_comp.c        - Compiler part of the PL/pgSQL
       4             :  *            procedural language
       5             :  *
       6             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/pl/plpgsql/src/pl_comp.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : 
      16             : #include "postgres.h"
      17             : 
      18             : #include <ctype.h>
      19             : 
      20             : #include "access/htup_details.h"
      21             : #include "catalog/namespace.h"
      22             : #include "catalog/pg_proc.h"
      23             : #include "catalog/pg_type.h"
      24             : #include "funcapi.h"
      25             : #include "nodes/makefuncs.h"
      26             : #include "parser/parse_type.h"
      27             : #include "utils/builtins.h"
      28             : #include "utils/guc.h"
      29             : #include "utils/lsyscache.h"
      30             : #include "utils/memutils.h"
      31             : #include "utils/regproc.h"
      32             : #include "utils/rel.h"
      33             : #include "utils/syscache.h"
      34             : #include "utils/typcache.h"
      35             : 
      36             : #include "plpgsql.h"
      37             : 
      38             : 
      39             : /* ----------
      40             :  * Our own local and global variables
      41             :  * ----------
      42             :  */
      43             : PLpgSQL_stmt_block *plpgsql_parse_result;
      44             : 
      45             : static int  datums_alloc;
      46             : int         plpgsql_nDatums;
      47             : PLpgSQL_datum **plpgsql_Datums;
      48             : static int  datums_last;
      49             : 
      50             : char       *plpgsql_error_funcname;
      51             : bool        plpgsql_DumpExecTree = false;
      52             : bool        plpgsql_check_syntax = false;
      53             : 
      54             : PLpgSQL_function *plpgsql_curr_compile;
      55             : 
      56             : /* A context appropriate for short-term allocs during compilation */
      57             : MemoryContext plpgsql_compile_tmp_cxt;
      58             : 
      59             : /* ----------
      60             :  * Hash table for compiled functions
      61             :  * ----------
      62             :  */
      63             : static HTAB *plpgsql_HashTable = NULL;
      64             : 
      65             : typedef struct plpgsql_hashent
      66             : {
      67             :     PLpgSQL_func_hashkey key;
      68             :     PLpgSQL_function *function;
      69             : } plpgsql_HashEnt;
      70             : 
      71             : #define FUNCS_PER_USER      128 /* initial table size */
      72             : 
      73             : /* ----------
      74             :  * Lookup table for EXCEPTION condition names
      75             :  * ----------
      76             :  */
      77             : typedef struct
      78             : {
      79             :     const char *label;
      80             :     int         sqlerrstate;
      81             : } ExceptionLabelMap;
      82             : 
      83             : static const ExceptionLabelMap exception_label_map[] = {
      84             : #include "plerrcodes.h"           /* pgrminclude ignore */
      85             :     {NULL, 0}
      86             : };
      87             : 
      88             : 
      89             : /* ----------
      90             :  * static prototypes
      91             :  * ----------
      92             :  */
      93             : static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
      94             :                                     HeapTuple procTup,
      95             :                                     PLpgSQL_function *function,
      96             :                                     PLpgSQL_func_hashkey *hashkey,
      97             :                                     bool forValidator);
      98             : static void plpgsql_compile_error_callback(void *arg);
      99             : static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name);
     100             : static void add_dummy_return(PLpgSQL_function *function);
     101             : static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
     102             : static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
     103             : static Node *plpgsql_param_ref(ParseState *pstate, ParamRef *pref);
     104             : static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
     105             :                                 ColumnRef *cref, bool error_if_no_field);
     106             : static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
     107             : static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
     108             : static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod,
     109             :                                     Oid collation, TypeName *origtypname);
     110             : static void plpgsql_start_datums(void);
     111             : static void plpgsql_finish_datums(PLpgSQL_function *function);
     112             : static void compute_function_hashkey(FunctionCallInfo fcinfo,
     113             :                                      Form_pg_proc procStruct,
     114             :                                      PLpgSQL_func_hashkey *hashkey,
     115             :                                      bool forValidator);
     116             : static void plpgsql_resolve_polymorphic_argtypes(int numargs,
     117             :                                                  Oid *argtypes, char *argmodes,
     118             :                                                  Node *call_expr, bool forValidator,
     119             :                                                  const char *proname);
     120             : static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
     121             : static void plpgsql_HashTableInsert(PLpgSQL_function *function,
     122             :                                     PLpgSQL_func_hashkey *func_key);
     123             : static void plpgsql_HashTableDelete(PLpgSQL_function *function);
     124             : static void delete_function(PLpgSQL_function *func);
     125             : 
     126             : /* ----------
     127             :  * plpgsql_compile      Make an execution tree for a PL/pgSQL function.
     128             :  *
     129             :  * If forValidator is true, we're only compiling for validation purposes,
     130             :  * and so some checks are skipped.
     131             :  *
     132             :  * Note: it's important for this to fall through quickly if the function
     133             :  * has already been compiled.
     134             :  * ----------
     135             :  */
     136             : PLpgSQL_function *
     137       66952 : plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
     138             : {
     139       66952 :     Oid         funcOid = fcinfo->flinfo->fn_oid;
     140             :     HeapTuple   procTup;
     141             :     Form_pg_proc procStruct;
     142             :     PLpgSQL_function *function;
     143             :     PLpgSQL_func_hashkey hashkey;
     144       66952 :     bool        function_valid = false;
     145       66952 :     bool        hashkey_valid = false;
     146             : 
     147             :     /*
     148             :      * Lookup the pg_proc tuple by Oid; we'll need it in any case
     149             :      */
     150       66952 :     procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
     151       66952 :     if (!HeapTupleIsValid(procTup))
     152           0 :         elog(ERROR, "cache lookup failed for function %u", funcOid);
     153       66952 :     procStruct = (Form_pg_proc) GETSTRUCT(procTup);
     154             : 
     155             :     /*
     156             :      * See if there's already a cache entry for the current FmgrInfo. If not,
     157             :      * try to find one in the hash table.
     158             :      */
     159       66952 :     function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
     160             : 
     161             : recheck:
     162       66952 :     if (!function)
     163             :     {
     164             :         /* Compute hashkey using function signature and actual arg types */
     165       15756 :         compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
     166       15756 :         hashkey_valid = true;
     167             : 
     168             :         /* And do the lookup */
     169       15756 :         function = plpgsql_HashTableLookup(&hashkey);
     170             :     }
     171             : 
     172       66952 :     if (function)
     173             :     {
     174             :         /* We have a compiled function, but is it still valid? */
     175      127486 :         if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
     176       63550 :             ItemPointerEquals(&function->fn_tid, &procTup->t_self))
     177       63550 :             function_valid = true;
     178             :         else
     179             :         {
     180             :             /*
     181             :              * Nope, so remove it from hashtable and try to drop associated
     182             :              * storage (if not done already).
     183             :              */
     184         386 :             delete_function(function);
     185             : 
     186             :             /*
     187             :              * If the function isn't in active use then we can overwrite the
     188             :              * func struct with new data, allowing any other existing fn_extra
     189             :              * pointers to make use of the new definition on their next use.
     190             :              * If it is in use then just leave it alone and make a new one.
     191             :              * (The active invocations will run to completion using the
     192             :              * previous definition, and then the cache entry will just be
     193             :              * leaked; doesn't seem worth adding code to clean it up, given
     194             :              * what a corner case this is.)
     195             :              *
     196             :              * If we found the function struct via fn_extra then it's possible
     197             :              * a replacement has already been made, so go back and recheck the
     198             :              * hashtable.
     199             :              */
     200         386 :             if (function->use_count != 0)
     201             :             {
     202           0 :                 function = NULL;
     203           0 :                 if (!hashkey_valid)
     204           0 :                     goto recheck;
     205             :             }
     206             :         }
     207             :     }
     208             : 
     209             :     /*
     210             :      * If the function wasn't found or was out-of-date, we have to compile it
     211             :      */
     212       66952 :     if (!function_valid)
     213             :     {
     214             :         /*
     215             :          * Calculate hashkey if we didn't already; we'll need it to store the
     216             :          * completed function.
     217             :          */
     218        3402 :         if (!hashkey_valid)
     219           0 :             compute_function_hashkey(fcinfo, procStruct, &hashkey,
     220             :                                      forValidator);
     221             : 
     222             :         /*
     223             :          * Do the hard part.
     224             :          */
     225        3402 :         function = do_compile(fcinfo, procTup, function,
     226             :                               &hashkey, forValidator);
     227             :     }
     228             : 
     229       66872 :     ReleaseSysCache(procTup);
     230             : 
     231             :     /*
     232             :      * Save pointer in FmgrInfo to avoid search on subsequent calls
     233             :      */
     234       66872 :     fcinfo->flinfo->fn_extra = (void *) function;
     235             : 
     236             :     /*
     237             :      * Finally return the compiled function
     238             :      */
     239       66872 :     return function;
     240             : }
     241             : 
     242             : /*
     243             :  * This is the slow part of plpgsql_compile().
     244             :  *
     245             :  * The passed-in "function" pointer is either NULL or an already-allocated
     246             :  * function struct to overwrite.
     247             :  *
     248             :  * While compiling a function, the CurrentMemoryContext is the
     249             :  * per-function memory context of the function we are compiling. That
     250             :  * means a palloc() will allocate storage with the same lifetime as
     251             :  * the function itself.
     252             :  *
     253             :  * Because palloc()'d storage will not be immediately freed, temporary
     254             :  * allocations should either be performed in a short-lived memory
     255             :  * context or explicitly pfree'd. Since not all backend functions are
     256             :  * careful about pfree'ing their allocations, it is also wise to
     257             :  * switch into a short-term context before calling into the
     258             :  * backend. An appropriate context for performing short-term
     259             :  * allocations is the plpgsql_compile_tmp_cxt.
     260             :  *
     261             :  * NB: this code is not re-entrant.  We assume that nothing we do here could
     262             :  * result in the invocation of another plpgsql function.
     263             :  */
     264             : static PLpgSQL_function *
     265        3402 : do_compile(FunctionCallInfo fcinfo,
     266             :            HeapTuple procTup,
     267             :            PLpgSQL_function *function,
     268             :            PLpgSQL_func_hashkey *hashkey,
     269             :            bool forValidator)
     270             : {
     271        3402 :     Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
     272        3402 :     bool        is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
     273        3402 :     bool        is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
     274             :     Datum       prosrcdatum;
     275             :     bool        isnull;
     276             :     char       *proc_source;
     277             :     HeapTuple   typeTup;
     278             :     Form_pg_type typeStruct;
     279             :     PLpgSQL_variable *var;
     280             :     PLpgSQL_rec *rec;
     281             :     int         i;
     282             :     ErrorContextCallback plerrcontext;
     283             :     int         parse_rc;
     284             :     Oid         rettypeid;
     285             :     int         numargs;
     286        3402 :     int         num_in_args = 0;
     287        3402 :     int         num_out_args = 0;
     288             :     Oid        *argtypes;
     289             :     char      **argnames;
     290             :     char       *argmodes;
     291        3402 :     int        *in_arg_varnos = NULL;
     292             :     PLpgSQL_variable **out_arg_variables;
     293             :     MemoryContext func_cxt;
     294             : 
     295             :     /*
     296             :      * Setup the scanner input and error info.  We assume that this function
     297             :      * cannot be invoked recursively, so there's no need to save and restore
     298             :      * the static variables used here.
     299             :      */
     300        3402 :     prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
     301             :                                   Anum_pg_proc_prosrc, &isnull);
     302        3402 :     if (isnull)
     303           0 :         elog(ERROR, "null prosrc");
     304        3402 :     proc_source = TextDatumGetCString(prosrcdatum);
     305        3402 :     plpgsql_scanner_init(proc_source);
     306             : 
     307        3402 :     plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
     308             : 
     309             :     /*
     310             :      * Setup error traceback support for ereport()
     311             :      */
     312        3402 :     plerrcontext.callback = plpgsql_compile_error_callback;
     313        3402 :     plerrcontext.arg = forValidator ? proc_source : NULL;
     314        3402 :     plerrcontext.previous = error_context_stack;
     315        3402 :     error_context_stack = &plerrcontext;
     316             : 
     317             :     /*
     318             :      * Do extra syntax checks when validating the function definition. We skip
     319             :      * this when actually compiling functions for execution, for performance
     320             :      * reasons.
     321             :      */
     322        3402 :     plpgsql_check_syntax = forValidator;
     323             : 
     324             :     /*
     325             :      * Create the new function struct, if not done already.  The function
     326             :      * structs are never thrown away, so keep them in TopMemoryContext.
     327             :      */
     328        3402 :     if (function == NULL)
     329             :     {
     330        3016 :         function = (PLpgSQL_function *)
     331        3016 :             MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function));
     332             :     }
     333             :     else
     334             :     {
     335             :         /* re-using a previously existing struct, so clear it out */
     336         386 :         memset(function, 0, sizeof(PLpgSQL_function));
     337             :     }
     338        3402 :     plpgsql_curr_compile = function;
     339             : 
     340             :     /*
     341             :      * All the permanent output of compilation (e.g. parse tree) is kept in a
     342             :      * per-function memory context, so it can be reclaimed easily.
     343             :      */
     344        3402 :     func_cxt = AllocSetContextCreate(TopMemoryContext,
     345             :                                      "PL/pgSQL function",
     346             :                                      ALLOCSET_DEFAULT_SIZES);
     347        3402 :     plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
     348             : 
     349        3402 :     function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
     350        3402 :     MemoryContextSetIdentifier(func_cxt, function->fn_signature);
     351        3402 :     function->fn_oid = fcinfo->flinfo->fn_oid;
     352        3402 :     function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
     353        3402 :     function->fn_tid = procTup->t_self;
     354        3402 :     function->fn_input_collation = fcinfo->fncollation;
     355        3402 :     function->fn_cxt = func_cxt;
     356        3402 :     function->out_param_varno = -1; /* set up for no OUT param */
     357        3402 :     function->resolve_option = plpgsql_variable_conflict;
     358        3402 :     function->print_strict_params = plpgsql_print_strict_params;
     359             :     /* only promote extra warnings and errors at CREATE FUNCTION time */
     360        3402 :     function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
     361        3402 :     function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
     362             : 
     363        3402 :     if (is_dml_trigger)
     364        1726 :         function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
     365        1676 :     else if (is_event_trigger)
     366          94 :         function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
     367             :     else
     368        1582 :         function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
     369             : 
     370        3402 :     function->fn_prokind = procStruct->prokind;
     371             : 
     372        3402 :     function->nstatements = 0;
     373             : 
     374             :     /*
     375             :      * Initialize the compiler, particularly the namespace stack.  The
     376             :      * outermost namespace contains function parameters and other special
     377             :      * variables (such as FOUND), and is named after the function itself.
     378             :      */
     379        3402 :     plpgsql_ns_init();
     380        3402 :     plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
     381        3402 :     plpgsql_DumpExecTree = false;
     382        3402 :     plpgsql_start_datums();
     383             : 
     384        3402 :     switch (function->fn_is_trigger)
     385             :     {
     386             :         case PLPGSQL_NOT_TRIGGER:
     387             : 
     388             :             /*
     389             :              * Fetch info about the procedure's parameters. Allocations aren't
     390             :              * needed permanently, so make them in tmp cxt.
     391             :              *
     392             :              * We also need to resolve any polymorphic input or output
     393             :              * argument types.  In validation mode we won't be able to, so we
     394             :              * arbitrarily assume we are dealing with integers.
     395             :              */
     396        1582 :             MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
     397             : 
     398        1582 :             numargs = get_func_arg_info(procTup,
     399             :                                         &argtypes, &argnames, &argmodes);
     400             : 
     401        3164 :             plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
     402        1582 :                                                  fcinfo->flinfo->fn_expr,
     403             :                                                  forValidator,
     404             :                                                  plpgsql_error_funcname);
     405             : 
     406        1582 :             in_arg_varnos = (int *) palloc(numargs * sizeof(int));
     407        1582 :             out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
     408             : 
     409        1582 :             MemoryContextSwitchTo(func_cxt);
     410             : 
     411             :             /*
     412             :              * Create the variables for the procedure's parameters.
     413             :              */
     414        3320 :             for (i = 0; i < numargs; i++)
     415             :             {
     416             :                 char        buf[32];
     417        1738 :                 Oid         argtypeid = argtypes[i];
     418        1738 :                 char        argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
     419             :                 PLpgSQL_type *argdtype;
     420             :                 PLpgSQL_variable *argvariable;
     421             :                 PLpgSQL_nsitem_type argitemtype;
     422             : 
     423             :                 /* Create $n name for variable */
     424        1738 :                 snprintf(buf, sizeof(buf), "$%d", i + 1);
     425             : 
     426             :                 /* Create datatype info */
     427        1738 :                 argdtype = plpgsql_build_datatype(argtypeid,
     428             :                                                   -1,
     429             :                                                   function->fn_input_collation,
     430             :                                                   NULL);
     431             : 
     432             :                 /* Disallow pseudotype argument */
     433             :                 /* (note we already replaced polymorphic types) */
     434             :                 /* (build_variable would do this, but wrong message) */
     435        1738 :                 if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
     436           0 :                     ereport(ERROR,
     437             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     438             :                              errmsg("PL/pgSQL functions cannot accept type %s",
     439             :                                     format_type_be(argtypeid))));
     440             : 
     441             :                 /*
     442             :                  * Build variable and add to datum list.  If there's a name
     443             :                  * for the argument, use that as refname, else use $n name.
     444             :                  */
     445        3930 :                 argvariable = plpgsql_build_variable((argnames &&
     446        1102 :                                                       argnames[i][0] != '\0') ?
     447        1090 :                                                      argnames[i] : buf,
     448             :                                                      0, argdtype, false);
     449             : 
     450        1738 :                 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
     451             :                 {
     452        1708 :                     argitemtype = PLPGSQL_NSTYPE_VAR;
     453             :                 }
     454             :                 else
     455             :                 {
     456             :                     Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
     457          30 :                     argitemtype = PLPGSQL_NSTYPE_REC;
     458             :                 }
     459             : 
     460             :                 /* Remember arguments in appropriate arrays */
     461        1738 :                 if (argmode == PROARGMODE_IN ||
     462         148 :                     argmode == PROARGMODE_INOUT ||
     463             :                     argmode == PROARGMODE_VARIADIC)
     464        1598 :                     in_arg_varnos[num_in_args++] = argvariable->dno;
     465        1738 :                 if (argmode == PROARGMODE_OUT ||
     466        1614 :                     argmode == PROARGMODE_INOUT ||
     467             :                     argmode == PROARGMODE_TABLE)
     468         180 :                     out_arg_variables[num_out_args++] = argvariable;
     469             : 
     470             :                 /* Add to namespace under the $n name */
     471        1738 :                 add_parameter_name(argitemtype, argvariable->dno, buf);
     472             : 
     473             :                 /* If there's a name for the argument, make an alias */
     474        1738 :                 if (argnames && argnames[i][0] != '\0')
     475        1090 :                     add_parameter_name(argitemtype, argvariable->dno,
     476        1090 :                                        argnames[i]);
     477             :             }
     478             : 
     479             :             /*
     480             :              * If there's just one OUT parameter, out_param_varno points
     481             :              * directly to it.  If there's more than one, build a row that
     482             :              * holds all of them.  Procedures return a row even for one OUT
     483             :              * parameter.
     484             :              */
     485        1582 :             if (num_out_args > 1 ||
     486          36 :                 (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
     487          78 :             {
     488          78 :                 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
     489             :                                                        num_out_args);
     490             : 
     491          78 :                 plpgsql_adddatum((PLpgSQL_datum *) row);
     492          78 :                 function->out_param_varno = row->dno;
     493             :             }
     494        1504 :             else if (num_out_args == 1)
     495          24 :                 function->out_param_varno = out_arg_variables[0]->dno;
     496             : 
     497             :             /*
     498             :              * Check for a polymorphic returntype. If found, use the actual
     499             :              * returntype type from the caller's FuncExpr node, if we have
     500             :              * one.  (In validation mode we arbitrarily assume we are dealing
     501             :              * with integers.)
     502             :              *
     503             :              * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
     504             :              * work; if it doesn't we're in some context that fails to make
     505             :              * the info available.
     506             :              */
     507        1582 :             rettypeid = procStruct->prorettype;
     508        1582 :             if (IsPolymorphicType(rettypeid))
     509             :             {
     510           8 :                 if (forValidator)
     511             :                 {
     512           4 :                     if (rettypeid == ANYARRAYOID)
     513           4 :                         rettypeid = INT4ARRAYOID;
     514           0 :                     else if (rettypeid == ANYRANGEOID)
     515           0 :                         rettypeid = INT4RANGEOID;
     516             :                     else        /* ANYELEMENT or ANYNONARRAY */
     517           0 :                         rettypeid = INT4OID;
     518             :                     /* XXX what could we use for ANYENUM? */
     519             :                 }
     520             :                 else
     521             :                 {
     522           4 :                     rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
     523           4 :                     if (!OidIsValid(rettypeid))
     524           0 :                         ereport(ERROR,
     525             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     526             :                                  errmsg("could not determine actual return type "
     527             :                                         "for polymorphic function \"%s\"",
     528             :                                         plpgsql_error_funcname)));
     529             :                 }
     530             :             }
     531             : 
     532             :             /*
     533             :              * Normal function has a defined returntype
     534             :              */
     535        1582 :             function->fn_rettype = rettypeid;
     536        1582 :             function->fn_retset = procStruct->proretset;
     537             : 
     538             :             /*
     539             :              * Lookup the function's return type
     540             :              */
     541        1582 :             typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
     542        1582 :             if (!HeapTupleIsValid(typeTup))
     543           0 :                 elog(ERROR, "cache lookup failed for type %u", rettypeid);
     544        1582 :             typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
     545             : 
     546             :             /* Disallow pseudotype result, except VOID or RECORD */
     547             :             /* (note we already replaced polymorphic types) */
     548        1582 :             if (typeStruct->typtype == TYPTYPE_PSEUDO)
     549             :             {
     550         532 :                 if (rettypeid == VOIDOID ||
     551             :                     rettypeid == RECORDOID)
     552             :                      /* okay */ ;
     553           0 :                 else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
     554           0 :                     ereport(ERROR,
     555             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     556             :                              errmsg("trigger functions can only be called as triggers")));
     557             :                 else
     558           0 :                     ereport(ERROR,
     559             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     560             :                              errmsg("PL/pgSQL functions cannot return type %s",
     561             :                                     format_type_be(rettypeid))));
     562             :             }
     563             : 
     564        1582 :             function->fn_retistuple = type_is_rowtype(rettypeid);
     565        1582 :             function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
     566        1582 :             function->fn_retbyval = typeStruct->typbyval;
     567        1582 :             function->fn_rettyplen = typeStruct->typlen;
     568             : 
     569             :             /*
     570             :              * install $0 reference, but only for polymorphic return types,
     571             :              * and not when the return is specified through an output
     572             :              * parameter.
     573             :              */
     574        1582 :             if (IsPolymorphicType(procStruct->prorettype) &&
     575             :                 num_out_args == 0)
     576             :             {
     577           8 :                 (void) plpgsql_build_variable("$0", 0,
     578             :                                               build_datatype(typeTup,
     579             :                                                              -1,
     580             :                                                              function->fn_input_collation,
     581             :                                                              NULL),
     582             :                                               true);
     583             :             }
     584             : 
     585        1582 :             ReleaseSysCache(typeTup);
     586        1582 :             break;
     587             : 
     588             :         case PLPGSQL_DML_TRIGGER:
     589             :             /* Trigger procedure's return type is unknown yet */
     590        1726 :             function->fn_rettype = InvalidOid;
     591        1726 :             function->fn_retbyval = false;
     592        1726 :             function->fn_retistuple = true;
     593        1726 :             function->fn_retisdomain = false;
     594        1726 :             function->fn_retset = false;
     595             : 
     596             :             /* shouldn't be any declared arguments */
     597        1726 :             if (procStruct->pronargs != 0)
     598           0 :                 ereport(ERROR,
     599             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
     600             :                          errmsg("trigger functions cannot have declared arguments"),
     601             :                          errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
     602             : 
     603             :             /* Add the record for referencing NEW ROW */
     604        1726 :             rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
     605        1726 :             function->new_varno = rec->dno;
     606             : 
     607             :             /* Add the record for referencing OLD ROW */
     608        1726 :             rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
     609        1726 :             function->old_varno = rec->dno;
     610             : 
     611             :             /* Add the variable tg_name */
     612        1726 :             var = plpgsql_build_variable("tg_name", 0,
     613             :                                          plpgsql_build_datatype(NAMEOID,
     614             :                                                                 -1,
     615             :                                                                 function->fn_input_collation,
     616             :                                                                 NULL),
     617             :                                          true);
     618             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     619        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     620        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
     621             : 
     622             :             /* Add the variable tg_when */
     623        1726 :             var = plpgsql_build_variable("tg_when", 0,
     624             :                                          plpgsql_build_datatype(TEXTOID,
     625             :                                                                 -1,
     626             :                                                                 function->fn_input_collation,
     627             :                                                                 NULL),
     628             :                                          true);
     629             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     630        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     631        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
     632             : 
     633             :             /* Add the variable tg_level */
     634        1726 :             var = plpgsql_build_variable("tg_level", 0,
     635             :                                          plpgsql_build_datatype(TEXTOID,
     636             :                                                                 -1,
     637             :                                                                 function->fn_input_collation,
     638             :                                                                 NULL),
     639             :                                          true);
     640             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     641        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     642        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
     643             : 
     644             :             /* Add the variable tg_op */
     645        1726 :             var = plpgsql_build_variable("tg_op", 0,
     646             :                                          plpgsql_build_datatype(TEXTOID,
     647             :                                                                 -1,
     648             :                                                                 function->fn_input_collation,
     649             :                                                                 NULL),
     650             :                                          true);
     651             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     652        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     653        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
     654             : 
     655             :             /* Add the variable tg_relid */
     656        1726 :             var = plpgsql_build_variable("tg_relid", 0,
     657             :                                          plpgsql_build_datatype(OIDOID,
     658             :                                                                 -1,
     659             :                                                                 InvalidOid,
     660             :                                                                 NULL),
     661             :                                          true);
     662             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     663        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     664        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
     665             : 
     666             :             /* Add the variable tg_relname */
     667        1726 :             var = plpgsql_build_variable("tg_relname", 0,
     668             :                                          plpgsql_build_datatype(NAMEOID,
     669             :                                                                 -1,
     670             :                                                                 function->fn_input_collation,
     671             :                                                                 NULL),
     672             :                                          true);
     673             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     674        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     675        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
     676             : 
     677             :             /* tg_table_name is now preferred to tg_relname */
     678        1726 :             var = plpgsql_build_variable("tg_table_name", 0,
     679             :                                          plpgsql_build_datatype(NAMEOID,
     680             :                                                                 -1,
     681             :                                                                 function->fn_input_collation,
     682             :                                                                 NULL),
     683             :                                          true);
     684             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     685        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     686        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
     687             : 
     688             :             /* add the variable tg_table_schema */
     689        1726 :             var = plpgsql_build_variable("tg_table_schema", 0,
     690             :                                          plpgsql_build_datatype(NAMEOID,
     691             :                                                                 -1,
     692             :                                                                 function->fn_input_collation,
     693             :                                                                 NULL),
     694             :                                          true);
     695             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     696        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     697        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
     698             : 
     699             :             /* Add the variable tg_nargs */
     700        1726 :             var = plpgsql_build_variable("tg_nargs", 0,
     701             :                                          plpgsql_build_datatype(INT4OID,
     702             :                                                                 -1,
     703             :                                                                 InvalidOid,
     704             :                                                                 NULL),
     705             :                                          true);
     706             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     707        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     708        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
     709             : 
     710             :             /* Add the variable tg_argv */
     711        1726 :             var = plpgsql_build_variable("tg_argv", 0,
     712             :                                          plpgsql_build_datatype(TEXTARRAYOID,
     713             :                                                                 -1,
     714             :                                                                 function->fn_input_collation,
     715             :                                                                 NULL),
     716             :                                          true);
     717             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     718        1726 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     719        1726 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
     720             : 
     721        1726 :             break;
     722             : 
     723             :         case PLPGSQL_EVENT_TRIGGER:
     724          94 :             function->fn_rettype = VOIDOID;
     725          94 :             function->fn_retbyval = false;
     726          94 :             function->fn_retistuple = true;
     727          94 :             function->fn_retisdomain = false;
     728          94 :             function->fn_retset = false;
     729             : 
     730             :             /* shouldn't be any declared arguments */
     731          94 :             if (procStruct->pronargs != 0)
     732           4 :                 ereport(ERROR,
     733             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
     734             :                          errmsg("event trigger functions cannot have declared arguments")));
     735             : 
     736             :             /* Add the variable tg_event */
     737          90 :             var = plpgsql_build_variable("tg_event", 0,
     738             :                                          plpgsql_build_datatype(TEXTOID,
     739             :                                                                 -1,
     740             :                                                                 function->fn_input_collation,
     741             :                                                                 NULL),
     742             :                                          true);
     743             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     744          90 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     745          90 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
     746             : 
     747             :             /* Add the variable tg_tag */
     748          90 :             var = plpgsql_build_variable("tg_tag", 0,
     749             :                                          plpgsql_build_datatype(TEXTOID,
     750             :                                                                 -1,
     751             :                                                                 function->fn_input_collation,
     752             :                                                                 NULL),
     753             :                                          true);
     754             :             Assert(var->dtype == PLPGSQL_DTYPE_VAR);
     755          90 :             var->dtype = PLPGSQL_DTYPE_PROMISE;
     756          90 :             ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
     757             : 
     758          90 :             break;
     759             : 
     760             :         default:
     761           0 :             elog(ERROR, "unrecognized function typecode: %d",
     762             :                  (int) function->fn_is_trigger);
     763             :             break;
     764             :     }
     765             : 
     766             :     /* Remember if function is STABLE/IMMUTABLE */
     767        3398 :     function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
     768             : 
     769             :     /*
     770             :      * Create the magic FOUND variable.
     771             :      */
     772        3398 :     var = plpgsql_build_variable("found", 0,
     773             :                                  plpgsql_build_datatype(BOOLOID,
     774             :                                                         -1,
     775             :                                                         InvalidOid,
     776             :                                                         NULL),
     777             :                                  true);
     778        3398 :     function->found_varno = var->dno;
     779             : 
     780             :     /*
     781             :      * Now parse the function's text
     782             :      */
     783        3398 :     parse_rc = plpgsql_yyparse();
     784        3322 :     if (parse_rc != 0)
     785           0 :         elog(ERROR, "plpgsql parser returned %d", parse_rc);
     786        3322 :     function->action = plpgsql_parse_result;
     787             : 
     788        3322 :     plpgsql_scanner_finish();
     789        3322 :     pfree(proc_source);
     790             : 
     791             :     /*
     792             :      * If it has OUT parameters or returns VOID or returns a set, we allow
     793             :      * control to fall off the end without an explicit RETURN statement. The
     794             :      * easiest way to implement this is to add a RETURN statement to the end
     795             :      * of the statement list during parsing.
     796             :      */
     797        6088 :     if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
     798        2766 :         function->fn_retset)
     799         670 :         add_dummy_return(function);
     800             : 
     801             :     /*
     802             :      * Complete the function's info
     803             :      */
     804        3322 :     function->fn_nargs = procStruct->pronargs;
     805        4898 :     for (i = 0; i < function->fn_nargs; i++)
     806        1576 :         function->fn_argvarnos[i] = in_arg_varnos[i];
     807             : 
     808        3322 :     plpgsql_finish_datums(function);
     809             : 
     810             :     /* Debug dump for completed functions */
     811        3322 :     if (plpgsql_DumpExecTree)
     812           0 :         plpgsql_dumptree(function);
     813             : 
     814             :     /*
     815             :      * add it to the hash table
     816             :      */
     817        3322 :     plpgsql_HashTableInsert(function, hashkey);
     818             : 
     819             :     /*
     820             :      * Pop the error context stack
     821             :      */
     822        3322 :     error_context_stack = plerrcontext.previous;
     823        3322 :     plpgsql_error_funcname = NULL;
     824             : 
     825        3322 :     plpgsql_check_syntax = false;
     826             : 
     827        3322 :     MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
     828        3322 :     plpgsql_compile_tmp_cxt = NULL;
     829        3322 :     return function;
     830             : }
     831             : 
     832             : /* ----------
     833             :  * plpgsql_compile_inline   Make an execution tree for an anonymous code block.
     834             :  *
     835             :  * Note: this is generally parallel to do_compile(); is it worth trying to
     836             :  * merge the two?
     837             :  *
     838             :  * Note: we assume the block will be thrown away so there is no need to build
     839             :  * persistent data structures.
     840             :  * ----------
     841             :  */
     842             : PLpgSQL_function *
     843         428 : plpgsql_compile_inline(char *proc_source)
     844             : {
     845         428 :     char       *func_name = "inline_code_block";
     846             :     PLpgSQL_function *function;
     847             :     ErrorContextCallback plerrcontext;
     848             :     PLpgSQL_variable *var;
     849             :     int         parse_rc;
     850             :     MemoryContext func_cxt;
     851             : 
     852             :     /*
     853             :      * Setup the scanner input and error info.  We assume that this function
     854             :      * cannot be invoked recursively, so there's no need to save and restore
     855             :      * the static variables used here.
     856             :      */
     857         428 :     plpgsql_scanner_init(proc_source);
     858             : 
     859         428 :     plpgsql_error_funcname = func_name;
     860             : 
     861             :     /*
     862             :      * Setup error traceback support for ereport()
     863             :      */
     864         428 :     plerrcontext.callback = plpgsql_compile_error_callback;
     865         428 :     plerrcontext.arg = proc_source;
     866         428 :     plerrcontext.previous = error_context_stack;
     867         428 :     error_context_stack = &plerrcontext;
     868             : 
     869             :     /* Do extra syntax checking if check_function_bodies is on */
     870         428 :     plpgsql_check_syntax = check_function_bodies;
     871             : 
     872             :     /* Function struct does not live past current statement */
     873         428 :     function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
     874             : 
     875         428 :     plpgsql_curr_compile = function;
     876             : 
     877             :     /*
     878             :      * All the rest of the compile-time storage (e.g. parse tree) is kept in
     879             :      * its own memory context, so it can be reclaimed easily.
     880             :      */
     881         428 :     func_cxt = AllocSetContextCreate(CurrentMemoryContext,
     882             :                                      "PL/pgSQL inline code context",
     883             :                                      ALLOCSET_DEFAULT_SIZES);
     884         428 :     plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
     885             : 
     886         428 :     function->fn_signature = pstrdup(func_name);
     887         428 :     function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
     888         428 :     function->fn_input_collation = InvalidOid;
     889         428 :     function->fn_cxt = func_cxt;
     890         428 :     function->out_param_varno = -1; /* set up for no OUT param */
     891         428 :     function->resolve_option = plpgsql_variable_conflict;
     892         428 :     function->print_strict_params = plpgsql_print_strict_params;
     893             : 
     894             :     /*
     895             :      * don't do extra validation for inline code as we don't want to add spam
     896             :      * at runtime
     897             :      */
     898         428 :     function->extra_warnings = 0;
     899         428 :     function->extra_errors = 0;
     900             : 
     901         428 :     function->nstatements = 0;
     902             : 
     903         428 :     plpgsql_ns_init();
     904         428 :     plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK);
     905         428 :     plpgsql_DumpExecTree = false;
     906         428 :     plpgsql_start_datums();
     907             : 
     908             :     /* Set up as though in a function returning VOID */
     909         428 :     function->fn_rettype = VOIDOID;
     910         428 :     function->fn_retset = false;
     911         428 :     function->fn_retistuple = false;
     912         428 :     function->fn_retisdomain = false;
     913         428 :     function->fn_prokind = PROKIND_FUNCTION;
     914             :     /* a bit of hardwired knowledge about type VOID here */
     915         428 :     function->fn_retbyval = true;
     916         428 :     function->fn_rettyplen = sizeof(int32);
     917             : 
     918             :     /*
     919             :      * Remember if function is STABLE/IMMUTABLE.  XXX would it be better to
     920             :      * set this true inside a read-only transaction?  Not clear.
     921             :      */
     922         428 :     function->fn_readonly = false;
     923             : 
     924             :     /*
     925             :      * Create the magic FOUND variable.
     926             :      */
     927         428 :     var = plpgsql_build_variable("found", 0,
     928             :                                  plpgsql_build_datatype(BOOLOID,
     929             :                                                         -1,
     930             :                                                         InvalidOid,
     931             :                                                         NULL),
     932             :                                  true);
     933         428 :     function->found_varno = var->dno;
     934             : 
     935             :     /*
     936             :      * Now parse the function's text
     937             :      */
     938         428 :     parse_rc = plpgsql_yyparse();
     939         406 :     if (parse_rc != 0)
     940           0 :         elog(ERROR, "plpgsql parser returned %d", parse_rc);
     941         406 :     function->action = plpgsql_parse_result;
     942             : 
     943         406 :     plpgsql_scanner_finish();
     944             : 
     945             :     /*
     946             :      * If it returns VOID (always true at the moment), we allow control to
     947             :      * fall off the end without an explicit RETURN statement.
     948             :      */
     949         406 :     if (function->fn_rettype == VOIDOID)
     950         406 :         add_dummy_return(function);
     951             : 
     952             :     /*
     953             :      * Complete the function's info
     954             :      */
     955         406 :     function->fn_nargs = 0;
     956             : 
     957         406 :     plpgsql_finish_datums(function);
     958             : 
     959             :     /*
     960             :      * Pop the error context stack
     961             :      */
     962         406 :     error_context_stack = plerrcontext.previous;
     963         406 :     plpgsql_error_funcname = NULL;
     964             : 
     965         406 :     plpgsql_check_syntax = false;
     966             : 
     967         406 :     MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
     968         406 :     plpgsql_compile_tmp_cxt = NULL;
     969         406 :     return function;
     970             : }
     971             : 
     972             : 
     973             : /*
     974             :  * error context callback to let us supply a call-stack traceback.
     975             :  * If we are validating or executing an anonymous code block, the function
     976             :  * source text is passed as an argument.
     977             :  */
     978             : static void
     979         146 : plpgsql_compile_error_callback(void *arg)
     980             : {
     981         146 :     if (arg)
     982             :     {
     983             :         /*
     984             :          * Try to convert syntax error position to reference text of original
     985             :          * CREATE FUNCTION or DO command.
     986             :          */
     987         144 :         if (function_parse_error_transpose((const char *) arg))
     988         132 :             return;
     989             : 
     990             :         /*
     991             :          * Done if a syntax error position was reported; otherwise we have to
     992             :          * fall back to a "near line N" report.
     993             :          */
     994             :     }
     995             : 
     996          14 :     if (plpgsql_error_funcname)
     997          14 :         errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
     998             :                    plpgsql_error_funcname, plpgsql_latest_lineno());
     999             : }
    1000             : 
    1001             : 
    1002             : /*
    1003             :  * Add a name for a function parameter to the function's namespace
    1004             :  */
    1005             : static void
    1006        2828 : add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
    1007             : {
    1008             :     /*
    1009             :      * Before adding the name, check for duplicates.  We need this even though
    1010             :      * functioncmds.c has a similar check, because that code explicitly
    1011             :      * doesn't complain about conflicting IN and OUT parameter names.  In
    1012             :      * plpgsql, such names are in the same namespace, so there is no way to
    1013             :      * disambiguate.
    1014             :      */
    1015        2828 :     if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
    1016             :                           name, NULL, NULL,
    1017             :                           NULL) != NULL)
    1018           0 :         ereport(ERROR,
    1019             :                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    1020             :                  errmsg("parameter name \"%s\" used more than once",
    1021             :                         name)));
    1022             : 
    1023             :     /* OK, add the name */
    1024        2828 :     plpgsql_ns_additem(itemtype, itemno, name);
    1025        2828 : }
    1026             : 
    1027             : /*
    1028             :  * Add a dummy RETURN statement to the given function's body
    1029             :  */
    1030             : static void
    1031        1076 : add_dummy_return(PLpgSQL_function *function)
    1032             : {
    1033             :     /*
    1034             :      * If the outer block has an EXCEPTION clause, we need to make a new outer
    1035             :      * block, since the added RETURN shouldn't act like it is inside the
    1036             :      * EXCEPTION clause.
    1037             :      */
    1038        1076 :     if (function->action->exceptions != NULL)
    1039             :     {
    1040             :         PLpgSQL_stmt_block *new;
    1041             : 
    1042          78 :         new = palloc0(sizeof(PLpgSQL_stmt_block));
    1043          78 :         new->cmd_type = PLPGSQL_STMT_BLOCK;
    1044          78 :         new->stmtid = ++function->nstatements;
    1045          78 :         new->body = list_make1(function->action);
    1046             : 
    1047          78 :         function->action = new;
    1048             :     }
    1049        2126 :     if (function->action->body == NIL ||
    1050        1050 :         ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
    1051             :     {
    1052             :         PLpgSQL_stmt_return *new;
    1053             : 
    1054        1022 :         new = palloc0(sizeof(PLpgSQL_stmt_return));
    1055        1022 :         new->cmd_type = PLPGSQL_STMT_RETURN;
    1056        1022 :         new->stmtid = ++function->nstatements;
    1057        1022 :         new->expr = NULL;
    1058        1022 :         new->retvarno = function->out_param_varno;
    1059             : 
    1060        1022 :         function->action->body = lappend(function->action->body, new);
    1061             :     }
    1062        1076 : }
    1063             : 
    1064             : 
    1065             : /*
    1066             :  * plpgsql_parser_setup     set up parser hooks for dynamic parameters
    1067             :  *
    1068             :  * Note: this routine, and the hook functions it prepares for, are logically
    1069             :  * part of plpgsql parsing.  But they actually run during function execution,
    1070             :  * when we are ready to evaluate a SQL query or expression that has not
    1071             :  * previously been parsed and planned.
    1072             :  */
    1073             : void
    1074       12546 : plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
    1075             : {
    1076       12546 :     pstate->p_pre_columnref_hook = plpgsql_pre_column_ref;
    1077       12546 :     pstate->p_post_columnref_hook = plpgsql_post_column_ref;
    1078       12546 :     pstate->p_paramref_hook = plpgsql_param_ref;
    1079             :     /* no need to use p_coerce_param_hook */
    1080       12546 :     pstate->p_ref_hook_state = (void *) expr;
    1081       12546 : }
    1082             : 
    1083             : /*
    1084             :  * plpgsql_pre_column_ref       parser callback before parsing a ColumnRef
    1085             :  */
    1086             : static Node *
    1087       11708 : plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
    1088             : {
    1089       11708 :     PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
    1090             : 
    1091       11708 :     if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
    1092           8 :         return resolve_column_ref(pstate, expr, cref, false);
    1093             :     else
    1094       11700 :         return NULL;
    1095             : }
    1096             : 
    1097             : /*
    1098             :  * plpgsql_post_column_ref      parser callback after parsing a ColumnRef
    1099             :  */
    1100             : static Node *
    1101       11704 : plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
    1102             : {
    1103       11704 :     PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
    1104             :     Node       *myvar;
    1105             : 
    1106       11704 :     if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
    1107           4 :         return NULL;            /* we already found there's no match */
    1108             : 
    1109       11700 :     if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
    1110           8 :         return NULL;            /* there's a table column, prefer that */
    1111             : 
    1112             :     /*
    1113             :      * If we find a record/row variable but can't match a field name, throw
    1114             :      * error if there was no core resolution for the ColumnRef either.  In
    1115             :      * that situation, the reference is inevitably going to fail, and
    1116             :      * complaining about the record/row variable is likely to be more on-point
    1117             :      * than the core parser's error message.  (It's too bad we don't have
    1118             :      * access to transformColumnRef's internal crerr state here, as in case of
    1119             :      * a conflict with a table name this could still be less than the most
    1120             :      * helpful error message possible.)
    1121             :      */
    1122       11692 :     myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
    1123             : 
    1124       11684 :     if (myvar != NULL && var != NULL)
    1125             :     {
    1126             :         /*
    1127             :          * We could leave it to the core parser to throw this error, but we
    1128             :          * can add a more useful detail message than the core could.
    1129             :          */
    1130           4 :         ereport(ERROR,
    1131             :                 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
    1132             :                  errmsg("column reference \"%s\" is ambiguous",
    1133             :                         NameListToString(cref->fields)),
    1134             :                  errdetail("It could refer to either a PL/pgSQL variable or a table column."),
    1135             :                  parser_errposition(pstate, cref->location)));
    1136             :     }
    1137             : 
    1138       11680 :     return myvar;
    1139             : }
    1140             : 
    1141             : /*
    1142             :  * plpgsql_param_ref        parser callback for ParamRefs ($n symbols)
    1143             :  */
    1144             : static Node *
    1145         604 : plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
    1146             : {
    1147         604 :     PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
    1148             :     char        pname[32];
    1149             :     PLpgSQL_nsitem *nse;
    1150             : 
    1151         604 :     snprintf(pname, sizeof(pname), "$%d", pref->number);
    1152             : 
    1153         604 :     nse = plpgsql_ns_lookup(expr->ns, false,
    1154             :                             pname, NULL, NULL,
    1155             :                             NULL);
    1156             : 
    1157         604 :     if (nse == NULL)
    1158           0 :         return NULL;            /* name not known to plpgsql */
    1159             : 
    1160         604 :     return make_datum_param(expr, nse->itemno, pref->location);
    1161             : }
    1162             : 
    1163             : /*
    1164             :  * resolve_column_ref       attempt to resolve a ColumnRef as a plpgsql var
    1165             :  *
    1166             :  * Returns the translated node structure, or NULL if name not found
    1167             :  *
    1168             :  * error_if_no_field tells whether to throw error or quietly return NULL if
    1169             :  * we are able to match a record/row name but don't find a field name match.
    1170             :  */
    1171             : static Node *
    1172       11700 : resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
    1173             :                    ColumnRef *cref, bool error_if_no_field)
    1174             : {
    1175             :     PLpgSQL_execstate *estate;
    1176             :     PLpgSQL_nsitem *nse;
    1177             :     const char *name1;
    1178       11700 :     const char *name2 = NULL;
    1179       11700 :     const char *name3 = NULL;
    1180       11700 :     const char *colname = NULL;
    1181             :     int         nnames;
    1182       11700 :     int         nnames_scalar = 0;
    1183       11700 :     int         nnames_wholerow = 0;
    1184       11700 :     int         nnames_field = 0;
    1185             : 
    1186             :     /*
    1187             :      * We use the function's current estate to resolve parameter data types.
    1188             :      * This is really pretty bogus because there is no provision for updating
    1189             :      * plans when those types change ...
    1190             :      */
    1191       11700 :     estate = expr->func->cur_estate;
    1192             : 
    1193             :     /*----------
    1194             :      * The allowed syntaxes are:
    1195             :      *
    1196             :      * A        Scalar variable reference, or whole-row record reference.
    1197             :      * A.B      Qualified scalar or whole-row reference, or field reference.
    1198             :      * A.B.C    Qualified record field reference.
    1199             :      * A.*      Whole-row record reference.
    1200             :      * A.B.*    Qualified whole-row record reference.
    1201             :      *----------
    1202             :      */
    1203       11700 :     switch (list_length(cref->fields))
    1204             :     {
    1205             :         case 1:
    1206             :             {
    1207        9018 :                 Node       *field1 = (Node *) linitial(cref->fields);
    1208             : 
    1209             :                 Assert(IsA(field1, String));
    1210        9018 :                 name1 = strVal(field1);
    1211        9018 :                 nnames_scalar = 1;
    1212        9018 :                 nnames_wholerow = 1;
    1213        9018 :                 break;
    1214             :             }
    1215             :         case 2:
    1216             :             {
    1217        2678 :                 Node       *field1 = (Node *) linitial(cref->fields);
    1218        2678 :                 Node       *field2 = (Node *) lsecond(cref->fields);
    1219             : 
    1220             :                 Assert(IsA(field1, String));
    1221        2678 :                 name1 = strVal(field1);
    1222             : 
    1223             :                 /* Whole-row reference? */
    1224        2678 :                 if (IsA(field2, A_Star))
    1225             :                 {
    1226             :                     /* Set name2 to prevent matches to scalar variables */
    1227          54 :                     name2 = "*";
    1228          54 :                     nnames_wholerow = 1;
    1229          54 :                     break;
    1230             :                 }
    1231             : 
    1232             :                 Assert(IsA(field2, String));
    1233        2624 :                 name2 = strVal(field2);
    1234        2624 :                 colname = name2;
    1235        2624 :                 nnames_scalar = 2;
    1236        2624 :                 nnames_wholerow = 2;
    1237        2624 :                 nnames_field = 1;
    1238        2624 :                 break;
    1239             :             }
    1240             :         case 3:
    1241             :             {
    1242           4 :                 Node       *field1 = (Node *) linitial(cref->fields);
    1243           4 :                 Node       *field2 = (Node *) lsecond(cref->fields);
    1244           4 :                 Node       *field3 = (Node *) lthird(cref->fields);
    1245             : 
    1246             :                 Assert(IsA(field1, String));
    1247           4 :                 name1 = strVal(field1);
    1248             :                 Assert(IsA(field2, String));
    1249           4 :                 name2 = strVal(field2);
    1250             : 
    1251             :                 /* Whole-row reference? */
    1252           4 :                 if (IsA(field3, A_Star))
    1253             :                 {
    1254             :                     /* Set name3 to prevent matches to scalar variables */
    1255           0 :                     name3 = "*";
    1256           0 :                     nnames_wholerow = 2;
    1257           0 :                     break;
    1258             :                 }
    1259             : 
    1260             :                 Assert(IsA(field3, String));
    1261           4 :                 name3 = strVal(field3);
    1262           4 :                 colname = name3;
    1263           4 :                 nnames_field = 2;
    1264           4 :                 break;
    1265             :             }
    1266             :         default:
    1267             :             /* too many names, ignore */
    1268           0 :             return NULL;
    1269             :     }
    1270             : 
    1271       11700 :     nse = plpgsql_ns_lookup(expr->ns, false,
    1272             :                             name1, name2, name3,
    1273             :                             &nnames);
    1274             : 
    1275       11700 :     if (nse == NULL)
    1276        1504 :         return NULL;            /* name not known to plpgsql */
    1277             : 
    1278       10196 :     switch (nse->itemtype)
    1279             :     {
    1280             :         case PLPGSQL_NSTYPE_VAR:
    1281        7444 :             if (nnames == nnames_scalar)
    1282        7444 :                 return make_datum_param(expr, nse->itemno, cref->location);
    1283           0 :             break;
    1284             :         case PLPGSQL_NSTYPE_REC:
    1285        2752 :             if (nnames == nnames_wholerow)
    1286         360 :                 return make_datum_param(expr, nse->itemno, cref->location);
    1287        2392 :             if (nnames == nnames_field)
    1288             :             {
    1289             :                 /* colname could be a field in this record */
    1290        2392 :                 PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
    1291             :                 int         i;
    1292             : 
    1293             :                 /* search for a datum referencing this field */
    1294        2392 :                 i = rec->firstfield;
    1295        7388 :                 while (i >= 0)
    1296             :                 {
    1297        4996 :                     PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
    1298             : 
    1299             :                     Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
    1300             :                            fld->recparentno == nse->itemno);
    1301        4996 :                     if (strcmp(fld->fieldname, colname) == 0)
    1302             :                     {
    1303        2392 :                         return make_datum_param(expr, i, cref->location);
    1304             :                     }
    1305        2604 :                     i = fld->nextfield;
    1306             :                 }
    1307             : 
    1308             :                 /*
    1309             :                  * We should not get here, because a RECFIELD datum should
    1310             :                  * have been built at parse time for every possible qualified
    1311             :                  * reference to fields of this record.  But if we do, handle
    1312             :                  * it like field-not-found: throw error or return NULL.
    1313             :                  */
    1314           0 :                 if (error_if_no_field)
    1315           0 :                     ereport(ERROR,
    1316             :                             (errcode(ERRCODE_UNDEFINED_COLUMN),
    1317             :                              errmsg("record \"%s\" has no field \"%s\"",
    1318             :                                     (nnames_field == 1) ? name1 : name2,
    1319             :                                     colname),
    1320             :                              parser_errposition(pstate, cref->location)));
    1321             :             }
    1322           0 :             break;
    1323             :         default:
    1324           0 :             elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
    1325             :     }
    1326             : 
    1327             :     /* Name format doesn't match the plpgsql variable type */
    1328           0 :     return NULL;
    1329             : }
    1330             : 
    1331             : /*
    1332             :  * Helper for columnref parsing: build a Param referencing a plpgsql datum,
    1333             :  * and make sure that that datum is listed in the expression's paramnos.
    1334             :  */
    1335             : static Node *
    1336       10800 : make_datum_param(PLpgSQL_expr *expr, int dno, int location)
    1337             : {
    1338             :     PLpgSQL_execstate *estate;
    1339             :     PLpgSQL_datum *datum;
    1340             :     Param      *param;
    1341             :     MemoryContext oldcontext;
    1342             : 
    1343             :     /* see comment in resolve_column_ref */
    1344       10800 :     estate = expr->func->cur_estate;
    1345             :     Assert(dno >= 0 && dno < estate->ndatums);
    1346       10800 :     datum = estate->datums[dno];
    1347             : 
    1348             :     /*
    1349             :      * Bitmapset must be allocated in function's permanent memory context
    1350             :      */
    1351       10800 :     oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
    1352       10800 :     expr->paramnos = bms_add_member(expr->paramnos, dno);
    1353       10800 :     MemoryContextSwitchTo(oldcontext);
    1354             : 
    1355       10800 :     param = makeNode(Param);
    1356       10800 :     param->paramkind = PARAM_EXTERN;
    1357       10800 :     param->paramid = dno + 1;
    1358       10800 :     plpgsql_exec_get_datum_type_info(estate,
    1359             :                                      datum,
    1360             :                                      &param->paramtype,
    1361             :                                      &param->paramtypmod,
    1362             :                                      &param->paramcollid);
    1363       10792 :     param->location = location;
    1364             : 
    1365       10792 :     return (Node *) param;
    1366             : }
    1367             : 
    1368             : 
    1369             : /* ----------
    1370             :  * plpgsql_parse_word       The scanner calls this to postparse
    1371             :  *              any single word that is not a reserved keyword.
    1372             :  *
    1373             :  * word1 is the downcased/dequoted identifier; it must be palloc'd in the
    1374             :  * function's long-term memory context.
    1375             :  *
    1376             :  * yytxt is the original token text; we need this to check for quoting,
    1377             :  * so that later checks for unreserved keywords work properly.
    1378             :  *
    1379             :  * We attempt to recognize the token as a variable only if lookup is true
    1380             :  * and the plpgsql_IdentifierLookup context permits it.
    1381             :  *
    1382             :  * If recognized as a variable, fill in *wdatum and return true;
    1383             :  * if not recognized, fill in *word and return false.
    1384             :  * (Note: those two pointers actually point to members of the same union,
    1385             :  * but for notational reasons we pass them separately.)
    1386             :  * ----------
    1387             :  */
    1388             : bool
    1389       47214 : plpgsql_parse_word(char *word1, const char *yytxt, bool lookup,
    1390             :                    PLwdatum *wdatum, PLword *word)
    1391             : {
    1392             :     PLpgSQL_nsitem *ns;
    1393             : 
    1394             :     /*
    1395             :      * We should not lookup variables in DECLARE sections.  In SQL
    1396             :      * expressions, there's no need to do so either --- lookup will happen
    1397             :      * when the expression is compiled.
    1398             :      */
    1399       47214 :     if (lookup && plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
    1400             :     {
    1401             :         /*
    1402             :          * Do a lookup in the current namespace stack
    1403             :          */
    1404       10676 :         ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
    1405             :                                word1, NULL, NULL,
    1406             :                                NULL);
    1407             : 
    1408       10676 :         if (ns != NULL)
    1409             :         {
    1410        5494 :             switch (ns->itemtype)
    1411             :             {
    1412             :                 case PLPGSQL_NSTYPE_VAR:
    1413             :                 case PLPGSQL_NSTYPE_REC:
    1414        5494 :                     wdatum->datum = plpgsql_Datums[ns->itemno];
    1415        5494 :                     wdatum->ident = word1;
    1416        5494 :                     wdatum->quoted = (yytxt[0] == '"');
    1417        5494 :                     wdatum->idents = NIL;
    1418        5494 :                     return true;
    1419             : 
    1420             :                 default:
    1421             :                     /* plpgsql_ns_lookup should never return anything else */
    1422           0 :                     elog(ERROR, "unrecognized plpgsql itemtype: %d",
    1423             :                          ns->itemtype);
    1424             :             }
    1425             :         }
    1426             :     }
    1427             : 
    1428             :     /*
    1429             :      * Nothing found - up to now it's a word without any special meaning for
    1430             :      * us.
    1431             :      */
    1432       41720 :     word->ident = word1;
    1433       41720 :     word->quoted = (yytxt[0] == '"');
    1434       41720 :     return false;
    1435             : }
    1436             : 
    1437             : 
    1438             : /* ----------
    1439             :  * plpgsql_parse_dblword        Same lookup for two words
    1440             :  *                  separated by a dot.
    1441             :  * ----------
    1442             :  */
    1443             : bool
    1444        4724 : plpgsql_parse_dblword(char *word1, char *word2,
    1445             :                       PLwdatum *wdatum, PLcword *cword)
    1446             : {
    1447             :     PLpgSQL_nsitem *ns;
    1448             :     List       *idents;
    1449             :     int         nnames;
    1450             : 
    1451        4724 :     idents = list_make2(makeString(word1),
    1452             :                         makeString(word2));
    1453             : 
    1454             :     /*
    1455             :      * We should do nothing in DECLARE sections.  In SQL expressions, we
    1456             :      * really only need to make sure that RECFIELD datums are created when
    1457             :      * needed.
    1458             :      */
    1459        4724 :     if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
    1460             :     {
    1461             :         /*
    1462             :          * Do a lookup in the current namespace stack
    1463             :          */
    1464        4708 :         ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
    1465             :                                word1, word2, NULL,
    1466             :                                &nnames);
    1467        4708 :         if (ns != NULL)
    1468             :         {
    1469        4230 :             switch (ns->itemtype)
    1470             :             {
    1471             :                 case PLPGSQL_NSTYPE_VAR:
    1472             :                     /* Block-qualified reference to scalar variable. */
    1473          18 :                     wdatum->datum = plpgsql_Datums[ns->itemno];
    1474          18 :                     wdatum->ident = NULL;
    1475          18 :                     wdatum->quoted = false; /* not used */
    1476          18 :                     wdatum->idents = idents;
    1477          18 :                     return true;
    1478             : 
    1479             :                 case PLPGSQL_NSTYPE_REC:
    1480        4212 :                     if (nnames == 1)
    1481             :                     {
    1482             :                         /*
    1483             :                          * First word is a record name, so second word could
    1484             :                          * be a field in this record.  We build a RECFIELD
    1485             :                          * datum whether it is or not --- any error will be
    1486             :                          * detected later.
    1487             :                          */
    1488             :                         PLpgSQL_rec *rec;
    1489             :                         PLpgSQL_recfield *new;
    1490             : 
    1491        4212 :                         rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
    1492        4212 :                         new = plpgsql_build_recfield(rec, word2);
    1493             : 
    1494        4212 :                         wdatum->datum = (PLpgSQL_datum *) new;
    1495             :                     }
    1496             :                     else
    1497             :                     {
    1498             :                         /* Block-qualified reference to record variable. */
    1499           0 :                         wdatum->datum = plpgsql_Datums[ns->itemno];
    1500             :                     }
    1501        4212 :                     wdatum->ident = NULL;
    1502        4212 :                     wdatum->quoted = false; /* not used */
    1503        4212 :                     wdatum->idents = idents;
    1504        4212 :                     return true;
    1505             : 
    1506             :                 default:
    1507           0 :                     break;
    1508             :             }
    1509             :         }
    1510             :     }
    1511             : 
    1512             :     /* Nothing found */
    1513         494 :     cword->idents = idents;
    1514         494 :     return false;
    1515             : }
    1516             : 
    1517             : 
    1518             : /* ----------
    1519             :  * plpgsql_parse_tripword       Same lookup for three words
    1520             :  *                  separated by dots.
    1521             :  * ----------
    1522             :  */
    1523             : bool
    1524           8 : plpgsql_parse_tripword(char *word1, char *word2, char *word3,
    1525             :                        PLwdatum *wdatum, PLcword *cword)
    1526             : {
    1527             :     PLpgSQL_nsitem *ns;
    1528             :     List       *idents;
    1529             :     int         nnames;
    1530             : 
    1531           8 :     idents = list_make3(makeString(word1),
    1532             :                         makeString(word2),
    1533             :                         makeString(word3));
    1534             : 
    1535             :     /*
    1536             :      * We should do nothing in DECLARE sections.  In SQL expressions, we
    1537             :      * really only need to make sure that RECFIELD datums are created when
    1538             :      * needed.
    1539             :      */
    1540           8 :     if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
    1541             :     {
    1542             :         /*
    1543             :          * Do a lookup in the current namespace stack. Must find a qualified
    1544             :          * reference, else ignore.
    1545             :          */
    1546           8 :         ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
    1547             :                                word1, word2, word3,
    1548             :                                &nnames);
    1549           8 :         if (ns != NULL && nnames == 2)
    1550             :         {
    1551           8 :             switch (ns->itemtype)
    1552             :             {
    1553             :                 case PLPGSQL_NSTYPE_REC:
    1554             :                     {
    1555             :                         /*
    1556             :                          * words 1/2 are a record name, so third word could be
    1557             :                          * a field in this record.
    1558             :                          */
    1559             :                         PLpgSQL_rec *rec;
    1560             :                         PLpgSQL_recfield *new;
    1561             : 
    1562           8 :                         rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
    1563           8 :                         new = plpgsql_build_recfield(rec, word3);
    1564             : 
    1565           8 :                         wdatum->datum = (PLpgSQL_datum *) new;
    1566           8 :                         wdatum->ident = NULL;
    1567           8 :                         wdatum->quoted = false; /* not used */
    1568           8 :                         wdatum->idents = idents;
    1569           8 :                         return true;
    1570             :                     }
    1571             : 
    1572             :                 default:
    1573           0 :                     break;
    1574             :             }
    1575             :         }
    1576             :     }
    1577             : 
    1578             :     /* Nothing found */
    1579           0 :     cword->idents = idents;
    1580           0 :     return false;
    1581             : }
    1582             : 
    1583             : 
    1584             : /* ----------
    1585             :  * plpgsql_parse_wordtype   The scanner found word%TYPE. word can be
    1586             :  *              a variable name or a basetype.
    1587             :  *
    1588             :  * Returns datatype struct, or NULL if no match found for word.
    1589             :  * ----------
    1590             :  */
    1591             : PLpgSQL_type *
    1592           0 : plpgsql_parse_wordtype(char *ident)
    1593             : {
    1594             :     PLpgSQL_type *dtype;
    1595             :     PLpgSQL_nsitem *nse;
    1596             :     TypeName   *typeName;
    1597             :     HeapTuple   typeTup;
    1598             : 
    1599             :     /*
    1600             :      * Do a lookup in the current namespace stack
    1601             :      */
    1602           0 :     nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
    1603             :                             ident, NULL, NULL,
    1604             :                             NULL);
    1605             : 
    1606           0 :     if (nse != NULL)
    1607             :     {
    1608           0 :         switch (nse->itemtype)
    1609             :         {
    1610             :             case PLPGSQL_NSTYPE_VAR:
    1611           0 :                 return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
    1612             : 
    1613             :                 /* XXX perhaps allow REC/ROW here? */
    1614             : 
    1615             :             default:
    1616           0 :                 return NULL;
    1617             :         }
    1618             :     }
    1619             : 
    1620             :     /*
    1621             :      * Word wasn't found in the namespace stack. Try to find a data type with
    1622             :      * that name, but ignore shell types and complex types.
    1623             :      */
    1624           0 :     typeName = makeTypeName(ident);
    1625           0 :     typeTup = LookupTypeName(NULL, typeName, NULL, false);
    1626           0 :     if (typeTup)
    1627             :     {
    1628           0 :         Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
    1629             : 
    1630           0 :         if (!typeStruct->typisdefined ||
    1631           0 :             typeStruct->typrelid != InvalidOid)
    1632             :         {
    1633           0 :             ReleaseSysCache(typeTup);
    1634           0 :             return NULL;
    1635             :         }
    1636             : 
    1637           0 :         dtype = build_datatype(typeTup, -1,
    1638           0 :                                plpgsql_curr_compile->fn_input_collation,
    1639             :                                typeName);
    1640             : 
    1641           0 :         ReleaseSysCache(typeTup);
    1642           0 :         return dtype;
    1643             :     }
    1644             : 
    1645             :     /*
    1646             :      * Nothing found - up to now it's a word without any special meaning for
    1647             :      * us.
    1648             :      */
    1649           0 :     return NULL;
    1650             : }
    1651             : 
    1652             : 
    1653             : /* ----------
    1654             :  * plpgsql_parse_cwordtype      Same lookup for compositeword%TYPE
    1655             :  * ----------
    1656             :  */
    1657             : PLpgSQL_type *
    1658          16 : plpgsql_parse_cwordtype(List *idents)
    1659             : {
    1660          16 :     PLpgSQL_type *dtype = NULL;
    1661             :     PLpgSQL_nsitem *nse;
    1662             :     const char *fldname;
    1663             :     Oid         classOid;
    1664          16 :     HeapTuple   classtup = NULL;
    1665          16 :     HeapTuple   attrtup = NULL;
    1666          16 :     HeapTuple   typetup = NULL;
    1667             :     Form_pg_class classStruct;
    1668             :     Form_pg_attribute attrStruct;
    1669             :     MemoryContext oldCxt;
    1670             : 
    1671             :     /* Avoid memory leaks in the long-term function context */
    1672          16 :     oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
    1673             : 
    1674          16 :     if (list_length(idents) == 2)
    1675             :     {
    1676             :         /*
    1677             :          * Do a lookup in the current namespace stack. We don't need to check
    1678             :          * number of names matched, because we will only consider scalar
    1679             :          * variables.
    1680             :          */
    1681          16 :         nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
    1682          16 :                                 strVal(linitial(idents)),
    1683          16 :                                 strVal(lsecond(idents)),
    1684             :                                 NULL,
    1685             :                                 NULL);
    1686             : 
    1687          16 :         if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
    1688             :         {
    1689           0 :             dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
    1690           0 :             goto done;
    1691             :         }
    1692             : 
    1693             :         /*
    1694             :          * First word could also be a table name
    1695             :          */
    1696          16 :         classOid = RelnameGetRelid(strVal(linitial(idents)));
    1697          16 :         if (!OidIsValid(classOid))
    1698           0 :             goto done;
    1699          16 :         fldname = strVal(lsecond(idents));
    1700             :     }
    1701           0 :     else if (list_length(idents) == 3)
    1702             :     {
    1703             :         RangeVar   *relvar;
    1704             : 
    1705           0 :         relvar = makeRangeVar(strVal(linitial(idents)),
    1706           0 :                               strVal(lsecond(idents)),
    1707             :                               -1);
    1708             :         /* Can't lock relation - we might not have privileges. */
    1709           0 :         classOid = RangeVarGetRelid(relvar, NoLock, true);
    1710           0 :         if (!OidIsValid(classOid))
    1711           0 :             goto done;
    1712           0 :         fldname = strVal(lthird(idents));
    1713             :     }
    1714             :     else
    1715           0 :         goto done;
    1716             : 
    1717          16 :     classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
    1718          16 :     if (!HeapTupleIsValid(classtup))
    1719           0 :         goto done;
    1720          16 :     classStruct = (Form_pg_class) GETSTRUCT(classtup);
    1721             : 
    1722             :     /*
    1723             :      * It must be a relation, sequence, view, materialized view, composite
    1724             :      * type, or foreign table
    1725             :      */
    1726          24 :     if (classStruct->relkind != RELKIND_RELATION &&
    1727          16 :         classStruct->relkind != RELKIND_SEQUENCE &&
    1728          16 :         classStruct->relkind != RELKIND_VIEW &&
    1729          16 :         classStruct->relkind != RELKIND_MATVIEW &&
    1730          16 :         classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
    1731          16 :         classStruct->relkind != RELKIND_FOREIGN_TABLE &&
    1732           8 :         classStruct->relkind != RELKIND_PARTITIONED_TABLE)
    1733           0 :         goto done;
    1734             : 
    1735             :     /*
    1736             :      * Fetch the named table field and its type
    1737             :      */
    1738          16 :     attrtup = SearchSysCacheAttName(classOid, fldname);
    1739          16 :     if (!HeapTupleIsValid(attrtup))
    1740           0 :         goto done;
    1741          16 :     attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
    1742             : 
    1743          16 :     typetup = SearchSysCache1(TYPEOID,
    1744          16 :                               ObjectIdGetDatum(attrStruct->atttypid));
    1745          16 :     if (!HeapTupleIsValid(typetup))
    1746           0 :         elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
    1747             : 
    1748             :     /*
    1749             :      * Found that - build a compiler type struct in the caller's cxt and
    1750             :      * return it.  Note that we treat the type as being found-by-OID; no
    1751             :      * attempt to re-look-up the type name will happen during invalidations.
    1752             :      */
    1753          16 :     MemoryContextSwitchTo(oldCxt);
    1754          16 :     dtype = build_datatype(typetup,
    1755             :                            attrStruct->atttypmod,
    1756             :                            attrStruct->attcollation,
    1757             :                            NULL);
    1758          16 :     MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
    1759             : 
    1760             : done:
    1761          16 :     if (HeapTupleIsValid(classtup))
    1762          16 :         ReleaseSysCache(classtup);
    1763          16 :     if (HeapTupleIsValid(attrtup))
    1764          16 :         ReleaseSysCache(attrtup);
    1765          16 :     if (HeapTupleIsValid(typetup))
    1766          16 :         ReleaseSysCache(typetup);
    1767             : 
    1768          16 :     MemoryContextSwitchTo(oldCxt);
    1769          16 :     return dtype;
    1770             : }
    1771             : 
    1772             : /* ----------
    1773             :  * plpgsql_parse_wordrowtype        Scanner found word%ROWTYPE.
    1774             :  *                  So word must be a table name.
    1775             :  * ----------
    1776             :  */
    1777             : PLpgSQL_type *
    1778          40 : plpgsql_parse_wordrowtype(char *ident)
    1779             : {
    1780             :     Oid         classOid;
    1781             : 
    1782             :     /*
    1783             :      * Look up the relation.  Note that because relation rowtypes have the
    1784             :      * same names as their relations, this could be handled as a type lookup
    1785             :      * equally well; we use the relation lookup code path only because the
    1786             :      * errors thrown here have traditionally referred to relations not types.
    1787             :      * But we'll make a TypeName in case we have to do re-look-up of the type.
    1788             :      */
    1789          40 :     classOid = RelnameGetRelid(ident);
    1790          40 :     if (!OidIsValid(classOid))
    1791           0 :         ereport(ERROR,
    1792             :                 (errcode(ERRCODE_UNDEFINED_TABLE),
    1793             :                  errmsg("relation \"%s\" does not exist", ident)));
    1794             : 
    1795             :     /* Build and return the row type struct */
    1796          40 :     return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
    1797             :                                   makeTypeName(ident));
    1798             : }
    1799             : 
    1800             : /* ----------
    1801             :  * plpgsql_parse_cwordrowtype       Scanner found compositeword%ROWTYPE.
    1802             :  *          So word must be a namespace qualified table name.
    1803             :  * ----------
    1804             :  */
    1805             : PLpgSQL_type *
    1806           0 : plpgsql_parse_cwordrowtype(List *idents)
    1807             : {
    1808             :     Oid         classOid;
    1809             :     RangeVar   *relvar;
    1810             :     MemoryContext oldCxt;
    1811             : 
    1812             :     /*
    1813             :      * As above, this is a relation lookup but could be a type lookup if we
    1814             :      * weren't being backwards-compatible about error wording.
    1815             :      */
    1816           0 :     if (list_length(idents) != 2)
    1817           0 :         return NULL;
    1818             : 
    1819             :     /* Avoid memory leaks in long-term function context */
    1820           0 :     oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
    1821             : 
    1822             :     /* Look up relation name.  Can't lock it - we might not have privileges. */
    1823           0 :     relvar = makeRangeVar(strVal(linitial(idents)),
    1824           0 :                           strVal(lsecond(idents)),
    1825             :                           -1);
    1826           0 :     classOid = RangeVarGetRelid(relvar, NoLock, false);
    1827             : 
    1828           0 :     MemoryContextSwitchTo(oldCxt);
    1829             : 
    1830             :     /* Build and return the row type struct */
    1831           0 :     return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid,
    1832             :                                   makeTypeNameFromNameList(idents));
    1833             : }
    1834             : 
    1835             : /*
    1836             :  * plpgsql_build_variable - build a datum-array entry of a given
    1837             :  * datatype
    1838             :  *
    1839             :  * The returned struct may be a PLpgSQL_var or PLpgSQL_rec
    1840             :  * depending on the given datatype, and is allocated via
    1841             :  * palloc.  The struct is automatically added to the current datum
    1842             :  * array, and optionally to the current namespace.
    1843             :  */
    1844             : PLpgSQL_variable *
    1845       26012 : plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
    1846             :                        bool add2namespace)
    1847             : {
    1848             :     PLpgSQL_variable *result;
    1849             : 
    1850       26012 :     switch (dtype->ttype)
    1851             :     {
    1852             :         case PLPGSQL_TTYPE_SCALAR:
    1853             :             {
    1854             :                 /* Ordinary scalar datatype */
    1855             :                 PLpgSQL_var *var;
    1856             : 
    1857       25382 :                 var = palloc0(sizeof(PLpgSQL_var));
    1858       25382 :                 var->dtype = PLPGSQL_DTYPE_VAR;
    1859       25382 :                 var->refname = pstrdup(refname);
    1860       25382 :                 var->lineno = lineno;
    1861       25382 :                 var->datatype = dtype;
    1862             :                 /* other fields are left as 0, might be changed by caller */
    1863             : 
    1864             :                 /* preset to NULL */
    1865       25382 :                 var->value = 0;
    1866       25382 :                 var->isnull = true;
    1867       25382 :                 var->freeval = false;
    1868             : 
    1869       25382 :                 plpgsql_adddatum((PLpgSQL_datum *) var);
    1870       25382 :                 if (add2namespace)
    1871       23674 :                     plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
    1872             :                                        var->dno,
    1873             :                                        refname);
    1874       25382 :                 result = (PLpgSQL_variable *) var;
    1875       25382 :                 break;
    1876             :             }
    1877             :         case PLPGSQL_TTYPE_REC:
    1878             :             {
    1879             :                 /* Composite type -- build a record variable */
    1880             :                 PLpgSQL_rec *rec;
    1881             : 
    1882         630 :                 rec = plpgsql_build_record(refname, lineno,
    1883             :                                            dtype, dtype->typoid,
    1884             :                                            add2namespace);
    1885         630 :                 result = (PLpgSQL_variable *) rec;
    1886         630 :                 break;
    1887             :             }
    1888             :         case PLPGSQL_TTYPE_PSEUDO:
    1889           0 :             ereport(ERROR,
    1890             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1891             :                      errmsg("variable \"%s\" has pseudo-type %s",
    1892             :                             refname, format_type_be(dtype->typoid))));
    1893             :             result = NULL;      /* keep compiler quiet */
    1894             :             break;
    1895             :         default:
    1896           0 :             elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
    1897             :             result = NULL;      /* keep compiler quiet */
    1898             :             break;
    1899             :     }
    1900             : 
    1901       26012 :     return result;
    1902             : }
    1903             : 
    1904             : /*
    1905             :  * Build empty named record variable, and optionally add it to namespace
    1906             :  */
    1907             : PLpgSQL_rec *
    1908        4106 : plpgsql_build_record(const char *refname, int lineno,
    1909             :                      PLpgSQL_type *dtype, Oid rectypeid,
    1910             :                      bool add2namespace)
    1911             : {
    1912             :     PLpgSQL_rec *rec;
    1913             : 
    1914        4106 :     rec = palloc0(sizeof(PLpgSQL_rec));
    1915        4106 :     rec->dtype = PLPGSQL_DTYPE_REC;
    1916        4106 :     rec->refname = pstrdup(refname);
    1917        4106 :     rec->lineno = lineno;
    1918             :     /* other fields are left as 0, might be changed by caller */
    1919        4106 :     rec->datatype = dtype;
    1920        4106 :     rec->rectypeid = rectypeid;
    1921        4106 :     rec->firstfield = -1;
    1922        4106 :     rec->erh = NULL;
    1923        4106 :     plpgsql_adddatum((PLpgSQL_datum *) rec);
    1924        4106 :     if (add2namespace)
    1925        4076 :         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->dno, rec->refname);
    1926             : 
    1927        4106 :     return rec;
    1928             : }
    1929             : 
    1930             : /*
    1931             :  * Build a row-variable data structure given the component variables.
    1932             :  * Include a rowtupdesc, since we will need to materialize the row result.
    1933             :  */
    1934             : static PLpgSQL_row *
    1935          78 : build_row_from_vars(PLpgSQL_variable **vars, int numvars)
    1936             : {
    1937             :     PLpgSQL_row *row;
    1938             :     int         i;
    1939             : 
    1940          78 :     row = palloc0(sizeof(PLpgSQL_row));
    1941          78 :     row->dtype = PLPGSQL_DTYPE_ROW;
    1942          78 :     row->refname = "(unnamed row)";
    1943          78 :     row->lineno = -1;
    1944          78 :     row->rowtupdesc = CreateTemplateTupleDesc(numvars);
    1945          78 :     row->nfields = numvars;
    1946          78 :     row->fieldnames = palloc(numvars * sizeof(char *));
    1947          78 :     row->varnos = palloc(numvars * sizeof(int));
    1948             : 
    1949         234 :     for (i = 0; i < numvars; i++)
    1950             :     {
    1951         156 :         PLpgSQL_variable *var = vars[i];
    1952             :         Oid         typoid;
    1953             :         int32       typmod;
    1954             :         Oid         typcoll;
    1955             : 
    1956             :         /* Member vars of a row should never be const */
    1957             :         Assert(!var->isconst);
    1958             : 
    1959         156 :         switch (var->dtype)
    1960             :         {
    1961             :             case PLPGSQL_DTYPE_VAR:
    1962             :             case PLPGSQL_DTYPE_PROMISE:
    1963         156 :                 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
    1964         156 :                 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
    1965         156 :                 typcoll = ((PLpgSQL_var *) var)->datatype->collation;
    1966         156 :                 break;
    1967             : 
    1968             :             case PLPGSQL_DTYPE_REC:
    1969             :                 /* shouldn't need to revalidate rectypeid already... */
    1970           0 :                 typoid = ((PLpgSQL_rec *) var)->rectypeid;
    1971           0 :                 typmod = -1;    /* don't know typmod, if it's used at all */
    1972           0 :                 typcoll = InvalidOid;   /* composite types have no collation */
    1973           0 :                 break;
    1974             : 
    1975             :             default:
    1976           0 :                 elog(ERROR, "unrecognized dtype: %d", var->dtype);
    1977             :                 typoid = InvalidOid;    /* keep compiler quiet */
    1978             :                 typmod = 0;
    1979             :                 typcoll = InvalidOid;
    1980             :                 break;
    1981             :         }
    1982             : 
    1983         156 :         row->fieldnames[i] = var->refname;
    1984         156 :         row->varnos[i] = var->dno;
    1985             : 
    1986         156 :         TupleDescInitEntry(row->rowtupdesc, i + 1,
    1987         156 :                            var->refname,
    1988             :                            typoid, typmod,
    1989             :                            0);
    1990         156 :         TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
    1991             :     }
    1992             : 
    1993          78 :     return row;
    1994             : }
    1995             : 
    1996             : /*
    1997             :  * Build a RECFIELD datum for the named field of the specified record variable
    1998             :  *
    1999             :  * If there's already such a datum, just return it; we don't need duplicates.
    2000             :  */
    2001             : PLpgSQL_recfield *
    2002        4220 : plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
    2003             : {
    2004             :     PLpgSQL_recfield *recfield;
    2005             :     int         i;
    2006             : 
    2007             :     /* search for an existing datum referencing this field */
    2008        4220 :     i = rec->firstfield;
    2009       10556 :     while (i >= 0)
    2010             :     {
    2011        3968 :         PLpgSQL_recfield *fld = (PLpgSQL_recfield *) plpgsql_Datums[i];
    2012             : 
    2013             :         Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
    2014             :                fld->recparentno == rec->dno);
    2015        3968 :         if (strcmp(fld->fieldname, fldname) == 0)
    2016        1852 :             return fld;
    2017        2116 :         i = fld->nextfield;
    2018             :     }
    2019             : 
    2020             :     /* nope, so make a new one */
    2021        2368 :     recfield = palloc0(sizeof(PLpgSQL_recfield));
    2022        2368 :     recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
    2023        2368 :     recfield->fieldname = pstrdup(fldname);
    2024        2368 :     recfield->recparentno = rec->dno;
    2025        2368 :     recfield->rectupledescid = INVALID_TUPLEDESC_IDENTIFIER;
    2026             : 
    2027        2368 :     plpgsql_adddatum((PLpgSQL_datum *) recfield);
    2028             : 
    2029             :     /* now we can link it into the parent's chain */
    2030        2368 :     recfield->nextfield = rec->firstfield;
    2031        2368 :     rec->firstfield = recfield->dno;
    2032             : 
    2033        2368 :     return recfield;
    2034             : }
    2035             : 
    2036             : /*
    2037             :  * plpgsql_build_datatype
    2038             :  *      Build PLpgSQL_type struct given type OID, typmod, collation,
    2039             :  *      and type's parsed name.
    2040             :  *
    2041             :  * If collation is not InvalidOid then it overrides the type's default
    2042             :  * collation.  But collation is ignored if the datatype is non-collatable.
    2043             :  *
    2044             :  * origtypname is the parsed form of what the user wrote as the type name.
    2045             :  * It can be NULL if the type could not be a composite type, or if it was
    2046             :  * identified by OID to begin with (e.g., it's a function argument type).
    2047             :  */
    2048             : PLpgSQL_type *
    2049       26010 : plpgsql_build_datatype(Oid typeOid, int32 typmod,
    2050             :                        Oid collation, TypeName *origtypname)
    2051             : {
    2052             :     HeapTuple   typeTup;
    2053             :     PLpgSQL_type *typ;
    2054             : 
    2055       26010 :     typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
    2056       26010 :     if (!HeapTupleIsValid(typeTup))
    2057           0 :         elog(ERROR, "cache lookup failed for type %u", typeOid);
    2058             : 
    2059       26010 :     typ = build_datatype(typeTup, typmod, collation, origtypname);
    2060             : 
    2061       26010 :     ReleaseSysCache(typeTup);
    2062             : 
    2063       26010 :     return typ;
    2064             : }
    2065             : 
    2066             : /*
    2067             :  * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
    2068             :  * and additional details (see comments for plpgsql_build_datatype).
    2069             :  */
    2070             : static PLpgSQL_type *
    2071       26034 : build_datatype(HeapTuple typeTup, int32 typmod,
    2072             :                Oid collation, TypeName *origtypname)
    2073             : {
    2074       26034 :     Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
    2075             :     PLpgSQL_type *typ;
    2076             : 
    2077       26034 :     if (!typeStruct->typisdefined)
    2078           0 :         ereport(ERROR,
    2079             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2080             :                  errmsg("type \"%s\" is only a shell",
    2081             :                         NameStr(typeStruct->typname))));
    2082             : 
    2083       26034 :     typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
    2084             : 
    2085       26034 :     typ->typname = pstrdup(NameStr(typeStruct->typname));
    2086       26034 :     typ->typoid = typeStruct->oid;
    2087       26034 :     switch (typeStruct->typtype)
    2088             :     {
    2089             :         case TYPTYPE_BASE:
    2090             :         case TYPTYPE_ENUM:
    2091             :         case TYPTYPE_RANGE:
    2092       25304 :             typ->ttype = PLPGSQL_TTYPE_SCALAR;
    2093       25304 :             break;
    2094             :         case TYPTYPE_COMPOSITE:
    2095         148 :             typ->ttype = PLPGSQL_TTYPE_REC;
    2096         148 :             break;
    2097             :         case TYPTYPE_DOMAIN:
    2098         136 :             if (type_is_rowtype(typeStruct->typbasetype))
    2099          36 :                 typ->ttype = PLPGSQL_TTYPE_REC;
    2100             :             else
    2101         100 :                 typ->ttype = PLPGSQL_TTYPE_SCALAR;
    2102         136 :             break;
    2103             :         case TYPTYPE_PSEUDO:
    2104         446 :             if (typ->typoid == RECORDOID)
    2105         446 :                 typ->ttype = PLPGSQL_TTYPE_REC;
    2106             :             else
    2107           0 :                 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
    2108         446 :             break;
    2109             :         default:
    2110           0 :             elog(ERROR, "unrecognized typtype: %d",
    2111             :                  (int) typeStruct->typtype);
    2112             :             break;
    2113             :     }
    2114       26034 :     typ->typlen = typeStruct->typlen;
    2115       26034 :     typ->typbyval = typeStruct->typbyval;
    2116       26034 :     typ->typtype = typeStruct->typtype;
    2117       26034 :     typ->collation = typeStruct->typcollation;
    2118       26034 :     if (OidIsValid(collation) && OidIsValid(typ->collation))
    2119         300 :         typ->collation = collation;
    2120             :     /* Detect if type is true array, or domain thereof */
    2121             :     /* NB: this is only used to decide whether to apply expand_array */
    2122       26034 :     if (typeStruct->typtype == TYPTYPE_BASE)
    2123             :     {
    2124             :         /*
    2125             :          * This test should include what get_element_type() checks.  We also
    2126             :          * disallow non-toastable array types (i.e. oidvector and int2vector).
    2127             :          */
    2128       59546 :         typ->typisarray = (typeStruct->typlen == -1 &&
    2129       27236 :                            OidIsValid(typeStruct->typelem) &&
    2130        1940 :                            typeStruct->typstorage != 'p');
    2131             :     }
    2132         738 :     else if (typeStruct->typtype == TYPTYPE_DOMAIN)
    2133             :     {
    2134             :         /* we can short-circuit looking up base types if it's not varlena */
    2135         350 :         typ->typisarray = (typeStruct->typlen == -1 &&
    2136         214 :                            typeStruct->typstorage != 'p' &&
    2137          78 :                            OidIsValid(get_base_element_type(typeStruct->typbasetype)));
    2138             :     }
    2139             :     else
    2140         602 :         typ->typisarray = false;
    2141       26034 :     typ->atttypmod = typmod;
    2142             : 
    2143             :     /*
    2144             :      * If it's a named composite type (or domain over one), find the typcache
    2145             :      * entry and record the current tupdesc ID, so we can detect changes
    2146             :      * (including drops).  We don't currently support on-the-fly replacement
    2147             :      * of non-composite types, else we might want to do this for them too.
    2148             :      */
    2149       26034 :     if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
    2150         184 :     {
    2151             :         TypeCacheEntry *typentry;
    2152             : 
    2153         184 :         typentry = lookup_type_cache(typ->typoid,
    2154             :                                      TYPECACHE_TUPDESC |
    2155             :                                      TYPECACHE_DOMAIN_BASE_INFO);
    2156         184 :         if (typentry->typtype == TYPTYPE_DOMAIN)
    2157          36 :             typentry = lookup_type_cache(typentry->domainBaseType,
    2158             :                                          TYPECACHE_TUPDESC);
    2159         184 :         if (typentry->tupDesc == NULL)
    2160           0 :             ereport(ERROR,
    2161             :                     (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    2162             :                      errmsg("type %s is not composite",
    2163             :                             format_type_be(typ->typoid))));
    2164             : 
    2165         184 :         typ->origtypname = origtypname;
    2166         184 :         typ->tcache = typentry;
    2167         184 :         typ->tupdesc_id = typentry->tupDesc_identifier;
    2168             :     }
    2169             :     else
    2170             :     {
    2171       25850 :         typ->origtypname = NULL;
    2172       25850 :         typ->tcache = NULL;
    2173       25850 :         typ->tupdesc_id = 0;
    2174             :     }
    2175             : 
    2176       26034 :     return typ;
    2177             : }
    2178             : 
    2179             : /*
    2180             :  *  plpgsql_recognize_err_condition
    2181             :  *      Check condition name and translate it to SQLSTATE.
    2182             :  *
    2183             :  * Note: there are some cases where the same condition name has multiple
    2184             :  * entries in the table.  We arbitrarily return the first match.
    2185             :  */
    2186             : int
    2187          84 : plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
    2188             : {
    2189             :     int         i;
    2190             : 
    2191          84 :     if (allow_sqlstate)
    2192             :     {
    2193         100 :         if (strlen(condname) == 5 &&
    2194          36 :             strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
    2195          36 :             return MAKE_SQLSTATE(condname[0],
    2196             :                                  condname[1],
    2197             :                                  condname[2],
    2198             :                                  condname[3],
    2199             :                                  condname[4]);
    2200             :     }
    2201             : 
    2202        2128 :     for (i = 0; exception_label_map[i].label != NULL; i++)
    2203             :     {
    2204        2128 :         if (strcmp(condname, exception_label_map[i].label) == 0)
    2205          48 :             return exception_label_map[i].sqlerrstate;
    2206             :     }
    2207             : 
    2208           0 :     ereport(ERROR,
    2209             :             (errcode(ERRCODE_UNDEFINED_OBJECT),
    2210             :              errmsg("unrecognized exception condition \"%s\"",
    2211             :                     condname)));
    2212             :     return 0;                   /* keep compiler quiet */
    2213             : }
    2214             : 
    2215             : /*
    2216             :  * plpgsql_parse_err_condition
    2217             :  *      Generate PLpgSQL_condition entry(s) for an exception condition name
    2218             :  *
    2219             :  * This has to be able to return a list because there are some duplicate
    2220             :  * names in the table of error code names.
    2221             :  */
    2222             : PLpgSQL_condition *
    2223         160 : plpgsql_parse_err_condition(char *condname)
    2224             : {
    2225             :     int         i;
    2226             :     PLpgSQL_condition *new;
    2227             :     PLpgSQL_condition *prev;
    2228             : 
    2229             :     /*
    2230             :      * XXX Eventually we will want to look for user-defined exception names
    2231             :      * here.
    2232             :      */
    2233             : 
    2234             :     /*
    2235             :      * OTHERS is represented as code 0 (which would map to '00000', but we
    2236             :      * have no need to represent that as an exception condition).
    2237             :      */
    2238         160 :     if (strcmp(condname, "others") == 0)
    2239             :     {
    2240          70 :         new = palloc(sizeof(PLpgSQL_condition));
    2241          70 :         new->sqlerrstate = 0;
    2242          70 :         new->condname = condname;
    2243          70 :         new->next = NULL;
    2244          70 :         return new;
    2245             :     }
    2246             : 
    2247          90 :     prev = NULL;
    2248       22230 :     for (i = 0; exception_label_map[i].label != NULL; i++)
    2249             :     {
    2250       22140 :         if (strcmp(condname, exception_label_map[i].label) == 0)
    2251             :         {
    2252          90 :             new = palloc(sizeof(PLpgSQL_condition));
    2253          90 :             new->sqlerrstate = exception_label_map[i].sqlerrstate;
    2254          90 :             new->condname = condname;
    2255          90 :             new->next = prev;
    2256          90 :             prev = new;
    2257             :         }
    2258             :     }
    2259             : 
    2260          90 :     if (!prev)
    2261           0 :         ereport(ERROR,
    2262             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    2263             :                  errmsg("unrecognized exception condition \"%s\"",
    2264             :                         condname)));
    2265             : 
    2266          90 :     return prev;
    2267             : }
    2268             : 
    2269             : /* ----------
    2270             :  * plpgsql_start_datums         Initialize datum list at compile startup.
    2271             :  * ----------
    2272             :  */
    2273             : static void
    2274        3830 : plpgsql_start_datums(void)
    2275             : {
    2276        3830 :     datums_alloc = 128;
    2277        3830 :     plpgsql_nDatums = 0;
    2278             :     /* This is short-lived, so needn't allocate in function's cxt */
    2279        3830 :     plpgsql_Datums = MemoryContextAlloc(plpgsql_compile_tmp_cxt,
    2280             :                                         sizeof(PLpgSQL_datum *) * datums_alloc);
    2281             :     /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
    2282        3830 :     datums_last = 0;
    2283        3830 : }
    2284             : 
    2285             : /* ----------
    2286             :  * plpgsql_adddatum         Add a variable, record or row
    2287             :  *                  to the compiler's datum list.
    2288             :  * ----------
    2289             :  */
    2290             : void
    2291       32520 : plpgsql_adddatum(PLpgSQL_datum *newdatum)
    2292             : {
    2293       32520 :     if (plpgsql_nDatums == datums_alloc)
    2294             :     {
    2295           0 :         datums_alloc *= 2;
    2296           0 :         plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
    2297             :     }
    2298             : 
    2299       32520 :     newdatum->dno = plpgsql_nDatums;
    2300       32520 :     plpgsql_Datums[plpgsql_nDatums++] = newdatum;
    2301       32520 : }
    2302             : 
    2303             : /* ----------
    2304             :  * plpgsql_finish_datums    Copy completed datum info into function struct.
    2305             :  * ----------
    2306             :  */
    2307             : static void
    2308        3728 : plpgsql_finish_datums(PLpgSQL_function *function)
    2309             : {
    2310        3728 :     Size        copiable_size = 0;
    2311             :     int         i;
    2312             : 
    2313        3728 :     function->ndatums = plpgsql_nDatums;
    2314        3728 :     function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
    2315       36014 :     for (i = 0; i < plpgsql_nDatums; i++)
    2316             :     {
    2317       32286 :         function->datums[i] = plpgsql_Datums[i];
    2318             : 
    2319             :         /* This must agree with copy_plpgsql_datums on what is copiable */
    2320       32286 :         switch (function->datums[i]->dtype)
    2321             :         {
    2322             :             case PLPGSQL_DTYPE_VAR:
    2323             :             case PLPGSQL_DTYPE_PROMISE:
    2324       25184 :                 copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
    2325       25184 :                 break;
    2326             :             case PLPGSQL_DTYPE_REC:
    2327        4090 :                 copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
    2328        4090 :                 break;
    2329             :             default:
    2330        3012 :                 break;
    2331             :         }
    2332             :     }
    2333        3728 :     function->copiable_size = copiable_size;
    2334        3728 : }
    2335             : 
    2336             : 
    2337             : /* ----------
    2338             :  * plpgsql_add_initdatums       Make an array of the datum numbers of
    2339             :  *                  all the initializable datums created since the last call
    2340             :  *                  to this function.
    2341             :  *
    2342             :  * If varnos is NULL, we just forget any datum entries created since the
    2343             :  * last call.
    2344             :  *
    2345             :  * This is used around a DECLARE section to create a list of the datums
    2346             :  * that have to be initialized at block entry.  Note that datums can also
    2347             :  * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
    2348             :  * the responsibility of special-purpose code to initialize them.
    2349             :  * ----------
    2350             :  */
    2351             : int
    2352        2972 : plpgsql_add_initdatums(int **varnos)
    2353             : {
    2354             :     int         i;
    2355        2972 :     int         n = 0;
    2356             : 
    2357             :     /*
    2358             :      * The set of dtypes recognized here must match what exec_stmt_block()
    2359             :      * cares about (re)initializing at block entry.
    2360             :      */
    2361       11234 :     for (i = datums_last; i < plpgsql_nDatums; i++)
    2362             :     {
    2363        8262 :         switch (plpgsql_Datums[i]->dtype)
    2364             :         {
    2365             :             case PLPGSQL_DTYPE_VAR:
    2366             :             case PLPGSQL_DTYPE_REC:
    2367        5470 :                 n++;
    2368        5470 :                 break;
    2369             : 
    2370             :             default:
    2371        2792 :                 break;
    2372             :         }
    2373             :     }
    2374             : 
    2375        2972 :     if (varnos != NULL)
    2376             :     {
    2377        1478 :         if (n > 0)
    2378             :         {
    2379        1478 :             *varnos = (int *) palloc(sizeof(int) * n);
    2380             : 
    2381        1478 :             n = 0;
    2382        4008 :             for (i = datums_last; i < plpgsql_nDatums; i++)
    2383             :             {
    2384        2530 :                 switch (plpgsql_Datums[i]->dtype)
    2385             :                 {
    2386             :                     case PLPGSQL_DTYPE_VAR:
    2387             :                     case PLPGSQL_DTYPE_REC:
    2388        2482 :                         (*varnos)[n++] = plpgsql_Datums[i]->dno;
    2389             : 
    2390             :                     default:
    2391        2530 :                         break;
    2392             :                 }
    2393             :             }
    2394             :         }
    2395             :         else
    2396           0 :             *varnos = NULL;
    2397             :     }
    2398             : 
    2399        2972 :     datums_last = plpgsql_nDatums;
    2400        2972 :     return n;
    2401             : }
    2402             : 
    2403             : 
    2404             : /*
    2405             :  * Compute the hashkey for a given function invocation
    2406             :  *
    2407             :  * The hashkey is returned into the caller-provided storage at *hashkey.
    2408             :  */
    2409             : static void
    2410       15756 : compute_function_hashkey(FunctionCallInfo fcinfo,
    2411             :                          Form_pg_proc procStruct,
    2412             :                          PLpgSQL_func_hashkey *hashkey,
    2413             :                          bool forValidator)
    2414             : {
    2415             :     /* Make sure any unused bytes of the struct are zero */
    2416       15756 :     MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
    2417             : 
    2418             :     /* get function OID */
    2419       15756 :     hashkey->funcOid = fcinfo->flinfo->fn_oid;
    2420             : 
    2421             :     /* get call context */
    2422       15756 :     hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
    2423             : 
    2424             :     /*
    2425             :      * if trigger, get its OID.  In validation mode we do not know what
    2426             :      * relation or transition table names are intended to be used, so we leave
    2427             :      * trigOid zero; the hash entry built in this case will never really be
    2428             :      * used.
    2429             :      */
    2430       15756 :     if (hashkey->isTrigger && !forValidator)
    2431             :     {
    2432        7512 :         TriggerData *trigdata = (TriggerData *) fcinfo->context;
    2433             : 
    2434        7512 :         hashkey->trigOid = trigdata->tg_trigger->tgoid;
    2435             :     }
    2436             : 
    2437             :     /* get input collation, if known */
    2438       15756 :     hashkey->inputCollation = fcinfo->fncollation;
    2439             : 
    2440       15756 :     if (procStruct->pronargs > 0)
    2441             :     {
    2442             :         /* get the argument types */
    2443        5702 :         memcpy(hashkey->argtypes, procStruct->proargtypes.values,
    2444        5702 :                procStruct->pronargs * sizeof(Oid));
    2445             : 
    2446             :         /* resolve any polymorphic argument types */
    2447       11404 :         plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
    2448        5702 :                                              hashkey->argtypes,
    2449             :                                              NULL,
    2450        5702 :                                              fcinfo->flinfo->fn_expr,
    2451             :                                              forValidator,
    2452        5702 :                                              NameStr(procStruct->proname));
    2453             :     }
    2454       15756 : }
    2455             : 
    2456             : /*
    2457             :  * This is the same as the standard resolve_polymorphic_argtypes() function,
    2458             :  * but with a special case for validation: assume that polymorphic arguments
    2459             :  * are integer, integer-array or integer-range.  Also, we go ahead and report
    2460             :  * the error if we can't resolve the types.
    2461             :  */
    2462             : static void
    2463        7284 : plpgsql_resolve_polymorphic_argtypes(int numargs,
    2464             :                                      Oid *argtypes, char *argmodes,
    2465             :                                      Node *call_expr, bool forValidator,
    2466             :                                      const char *proname)
    2467             : {
    2468             :     int         i;
    2469             : 
    2470        7284 :     if (!forValidator)
    2471             :     {
    2472             :         /* normal case, pass to standard routine */
    2473        5108 :         if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
    2474             :                                           call_expr))
    2475           0 :             ereport(ERROR,
    2476             :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2477             :                      errmsg("could not determine actual argument "
    2478             :                             "type for polymorphic function \"%s\"",
    2479             :                             proname)));
    2480             :     }
    2481             :     else
    2482             :     {
    2483             :         /* special validation case */
    2484        4816 :         for (i = 0; i < numargs; i++)
    2485             :         {
    2486        2640 :             switch (argtypes[i])
    2487             :             {
    2488             :                 case ANYELEMENTOID:
    2489             :                 case ANYNONARRAYOID:
    2490             :                 case ANYENUMOID:    /* XXX dubious */
    2491         380 :                     argtypes[i] = INT4OID;
    2492         380 :                     break;
    2493             :                 case ANYARRAYOID:
    2494          68 :                     argtypes[i] = INT4ARRAYOID;
    2495          68 :                     break;
    2496             :                 case ANYRANGEOID:
    2497           0 :                     argtypes[i] = INT4RANGEOID;
    2498           0 :                     break;
    2499             :                 default:
    2500        2192 :                     break;
    2501             :             }
    2502             :         }
    2503             :     }
    2504        7284 : }
    2505             : 
    2506             : /*
    2507             :  * delete_function - clean up as much as possible of a stale function cache
    2508             :  *
    2509             :  * We can't release the PLpgSQL_function struct itself, because of the
    2510             :  * possibility that there are fn_extra pointers to it.  We can release
    2511             :  * the subsidiary storage, but only if there are no active evaluations
    2512             :  * in progress.  Otherwise we'll just leak that storage.  Since the
    2513             :  * case would only occur if a pg_proc update is detected during a nested
    2514             :  * recursive call on the function, a leak seems acceptable.
    2515             :  *
    2516             :  * Note that this can be called more than once if there are multiple fn_extra
    2517             :  * pointers to the same function cache.  Hence be careful not to do things
    2518             :  * twice.
    2519             :  */
    2520             : static void
    2521         386 : delete_function(PLpgSQL_function *func)
    2522             : {
    2523             :     /* remove function from hash table (might be done already) */
    2524         386 :     plpgsql_HashTableDelete(func);
    2525             : 
    2526             :     /* release the function's storage if safe and not done already */
    2527         386 :     if (func->use_count == 0)
    2528         386 :         plpgsql_free_function_memory(func);
    2529         386 : }
    2530             : 
    2531             : /* exported so we can call it from _PG_init() */
    2532             : void
    2533        2148 : plpgsql_HashTableInit(void)
    2534             : {
    2535             :     HASHCTL     ctl;
    2536             : 
    2537             :     /* don't allow double-initialization */
    2538             :     Assert(plpgsql_HashTable == NULL);
    2539             : 
    2540        2148 :     memset(&ctl, 0, sizeof(ctl));
    2541        2148 :     ctl.keysize = sizeof(PLpgSQL_func_hashkey);
    2542        2148 :     ctl.entrysize = sizeof(plpgsql_HashEnt);
    2543        2148 :     plpgsql_HashTable = hash_create("PLpgSQL function hash",
    2544             :                                     FUNCS_PER_USER,
    2545             :                                     &ctl,
    2546             :                                     HASH_ELEM | HASH_BLOBS);
    2547        2148 : }
    2548             : 
    2549             : static PLpgSQL_function *
    2550       15756 : plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
    2551             : {
    2552             :     plpgsql_HashEnt *hentry;
    2553             : 
    2554       15756 :     hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
    2555             :                                              (void *) func_key,
    2556             :                                              HASH_FIND,
    2557             :                                              NULL);
    2558       15756 :     if (hentry)
    2559       12740 :         return hentry->function;
    2560             :     else
    2561        3016 :         return NULL;
    2562             : }
    2563             : 
    2564             : static void
    2565        3322 : plpgsql_HashTableInsert(PLpgSQL_function *function,
    2566             :                         PLpgSQL_func_hashkey *func_key)
    2567             : {
    2568             :     plpgsql_HashEnt *hentry;
    2569             :     bool        found;
    2570             : 
    2571        3322 :     hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
    2572             :                                              (void *) func_key,
    2573             :                                              HASH_ENTER,
    2574             :                                              &found);
    2575        3322 :     if (found)
    2576           0 :         elog(WARNING, "trying to insert a function that already exists");
    2577             : 
    2578        3322 :     hentry->function = function;
    2579             :     /* prepare back link from function to hashtable key */
    2580        3322 :     function->fn_hashkey = &hentry->key;
    2581        3322 : }
    2582             : 
    2583             : static void
    2584         386 : plpgsql_HashTableDelete(PLpgSQL_function *function)
    2585             : {
    2586             :     plpgsql_HashEnt *hentry;
    2587             : 
    2588             :     /* do nothing if not in table */
    2589         386 :     if (function->fn_hashkey == NULL)
    2590           0 :         return;
    2591             : 
    2592         386 :     hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
    2593         386 :                                              (void *) function->fn_hashkey,
    2594             :                                              HASH_REMOVE,
    2595             :                                              NULL);
    2596         386 :     if (hentry == NULL)
    2597           0 :         elog(WARNING, "trying to delete function that does not exist");
    2598             : 
    2599             :     /* remove back link, which no longer points to allocated storage */
    2600         386 :     function->fn_hashkey = NULL;
    2601             : }

Generated by: LCOV version 1.13