LCOV - code coverage report
Current view: top level - src/pl/plpgsql/src - pl_comp.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 728 852 85.4 %
Date: 2017-09-29 15:12:54 Functions: 36 38 94.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11