Header And Logo

PostgreSQL
| The world's most advanced open source database.

pl_comp.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pl_comp.c        - Compiler part of the PL/pgSQL
00004  *            procedural language
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/pl/plpgsql/src/pl_comp.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "plpgsql.h"
00017 
00018 #include <ctype.h>
00019 
00020 #include "access/htup_details.h"
00021 #include "catalog/namespace.h"
00022 #include "catalog/pg_proc.h"
00023 #include "catalog/pg_proc_fn.h"
00024 #include "catalog/pg_type.h"
00025 #include "funcapi.h"
00026 #include "nodes/makefuncs.h"
00027 #include "parser/parse_type.h"
00028 #include "utils/builtins.h"
00029 #include "utils/guc.h"
00030 #include "utils/lsyscache.h"
00031 #include "utils/memutils.h"
00032 #include "utils/rel.h"
00033 #include "utils/syscache.h"
00034 
00035 
00036 /* ----------
00037  * Our own local and global variables
00038  * ----------
00039  */
00040 PLpgSQL_stmt_block *plpgsql_parse_result;
00041 
00042 static int  datums_alloc;
00043 int         plpgsql_nDatums;
00044 PLpgSQL_datum **plpgsql_Datums;
00045 static int  datums_last = 0;
00046 
00047 char       *plpgsql_error_funcname;
00048 bool        plpgsql_DumpExecTree = false;
00049 bool        plpgsql_check_syntax = false;
00050 
00051 PLpgSQL_function *plpgsql_curr_compile;
00052 
00053 /* A context appropriate for short-term allocs during compilation */
00054 MemoryContext compile_tmp_cxt;
00055 
00056 /* ----------
00057  * Hash table for compiled functions
00058  * ----------
00059  */
00060 static HTAB *plpgsql_HashTable = NULL;
00061 
00062 typedef struct plpgsql_hashent
00063 {
00064     PLpgSQL_func_hashkey key;
00065     PLpgSQL_function *function;
00066 } plpgsql_HashEnt;
00067 
00068 #define FUNCS_PER_USER      128 /* initial table size */
00069 
00070 /* ----------
00071  * Lookup table for EXCEPTION condition names
00072  * ----------
00073  */
00074 typedef struct
00075 {
00076     const char *label;
00077     int         sqlerrstate;
00078 } ExceptionLabelMap;
00079 
00080 static const ExceptionLabelMap exception_label_map[] = {
00081 #include "plerrcodes.h"         /* pgrminclude ignore */
00082     {NULL, 0}
00083 };
00084 
00085 
00086 /* ----------
00087  * static prototypes
00088  * ----------
00089  */
00090 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
00091            HeapTuple procTup,
00092            PLpgSQL_function *function,
00093            PLpgSQL_func_hashkey *hashkey,
00094            bool forValidator);
00095 static void plpgsql_compile_error_callback(void *arg);
00096 static void add_parameter_name(int itemtype, int itemno, const char *name);
00097 static void add_dummy_return(PLpgSQL_function *function);
00098 static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
00099 static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
00100 static Node *plpgsql_param_ref(ParseState *pstate, ParamRef *pref);
00101 static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
00102                    ColumnRef *cref, bool error_if_no_field);
00103 static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
00104 static PLpgSQL_row *build_row_from_class(Oid classOid);
00105 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
00106 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod, Oid collation);
00107 static void compute_function_hashkey(FunctionCallInfo fcinfo,
00108                          Form_pg_proc procStruct,
00109                          PLpgSQL_func_hashkey *hashkey,
00110                          bool forValidator);
00111 static void plpgsql_resolve_polymorphic_argtypes(int numargs,
00112                                      Oid *argtypes, char *argmodes,
00113                                      Node *call_expr, bool forValidator,
00114                                      const char *proname);
00115 static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
00116 static void plpgsql_HashTableInsert(PLpgSQL_function *function,
00117                         PLpgSQL_func_hashkey *func_key);
00118 static void plpgsql_HashTableDelete(PLpgSQL_function *function);
00119 static void delete_function(PLpgSQL_function *func);
00120 
00121 /* ----------
00122  * plpgsql_compile      Make an execution tree for a PL/pgSQL function.
00123  *
00124  * If forValidator is true, we're only compiling for validation purposes,
00125  * and so some checks are skipped.
00126  *
00127  * Note: it's important for this to fall through quickly if the function
00128  * has already been compiled.
00129  * ----------
00130  */
00131 PLpgSQL_function *
00132 plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
00133 {
00134     Oid         funcOid = fcinfo->flinfo->fn_oid;
00135     HeapTuple   procTup;
00136     Form_pg_proc procStruct;
00137     PLpgSQL_function *function;
00138     PLpgSQL_func_hashkey hashkey;
00139     bool        function_valid = false;
00140     bool        hashkey_valid = false;
00141 
00142     /*
00143      * Lookup the pg_proc tuple by Oid; we'll need it in any case
00144      */
00145     procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
00146     if (!HeapTupleIsValid(procTup))
00147         elog(ERROR, "cache lookup failed for function %u", funcOid);
00148     procStruct = (Form_pg_proc) GETSTRUCT(procTup);
00149 
00150     /*
00151      * See if there's already a cache entry for the current FmgrInfo. If not,
00152      * try to find one in the hash table.
00153      */
00154     function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
00155 
00156 recheck:
00157     if (!function)
00158     {
00159         /* Compute hashkey using function signature and actual arg types */
00160         compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
00161         hashkey_valid = true;
00162 
00163         /* And do the lookup */
00164         function = plpgsql_HashTableLookup(&hashkey);
00165     }
00166 
00167     if (function)
00168     {
00169         /* We have a compiled function, but is it still valid? */
00170         if (function->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
00171             ItemPointerEquals(&function->fn_tid, &procTup->t_self))
00172             function_valid = true;
00173         else
00174         {
00175             /*
00176              * Nope, so remove it from hashtable and try to drop associated
00177              * storage (if not done already).
00178              */
00179             delete_function(function);
00180 
00181             /*
00182              * If the function isn't in active use then we can overwrite the
00183              * func struct with new data, allowing any other existing fn_extra
00184              * pointers to make use of the new definition on their next use.
00185              * If it is in use then just leave it alone and make a new one.
00186              * (The active invocations will run to completion using the
00187              * previous definition, and then the cache entry will just be
00188              * leaked; doesn't seem worth adding code to clean it up, given
00189              * what a corner case this is.)
00190              *
00191              * If we found the function struct via fn_extra then it's possible
00192              * a replacement has already been made, so go back and recheck the
00193              * hashtable.
00194              */
00195             if (function->use_count != 0)
00196             {
00197                 function = NULL;
00198                 if (!hashkey_valid)
00199                     goto recheck;
00200             }
00201         }
00202     }
00203 
00204     /*
00205      * If the function wasn't found or was out-of-date, we have to compile it
00206      */
00207     if (!function_valid)
00208     {
00209         /*
00210          * Calculate hashkey if we didn't already; we'll need it to store the
00211          * completed function.
00212          */
00213         if (!hashkey_valid)
00214             compute_function_hashkey(fcinfo, procStruct, &hashkey,
00215                                      forValidator);
00216 
00217         /*
00218          * Do the hard part.
00219          */
00220         function = do_compile(fcinfo, procTup, function,
00221                               &hashkey, forValidator);
00222     }
00223 
00224     ReleaseSysCache(procTup);
00225 
00226     /*
00227      * Save pointer in FmgrInfo to avoid search on subsequent calls
00228      */
00229     fcinfo->flinfo->fn_extra = (void *) function;
00230 
00231     /*
00232      * Finally return the compiled function
00233      */
00234     return function;
00235 }
00236 
00237 /*
00238  * This is the slow part of plpgsql_compile().
00239  *
00240  * The passed-in "function" pointer is either NULL or an already-allocated
00241  * function struct to overwrite.
00242  *
00243  * While compiling a function, the CurrentMemoryContext is the
00244  * per-function memory context of the function we are compiling. That
00245  * means a palloc() will allocate storage with the same lifetime as
00246  * the function itself.
00247  *
00248  * Because palloc()'d storage will not be immediately freed, temporary
00249  * allocations should either be performed in a short-lived memory
00250  * context or explicitly pfree'd. Since not all backend functions are
00251  * careful about pfree'ing their allocations, it is also wise to
00252  * switch into a short-term context before calling into the
00253  * backend. An appropriate context for performing short-term
00254  * allocations is the compile_tmp_cxt.
00255  *
00256  * NB: this code is not re-entrant.  We assume that nothing we do here could
00257  * result in the invocation of another plpgsql function.
00258  */
00259 static PLpgSQL_function *
00260 do_compile(FunctionCallInfo fcinfo,
00261            HeapTuple procTup,
00262            PLpgSQL_function *function,
00263            PLpgSQL_func_hashkey *hashkey,
00264            bool forValidator)
00265 {
00266     Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
00267     bool        is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
00268     bool        is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
00269     Datum       prosrcdatum;
00270     bool        isnull;
00271     char       *proc_source;
00272     HeapTuple   typeTup;
00273     Form_pg_type typeStruct;
00274     PLpgSQL_variable *var;
00275     PLpgSQL_rec *rec;
00276     int         i;
00277     ErrorContextCallback plerrcontext;
00278     int         parse_rc;
00279     Oid         rettypeid;
00280     int         numargs;
00281     int         num_in_args = 0;
00282     int         num_out_args = 0;
00283     Oid        *argtypes;
00284     char      **argnames;
00285     char       *argmodes;
00286     int        *in_arg_varnos = NULL;
00287     PLpgSQL_variable **out_arg_variables;
00288     MemoryContext func_cxt;
00289 
00290     /*
00291      * Setup the scanner input and error info.  We assume that this function
00292      * cannot be invoked recursively, so there's no need to save and restore
00293      * the static variables used here.
00294      */
00295     prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
00296                                   Anum_pg_proc_prosrc, &isnull);
00297     if (isnull)
00298         elog(ERROR, "null prosrc");
00299     proc_source = TextDatumGetCString(prosrcdatum);
00300     plpgsql_scanner_init(proc_source);
00301 
00302     plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
00303 
00304     /*
00305      * Setup error traceback support for ereport()
00306      */
00307     plerrcontext.callback = plpgsql_compile_error_callback;
00308     plerrcontext.arg = forValidator ? proc_source : NULL;
00309     plerrcontext.previous = error_context_stack;
00310     error_context_stack = &plerrcontext;
00311 
00312     /*
00313      * Do extra syntax checks when validating the function definition. We skip
00314      * this when actually compiling functions for execution, for performance
00315      * reasons.
00316      */
00317     plpgsql_check_syntax = forValidator;
00318 
00319     /*
00320      * Create the new function struct, if not done already.  The function
00321      * structs are never thrown away, so keep them in TopMemoryContext.
00322      */
00323     if (function == NULL)
00324     {
00325         function = (PLpgSQL_function *)
00326             MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function));
00327     }
00328     else
00329     {
00330         /* re-using a previously existing struct, so clear it out */
00331         memset(function, 0, sizeof(PLpgSQL_function));
00332     }
00333     plpgsql_curr_compile = function;
00334 
00335     /*
00336      * All the permanent output of compilation (e.g. parse tree) is kept in a
00337      * per-function memory context, so it can be reclaimed easily.
00338      */
00339     func_cxt = AllocSetContextCreate(TopMemoryContext,
00340                                      "PL/pgSQL function context",
00341                                      ALLOCSET_DEFAULT_MINSIZE,
00342                                      ALLOCSET_DEFAULT_INITSIZE,
00343                                      ALLOCSET_DEFAULT_MAXSIZE);
00344     compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
00345 
00346     function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
00347     function->fn_oid = fcinfo->flinfo->fn_oid;
00348     function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
00349     function->fn_tid = procTup->t_self;
00350     function->fn_input_collation = fcinfo->fncollation;
00351     function->fn_cxt = func_cxt;
00352     function->out_param_varno = -1;     /* set up for no OUT param */
00353     function->resolve_option = plpgsql_variable_conflict;
00354 
00355     if (is_dml_trigger)
00356         function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
00357     else if (is_event_trigger)
00358         function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
00359     else
00360         function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
00361 
00362     /*
00363      * Initialize the compiler, particularly the namespace stack.  The
00364      * outermost namespace contains function parameters and other special
00365      * variables (such as FOUND), and is named after the function itself.
00366      */
00367     plpgsql_ns_init();
00368     plpgsql_ns_push(NameStr(procStruct->proname));
00369     plpgsql_DumpExecTree = false;
00370 
00371     datums_alloc = 128;
00372     plpgsql_nDatums = 0;
00373     /* This is short-lived, so needn't allocate in function's cxt */
00374     plpgsql_Datums = MemoryContextAlloc(compile_tmp_cxt,
00375                                      sizeof(PLpgSQL_datum *) * datums_alloc);
00376     datums_last = 0;
00377 
00378     switch (function->fn_is_trigger)
00379     {
00380         case PLPGSQL_NOT_TRIGGER:
00381 
00382             /*
00383              * Fetch info about the procedure's parameters. Allocations aren't
00384              * needed permanently, so make them in tmp cxt.
00385              *
00386              * We also need to resolve any polymorphic input or output
00387              * argument types.  In validation mode we won't be able to, so we
00388              * arbitrarily assume we are dealing with integers.
00389              */
00390             MemoryContextSwitchTo(compile_tmp_cxt);
00391 
00392             numargs = get_func_arg_info(procTup,
00393                                         &argtypes, &argnames, &argmodes);
00394 
00395             plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
00396                                                  fcinfo->flinfo->fn_expr,
00397                                                  forValidator,
00398                                                  plpgsql_error_funcname);
00399 
00400             in_arg_varnos = (int *) palloc(numargs * sizeof(int));
00401             out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
00402 
00403             MemoryContextSwitchTo(func_cxt);
00404 
00405             /*
00406              * Create the variables for the procedure's parameters.
00407              */
00408             for (i = 0; i < numargs; i++)
00409             {
00410                 char        buf[32];
00411                 Oid         argtypeid = argtypes[i];
00412                 char        argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
00413                 PLpgSQL_type *argdtype;
00414                 PLpgSQL_variable *argvariable;
00415                 int         argitemtype;
00416 
00417                 /* Create $n name for variable */
00418                 snprintf(buf, sizeof(buf), "$%d", i + 1);
00419 
00420                 /* Create datatype info */
00421                 argdtype = plpgsql_build_datatype(argtypeid,
00422                                                   -1,
00423                                                function->fn_input_collation);
00424 
00425                 /* Disallow pseudotype argument */
00426                 /* (note we already replaced polymorphic types) */
00427                 /* (build_variable would do this, but wrong message) */
00428                 if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
00429                     argdtype->ttype != PLPGSQL_TTYPE_ROW)
00430                     ereport(ERROR,
00431                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00432                            errmsg("PL/pgSQL functions cannot accept type %s",
00433                                   format_type_be(argtypeid))));
00434 
00435                 /* Build variable and add to datum list */
00436                 argvariable = plpgsql_build_variable(buf, 0,
00437                                                      argdtype, false);
00438 
00439                 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
00440                 {
00441                     argitemtype = PLPGSQL_NSTYPE_VAR;
00442                 }
00443                 else
00444                 {
00445                     Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
00446                     argitemtype = PLPGSQL_NSTYPE_ROW;
00447                 }
00448 
00449                 /* Remember arguments in appropriate arrays */
00450                 if (argmode == PROARGMODE_IN ||
00451                     argmode == PROARGMODE_INOUT ||
00452                     argmode == PROARGMODE_VARIADIC)
00453                     in_arg_varnos[num_in_args++] = argvariable->dno;
00454                 if (argmode == PROARGMODE_OUT ||
00455                     argmode == PROARGMODE_INOUT ||
00456                     argmode == PROARGMODE_TABLE)
00457                     out_arg_variables[num_out_args++] = argvariable;
00458 
00459                 /* Add to namespace under the $n name */
00460                 add_parameter_name(argitemtype, argvariable->dno, buf);
00461 
00462                 /* If there's a name for the argument, make an alias */
00463                 if (argnames && argnames[i][0] != '\0')
00464                     add_parameter_name(argitemtype, argvariable->dno,
00465                                        argnames[i]);
00466             }
00467 
00468             /*
00469              * If there's just one OUT parameter, out_param_varno points
00470              * directly to it.  If there's more than one, build a row that
00471              * holds all of them.
00472              */
00473             if (num_out_args == 1)
00474                 function->out_param_varno = out_arg_variables[0]->dno;
00475             else if (num_out_args > 1)
00476             {
00477                 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
00478                                                        num_out_args);
00479 
00480                 plpgsql_adddatum((PLpgSQL_datum *) row);
00481                 function->out_param_varno = row->dno;
00482             }
00483 
00484             /*
00485              * Check for a polymorphic returntype. If found, use the actual
00486              * returntype type from the caller's FuncExpr node, if we have
00487              * one.  (In validation mode we arbitrarily assume we are dealing
00488              * with integers.)
00489              *
00490              * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
00491              * work; if it doesn't we're in some context that fails to make
00492              * the info available.
00493              */
00494             rettypeid = procStruct->prorettype;
00495             if (IsPolymorphicType(rettypeid))
00496             {
00497                 if (forValidator)
00498                 {
00499                     if (rettypeid == ANYARRAYOID)
00500                         rettypeid = INT4ARRAYOID;
00501                     else if (rettypeid == ANYRANGEOID)
00502                         rettypeid = INT4RANGEOID;
00503                     else    /* ANYELEMENT or ANYNONARRAY */
00504                         rettypeid = INT4OID;
00505                     /* XXX what could we use for ANYENUM? */
00506                 }
00507                 else
00508                 {
00509                     rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
00510                     if (!OidIsValid(rettypeid))
00511                         ereport(ERROR,
00512                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00513                              errmsg("could not determine actual return type "
00514                                     "for polymorphic function \"%s\"",
00515                                     plpgsql_error_funcname)));
00516                 }
00517             }
00518 
00519             /*
00520              * Normal function has a defined returntype
00521              */
00522             function->fn_rettype = rettypeid;
00523             function->fn_retset = procStruct->proretset;
00524 
00525             /*
00526              * Lookup the function's return type
00527              */
00528             typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
00529             if (!HeapTupleIsValid(typeTup))
00530                 elog(ERROR, "cache lookup failed for type %u", rettypeid);
00531             typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
00532 
00533             /* Disallow pseudotype result, except VOID or RECORD */
00534             /* (note we already replaced polymorphic types) */
00535             if (typeStruct->typtype == TYPTYPE_PSEUDO)
00536             {
00537                 if (rettypeid == VOIDOID ||
00538                     rettypeid == RECORDOID)
00539                      /* okay */ ;
00540                 else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
00541                     ereport(ERROR,
00542                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00543                              errmsg("trigger functions can only be called as triggers")));
00544                 else
00545                     ereport(ERROR,
00546                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00547                            errmsg("PL/pgSQL functions cannot return type %s",
00548                                   format_type_be(rettypeid))));
00549             }
00550 
00551             if (typeStruct->typrelid != InvalidOid ||
00552                 rettypeid == RECORDOID)
00553                 function->fn_retistuple = true;
00554             else
00555             {
00556                 function->fn_retbyval = typeStruct->typbyval;
00557                 function->fn_rettyplen = typeStruct->typlen;
00558                 function->fn_rettypioparam = getTypeIOParam(typeTup);
00559                 fmgr_info(typeStruct->typinput, &(function->fn_retinput));
00560 
00561                 /*
00562                  * install $0 reference, but only for polymorphic return
00563                  * types, and not when the return is specified through an
00564                  * output parameter.
00565                  */
00566                 if (IsPolymorphicType(procStruct->prorettype) &&
00567                     num_out_args == 0)
00568                 {
00569                     (void) plpgsql_build_variable("$0", 0,
00570                                                   build_datatype(typeTup,
00571                                                                  -1,
00572                                                function->fn_input_collation),
00573                                                   true);
00574                 }
00575             }
00576             ReleaseSysCache(typeTup);
00577             break;
00578 
00579         case PLPGSQL_DML_TRIGGER:
00580             /* Trigger procedure's return type is unknown yet */
00581             function->fn_rettype = InvalidOid;
00582             function->fn_retbyval = false;
00583             function->fn_retistuple = true;
00584             function->fn_retset = false;
00585 
00586             /* shouldn't be any declared arguments */
00587             if (procStruct->pronargs != 0)
00588                 ereport(ERROR,
00589                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00590                   errmsg("trigger functions cannot have declared arguments"),
00591                          errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
00592 
00593             /* Add the record for referencing NEW */
00594             rec = plpgsql_build_record("new", 0, true);
00595             function->new_varno = rec->dno;
00596 
00597             /* Add the record for referencing OLD */
00598             rec = plpgsql_build_record("old", 0, true);
00599             function->old_varno = rec->dno;
00600 
00601             /* Add the variable tg_name */
00602             var = plpgsql_build_variable("tg_name", 0,
00603                                          plpgsql_build_datatype(NAMEOID,
00604                                                                 -1,
00605                                                                 InvalidOid),
00606                                          true);
00607             function->tg_name_varno = var->dno;
00608 
00609             /* Add the variable tg_when */
00610             var = plpgsql_build_variable("tg_when", 0,
00611                                          plpgsql_build_datatype(TEXTOID,
00612                                                                 -1,
00613                                                function->fn_input_collation),
00614                                          true);
00615             function->tg_when_varno = var->dno;
00616 
00617             /* Add the variable tg_level */
00618             var = plpgsql_build_variable("tg_level", 0,
00619                                          plpgsql_build_datatype(TEXTOID,
00620                                                                 -1,
00621                                                function->fn_input_collation),
00622                                          true);
00623             function->tg_level_varno = var->dno;
00624 
00625             /* Add the variable tg_op */
00626             var = plpgsql_build_variable("tg_op", 0,
00627                                          plpgsql_build_datatype(TEXTOID,
00628                                                                 -1,
00629                                                function->fn_input_collation),
00630                                          true);
00631             function->tg_op_varno = var->dno;
00632 
00633             /* Add the variable tg_relid */
00634             var = plpgsql_build_variable("tg_relid", 0,
00635                                          plpgsql_build_datatype(OIDOID,
00636                                                                 -1,
00637                                                                 InvalidOid),
00638                                          true);
00639             function->tg_relid_varno = var->dno;
00640 
00641             /* Add the variable tg_relname */
00642             var = plpgsql_build_variable("tg_relname", 0,
00643                                          plpgsql_build_datatype(NAMEOID,
00644                                                                 -1,
00645                                                                 InvalidOid),
00646                                          true);
00647             function->tg_relname_varno = var->dno;
00648 
00649             /* tg_table_name is now preferred to tg_relname */
00650             var = plpgsql_build_variable("tg_table_name", 0,
00651                                          plpgsql_build_datatype(NAMEOID,
00652                                                                 -1,
00653                                                                 InvalidOid),
00654                                          true);
00655             function->tg_table_name_varno = var->dno;
00656 
00657             /* add the variable tg_table_schema */
00658             var = plpgsql_build_variable("tg_table_schema", 0,
00659                                          plpgsql_build_datatype(NAMEOID,
00660                                                                 -1,
00661                                                                 InvalidOid),
00662                                          true);
00663             function->tg_table_schema_varno = var->dno;
00664 
00665             /* Add the variable tg_nargs */
00666             var = plpgsql_build_variable("tg_nargs", 0,
00667                                          plpgsql_build_datatype(INT4OID,
00668                                                                 -1,
00669                                                                 InvalidOid),
00670                                          true);
00671             function->tg_nargs_varno = var->dno;
00672 
00673             /* Add the variable tg_argv */
00674             var = plpgsql_build_variable("tg_argv", 0,
00675                                          plpgsql_build_datatype(TEXTARRAYOID,
00676                                                                 -1,
00677                                                function->fn_input_collation),
00678                                          true);
00679             function->tg_argv_varno = var->dno;
00680 
00681             break;
00682 
00683         case PLPGSQL_EVENT_TRIGGER:
00684             function->fn_rettype = VOIDOID;
00685             function->fn_retbyval = false;
00686             function->fn_retistuple = true;
00687             function->fn_retset = false;
00688 
00689             /* shouldn't be any declared arguments */
00690             if (procStruct->pronargs != 0)
00691                 ereport(ERROR,
00692                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00693                          errmsg("event trigger functions cannot have declared arguments")));
00694 
00695             /* Add the variable tg_event */
00696             var = plpgsql_build_variable("tg_event", 0,
00697                                          plpgsql_build_datatype(TEXTOID,
00698                                                                 -1,
00699                                                function->fn_input_collation),
00700                                          true);
00701             function->tg_event_varno = var->dno;
00702 
00703             /* Add the variable tg_tag */
00704             var = plpgsql_build_variable("tg_tag", 0,
00705                                          plpgsql_build_datatype(TEXTOID,
00706                                                                 -1,
00707                                                function->fn_input_collation),
00708                                          true);
00709             function->tg_tag_varno = var->dno;
00710 
00711             break;
00712 
00713         default:
00714             elog(ERROR, "unrecognized function typecode: %d",
00715                  (int) function->fn_is_trigger);
00716             break;
00717     }
00718 
00719     /* Remember if function is STABLE/IMMUTABLE */
00720     function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
00721 
00722     /*
00723      * Create the magic FOUND variable.
00724      */
00725     var = plpgsql_build_variable("found", 0,
00726                                  plpgsql_build_datatype(BOOLOID,
00727                                                         -1,
00728                                                         InvalidOid),
00729                                  true);
00730     function->found_varno = var->dno;
00731 
00732     /*
00733      * Now parse the function's text
00734      */
00735     parse_rc = plpgsql_yyparse();
00736     if (parse_rc != 0)
00737         elog(ERROR, "plpgsql parser returned %d", parse_rc);
00738     function->action = plpgsql_parse_result;
00739 
00740     plpgsql_scanner_finish();
00741     pfree(proc_source);
00742 
00743     /*
00744      * If it has OUT parameters or returns VOID or returns a set, we allow
00745      * control to fall off the end without an explicit RETURN statement. The
00746      * easiest way to implement this is to add a RETURN statement to the end
00747      * of the statement list during parsing.
00748      */
00749     if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
00750         function->fn_retset)
00751         add_dummy_return(function);
00752 
00753     /*
00754      * Complete the function's info
00755      */
00756     function->fn_nargs = procStruct->pronargs;
00757     for (i = 0; i < function->fn_nargs; i++)
00758         function->fn_argvarnos[i] = in_arg_varnos[i];
00759     function->ndatums = plpgsql_nDatums;
00760     function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
00761     for (i = 0; i < plpgsql_nDatums; i++)
00762         function->datums[i] = plpgsql_Datums[i];
00763 
00764     /* Debug dump for completed functions */
00765     if (plpgsql_DumpExecTree)
00766         plpgsql_dumptree(function);
00767 
00768     /*
00769      * add it to the hash table
00770      */
00771     plpgsql_HashTableInsert(function, hashkey);
00772 
00773     /*
00774      * Pop the error context stack
00775      */
00776     error_context_stack = plerrcontext.previous;
00777     plpgsql_error_funcname = NULL;
00778 
00779     plpgsql_check_syntax = false;
00780 
00781     MemoryContextSwitchTo(compile_tmp_cxt);
00782     compile_tmp_cxt = NULL;
00783     return function;
00784 }
00785 
00786 /* ----------
00787  * plpgsql_compile_inline   Make an execution tree for an anonymous code block.
00788  *
00789  * Note: this is generally parallel to do_compile(); is it worth trying to
00790  * merge the two?
00791  *
00792  * Note: we assume the block will be thrown away so there is no need to build
00793  * persistent data structures.
00794  * ----------
00795  */
00796 PLpgSQL_function *
00797 plpgsql_compile_inline(char *proc_source)
00798 {
00799     char       *func_name = "inline_code_block";
00800     PLpgSQL_function *function;
00801     ErrorContextCallback plerrcontext;
00802     Oid         typinput;
00803     PLpgSQL_variable *var;
00804     int         parse_rc;
00805     MemoryContext func_cxt;
00806     int         i;
00807 
00808     /*
00809      * Setup the scanner input and error info.  We assume that this function
00810      * cannot be invoked recursively, so there's no need to save and restore
00811      * the static variables used here.
00812      */
00813     plpgsql_scanner_init(proc_source);
00814 
00815     plpgsql_error_funcname = func_name;
00816 
00817     /*
00818      * Setup error traceback support for ereport()
00819      */
00820     plerrcontext.callback = plpgsql_compile_error_callback;
00821     plerrcontext.arg = proc_source;
00822     plerrcontext.previous = error_context_stack;
00823     error_context_stack = &plerrcontext;
00824 
00825     /* Do extra syntax checking if check_function_bodies is on */
00826     plpgsql_check_syntax = check_function_bodies;
00827 
00828     /* Function struct does not live past current statement */
00829     function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
00830 
00831     plpgsql_curr_compile = function;
00832 
00833     /*
00834      * All the rest of the compile-time storage (e.g. parse tree) is kept in
00835      * its own memory context, so it can be reclaimed easily.
00836      */
00837     func_cxt = AllocSetContextCreate(CurrentMemoryContext,
00838                                      "PL/pgSQL function context",
00839                                      ALLOCSET_DEFAULT_MINSIZE,
00840                                      ALLOCSET_DEFAULT_INITSIZE,
00841                                      ALLOCSET_DEFAULT_MAXSIZE);
00842     compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
00843 
00844     function->fn_signature = pstrdup(func_name);
00845     function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
00846     function->fn_input_collation = InvalidOid;
00847     function->fn_cxt = func_cxt;
00848     function->out_param_varno = -1;     /* set up for no OUT param */
00849     function->resolve_option = plpgsql_variable_conflict;
00850 
00851     plpgsql_ns_init();
00852     plpgsql_ns_push(func_name);
00853     plpgsql_DumpExecTree = false;
00854 
00855     datums_alloc = 128;
00856     plpgsql_nDatums = 0;
00857     plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
00858     datums_last = 0;
00859 
00860     /* Set up as though in a function returning VOID */
00861     function->fn_rettype = VOIDOID;
00862     function->fn_retset = false;
00863     function->fn_retistuple = false;
00864     /* a bit of hardwired knowledge about type VOID here */
00865     function->fn_retbyval = true;
00866     function->fn_rettyplen = sizeof(int32);
00867     getTypeInputInfo(VOIDOID, &typinput, &function->fn_rettypioparam);
00868     fmgr_info(typinput, &(function->fn_retinput));
00869 
00870     /*
00871      * Remember if function is STABLE/IMMUTABLE.  XXX would it be better to
00872      * set this TRUE inside a read-only transaction?  Not clear.
00873      */
00874     function->fn_readonly = false;
00875 
00876     /*
00877      * Create the magic FOUND variable.
00878      */
00879     var = plpgsql_build_variable("found", 0,
00880                                  plpgsql_build_datatype(BOOLOID,
00881                                                         -1,
00882                                                         InvalidOid),
00883                                  true);
00884     function->found_varno = var->dno;
00885 
00886     /*
00887      * Now parse the function's text
00888      */
00889     parse_rc = plpgsql_yyparse();
00890     if (parse_rc != 0)
00891         elog(ERROR, "plpgsql parser returned %d", parse_rc);
00892     function->action = plpgsql_parse_result;
00893 
00894     plpgsql_scanner_finish();
00895 
00896     /*
00897      * If it returns VOID (always true at the moment), we allow control to
00898      * fall off the end without an explicit RETURN statement.
00899      */
00900     if (function->fn_rettype == VOIDOID)
00901         add_dummy_return(function);
00902 
00903     /*
00904      * Complete the function's info
00905      */
00906     function->fn_nargs = 0;
00907     function->ndatums = plpgsql_nDatums;
00908     function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
00909     for (i = 0; i < plpgsql_nDatums; i++)
00910         function->datums[i] = plpgsql_Datums[i];
00911 
00912     /*
00913      * Pop the error context stack
00914      */
00915     error_context_stack = plerrcontext.previous;
00916     plpgsql_error_funcname = NULL;
00917 
00918     plpgsql_check_syntax = false;
00919 
00920     MemoryContextSwitchTo(compile_tmp_cxt);
00921     compile_tmp_cxt = NULL;
00922     return function;
00923 }
00924 
00925 
00926 /*
00927  * error context callback to let us supply a call-stack traceback.
00928  * If we are validating or executing an anonymous code block, the function
00929  * source text is passed as an argument.
00930  */
00931 static void
00932 plpgsql_compile_error_callback(void *arg)
00933 {
00934     if (arg)
00935     {
00936         /*
00937          * Try to convert syntax error position to reference text of original
00938          * CREATE FUNCTION or DO command.
00939          */
00940         if (function_parse_error_transpose((const char *) arg))
00941             return;
00942 
00943         /*
00944          * Done if a syntax error position was reported; otherwise we have to
00945          * fall back to a "near line N" report.
00946          */
00947     }
00948 
00949     if (plpgsql_error_funcname)
00950         errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
00951                    plpgsql_error_funcname, plpgsql_latest_lineno());
00952 }
00953 
00954 
00955 /*
00956  * Add a name for a function parameter to the function's namespace
00957  */
00958 static void
00959 add_parameter_name(int itemtype, int itemno, const char *name)
00960 {
00961     /*
00962      * Before adding the name, check for duplicates.  We need this even though
00963      * functioncmds.c has a similar check, because that code explicitly
00964      * doesn't complain about conflicting IN and OUT parameter names.  In
00965      * plpgsql, such names are in the same namespace, so there is no way to
00966      * disambiguate.
00967      */
00968     if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
00969                           name, NULL, NULL,
00970                           NULL) != NULL)
00971         ereport(ERROR,
00972                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
00973                  errmsg("parameter name \"%s\" used more than once",
00974                         name)));
00975 
00976     /* OK, add the name */
00977     plpgsql_ns_additem(itemtype, itemno, name);
00978 }
00979 
00980 /*
00981  * Add a dummy RETURN statement to the given function's body
00982  */
00983 static void
00984 add_dummy_return(PLpgSQL_function *function)
00985 {
00986     /*
00987      * If the outer block has an EXCEPTION clause, we need to make a new outer
00988      * block, since the added RETURN shouldn't act like it is inside the
00989      * EXCEPTION clause.
00990      */
00991     if (function->action->exceptions != NULL)
00992     {
00993         PLpgSQL_stmt_block *new;
00994 
00995         new = palloc0(sizeof(PLpgSQL_stmt_block));
00996         new->cmd_type = PLPGSQL_STMT_BLOCK;
00997         new->body = list_make1(function->action);
00998 
00999         function->action = new;
01000     }
01001     if (function->action->body == NIL ||
01002         ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
01003     {
01004         PLpgSQL_stmt_return *new;
01005 
01006         new = palloc0(sizeof(PLpgSQL_stmt_return));
01007         new->cmd_type = PLPGSQL_STMT_RETURN;
01008         new->expr = NULL;
01009         new->retvarno = function->out_param_varno;
01010 
01011         function->action->body = lappend(function->action->body, new);
01012     }
01013 }
01014 
01015 
01016 /*
01017  * plpgsql_parser_setup     set up parser hooks for dynamic parameters
01018  *
01019  * Note: this routine, and the hook functions it prepares for, are logically
01020  * part of plpgsql parsing.  But they actually run during function execution,
01021  * when we are ready to evaluate a SQL query or expression that has not
01022  * previously been parsed and planned.
01023  */
01024 void
01025 plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
01026 {
01027     pstate->p_pre_columnref_hook = plpgsql_pre_column_ref;
01028     pstate->p_post_columnref_hook = plpgsql_post_column_ref;
01029     pstate->p_paramref_hook = plpgsql_param_ref;
01030     /* no need to use p_coerce_param_hook */
01031     pstate->p_ref_hook_state = (void *) expr;
01032 }
01033 
01034 /*
01035  * plpgsql_pre_column_ref       parser callback before parsing a ColumnRef
01036  */
01037 static Node *
01038 plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
01039 {
01040     PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
01041 
01042     if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
01043         return resolve_column_ref(pstate, expr, cref, false);
01044     else
01045         return NULL;
01046 }
01047 
01048 /*
01049  * plpgsql_post_column_ref      parser callback after parsing a ColumnRef
01050  */
01051 static Node *
01052 plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
01053 {
01054     PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
01055     Node       *myvar;
01056 
01057     if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
01058         return NULL;            /* we already found there's no match */
01059 
01060     if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
01061         return NULL;            /* there's a table column, prefer that */
01062 
01063     /*
01064      * If we find a record/row variable but can't match a field name, throw
01065      * error if there was no core resolution for the ColumnRef either.  In
01066      * that situation, the reference is inevitably going to fail, and
01067      * complaining about the record/row variable is likely to be more on-point
01068      * than the core parser's error message.  (It's too bad we don't have
01069      * access to transformColumnRef's internal crerr state here, as in case of
01070      * a conflict with a table name this could still be less than the most
01071      * helpful error message possible.)
01072      */
01073     myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
01074 
01075     if (myvar != NULL && var != NULL)
01076     {
01077         /*
01078          * We could leave it to the core parser to throw this error, but we
01079          * can add a more useful detail message than the core could.
01080          */
01081         ereport(ERROR,
01082                 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
01083                  errmsg("column reference \"%s\" is ambiguous",
01084                         NameListToString(cref->fields)),
01085                  errdetail("It could refer to either a PL/pgSQL variable or a table column."),
01086                  parser_errposition(pstate, cref->location)));
01087     }
01088 
01089     return myvar;
01090 }
01091 
01092 /*
01093  * plpgsql_param_ref        parser callback for ParamRefs ($n symbols)
01094  */
01095 static Node *
01096 plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
01097 {
01098     PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
01099     char        pname[32];
01100     PLpgSQL_nsitem *nse;
01101 
01102     snprintf(pname, sizeof(pname), "$%d", pref->number);
01103 
01104     nse = plpgsql_ns_lookup(expr->ns, false,
01105                             pname, NULL, NULL,
01106                             NULL);
01107 
01108     if (nse == NULL)
01109         return NULL;            /* name not known to plpgsql */
01110 
01111     return make_datum_param(expr, nse->itemno, pref->location);
01112 }
01113 
01114 /*
01115  * resolve_column_ref       attempt to resolve a ColumnRef as a plpgsql var
01116  *
01117  * Returns the translated node structure, or NULL if name not found
01118  *
01119  * error_if_no_field tells whether to throw error or quietly return NULL if
01120  * we are able to match a record/row name but don't find a field name match.
01121  */
01122 static Node *
01123 resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
01124                    ColumnRef *cref, bool error_if_no_field)
01125 {
01126     PLpgSQL_execstate *estate;
01127     PLpgSQL_nsitem *nse;
01128     const char *name1;
01129     const char *name2 = NULL;
01130     const char *name3 = NULL;
01131     const char *colname = NULL;
01132     int         nnames;
01133     int         nnames_scalar = 0;
01134     int         nnames_wholerow = 0;
01135     int         nnames_field = 0;
01136 
01137     /*
01138      * We use the function's current estate to resolve parameter data types.
01139      * This is really pretty bogus because there is no provision for updating
01140      * plans when those types change ...
01141      */
01142     estate = expr->func->cur_estate;
01143 
01144     /*----------
01145      * The allowed syntaxes are:
01146      *
01147      * A        Scalar variable reference, or whole-row record reference.
01148      * A.B      Qualified scalar or whole-row reference, or field reference.
01149      * A.B.C    Qualified record field reference.
01150      * A.*      Whole-row record reference.
01151      * A.B.*    Qualified whole-row record reference.
01152      *----------
01153      */
01154     switch (list_length(cref->fields))
01155     {
01156         case 1:
01157             {
01158                 Node       *field1 = (Node *) linitial(cref->fields);
01159 
01160                 Assert(IsA(field1, String));
01161                 name1 = strVal(field1);
01162                 nnames_scalar = 1;
01163                 nnames_wholerow = 1;
01164                 break;
01165             }
01166         case 2:
01167             {
01168                 Node       *field1 = (Node *) linitial(cref->fields);
01169                 Node       *field2 = (Node *) lsecond(cref->fields);
01170 
01171                 Assert(IsA(field1, String));
01172                 name1 = strVal(field1);
01173 
01174                 /* Whole-row reference? */
01175                 if (IsA(field2, A_Star))
01176                 {
01177                     /* Set name2 to prevent matches to scalar variables */
01178                     name2 = "*";
01179                     nnames_wholerow = 1;
01180                     break;
01181                 }
01182 
01183                 Assert(IsA(field2, String));
01184                 name2 = strVal(field2);
01185                 colname = name2;
01186                 nnames_scalar = 2;
01187                 nnames_wholerow = 2;
01188                 nnames_field = 1;
01189                 break;
01190             }
01191         case 3:
01192             {
01193                 Node       *field1 = (Node *) linitial(cref->fields);
01194                 Node       *field2 = (Node *) lsecond(cref->fields);
01195                 Node       *field3 = (Node *) lthird(cref->fields);
01196 
01197                 Assert(IsA(field1, String));
01198                 name1 = strVal(field1);
01199                 Assert(IsA(field2, String));
01200                 name2 = strVal(field2);
01201 
01202                 /* Whole-row reference? */
01203                 if (IsA(field3, A_Star))
01204                 {
01205                     /* Set name3 to prevent matches to scalar variables */
01206                     name3 = "*";
01207                     nnames_wholerow = 2;
01208                     break;
01209                 }
01210 
01211                 Assert(IsA(field3, String));
01212                 name3 = strVal(field3);
01213                 colname = name3;
01214                 nnames_field = 2;
01215                 break;
01216             }
01217         default:
01218             /* too many names, ignore */
01219             return NULL;
01220     }
01221 
01222     nse = plpgsql_ns_lookup(expr->ns, false,
01223                             name1, name2, name3,
01224                             &nnames);
01225 
01226     if (nse == NULL)
01227         return NULL;            /* name not known to plpgsql */
01228 
01229     switch (nse->itemtype)
01230     {
01231         case PLPGSQL_NSTYPE_VAR:
01232             if (nnames == nnames_scalar)
01233                 return make_datum_param(expr, nse->itemno, cref->location);
01234             break;
01235         case PLPGSQL_NSTYPE_REC:
01236             if (nnames == nnames_wholerow)
01237                 return make_datum_param(expr, nse->itemno, cref->location);
01238             if (nnames == nnames_field)
01239             {
01240                 /* colname could be a field in this record */
01241                 int         i;
01242 
01243                 /* search for a datum referencing this field */
01244                 for (i = 0; i < estate->ndatums; i++)
01245                 {
01246                     PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
01247 
01248                     if (fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
01249                         fld->recparentno == nse->itemno &&
01250                         strcmp(fld->fieldname, colname) == 0)
01251                     {
01252                         return make_datum_param(expr, i, cref->location);
01253                     }
01254                 }
01255 
01256                 /*
01257                  * We should not get here, because a RECFIELD datum should
01258                  * have been built at parse time for every possible qualified
01259                  * reference to fields of this record.  But if we do, handle
01260                  * it like field-not-found: throw error or return NULL.
01261                  */
01262                 if (error_if_no_field)
01263                     ereport(ERROR,
01264                             (errcode(ERRCODE_UNDEFINED_COLUMN),
01265                              errmsg("record \"%s\" has no field \"%s\"",
01266                                     (nnames_field == 1) ? name1 : name2,
01267                                     colname),
01268                              parser_errposition(pstate, cref->location)));
01269             }
01270             break;
01271         case PLPGSQL_NSTYPE_ROW:
01272             if (nnames == nnames_wholerow)
01273                 return make_datum_param(expr, nse->itemno, cref->location);
01274             if (nnames == nnames_field)
01275             {
01276                 /* colname could be a field in this row */
01277                 PLpgSQL_row *row = (PLpgSQL_row *) estate->datums[nse->itemno];
01278                 int         i;
01279 
01280                 for (i = 0; i < row->nfields; i++)
01281                 {
01282                     if (row->fieldnames[i] &&
01283                         strcmp(row->fieldnames[i], colname) == 0)
01284                     {
01285                         return make_datum_param(expr, row->varnos[i],
01286                                                 cref->location);
01287                     }
01288                 }
01289                 /* Not found, so throw error or return NULL */
01290                 if (error_if_no_field)
01291                     ereport(ERROR,
01292                             (errcode(ERRCODE_UNDEFINED_COLUMN),
01293                              errmsg("record \"%s\" has no field \"%s\"",
01294                                     (nnames_field == 1) ? name1 : name2,
01295                                     colname),
01296                              parser_errposition(pstate, cref->location)));
01297             }
01298             break;
01299         default:
01300             elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
01301     }
01302 
01303     /* Name format doesn't match the plpgsql variable type */
01304     return NULL;
01305 }
01306 
01307 /*
01308  * Helper for columnref parsing: build a Param referencing a plpgsql datum,
01309  * and make sure that that datum is listed in the expression's paramnos.
01310  */
01311 static Node *
01312 make_datum_param(PLpgSQL_expr *expr, int dno, int location)
01313 {
01314     PLpgSQL_execstate *estate;
01315     PLpgSQL_datum *datum;
01316     Param      *param;
01317     MemoryContext oldcontext;
01318 
01319     /* see comment in resolve_column_ref */
01320     estate = expr->func->cur_estate;
01321     Assert(dno >= 0 && dno < estate->ndatums);
01322     datum = estate->datums[dno];
01323 
01324     /*
01325      * Bitmapset must be allocated in function's permanent memory context
01326      */
01327     oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
01328     expr->paramnos = bms_add_member(expr->paramnos, dno);
01329     MemoryContextSwitchTo(oldcontext);
01330 
01331     param = makeNode(Param);
01332     param->paramkind = PARAM_EXTERN;
01333     param->paramid = dno + 1;
01334     exec_get_datum_type_info(estate,
01335                              datum,
01336                              &param->paramtype,
01337                              &param->paramtypmod,
01338                              &param->paramcollid);
01339     param->location = location;
01340 
01341     return (Node *) param;
01342 }
01343 
01344 
01345 /* ----------
01346  * plpgsql_parse_word       The scanner calls this to postparse
01347  *              any single word that is not a reserved keyword.
01348  *
01349  * word1 is the downcased/dequoted identifier; it must be palloc'd in the
01350  * function's long-term memory context.
01351  *
01352  * yytxt is the original token text; we need this to check for quoting,
01353  * so that later checks for unreserved keywords work properly.
01354  *
01355  * If recognized as a variable, fill in *wdatum and return TRUE;
01356  * if not recognized, fill in *word and return FALSE.
01357  * (Note: those two pointers actually point to members of the same union,
01358  * but for notational reasons we pass them separately.)
01359  * ----------
01360  */
01361 bool
01362 plpgsql_parse_word(char *word1, const char *yytxt,
01363                    PLwdatum *wdatum, PLword *word)
01364 {
01365     PLpgSQL_nsitem *ns;
01366 
01367     /*
01368      * We should do nothing in DECLARE sections.  In SQL expressions, there's
01369      * no need to do anything either --- lookup will happen when the
01370      * expression is compiled.
01371      */
01372     if (plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
01373     {
01374         /*
01375          * Do a lookup in the current namespace stack
01376          */
01377         ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
01378                                word1, NULL, NULL,
01379                                NULL);
01380 
01381         if (ns != NULL)
01382         {
01383             switch (ns->itemtype)
01384             {
01385                 case PLPGSQL_NSTYPE_VAR:
01386                 case PLPGSQL_NSTYPE_ROW:
01387                 case PLPGSQL_NSTYPE_REC:
01388                     wdatum->datum = plpgsql_Datums[ns->itemno];
01389                     wdatum->ident = word1;
01390                     wdatum->quoted = (yytxt[0] == '"');
01391                     wdatum->idents = NIL;
01392                     return true;
01393 
01394                 default:
01395                     /* plpgsql_ns_lookup should never return anything else */
01396                     elog(ERROR, "unrecognized plpgsql itemtype: %d",
01397                          ns->itemtype);
01398             }
01399         }
01400     }
01401 
01402     /*
01403      * Nothing found - up to now it's a word without any special meaning for
01404      * us.
01405      */
01406     word->ident = word1;
01407     word->quoted = (yytxt[0] == '"');
01408     return false;
01409 }
01410 
01411 
01412 /* ----------
01413  * plpgsql_parse_dblword        Same lookup for two words
01414  *                  separated by a dot.
01415  * ----------
01416  */
01417 bool
01418 plpgsql_parse_dblword(char *word1, char *word2,
01419                       PLwdatum *wdatum, PLcword *cword)
01420 {
01421     PLpgSQL_nsitem *ns;
01422     List       *idents;
01423     int         nnames;
01424 
01425     idents = list_make2(makeString(word1),
01426                         makeString(word2));
01427 
01428     /*
01429      * We should do nothing in DECLARE sections.  In SQL expressions, we
01430      * really only need to make sure that RECFIELD datums are created when
01431      * needed.
01432      */
01433     if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
01434     {
01435         /*
01436          * Do a lookup in the current namespace stack
01437          */
01438         ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
01439                                word1, word2, NULL,
01440                                &nnames);
01441         if (ns != NULL)
01442         {
01443             switch (ns->itemtype)
01444             {
01445                 case PLPGSQL_NSTYPE_VAR:
01446                     /* Block-qualified reference to scalar variable. */
01447                     wdatum->datum = plpgsql_Datums[ns->itemno];
01448                     wdatum->ident = NULL;
01449                     wdatum->quoted = false;     /* not used */
01450                     wdatum->idents = idents;
01451                     return true;
01452 
01453                 case PLPGSQL_NSTYPE_REC:
01454                     if (nnames == 1)
01455                     {
01456                         /*
01457                          * First word is a record name, so second word could
01458                          * be a field in this record.  We build a RECFIELD
01459                          * datum whether it is or not --- any error will be
01460                          * detected later.
01461                          */
01462                         PLpgSQL_recfield *new;
01463 
01464                         new = palloc(sizeof(PLpgSQL_recfield));
01465                         new->dtype = PLPGSQL_DTYPE_RECFIELD;
01466                         new->fieldname = pstrdup(word2);
01467                         new->recparentno = ns->itemno;
01468 
01469                         plpgsql_adddatum((PLpgSQL_datum *) new);
01470 
01471                         wdatum->datum = (PLpgSQL_datum *) new;
01472                     }
01473                     else
01474                     {
01475                         /* Block-qualified reference to record variable. */
01476                         wdatum->datum = plpgsql_Datums[ns->itemno];
01477                     }
01478                     wdatum->ident = NULL;
01479                     wdatum->quoted = false;     /* not used */
01480                     wdatum->idents = idents;
01481                     return true;
01482 
01483                 case PLPGSQL_NSTYPE_ROW:
01484                     if (nnames == 1)
01485                     {
01486                         /*
01487                          * First word is a row name, so second word could be a
01488                          * field in this row.  Again, no error now if it
01489                          * isn't.
01490                          */
01491                         PLpgSQL_row *row;
01492                         int         i;
01493 
01494                         row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
01495                         for (i = 0; i < row->nfields; i++)
01496                         {
01497                             if (row->fieldnames[i] &&
01498                                 strcmp(row->fieldnames[i], word2) == 0)
01499                             {
01500                                 wdatum->datum = plpgsql_Datums[row->varnos[i]];
01501                                 wdatum->ident = NULL;
01502                                 wdatum->quoted = false; /* not used */
01503                                 wdatum->idents = idents;
01504                                 return true;
01505                             }
01506                         }
01507                         /* fall through to return CWORD */
01508                     }
01509                     else
01510                     {
01511                         /* Block-qualified reference to row variable. */
01512                         wdatum->datum = plpgsql_Datums[ns->itemno];
01513                         wdatum->ident = NULL;
01514                         wdatum->quoted = false; /* not used */
01515                         wdatum->idents = idents;
01516                         return true;
01517                     }
01518                     break;
01519 
01520                 default:
01521                     break;
01522             }
01523         }
01524     }
01525 
01526     /* Nothing found */
01527     cword->idents = idents;
01528     return false;
01529 }
01530 
01531 
01532 /* ----------
01533  * plpgsql_parse_tripword       Same lookup for three words
01534  *                  separated by dots.
01535  * ----------
01536  */
01537 bool
01538 plpgsql_parse_tripword(char *word1, char *word2, char *word3,
01539                        PLwdatum *wdatum, PLcword *cword)
01540 {
01541     PLpgSQL_nsitem *ns;
01542     List       *idents;
01543     int         nnames;
01544 
01545     idents = list_make3(makeString(word1),
01546                         makeString(word2),
01547                         makeString(word3));
01548 
01549     /*
01550      * We should do nothing in DECLARE sections.  In SQL expressions, we
01551      * really only need to make sure that RECFIELD datums are created when
01552      * needed.
01553      */
01554     if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
01555     {
01556         /*
01557          * Do a lookup in the current namespace stack. Must find a qualified
01558          * reference, else ignore.
01559          */
01560         ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
01561                                word1, word2, word3,
01562                                &nnames);
01563         if (ns != NULL && nnames == 2)
01564         {
01565             switch (ns->itemtype)
01566             {
01567                 case PLPGSQL_NSTYPE_REC:
01568                     {
01569                         /*
01570                          * words 1/2 are a record name, so third word could be
01571                          * a field in this record.
01572                          */
01573                         PLpgSQL_recfield *new;
01574 
01575                         new = palloc(sizeof(PLpgSQL_recfield));
01576                         new->dtype = PLPGSQL_DTYPE_RECFIELD;
01577                         new->fieldname = pstrdup(word3);
01578                         new->recparentno = ns->itemno;
01579 
01580                         plpgsql_adddatum((PLpgSQL_datum *) new);
01581 
01582                         wdatum->datum = (PLpgSQL_datum *) new;
01583                         wdatum->ident = NULL;
01584                         wdatum->quoted = false; /* not used */
01585                         wdatum->idents = idents;
01586                         return true;
01587                     }
01588 
01589                 case PLPGSQL_NSTYPE_ROW:
01590                     {
01591                         /*
01592                          * words 1/2 are a row name, so third word could be a
01593                          * field in this row.
01594                          */
01595                         PLpgSQL_row *row;
01596                         int         i;
01597 
01598                         row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
01599                         for (i = 0; i < row->nfields; i++)
01600                         {
01601                             if (row->fieldnames[i] &&
01602                                 strcmp(row->fieldnames[i], word3) == 0)
01603                             {
01604                                 wdatum->datum = plpgsql_Datums[row->varnos[i]];
01605                                 wdatum->ident = NULL;
01606                                 wdatum->quoted = false; /* not used */
01607                                 wdatum->idents = idents;
01608                                 return true;
01609                             }
01610                         }
01611                         /* fall through to return CWORD */
01612                         break;
01613                     }
01614 
01615                 default:
01616                     break;
01617             }
01618         }
01619     }
01620 
01621     /* Nothing found */
01622     cword->idents = idents;
01623     return false;
01624 }
01625 
01626 
01627 /* ----------
01628  * plpgsql_parse_wordtype   The scanner found word%TYPE. word can be
01629  *              a variable name or a basetype.
01630  *
01631  * Returns datatype struct, or NULL if no match found for word.
01632  * ----------
01633  */
01634 PLpgSQL_type *
01635 plpgsql_parse_wordtype(char *ident)
01636 {
01637     PLpgSQL_type *dtype;
01638     PLpgSQL_nsitem *nse;
01639     HeapTuple   typeTup;
01640 
01641     /*
01642      * Do a lookup in the current namespace stack
01643      */
01644     nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
01645                             ident, NULL, NULL,
01646                             NULL);
01647 
01648     if (nse != NULL)
01649     {
01650         switch (nse->itemtype)
01651         {
01652             case PLPGSQL_NSTYPE_VAR:
01653                 return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
01654 
01655                 /* XXX perhaps allow REC/ROW here? */
01656 
01657             default:
01658                 return NULL;
01659         }
01660     }
01661 
01662     /*
01663      * Word wasn't found in the namespace stack. Try to find a data type with
01664      * that name, but ignore shell types and complex types.
01665      */
01666     typeTup = LookupTypeName(NULL, makeTypeName(ident), NULL);
01667     if (typeTup)
01668     {
01669         Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
01670 
01671         if (!typeStruct->typisdefined ||
01672             typeStruct->typrelid != InvalidOid)
01673         {
01674             ReleaseSysCache(typeTup);
01675             return NULL;
01676         }
01677 
01678         dtype = build_datatype(typeTup, -1,
01679                                plpgsql_curr_compile->fn_input_collation);
01680 
01681         ReleaseSysCache(typeTup);
01682         return dtype;
01683     }
01684 
01685     /*
01686      * Nothing found - up to now it's a word without any special meaning for
01687      * us.
01688      */
01689     return NULL;
01690 }
01691 
01692 
01693 /* ----------
01694  * plpgsql_parse_cwordtype      Same lookup for compositeword%TYPE
01695  * ----------
01696  */
01697 PLpgSQL_type *
01698 plpgsql_parse_cwordtype(List *idents)
01699 {
01700     PLpgSQL_type *dtype = NULL;
01701     PLpgSQL_nsitem *nse;
01702     const char *fldname;
01703     Oid         classOid;
01704     HeapTuple   classtup = NULL;
01705     HeapTuple   attrtup = NULL;
01706     HeapTuple   typetup = NULL;
01707     Form_pg_class classStruct;
01708     Form_pg_attribute attrStruct;
01709     MemoryContext oldCxt;
01710 
01711     /* Avoid memory leaks in the long-term function context */
01712     oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
01713 
01714     if (list_length(idents) == 2)
01715     {
01716         /*
01717          * Do a lookup in the current namespace stack. We don't need to check
01718          * number of names matched, because we will only consider scalar
01719          * variables.
01720          */
01721         nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
01722                                 strVal(linitial(idents)),
01723                                 strVal(lsecond(idents)),
01724                                 NULL,
01725                                 NULL);
01726 
01727         if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
01728         {
01729             dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
01730             goto done;
01731         }
01732 
01733         /*
01734          * First word could also be a table name
01735          */
01736         classOid = RelnameGetRelid(strVal(linitial(idents)));
01737         if (!OidIsValid(classOid))
01738             goto done;
01739         fldname = strVal(lsecond(idents));
01740     }
01741     else if (list_length(idents) == 3)
01742     {
01743         RangeVar   *relvar;
01744 
01745         relvar = makeRangeVar(strVal(linitial(idents)),
01746                               strVal(lsecond(idents)),
01747                               -1);
01748         /* Can't lock relation - we might not have privileges. */
01749         classOid = RangeVarGetRelid(relvar, NoLock, true);
01750         if (!OidIsValid(classOid))
01751             goto done;
01752         fldname = strVal(lthird(idents));
01753     }
01754     else
01755         goto done;
01756 
01757     classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
01758     if (!HeapTupleIsValid(classtup))
01759         goto done;
01760     classStruct = (Form_pg_class) GETSTRUCT(classtup);
01761 
01762     /*
01763      * It must be a relation, sequence, view, materialized view, composite
01764      * type, or foreign table
01765      */
01766     if (classStruct->relkind != RELKIND_RELATION &&
01767         classStruct->relkind != RELKIND_SEQUENCE &&
01768         classStruct->relkind != RELKIND_VIEW &&
01769         classStruct->relkind != RELKIND_MATVIEW &&
01770         classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
01771         classStruct->relkind != RELKIND_FOREIGN_TABLE)
01772         goto done;
01773 
01774     /*
01775      * Fetch the named table field and its type
01776      */
01777     attrtup = SearchSysCacheAttName(classOid, fldname);
01778     if (!HeapTupleIsValid(attrtup))
01779         goto done;
01780     attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
01781 
01782     typetup = SearchSysCache1(TYPEOID,
01783                               ObjectIdGetDatum(attrStruct->atttypid));
01784     if (!HeapTupleIsValid(typetup))
01785         elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
01786 
01787     /*
01788      * Found that - build a compiler type struct in the caller's cxt and
01789      * return it
01790      */
01791     MemoryContextSwitchTo(oldCxt);
01792     dtype = build_datatype(typetup,
01793                            attrStruct->atttypmod,
01794                            attrStruct->attcollation);
01795     MemoryContextSwitchTo(compile_tmp_cxt);
01796 
01797 done:
01798     if (HeapTupleIsValid(classtup))
01799         ReleaseSysCache(classtup);
01800     if (HeapTupleIsValid(attrtup))
01801         ReleaseSysCache(attrtup);
01802     if (HeapTupleIsValid(typetup))
01803         ReleaseSysCache(typetup);
01804 
01805     MemoryContextSwitchTo(oldCxt);
01806     return dtype;
01807 }
01808 
01809 /* ----------
01810  * plpgsql_parse_wordrowtype        Scanner found word%ROWTYPE.
01811  *                  So word must be a table name.
01812  * ----------
01813  */
01814 PLpgSQL_type *
01815 plpgsql_parse_wordrowtype(char *ident)
01816 {
01817     Oid         classOid;
01818 
01819     /* Lookup the relation */
01820     classOid = RelnameGetRelid(ident);
01821     if (!OidIsValid(classOid))
01822         ereport(ERROR,
01823                 (errcode(ERRCODE_UNDEFINED_TABLE),
01824                  errmsg("relation \"%s\" does not exist", ident)));
01825 
01826     /* Build and return the row type struct */
01827     return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
01828 }
01829 
01830 /* ----------
01831  * plpgsql_parse_cwordrowtype       Scanner found compositeword%ROWTYPE.
01832  *          So word must be a namespace qualified table name.
01833  * ----------
01834  */
01835 PLpgSQL_type *
01836 plpgsql_parse_cwordrowtype(List *idents)
01837 {
01838     Oid         classOid;
01839     RangeVar   *relvar;
01840     MemoryContext oldCxt;
01841 
01842     if (list_length(idents) != 2)
01843         return NULL;
01844 
01845     /* Avoid memory leaks in long-term function context */
01846     oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
01847 
01848     /* Look up relation name.  Can't lock it - we might not have privileges. */
01849     relvar = makeRangeVar(strVal(linitial(idents)),
01850                           strVal(lsecond(idents)),
01851                           -1);
01852     classOid = RangeVarGetRelid(relvar, NoLock, false);
01853 
01854     MemoryContextSwitchTo(oldCxt);
01855 
01856     /* Build and return the row type struct */
01857     return plpgsql_build_datatype(get_rel_type_id(classOid), -1, InvalidOid);
01858 }
01859 
01860 /*
01861  * plpgsql_build_variable - build a datum-array entry of a given
01862  * datatype
01863  *
01864  * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or
01865  * PLpgSQL_rec depending on the given datatype, and is allocated via
01866  * palloc.  The struct is automatically added to the current datum
01867  * array, and optionally to the current namespace.
01868  */
01869 PLpgSQL_variable *
01870 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
01871                        bool add2namespace)
01872 {
01873     PLpgSQL_variable *result;
01874 
01875     switch (dtype->ttype)
01876     {
01877         case PLPGSQL_TTYPE_SCALAR:
01878             {
01879                 /* Ordinary scalar datatype */
01880                 PLpgSQL_var *var;
01881 
01882                 var = palloc0(sizeof(PLpgSQL_var));
01883                 var->dtype = PLPGSQL_DTYPE_VAR;
01884                 var->refname = pstrdup(refname);
01885                 var->lineno = lineno;
01886                 var->datatype = dtype;
01887                 /* other fields might be filled by caller */
01888 
01889                 /* preset to NULL */
01890                 var->value = 0;
01891                 var->isnull = true;
01892                 var->freeval = false;
01893 
01894                 plpgsql_adddatum((PLpgSQL_datum *) var);
01895                 if (add2namespace)
01896                     plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
01897                                        var->dno,
01898                                        refname);
01899                 result = (PLpgSQL_variable *) var;
01900                 break;
01901             }
01902         case PLPGSQL_TTYPE_ROW:
01903             {
01904                 /* Composite type -- build a row variable */
01905                 PLpgSQL_row *row;
01906 
01907                 row = build_row_from_class(dtype->typrelid);
01908 
01909                 row->dtype = PLPGSQL_DTYPE_ROW;
01910                 row->refname = pstrdup(refname);
01911                 row->lineno = lineno;
01912 
01913                 plpgsql_adddatum((PLpgSQL_datum *) row);
01914                 if (add2namespace)
01915                     plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
01916                                        row->dno,
01917                                        refname);
01918                 result = (PLpgSQL_variable *) row;
01919                 break;
01920             }
01921         case PLPGSQL_TTYPE_REC:
01922             {
01923                 /* "record" type -- build a record variable */
01924                 PLpgSQL_rec *rec;
01925 
01926                 rec = plpgsql_build_record(refname, lineno, add2namespace);
01927                 result = (PLpgSQL_variable *) rec;
01928                 break;
01929             }
01930         case PLPGSQL_TTYPE_PSEUDO:
01931             ereport(ERROR,
01932                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01933                      errmsg("variable \"%s\" has pseudo-type %s",
01934                             refname, format_type_be(dtype->typoid))));
01935             result = NULL;      /* keep compiler quiet */
01936             break;
01937         default:
01938             elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
01939             result = NULL;      /* keep compiler quiet */
01940             break;
01941     }
01942 
01943     return result;
01944 }
01945 
01946 /*
01947  * Build empty named record variable, and optionally add it to namespace
01948  */
01949 PLpgSQL_rec *
01950 plpgsql_build_record(const char *refname, int lineno, bool add2namespace)
01951 {
01952     PLpgSQL_rec *rec;
01953 
01954     rec = palloc0(sizeof(PLpgSQL_rec));
01955     rec->dtype = PLPGSQL_DTYPE_REC;
01956     rec->refname = pstrdup(refname);
01957     rec->lineno = lineno;
01958     rec->tup = NULL;
01959     rec->tupdesc = NULL;
01960     rec->freetup = false;
01961     plpgsql_adddatum((PLpgSQL_datum *) rec);
01962     if (add2namespace)
01963         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->dno, rec->refname);
01964 
01965     return rec;
01966 }
01967 
01968 /*
01969  * Build a row-variable data structure given the pg_class OID.
01970  */
01971 static PLpgSQL_row *
01972 build_row_from_class(Oid classOid)
01973 {
01974     PLpgSQL_row *row;
01975     Relation    rel;
01976     Form_pg_class classStruct;
01977     const char *relname;
01978     int         i;
01979 
01980     /*
01981      * Open the relation to get info.
01982      */
01983     rel = relation_open(classOid, AccessShareLock);
01984     classStruct = RelationGetForm(rel);
01985     relname = RelationGetRelationName(rel);
01986 
01987     /*
01988      * Accept relation, sequence, view, materialized view, composite type, or
01989      * foreign table.
01990      */
01991     if (classStruct->relkind != RELKIND_RELATION &&
01992         classStruct->relkind != RELKIND_SEQUENCE &&
01993         classStruct->relkind != RELKIND_VIEW &&
01994         classStruct->relkind != RELKIND_MATVIEW &&
01995         classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
01996         classStruct->relkind != RELKIND_FOREIGN_TABLE)
01997         ereport(ERROR,
01998                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
01999                  errmsg("relation \"%s\" is not a table", relname)));
02000 
02001     /*
02002      * Create a row datum entry and all the required variables that it will
02003      * point to.
02004      */
02005     row = palloc0(sizeof(PLpgSQL_row));
02006     row->dtype = PLPGSQL_DTYPE_ROW;
02007     row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
02008     row->nfields = classStruct->relnatts;
02009     row->fieldnames = palloc(sizeof(char *) * row->nfields);
02010     row->varnos = palloc(sizeof(int) * row->nfields);
02011 
02012     for (i = 0; i < row->nfields; i++)
02013     {
02014         Form_pg_attribute attrStruct;
02015 
02016         /*
02017          * Get the attribute and check for dropped column
02018          */
02019         attrStruct = row->rowtupdesc->attrs[i];
02020 
02021         if (!attrStruct->attisdropped)
02022         {
02023             char       *attname;
02024             char        refname[(NAMEDATALEN * 2) + 100];
02025             PLpgSQL_variable *var;
02026 
02027             attname = NameStr(attrStruct->attname);
02028             snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
02029 
02030             /*
02031              * Create the internal variable for the field
02032              *
02033              * We know if the table definitions contain a default value or if
02034              * the field is declared in the table as NOT NULL. But it's
02035              * possible to create a table field as NOT NULL without a default
02036              * value and that would lead to problems later when initializing
02037              * the variables due to entering a block at execution time. Thus
02038              * we ignore this information for now.
02039              */
02040             var = plpgsql_build_variable(refname, 0,
02041                                  plpgsql_build_datatype(attrStruct->atttypid,
02042                                                         attrStruct->atttypmod,
02043                                                    attrStruct->attcollation),
02044                                          false);
02045 
02046             /* Add the variable to the row */
02047             row->fieldnames[i] = attname;
02048             row->varnos[i] = var->dno;
02049         }
02050         else
02051         {
02052             /* Leave a hole in the row structure for the dropped col */
02053             row->fieldnames[i] = NULL;
02054             row->varnos[i] = -1;
02055         }
02056     }
02057 
02058     relation_close(rel, AccessShareLock);
02059 
02060     return row;
02061 }
02062 
02063 /*
02064  * Build a row-variable data structure given the component variables.
02065  */
02066 static PLpgSQL_row *
02067 build_row_from_vars(PLpgSQL_variable **vars, int numvars)
02068 {
02069     PLpgSQL_row *row;
02070     int         i;
02071 
02072     row = palloc0(sizeof(PLpgSQL_row));
02073     row->dtype = PLPGSQL_DTYPE_ROW;
02074     row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
02075     row->nfields = numvars;
02076     row->fieldnames = palloc(numvars * sizeof(char *));
02077     row->varnos = palloc(numvars * sizeof(int));
02078 
02079     for (i = 0; i < numvars; i++)
02080     {
02081         PLpgSQL_variable *var = vars[i];
02082         Oid         typoid = RECORDOID;
02083         int32       typmod = -1;
02084         Oid         typcoll = InvalidOid;
02085 
02086         switch (var->dtype)
02087         {
02088             case PLPGSQL_DTYPE_VAR:
02089                 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
02090                 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
02091                 typcoll = ((PLpgSQL_var *) var)->datatype->collation;
02092                 break;
02093 
02094             case PLPGSQL_DTYPE_REC:
02095                 break;
02096 
02097             case PLPGSQL_DTYPE_ROW:
02098                 if (((PLpgSQL_row *) var)->rowtupdesc)
02099                 {
02100                     typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
02101                     typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
02102                     /* composite types have no collation */
02103                 }
02104                 break;
02105 
02106             default:
02107                 elog(ERROR, "unrecognized dtype: %d", var->dtype);
02108         }
02109 
02110         row->fieldnames[i] = var->refname;
02111         row->varnos[i] = var->dno;
02112 
02113         TupleDescInitEntry(row->rowtupdesc, i + 1,
02114                            var->refname,
02115                            typoid, typmod,
02116                            0);
02117         TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
02118     }
02119 
02120     return row;
02121 }
02122 
02123 /*
02124  * plpgsql_build_datatype
02125  *      Build PLpgSQL_type struct given type OID, typmod, and collation.
02126  *
02127  * If collation is not InvalidOid then it overrides the type's default
02128  * collation.  But collation is ignored if the datatype is non-collatable.
02129  */
02130 PLpgSQL_type *
02131 plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation)
02132 {
02133     HeapTuple   typeTup;
02134     PLpgSQL_type *typ;
02135 
02136     typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
02137     if (!HeapTupleIsValid(typeTup))
02138         elog(ERROR, "cache lookup failed for type %u", typeOid);
02139 
02140     typ = build_datatype(typeTup, typmod, collation);
02141 
02142     ReleaseSysCache(typeTup);
02143 
02144     return typ;
02145 }
02146 
02147 /*
02148  * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
02149  */
02150 static PLpgSQL_type *
02151 build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
02152 {
02153     Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
02154     PLpgSQL_type *typ;
02155 
02156     if (!typeStruct->typisdefined)
02157         ereport(ERROR,
02158                 (errcode(ERRCODE_UNDEFINED_OBJECT),
02159                  errmsg("type \"%s\" is only a shell",
02160                         NameStr(typeStruct->typname))));
02161 
02162     typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
02163 
02164     typ->typname = pstrdup(NameStr(typeStruct->typname));
02165     typ->typoid = HeapTupleGetOid(typeTup);
02166     switch (typeStruct->typtype)
02167     {
02168         case TYPTYPE_BASE:
02169         case TYPTYPE_DOMAIN:
02170         case TYPTYPE_ENUM:
02171         case TYPTYPE_RANGE:
02172             typ->ttype = PLPGSQL_TTYPE_SCALAR;
02173             break;
02174         case TYPTYPE_COMPOSITE:
02175             Assert(OidIsValid(typeStruct->typrelid));
02176             typ->ttype = PLPGSQL_TTYPE_ROW;
02177             break;
02178         case TYPTYPE_PSEUDO:
02179             if (typ->typoid == RECORDOID)
02180                 typ->ttype = PLPGSQL_TTYPE_REC;
02181             else
02182                 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
02183             break;
02184         default:
02185             elog(ERROR, "unrecognized typtype: %d",
02186                  (int) typeStruct->typtype);
02187             break;
02188     }
02189     typ->typlen = typeStruct->typlen;
02190     typ->typbyval = typeStruct->typbyval;
02191     typ->typrelid = typeStruct->typrelid;
02192     typ->typioparam = getTypeIOParam(typeTup);
02193     typ->collation = typeStruct->typcollation;
02194     if (OidIsValid(collation) && OidIsValid(typ->collation))
02195         typ->collation = collation;
02196     fmgr_info(typeStruct->typinput, &(typ->typinput));
02197     typ->atttypmod = typmod;
02198 
02199     return typ;
02200 }
02201 
02202 /*
02203  *  plpgsql_recognize_err_condition
02204  *      Check condition name and translate it to SQLSTATE.
02205  *
02206  * Note: there are some cases where the same condition name has multiple
02207  * entries in the table.  We arbitrarily return the first match.
02208  */
02209 int
02210 plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
02211 {
02212     int         i;
02213 
02214     if (allow_sqlstate)
02215     {
02216         if (strlen(condname) == 5 &&
02217             strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
02218             return MAKE_SQLSTATE(condname[0],
02219                                  condname[1],
02220                                  condname[2],
02221                                  condname[3],
02222                                  condname[4]);
02223     }
02224 
02225     for (i = 0; exception_label_map[i].label != NULL; i++)
02226     {
02227         if (strcmp(condname, exception_label_map[i].label) == 0)
02228             return exception_label_map[i].sqlerrstate;
02229     }
02230 
02231     ereport(ERROR,
02232             (errcode(ERRCODE_UNDEFINED_OBJECT),
02233              errmsg("unrecognized exception condition \"%s\"",
02234                     condname)));
02235     return 0;                   /* keep compiler quiet */
02236 }
02237 
02238 /*
02239  * plpgsql_parse_err_condition
02240  *      Generate PLpgSQL_condition entry(s) for an exception condition name
02241  *
02242  * This has to be able to return a list because there are some duplicate
02243  * names in the table of error code names.
02244  */
02245 PLpgSQL_condition *
02246 plpgsql_parse_err_condition(char *condname)
02247 {
02248     int         i;
02249     PLpgSQL_condition *new;
02250     PLpgSQL_condition *prev;
02251 
02252     /*
02253      * XXX Eventually we will want to look for user-defined exception names
02254      * here.
02255      */
02256 
02257     /*
02258      * OTHERS is represented as code 0 (which would map to '00000', but we
02259      * have no need to represent that as an exception condition).
02260      */
02261     if (strcmp(condname, "others") == 0)
02262     {
02263         new = palloc(sizeof(PLpgSQL_condition));
02264         new->sqlerrstate = 0;
02265         new->condname = condname;
02266         new->next = NULL;
02267         return new;
02268     }
02269 
02270     prev = NULL;
02271     for (i = 0; exception_label_map[i].label != NULL; i++)
02272     {
02273         if (strcmp(condname, exception_label_map[i].label) == 0)
02274         {
02275             new = palloc(sizeof(PLpgSQL_condition));
02276             new->sqlerrstate = exception_label_map[i].sqlerrstate;
02277             new->condname = condname;
02278             new->next = prev;
02279             prev = new;
02280         }
02281     }
02282 
02283     if (!prev)
02284         ereport(ERROR,
02285                 (errcode(ERRCODE_UNDEFINED_OBJECT),
02286                  errmsg("unrecognized exception condition \"%s\"",
02287                         condname)));
02288 
02289     return prev;
02290 }
02291 
02292 /* ----------
02293  * plpgsql_adddatum         Add a variable, record or row
02294  *                  to the compiler's datum list.
02295  * ----------
02296  */
02297 void
02298 plpgsql_adddatum(PLpgSQL_datum *new)
02299 {
02300     if (plpgsql_nDatums == datums_alloc)
02301     {
02302         datums_alloc *= 2;
02303         plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
02304     }
02305 
02306     new->dno = plpgsql_nDatums;
02307     plpgsql_Datums[plpgsql_nDatums++] = new;
02308 }
02309 
02310 
02311 /* ----------
02312  * plpgsql_add_initdatums       Make an array of the datum numbers of
02313  *                  all the simple VAR datums created since the last call
02314  *                  to this function.
02315  *
02316  * If varnos is NULL, we just forget any datum entries created since the
02317  * last call.
02318  *
02319  * This is used around a DECLARE section to create a list of the VARs
02320  * that have to be initialized at block entry.  Note that VARs can also
02321  * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
02322  * the responsibility of special-purpose code to initialize them.
02323  * ----------
02324  */
02325 int
02326 plpgsql_add_initdatums(int **varnos)
02327 {
02328     int         i;
02329     int         n = 0;
02330 
02331     for (i = datums_last; i < plpgsql_nDatums; i++)
02332     {
02333         switch (plpgsql_Datums[i]->dtype)
02334         {
02335             case PLPGSQL_DTYPE_VAR:
02336                 n++;
02337                 break;
02338 
02339             default:
02340                 break;
02341         }
02342     }
02343 
02344     if (varnos != NULL)
02345     {
02346         if (n > 0)
02347         {
02348             *varnos = (int *) palloc(sizeof(int) * n);
02349 
02350             n = 0;
02351             for (i = datums_last; i < plpgsql_nDatums; i++)
02352             {
02353                 switch (plpgsql_Datums[i]->dtype)
02354                 {
02355                     case PLPGSQL_DTYPE_VAR:
02356                         (*varnos)[n++] = plpgsql_Datums[i]->dno;
02357 
02358                     default:
02359                         break;
02360                 }
02361             }
02362         }
02363         else
02364             *varnos = NULL;
02365     }
02366 
02367     datums_last = plpgsql_nDatums;
02368     return n;
02369 }
02370 
02371 
02372 /*
02373  * Compute the hashkey for a given function invocation
02374  *
02375  * The hashkey is returned into the caller-provided storage at *hashkey.
02376  */
02377 static void
02378 compute_function_hashkey(FunctionCallInfo fcinfo,
02379                          Form_pg_proc procStruct,
02380                          PLpgSQL_func_hashkey *hashkey,
02381                          bool forValidator)
02382 {
02383     /* Make sure any unused bytes of the struct are zero */
02384     MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
02385 
02386     /* get function OID */
02387     hashkey->funcOid = fcinfo->flinfo->fn_oid;
02388 
02389     /* get call context */
02390     hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
02391 
02392     /*
02393      * if trigger, get relation OID.  In validation mode we do not know what
02394      * relation is intended to be used, so we leave trigrelOid zero; the hash
02395      * entry built in this case will never really be used.
02396      */
02397     if (hashkey->isTrigger && !forValidator)
02398     {
02399         TriggerData *trigdata = (TriggerData *) fcinfo->context;
02400 
02401         hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
02402     }
02403 
02404     /* get input collation, if known */
02405     hashkey->inputCollation = fcinfo->fncollation;
02406 
02407     if (procStruct->pronargs > 0)
02408     {
02409         /* get the argument types */
02410         memcpy(hashkey->argtypes, procStruct->proargtypes.values,
02411                procStruct->pronargs * sizeof(Oid));
02412 
02413         /* resolve any polymorphic argument types */
02414         plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
02415                                              hashkey->argtypes,
02416                                              NULL,
02417                                              fcinfo->flinfo->fn_expr,
02418                                              forValidator,
02419                                              NameStr(procStruct->proname));
02420     }
02421 }
02422 
02423 /*
02424  * This is the same as the standard resolve_polymorphic_argtypes() function,
02425  * but with a special case for validation: assume that polymorphic arguments
02426  * are integer, integer-array or integer-range.  Also, we go ahead and report
02427  * the error if we can't resolve the types.
02428  */
02429 static void
02430 plpgsql_resolve_polymorphic_argtypes(int numargs,
02431                                      Oid *argtypes, char *argmodes,
02432                                      Node *call_expr, bool forValidator,
02433                                      const char *proname)
02434 {
02435     int         i;
02436 
02437     if (!forValidator)
02438     {
02439         /* normal case, pass to standard routine */
02440         if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
02441                                           call_expr))
02442             ereport(ERROR,
02443                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02444                      errmsg("could not determine actual argument "
02445                             "type for polymorphic function \"%s\"",
02446                             proname)));
02447     }
02448     else
02449     {
02450         /* special validation case */
02451         for (i = 0; i < numargs; i++)
02452         {
02453             switch (argtypes[i])
02454             {
02455                 case ANYELEMENTOID:
02456                 case ANYNONARRAYOID:
02457                 case ANYENUMOID:        /* XXX dubious */
02458                     argtypes[i] = INT4OID;
02459                     break;
02460                 case ANYARRAYOID:
02461                     argtypes[i] = INT4ARRAYOID;
02462                     break;
02463                 case ANYRANGEOID:
02464                     argtypes[i] = INT4RANGEOID;
02465                     break;
02466                 default:
02467                     break;
02468             }
02469         }
02470     }
02471 }
02472 
02473 /*
02474  * delete_function - clean up as much as possible of a stale function cache
02475  *
02476  * We can't release the PLpgSQL_function struct itself, because of the
02477  * possibility that there are fn_extra pointers to it.  We can release
02478  * the subsidiary storage, but only if there are no active evaluations
02479  * in progress.  Otherwise we'll just leak that storage.  Since the
02480  * case would only occur if a pg_proc update is detected during a nested
02481  * recursive call on the function, a leak seems acceptable.
02482  *
02483  * Note that this can be called more than once if there are multiple fn_extra
02484  * pointers to the same function cache.  Hence be careful not to do things
02485  * twice.
02486  */
02487 static void
02488 delete_function(PLpgSQL_function *func)
02489 {
02490     /* remove function from hash table (might be done already) */
02491     plpgsql_HashTableDelete(func);
02492 
02493     /* release the function's storage if safe and not done already */
02494     if (func->use_count == 0)
02495         plpgsql_free_function_memory(func);
02496 }
02497 
02498 /* exported so we can call it from plpgsql_init() */
02499 void
02500 plpgsql_HashTableInit(void)
02501 {
02502     HASHCTL     ctl;
02503 
02504     /* don't allow double-initialization */
02505     Assert(plpgsql_HashTable == NULL);
02506 
02507     memset(&ctl, 0, sizeof(ctl));
02508     ctl.keysize = sizeof(PLpgSQL_func_hashkey);
02509     ctl.entrysize = sizeof(plpgsql_HashEnt);
02510     ctl.hash = tag_hash;
02511     plpgsql_HashTable = hash_create("PLpgSQL function cache",
02512                                     FUNCS_PER_USER,
02513                                     &ctl,
02514                                     HASH_ELEM | HASH_FUNCTION);
02515 }
02516 
02517 static PLpgSQL_function *
02518 plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
02519 {
02520     plpgsql_HashEnt *hentry;
02521 
02522     hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
02523                                              (void *) func_key,
02524                                              HASH_FIND,
02525                                              NULL);
02526     if (hentry)
02527         return hentry->function;
02528     else
02529         return NULL;
02530 }
02531 
02532 static void
02533 plpgsql_HashTableInsert(PLpgSQL_function *function,
02534                         PLpgSQL_func_hashkey *func_key)
02535 {
02536     plpgsql_HashEnt *hentry;
02537     bool        found;
02538 
02539     hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
02540                                              (void *) func_key,
02541                                              HASH_ENTER,
02542                                              &found);
02543     if (found)
02544         elog(WARNING, "trying to insert a function that already exists");
02545 
02546     hentry->function = function;
02547     /* prepare back link from function to hashtable key */
02548     function->fn_hashkey = &hentry->key;
02549 }
02550 
02551 static void
02552 plpgsql_HashTableDelete(PLpgSQL_function *function)
02553 {
02554     plpgsql_HashEnt *hentry;
02555 
02556     /* do nothing if not in table */
02557     if (function->fn_hashkey == NULL)
02558         return;
02559 
02560     hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
02561                                              (void *) function->fn_hashkey,
02562                                              HASH_REMOVE,
02563                                              NULL);
02564     if (hentry == NULL)
02565         elog(WARNING, "trying to delete function that does not exist");
02566 
02567     /* remove back link, which no longer points to allocated storage */
02568     function->fn_hashkey = NULL;
02569 }