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

Generated by: LCOV version 1.16