LCOV - code coverage report
Current view: top level - src/pl/plpgsql/src - pl_comp.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 703 806 87.2 %
Date: 2019-06-19 16:07:09 Functions: 36 38 94.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13