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

Generated by: LCOV version 1.14