OSDN Git Service

2c84899519b62cce8d5213a38ab5b03c3f09973f
[pg-rex/syncrep.git] / src / pl / plpgsql / src / pl_comp.c
1 /**********************************************************************
2  * pl_comp.c            - Compiler part of the PL/pgSQL
3  *                        procedural language
4  *
5  * IDENTIFICATION
6  *        $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.94 2005/10/15 02:49:49 momjian Exp $
7  *
8  *        This software is copyrighted by Jan Wieck - Hamburg.
9  *
10  *        The author hereby grants permission  to  use,  copy,  modify,
11  *        distribute,  and      license this software and its documentation
12  *        for any purpose, provided that existing copyright notices are
13  *        retained      in      all  copies  and  that  this notice is included
14  *        verbatim in any distributions. No written agreement, license,
15  *        or  royalty  fee      is required for any of the authorized uses.
16  *        Modifications to this software may be  copyrighted  by  their
17  *        author  and  need  not  follow  the licensing terms described
18  *        here, provided that the new terms are  clearly  indicated  on
19  *        the first page of each file where they apply.
20  *
21  *        IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
22  *        PARTY  FOR  DIRECT,   INDIRECT,       SPECIAL,   INCIDENTAL,   OR
23  *        CONSEQUENTIAL   DAMAGES  ARISING      OUT  OF  THE  USE  OF  THIS
24  *        SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
25  *        IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
26  *        DAMAGE.
27  *
28  *        THE  AUTHOR  AND      DISTRIBUTORS  SPECIFICALLY       DISCLAIM       ANY
29  *        WARRANTIES,  INCLUDING,  BUT  NOT  LIMITED  TO,  THE  IMPLIED
30  *        WARRANTIES  OF  MERCHANTABILITY,      FITNESS  FOR  A  PARTICULAR
31  *        PURPOSE,      AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
32  *        AN "AS IS" BASIS, AND THE AUTHOR      AND  DISTRIBUTORS  HAVE  NO
33  *        OBLIGATION   TO       PROVIDE   MAINTENANCE,   SUPPORT,  UPDATES,
34  *        ENHANCEMENTS, OR MODIFICATIONS.
35  *
36  **********************************************************************/
37
38 #include "plpgsql.h"
39
40 #include <ctype.h>
41
42 #include "pl.tab.h"
43
44 #include "access/heapam.h"
45 #include "catalog/namespace.h"
46 #include "catalog/pg_attribute.h"
47 #include "catalog/pg_attrdef.h"
48 #include "catalog/pg_class.h"
49 #include "catalog/pg_proc.h"
50 #include "catalog/pg_type.h"
51 #include "funcapi.h"
52 #include "nodes/makefuncs.h"
53 #include "parser/gramparse.h"
54 #include "parser/parse_type.h"
55 #include "tcop/tcopprot.h"
56 #include "utils/array.h"
57 #include "utils/builtins.h"
58 #include "utils/lsyscache.h"
59 #include "utils/memutils.h"
60 #include "utils/syscache.h"
61
62
63 /* ----------
64  * Variables in the parser that shouldn't go into plpgsql.h
65  * ----------
66  */
67 extern PLPGSQL_YYSTYPE plpgsql_yylval;
68
69 /* ----------
70  * Our own local and global variables
71  * ----------
72  */
73 static int      datums_alloc;
74 int                     plpgsql_nDatums;
75 PLpgSQL_datum **plpgsql_Datums;
76 static int      datums_last = 0;
77
78 int                     plpgsql_error_lineno;
79 char       *plpgsql_error_funcname;
80 bool            plpgsql_DumpExecTree = false;
81 bool            plpgsql_check_syntax = false;
82
83 PLpgSQL_function *plpgsql_curr_compile;
84
85 /* A context appropriate for short-term allocs during compilation */
86 MemoryContext compile_tmp_cxt;
87
88 /* ----------
89  * Hash table for compiled functions
90  * ----------
91  */
92 static HTAB *plpgsql_HashTable = NULL;
93
94 typedef struct plpgsql_hashent
95 {
96         PLpgSQL_func_hashkey key;
97         PLpgSQL_function *function;
98 }       plpgsql_HashEnt;
99
100 #define FUNCS_PER_USER          128 /* initial table size */
101
102 /* ----------
103  * Lookup table for EXCEPTION condition names
104  * ----------
105  */
106 typedef struct
107 {
108         const char *label;
109         int                     sqlerrstate;
110 }       ExceptionLabelMap;
111
112 static const ExceptionLabelMap exception_label_map[] = {
113 #include "plerrcodes.h"
114         {NULL, 0}
115 };
116
117
118 /* ----------
119  * static prototypes
120  * ----------
121  */
122 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
123                    HeapTuple procTup,
124                    PLpgSQL_func_hashkey * hashkey,
125                    bool forValidator);
126 static int fetchArgInfo(HeapTuple procTup,
127                          Oid **p_argtypes, char ***p_argnames,
128                          char **p_argmodes);
129 static PLpgSQL_row *build_row_from_class(Oid classOid);
130 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable ** vars, int numvars);
131 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
132 static void compute_function_hashkey(FunctionCallInfo fcinfo,
133                                                  Form_pg_proc procStruct,
134                                                  PLpgSQL_func_hashkey * hashkey,
135                                                  bool forValidator);
136 static void plpgsql_resolve_polymorphic_argtypes(int numargs,
137                                                                          Oid *argtypes, char *argmodes,
138                                                                          Node *call_expr, bool forValidator,
139                                                                          const char *proname);
140 static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key);
141 static void plpgsql_HashTableInsert(PLpgSQL_function * function,
142                                                 PLpgSQL_func_hashkey * func_key);
143 static void plpgsql_HashTableDelete(PLpgSQL_function * function);
144 static void delete_function(PLpgSQL_function * func);
145
146 /* ----------
147  * plpgsql_compile              Make an execution tree for a PL/pgSQL function.
148  *
149  * If forValidator is true, we're only compiling for validation purposes,
150  * and so some checks are skipped.
151  *
152  * Note: it's important for this to fall through quickly if the function
153  * has already been compiled.
154  * ----------
155  */
156 PLpgSQL_function *
157 plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
158 {
159         Oid                     funcOid = fcinfo->flinfo->fn_oid;
160         HeapTuple       procTup;
161         Form_pg_proc procStruct;
162         PLpgSQL_function *function;
163         PLpgSQL_func_hashkey hashkey;
164         bool            hashkey_valid = false;
165
166         /*
167          * Lookup the pg_proc tuple by Oid; we'll need it in any case
168          */
169         procTup = SearchSysCache(PROCOID,
170                                                          ObjectIdGetDatum(funcOid),
171                                                          0, 0, 0);
172         if (!HeapTupleIsValid(procTup))
173                 elog(ERROR, "cache lookup failed for function %u", funcOid);
174         procStruct = (Form_pg_proc) GETSTRUCT(procTup);
175
176         /*
177          * See if there's already a cache entry for the current FmgrInfo. If not,
178          * try to find one in the hash table.
179          */
180         function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
181
182         if (!function)
183         {
184                 /* Compute hashkey using function signature and actual arg types */
185                 compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
186                 hashkey_valid = true;
187
188                 /* And do the lookup */
189                 function = plpgsql_HashTableLookup(&hashkey);
190         }
191
192         if (function)
193         {
194                 /* We have a compiled function, but is it still valid? */
195                 if (!(function->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
196                           function->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data)))
197                 {
198                         /* Nope, drop the function and associated storage */
199                         delete_function(function);
200                         function = NULL;
201                 }
202         }
203
204         /*
205          * If the function wasn't found or was out-of-date, we have to compile it
206          */
207         if (!function)
208         {
209                 /*
210                  * Calculate hashkey if we didn't already; we'll need it to store the
211                  * completed function.
212                  */
213                 if (!hashkey_valid)
214                         compute_function_hashkey(fcinfo, procStruct, &hashkey,
215                                                                          forValidator);
216
217                 /*
218                  * Do the hard part.
219                  */
220                 function = do_compile(fcinfo, procTup, &hashkey, forValidator);
221         }
222
223         ReleaseSysCache(procTup);
224
225         /*
226          * Save pointer in FmgrInfo to avoid search on subsequent calls
227          */
228         fcinfo->flinfo->fn_extra = (void *) function;
229
230         /*
231          * Finally return the compiled function
232          */
233         return function;
234 }
235
236 /*
237  * This is the slow part of plpgsql_compile().
238  *
239  * While compiling a function, the CurrentMemoryContext is the
240  * per-function memory context of the function we are compiling. That
241  * means a palloc() will allocate storage with the same lifetime as
242  * the function itself.
243  *
244  * Because palloc()'d storage will not be immediately freed, temporary
245  * allocations should either be performed in a short-lived memory
246  * context or explicitly pfree'd. Since not all backend functions are
247  * careful about pfree'ing their allocations, it is also wise to
248  * switch into a short-term context before calling into the
249  * backend. An appropriate context for performing short-term
250  * allocations is the compile_tmp_cxt.
251  */
252 static PLpgSQL_function *
253 do_compile(FunctionCallInfo fcinfo,
254                    HeapTuple procTup,
255                    PLpgSQL_func_hashkey * hashkey,
256                    bool forValidator)
257 {
258         Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
259         int                     functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
260         PLpgSQL_function *function;
261         Datum           prosrcdatum;
262         bool            isnull;
263         char       *proc_source;
264         HeapTuple       typeTup;
265         Form_pg_type typeStruct;
266         PLpgSQL_variable *var;
267         PLpgSQL_rec *rec;
268         int                     i;
269         ErrorContextCallback plerrcontext;
270         int                     parse_rc;
271         Oid                     rettypeid;
272         int                     numargs;
273         int                     num_in_args = 0;
274         int                     num_out_args = 0;
275         Oid                *argtypes;
276         char      **argnames;
277         char       *argmodes;
278         int                *in_arg_varnos = NULL;
279         PLpgSQL_variable **out_arg_variables;
280         MemoryContext func_cxt;
281
282         /*
283          * Setup the scanner input and error info.      We assume that this function
284          * cannot be invoked recursively, so there's no need to save and restore
285          * the static variables used here.
286          */
287         prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
288                                                                   Anum_pg_proc_prosrc, &isnull);
289         if (isnull)
290                 elog(ERROR, "null prosrc");
291         proc_source = DatumGetCString(DirectFunctionCall1(textout, prosrcdatum));
292         plpgsql_scanner_init(proc_source, functype);
293
294         plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
295         plpgsql_error_lineno = 0;
296
297         /*
298          * Setup error traceback support for ereport()
299          */
300         plerrcontext.callback = plpgsql_compile_error_callback;
301         plerrcontext.arg = forValidator ? proc_source : NULL;
302         plerrcontext.previous = error_context_stack;
303         error_context_stack = &plerrcontext;
304
305         /*
306          * Initialize the compiler
307          */
308         plpgsql_ns_init();
309         plpgsql_ns_push(NULL);
310         plpgsql_DumpExecTree = false;
311
312         datums_alloc = 128;
313         plpgsql_nDatums = 0;
314         /* This is short-lived, so needn't allocate in function's cxt */
315         plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
316         datums_last = 0;
317
318         /*
319          * Do extra syntax checks when validating the function definition. We skip
320          * this when actually compiling functions for execution, for performance
321          * reasons.
322          */
323         plpgsql_check_syntax = forValidator;
324
325         /*
326          * Create the new function node. We allocate the function and all of its
327          * compile-time storage (e.g. parse tree) in its own memory context. This
328          * allows us to reclaim the function's storage cleanly.
329          */
330         func_cxt = AllocSetContextCreate(TopMemoryContext,
331                                                                          "PL/PgSQL function context",
332                                                                          ALLOCSET_DEFAULT_MINSIZE,
333                                                                          ALLOCSET_DEFAULT_INITSIZE,
334                                                                          ALLOCSET_DEFAULT_MAXSIZE);
335         compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
336         function = palloc0(sizeof(*function));
337         plpgsql_curr_compile = function;
338
339         function->fn_name = pstrdup(NameStr(procStruct->proname));
340         function->fn_oid = fcinfo->flinfo->fn_oid;
341         function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
342         function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
343         function->fn_functype = functype;
344         function->fn_cxt = func_cxt;
345         function->out_param_varno = -1;         /* set up for no OUT param */
346
347         switch (functype)
348         {
349                 case T_FUNCTION:
350
351                         /*
352                          * Fetch info about the procedure's parameters. Allocations aren't
353                          * needed permanently, so make them in tmp cxt.
354                          *
355                          * We also need to resolve any polymorphic input or output argument
356                          * types.  In validation mode we won't be able to, so we
357                          * arbitrarily assume we are dealing with integers.
358                          */
359                         MemoryContextSwitchTo(compile_tmp_cxt);
360
361                         numargs = fetchArgInfo(procTup, &argtypes, &argnames, &argmodes);
362
363                         plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
364                                                                                                  fcinfo->flinfo->fn_expr,
365                                                                                                  forValidator,
366                                                                                                  plpgsql_error_funcname);
367
368                         in_arg_varnos = (int *) palloc(numargs * sizeof(int));
369                         out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
370
371                         MemoryContextSwitchTo(func_cxt);
372
373                         /*
374                          * Create the variables for the procedure's parameters.
375                          */
376                         for (i = 0; i < numargs; i++)
377                         {
378                                 char            buf[32];
379                                 Oid                     argtypeid = argtypes[i];
380                                 char            argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
381                                 PLpgSQL_type *argdtype;
382                                 PLpgSQL_variable *argvariable;
383                                 int                     argitemtype;
384
385                                 /* Create $n name for variable */
386                                 snprintf(buf, sizeof(buf), "$%d", i + 1);
387
388                                 /* Create datatype info */
389                                 argdtype = plpgsql_build_datatype(argtypeid, -1);
390
391                                 /* Disallow pseudotype argument */
392                                 /* (note we already replaced ANYARRAY/ANYELEMENT) */
393                                 /* (build_variable would do this, but wrong message) */
394                                 if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
395                                         argdtype->ttype != PLPGSQL_TTYPE_ROW)
396                                         ereport(ERROR,
397                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
398                                                          errmsg("plpgsql functions cannot take type %s",
399                                                                         format_type_be(argtypeid))));
400
401                                 /* Build variable and add to datum list */
402                                 argvariable = plpgsql_build_variable(buf, 0,
403                                                                                                          argdtype, false);
404
405                                 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
406                                 {
407                                         argitemtype = PLPGSQL_NSTYPE_VAR;
408                                         /* input argument vars are forced to be CONSTANT */
409                                         if (argmode == PROARGMODE_IN)
410                                                 ((PLpgSQL_var *) argvariable)->isconst = true;
411                                 }
412                                 else
413                                 {
414                                         Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
415                                         argitemtype = PLPGSQL_NSTYPE_ROW;
416                                 }
417
418                                 /* Remember arguments in appropriate arrays */
419                                 if (argmode == PROARGMODE_IN || argmode == PROARGMODE_INOUT)
420                                         in_arg_varnos[num_in_args++] = argvariable->dno;
421                                 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_INOUT)
422                                         out_arg_variables[num_out_args++] = argvariable;
423
424                                 /* Add to namespace under the $n name */
425                                 plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
426
427                                 /* If there's a name for the argument, make an alias */
428                                 if (argnames && argnames[i][0] != '\0')
429                                         plpgsql_ns_additem(argitemtype, argvariable->dno,
430                                                                            argnames[i]);
431                         }
432
433                         /*
434                          * If there's just one OUT parameter, out_param_varno points
435                          * directly to it.      If there's more than one, build a row that
436                          * holds all of them.
437                          */
438                         if (num_out_args == 1)
439                                 function->out_param_varno = out_arg_variables[0]->dno;
440                         else if (num_out_args > 1)
441                         {
442                                 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
443                                                                                                            num_out_args);
444
445                                 plpgsql_adddatum((PLpgSQL_datum *) row);
446                                 function->out_param_varno = row->rowno;
447                         }
448
449                         /*
450                          * Check for a polymorphic returntype. If found, use the actual
451                          * returntype type from the caller's FuncExpr node, if we have
452                          * one.  (In validation mode we arbitrarily assume we are dealing
453                          * with integers.)
454                          *
455                          * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
456                          * work; if it doesn't we're in some context that fails to make
457                          * the info available.
458                          */
459                         rettypeid = procStruct->prorettype;
460                         if (rettypeid == ANYARRAYOID || rettypeid == ANYELEMENTOID)
461                         {
462                                 if (forValidator)
463                                 {
464                                         if (rettypeid == ANYARRAYOID)
465                                                 rettypeid = INT4ARRAYOID;
466                                         else
467                                                 rettypeid = INT4OID;
468                                 }
469                                 else
470                                 {
471                                         rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
472                                         if (!OidIsValid(rettypeid))
473                                                 ereport(ERROR,
474                                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
475                                                          errmsg("could not determine actual return type "
476                                                                         "for polymorphic function \"%s\"",
477                                                                         plpgsql_error_funcname)));
478                                 }
479                         }
480
481                         /*
482                          * Normal function has a defined returntype
483                          */
484                         function->fn_rettype = rettypeid;
485                         function->fn_retset = procStruct->proretset;
486
487                         /*
488                          * Lookup the function's return type
489                          */
490                         typeTup = SearchSysCache(TYPEOID,
491                                                                          ObjectIdGetDatum(rettypeid),
492                                                                          0, 0, 0);
493                         if (!HeapTupleIsValid(typeTup))
494                                 elog(ERROR, "cache lookup failed for type %u", rettypeid);
495                         typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
496
497                         /* Disallow pseudotype result, except VOID or RECORD */
498                         /* (note we already replaced ANYARRAY/ANYELEMENT) */
499                         if (typeStruct->typtype == 'p')
500                         {
501                                 if (rettypeid == VOIDOID ||
502                                         rettypeid == RECORDOID)
503                                          /* okay */ ;
504                                 else if (rettypeid == TRIGGEROID)
505                                         ereport(ERROR,
506                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
507                                                          errmsg("trigger functions may only be called as triggers")));
508                                 else
509                                         ereport(ERROR,
510                                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
511                                                          errmsg("plpgsql functions cannot return type %s",
512                                                                         format_type_be(rettypeid))));
513                         }
514
515                         if (typeStruct->typrelid != InvalidOid ||
516                                 rettypeid == RECORDOID)
517                                 function->fn_retistuple = true;
518                         else
519                         {
520                                 function->fn_retbyval = typeStruct->typbyval;
521                                 function->fn_rettyplen = typeStruct->typlen;
522                                 function->fn_rettypioparam = getTypeIOParam(typeTup);
523                                 fmgr_info(typeStruct->typinput, &(function->fn_retinput));
524
525                                 /*
526                                  * install $0 reference, but only for polymorphic return
527                                  * types, and not when the return is specified through an
528                                  * output parameter.
529                                  */
530                                 if ((procStruct->prorettype == ANYARRAYOID ||
531                                          procStruct->prorettype == ANYELEMENTOID) &&
532                                         num_out_args == 0)
533                                 {
534                                         (void) plpgsql_build_variable("$0", 0,
535                                                                                                   build_datatype(typeTup, -1),
536                                                                                                   true);
537                                 }
538                         }
539                         ReleaseSysCache(typeTup);
540                         break;
541
542                 case T_TRIGGER:
543                         /* Trigger procedure's return type is unknown yet */
544                         function->fn_rettype = InvalidOid;
545                         function->fn_retbyval = false;
546                         function->fn_retistuple = true;
547                         function->fn_retset = false;
548
549                         /* shouldn't be any declared arguments */
550                         if (procStruct->pronargs != 0)
551                                 ereport(ERROR,
552                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
553                                   errmsg("trigger functions cannot have declared arguments"),
554                                                  errhint("You probably want to use TG_NARGS and TG_ARGV instead.")));
555
556                         /* Add the record for referencing NEW */
557                         rec = palloc0(sizeof(PLpgSQL_rec));
558                         rec->dtype = PLPGSQL_DTYPE_REC;
559                         rec->refname = pstrdup("new");
560                         rec->tup = NULL;
561                         rec->tupdesc = NULL;
562                         rec->freetup = false;
563                         plpgsql_adddatum((PLpgSQL_datum *) rec);
564                         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
565                         function->new_varno = rec->recno;
566
567                         /* Add the record for referencing OLD */
568                         rec = palloc0(sizeof(PLpgSQL_rec));
569                         rec->dtype = PLPGSQL_DTYPE_REC;
570                         rec->refname = pstrdup("old");
571                         rec->tup = NULL;
572                         rec->tupdesc = NULL;
573                         rec->freetup = false;
574                         plpgsql_adddatum((PLpgSQL_datum *) rec);
575                         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
576                         function->old_varno = rec->recno;
577
578                         /* Add the variable tg_name */
579                         var = plpgsql_build_variable("tg_name", 0,
580                                                                                  plpgsql_build_datatype(NAMEOID, -1),
581                                                                                  true);
582                         function->tg_name_varno = var->dno;
583
584                         /* Add the variable tg_when */
585                         var = plpgsql_build_variable("tg_when", 0,
586                                                                                  plpgsql_build_datatype(TEXTOID, -1),
587                                                                                  true);
588                         function->tg_when_varno = var->dno;
589
590                         /* Add the variable tg_level */
591                         var = plpgsql_build_variable("tg_level", 0,
592                                                                                  plpgsql_build_datatype(TEXTOID, -1),
593                                                                                  true);
594                         function->tg_level_varno = var->dno;
595
596                         /* Add the variable tg_op */
597                         var = plpgsql_build_variable("tg_op", 0,
598                                                                                  plpgsql_build_datatype(TEXTOID, -1),
599                                                                                  true);
600                         function->tg_op_varno = var->dno;
601
602                         /* Add the variable tg_relid */
603                         var = plpgsql_build_variable("tg_relid", 0,
604                                                                                  plpgsql_build_datatype(OIDOID, -1),
605                                                                                  true);
606                         function->tg_relid_varno = var->dno;
607
608                         /* Add the variable tg_relname */
609                         var = plpgsql_build_variable("tg_relname", 0,
610                                                                                  plpgsql_build_datatype(NAMEOID, -1),
611                                                                                  true);
612                         function->tg_relname_varno = var->dno;
613
614                         /* Add the variable tg_nargs */
615                         var = plpgsql_build_variable("tg_nargs", 0,
616                                                                                  plpgsql_build_datatype(INT4OID, -1),
617                                                                                  true);
618                         function->tg_nargs_varno = var->dno;
619
620                         break;
621
622                 default:
623                         elog(ERROR, "unrecognized function typecode: %u", functype);
624                         break;
625         }
626
627         /* Remember if function is STABLE/IMMUTABLE */
628         function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
629
630         /*
631          * Create the magic FOUND variable.
632          */
633         var = plpgsql_build_variable("found", 0,
634                                                                  plpgsql_build_datatype(BOOLOID, -1),
635                                                                  true);
636         function->found_varno = var->dno;
637
638         /*
639          * Forget about the above created variables
640          */
641         plpgsql_add_initdatums(NULL);
642
643         /*
644          * Now parse the function's text
645          */
646         parse_rc = plpgsql_yyparse();
647         if (parse_rc != 0)
648                 elog(ERROR, "plpgsql parser returned %d", parse_rc);
649         function->action = plpgsql_yylval.program;
650
651         plpgsql_scanner_finish();
652         pfree(proc_source);
653
654         /*
655          * If it has OUT parameters or returns VOID or returns a set, we allow
656          * control to fall off the end without an explicit RETURN statement. The
657          * easiest way to implement this is to add a RETURN statement to the end
658          * of the statement list during parsing.  However, if the outer block has
659          * an EXCEPTION clause, we need to make a new outer block, since the added
660          * RETURN shouldn't act like it is inside the EXCEPTION clause.
661          */
662         if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
663                 function->fn_retset)
664         {
665                 if (function->action->exceptions != NULL)
666                 {
667                         PLpgSQL_stmt_block *new;
668
669                         new = palloc0(sizeof(PLpgSQL_stmt_block));
670                         new->cmd_type = PLPGSQL_STMT_BLOCK;
671                         new->body = list_make1(function->action);
672
673                         function->action = new;
674                 }
675                 if (function->action->body == NIL ||
676                         ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
677                 {
678                         PLpgSQL_stmt_return *new;
679
680                         new = palloc0(sizeof(PLpgSQL_stmt_return));
681                         new->cmd_type = PLPGSQL_STMT_RETURN;
682                         new->expr = NULL;
683                         new->retvarno = function->out_param_varno;
684
685                         function->action->body = lappend(function->action->body, new);
686                 }
687         }
688
689         /*
690          * Complete the function's info
691          */
692         function->fn_nargs = procStruct->pronargs;
693         for (i = 0; i < function->fn_nargs; i++)
694                 function->fn_argvarnos[i] = in_arg_varnos[i];
695         function->ndatums = plpgsql_nDatums;
696         function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
697         for (i = 0; i < plpgsql_nDatums; i++)
698                 function->datums[i] = plpgsql_Datums[i];
699
700         /* Debug dump for completed functions */
701         if (plpgsql_DumpExecTree)
702                 plpgsql_dumptree(function);
703
704         /*
705          * add it to the hash table
706          */
707         plpgsql_HashTableInsert(function, hashkey);
708
709         /*
710          * Pop the error context stack
711          */
712         error_context_stack = plerrcontext.previous;
713         plpgsql_error_funcname = NULL;
714         plpgsql_error_lineno = 0;
715
716         plpgsql_check_syntax = false;
717
718         MemoryContextSwitchTo(compile_tmp_cxt);
719         compile_tmp_cxt = NULL;
720         return function;
721 }
722
723
724 /*
725  * error context callback to let us supply a call-stack traceback. If
726  * we are validating, the function source is passed as an
727  * argument. This function is public only for the sake of an assertion
728  * in gram.y
729  */
730 void
731 plpgsql_compile_error_callback(void *arg)
732 {
733         if (arg)
734         {
735                 /*
736                  * Try to convert syntax error position to reference text of original
737                  * CREATE FUNCTION command.
738                  */
739                 if (function_parse_error_transpose((const char *) arg))
740                         return;
741
742                 /*
743                  * Done if a syntax error position was reported; otherwise we have to
744                  * fall back to a "near line N" report.
745                  */
746         }
747
748         if (plpgsql_error_funcname)
749                 errcontext("compile of PL/pgSQL function \"%s\" near line %d",
750                                    plpgsql_error_funcname, plpgsql_error_lineno);
751 }
752
753
754 /*
755  * Fetch info about the argument types, names, and IN/OUT modes from the
756  * pg_proc tuple.  Return value is the number of arguments.
757  * Other results are palloc'd.
758  */
759 static int
760 fetchArgInfo(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames,
761                          char **p_argmodes)
762 {
763         Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
764         Datum           proallargtypes;
765         Datum           proargmodes;
766         Datum           proargnames;
767         bool            isNull;
768         ArrayType  *arr;
769         int                     numargs;
770         Datum      *elems;
771         int                     nelems;
772         int                     i;
773
774         /* First discover the total number of parameters and get their types */
775         proallargtypes = SysCacheGetAttr(PROCOID, procTup,
776                                                                          Anum_pg_proc_proallargtypes,
777                                                                          &isNull);
778         if (!isNull)
779         {
780                 /*
781                  * We expect the arrays to be 1-D arrays of the right types; verify
782                  * that.  For the OID and char arrays, we don't need to use
783                  * deconstruct_array() since the array data is just going to look like
784                  * a C array of values.
785                  */
786                 arr = DatumGetArrayTypeP(proallargtypes);               /* ensure not toasted */
787                 numargs = ARR_DIMS(arr)[0];
788                 if (ARR_NDIM(arr) != 1 ||
789                         numargs < 0 ||
790                         ARR_ELEMTYPE(arr) != OIDOID)
791                         elog(ERROR, "proallargtypes is not a 1-D Oid array");
792                 Assert(numargs >= procStruct->pronargs);
793                 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
794                 memcpy(*p_argtypes, ARR_DATA_PTR(arr),
795                            numargs * sizeof(Oid));
796         }
797         else
798         {
799                 /* If no proallargtypes, use proargtypes */
800                 numargs = procStruct->proargtypes.dim1;
801                 Assert(numargs == procStruct->pronargs);
802                 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
803                 memcpy(*p_argtypes, procStruct->proargtypes.values,
804                            numargs * sizeof(Oid));
805         }
806
807         /* Get argument names, if available */
808         proargnames = SysCacheGetAttr(PROCOID, procTup,
809                                                                   Anum_pg_proc_proargnames,
810                                                                   &isNull);
811         if (isNull)
812                 *p_argnames = NULL;
813         else
814         {
815                 deconstruct_array(DatumGetArrayTypeP(proargnames),
816                                                   TEXTOID, -1, false, 'i',
817                                                   &elems, &nelems);
818                 if (nelems != numargs)  /* should not happen */
819                         elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
820                 *p_argnames = (char **) palloc(sizeof(char *) * numargs);
821                 for (i = 0; i < numargs; i++)
822                         (*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
823                                                                                                                                    elems[i]));
824         }
825
826         /* Get argument modes, if available */
827         proargmodes = SysCacheGetAttr(PROCOID, procTup,
828                                                                   Anum_pg_proc_proargmodes,
829                                                                   &isNull);
830         if (isNull)
831                 *p_argmodes = NULL;
832         else
833         {
834                 arr = DatumGetArrayTypeP(proargmodes);  /* ensure not toasted */
835                 if (ARR_NDIM(arr) != 1 ||
836                         ARR_DIMS(arr)[0] != numargs ||
837                         ARR_ELEMTYPE(arr) != CHAROID)
838                         elog(ERROR, "proargmodes is not a 1-D char array");
839                 *p_argmodes = (char *) palloc(numargs * sizeof(char));
840                 memcpy(*p_argmodes, ARR_DATA_PTR(arr),
841                            numargs * sizeof(char));
842         }
843
844         return numargs;
845 }
846
847
848 /* ----------
849  * plpgsql_parse_word           The scanner calls this to postparse
850  *                              any single word not found by a
851  *                              keyword rule.
852  * ----------
853  */
854 int
855 plpgsql_parse_word(char *word)
856 {
857         PLpgSQL_nsitem *nse;
858         char       *cp[1];
859
860         /* Do case conversion and word separation */
861         plpgsql_convert_ident(word, cp, 1);
862
863         /*
864          * Recognize tg_argv when compiling triggers
865          */
866         if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
867         {
868                 if (strcmp(cp[0], "tg_argv") == 0)
869                 {
870                         bool            save_spacescanned = plpgsql_SpaceScanned;
871                         PLpgSQL_trigarg *trigarg;
872
873                         trigarg = palloc0(sizeof(PLpgSQL_trigarg));
874                         trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
875
876                         if (plpgsql_yylex() != '[')
877                                 plpgsql_yyerror("expected \"[\"");
878
879                         trigarg->argnum = plpgsql_read_expression(']', "]");
880
881                         plpgsql_adddatum((PLpgSQL_datum *) trigarg);
882                         plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
883
884                         plpgsql_SpaceScanned = save_spacescanned;
885                         pfree(cp[0]);
886                         return T_SCALAR;
887                 }
888         }
889
890         /*
891          * Do a lookup on the compiler's namestack
892          */
893         nse = plpgsql_ns_lookup(cp[0], NULL);
894         if (nse != NULL)
895         {
896                 pfree(cp[0]);
897                 switch (nse->itemtype)
898                 {
899                         case PLPGSQL_NSTYPE_LABEL:
900                                 return T_LABEL;
901
902                         case PLPGSQL_NSTYPE_VAR:
903                                 plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
904                                 return T_SCALAR;
905
906                         case PLPGSQL_NSTYPE_REC:
907                                 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
908                                 return T_RECORD;
909
910                         case PLPGSQL_NSTYPE_ROW:
911                                 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
912                                 return T_ROW;
913
914                         default:
915                                 return T_ERROR;
916                 }
917         }
918
919         /*
920          * Nothing found - up to now it's a word without any special meaning for
921          * us.
922          */
923         pfree(cp[0]);
924         return T_WORD;
925 }
926
927
928 /* ----------
929  * plpgsql_parse_dblword                Same lookup for two words
930  *                                      separated by a dot.
931  * ----------
932  */
933 int
934 plpgsql_parse_dblword(char *word)
935 {
936         PLpgSQL_nsitem *ns;
937         char       *cp[2];
938
939         /* Do case conversion and word separation */
940         plpgsql_convert_ident(word, cp, 2);
941
942         /*
943          * Lookup the first word
944          */
945         ns = plpgsql_ns_lookup(cp[0], NULL);
946         if (ns == NULL)
947         {
948                 pfree(cp[0]);
949                 pfree(cp[1]);
950                 return T_ERROR;
951         }
952
953         switch (ns->itemtype)
954         {
955                 case PLPGSQL_NSTYPE_LABEL:
956
957                         /*
958                          * First word is a label, so second word could be a variable,
959                          * record or row in that bodies namestack. Anything else could
960                          * only be something in a query given to the SPI manager and
961                          * T_ERROR will get eaten up by the collector routines.
962                          */
963                         ns = plpgsql_ns_lookup(cp[1], cp[0]);
964                         pfree(cp[0]);
965                         pfree(cp[1]);
966                         if (ns == NULL)
967                                 return T_ERROR;
968                         switch (ns->itemtype)
969                         {
970                                 case PLPGSQL_NSTYPE_VAR:
971                                         plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
972                                         return T_SCALAR;
973
974                                 case PLPGSQL_NSTYPE_REC:
975                                         plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
976                                         return T_RECORD;
977
978                                 case PLPGSQL_NSTYPE_ROW:
979                                         plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
980                                         return T_ROW;
981
982                                 default:
983                                         return T_ERROR;
984                         }
985                         break;
986
987                 case PLPGSQL_NSTYPE_REC:
988                         {
989                                 /*
990                                  * First word is a record name, so second word must be a field
991                                  * in this record.
992                                  */
993                                 PLpgSQL_recfield *new;
994
995                                 new = palloc(sizeof(PLpgSQL_recfield));
996                                 new->dtype = PLPGSQL_DTYPE_RECFIELD;
997                                 new->fieldname = pstrdup(cp[1]);
998                                 new->recparentno = ns->itemno;
999
1000                                 plpgsql_adddatum((PLpgSQL_datum *) new);
1001
1002                                 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1003
1004                                 pfree(cp[0]);
1005                                 pfree(cp[1]);
1006                                 return T_SCALAR;
1007                         }
1008
1009                 case PLPGSQL_NSTYPE_ROW:
1010                         {
1011                                 /*
1012                                  * First word is a row name, so second word must be a field in
1013                                  * this row.
1014                                  */
1015                                 PLpgSQL_row *row;
1016                                 int                     i;
1017
1018                                 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1019                                 for (i = 0; i < row->nfields; i++)
1020                                 {
1021                                         if (row->fieldnames[i] &&
1022                                                 strcmp(row->fieldnames[i], cp[1]) == 0)
1023                                         {
1024                                                 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1025                                                 pfree(cp[0]);
1026                                                 pfree(cp[1]);
1027                                                 return T_SCALAR;
1028                                         }
1029                                 }
1030                                 ereport(ERROR,
1031                                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
1032                                                  errmsg("row \"%s\" has no field \"%s\"",
1033                                                                 cp[0], cp[1])));
1034                         }
1035
1036                 default:
1037                         break;
1038         }
1039
1040         pfree(cp[0]);
1041         pfree(cp[1]);
1042         return T_ERROR;
1043 }
1044
1045
1046 /* ----------
1047  * plpgsql_parse_tripword               Same lookup for three words
1048  *                                      separated by dots.
1049  * ----------
1050  */
1051 int
1052 plpgsql_parse_tripword(char *word)
1053 {
1054         PLpgSQL_nsitem *ns;
1055         char       *cp[3];
1056
1057         /* Do case conversion and word separation */
1058         plpgsql_convert_ident(word, cp, 3);
1059
1060         /*
1061          * Lookup the first word - it must be a label
1062          */
1063         ns = plpgsql_ns_lookup(cp[0], NULL);
1064         if (ns == NULL)
1065         {
1066                 pfree(cp[0]);
1067                 pfree(cp[1]);
1068                 pfree(cp[2]);
1069                 return T_ERROR;
1070         }
1071         if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
1072         {
1073                 pfree(cp[0]);
1074                 pfree(cp[1]);
1075                 pfree(cp[2]);
1076                 return T_ERROR;
1077         }
1078
1079         /*
1080          * First word is a label, so second word could be a record or row
1081          */
1082         ns = plpgsql_ns_lookup(cp[1], cp[0]);
1083         if (ns == NULL)
1084         {
1085                 pfree(cp[0]);
1086                 pfree(cp[1]);
1087                 pfree(cp[2]);
1088                 return T_ERROR;
1089         }
1090
1091         switch (ns->itemtype)
1092         {
1093                 case PLPGSQL_NSTYPE_REC:
1094                         {
1095                                 /*
1096                                  * This word is a record name, so third word must be a field
1097                                  * in this record.
1098                                  */
1099                                 PLpgSQL_recfield *new;
1100
1101                                 new = palloc(sizeof(PLpgSQL_recfield));
1102                                 new->dtype = PLPGSQL_DTYPE_RECFIELD;
1103                                 new->fieldname = pstrdup(cp[2]);
1104                                 new->recparentno = ns->itemno;
1105
1106                                 plpgsql_adddatum((PLpgSQL_datum *) new);
1107
1108                                 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1109
1110                                 pfree(cp[0]);
1111                                 pfree(cp[1]);
1112                                 pfree(cp[2]);
1113
1114                                 return T_SCALAR;
1115                         }
1116
1117                 case PLPGSQL_NSTYPE_ROW:
1118                         {
1119                                 /*
1120                                  * This word is a row name, so third word must be a field in
1121                                  * this row.
1122                                  */
1123                                 PLpgSQL_row *row;
1124                                 int                     i;
1125
1126                                 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1127                                 for (i = 0; i < row->nfields; i++)
1128                                 {
1129                                         if (row->fieldnames[i] &&
1130                                                 strcmp(row->fieldnames[i], cp[2]) == 0)
1131                                         {
1132                                                 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1133
1134                                                 pfree(cp[0]);
1135                                                 pfree(cp[1]);
1136                                                 pfree(cp[2]);
1137
1138                                                 return T_SCALAR;
1139                                         }
1140                                 }
1141                                 ereport(ERROR,
1142                                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
1143                                                  errmsg("row \"%s.%s\" has no field \"%s\"",
1144                                                                 cp[0], cp[1], cp[2])));
1145                         }
1146
1147                 default:
1148                         break;
1149         }
1150
1151         pfree(cp[0]);
1152         pfree(cp[1]);
1153         pfree(cp[2]);
1154         return T_ERROR;
1155 }
1156
1157
1158 /* ----------
1159  * plpgsql_parse_wordtype       The scanner found word%TYPE. word can be
1160  *                              a variable name or a basetype.
1161  * ----------
1162  */
1163 int
1164 plpgsql_parse_wordtype(char *word)
1165 {
1166         PLpgSQL_nsitem *nse;
1167         bool            old_nsstate;
1168         Oid                     typeOid;
1169         char       *cp[2];
1170         int                     i;
1171
1172         /* Do case conversion and word separation */
1173         /* We convert %type to .type momentarily to keep converter happy */
1174         i = strlen(word) - 5;
1175         Assert(word[i] == '%');
1176         word[i] = '.';
1177         plpgsql_convert_ident(word, cp, 2);
1178         word[i] = '%';
1179         pfree(cp[1]);
1180
1181         /*
1182          * Do a lookup on the compiler's namestack. But ensure it moves up to the
1183          * toplevel.
1184          */
1185         old_nsstate = plpgsql_ns_setlocal(false);
1186         nse = plpgsql_ns_lookup(cp[0], NULL);
1187         plpgsql_ns_setlocal(old_nsstate);
1188
1189         if (nse != NULL)
1190         {
1191                 pfree(cp[0]);
1192                 switch (nse->itemtype)
1193                 {
1194                         case PLPGSQL_NSTYPE_VAR:
1195                                 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1196                                 return T_DTYPE;
1197
1198                                 /* XXX perhaps allow REC here? */
1199
1200                         default:
1201                                 return T_ERROR;
1202                 }
1203         }
1204
1205         /*
1206          * Word wasn't found on the namestack. Try to find a data type with that
1207          * name, but ignore pg_type entries that are in fact class types.
1208          */
1209         typeOid = LookupTypeName(makeTypeName(cp[0]));
1210         if (OidIsValid(typeOid))
1211         {
1212                 HeapTuple       typeTup;
1213
1214                 typeTup = SearchSysCache(TYPEOID,
1215                                                                  ObjectIdGetDatum(typeOid),
1216                                                                  0, 0, 0);
1217                 if (HeapTupleIsValid(typeTup))
1218                 {
1219                         Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1220
1221                         if (!typeStruct->typisdefined ||
1222                                 typeStruct->typrelid != InvalidOid)
1223                         {
1224                                 ReleaseSysCache(typeTup);
1225                                 pfree(cp[0]);
1226                                 return T_ERROR;
1227                         }
1228
1229                         plpgsql_yylval.dtype = build_datatype(typeTup, -1);
1230
1231                         ReleaseSysCache(typeTup);
1232                         pfree(cp[0]);
1233                         return T_DTYPE;
1234                 }
1235         }
1236
1237         /*
1238          * Nothing found - up to now it's a word without any special meaning for
1239          * us.
1240          */
1241         pfree(cp[0]);
1242         return T_ERROR;
1243 }
1244
1245
1246 /* ----------
1247  * plpgsql_parse_dblwordtype            Same lookup for word.word%TYPE
1248  * ----------
1249  */
1250 int
1251 plpgsql_parse_dblwordtype(char *word)
1252 {
1253         PLpgSQL_nsitem *nse;
1254         bool            old_nsstate;
1255         Oid                     classOid;
1256         HeapTuple       classtup = NULL;
1257         HeapTuple       attrtup = NULL;
1258         HeapTuple       typetup = NULL;
1259         Form_pg_class classStruct;
1260         Form_pg_attribute attrStruct;
1261         char       *cp[3];
1262         int                     i;
1263         MemoryContext oldCxt;
1264         int                     result = T_ERROR;
1265
1266         /* Avoid memory leaks in the long-term function context */
1267         oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1268
1269         /* Do case conversion and word separation */
1270         /* We convert %type to .type momentarily to keep converter happy */
1271         i = strlen(word) - 5;
1272         Assert(word[i] == '%');
1273         word[i] = '.';
1274         plpgsql_convert_ident(word, cp, 3);
1275         word[i] = '%';
1276
1277         /*
1278          * Lookup the first word
1279          */
1280         nse = plpgsql_ns_lookup(cp[0], NULL);
1281
1282         /*
1283          * If this is a label lookup the second word in that label's namestack
1284          * level
1285          */
1286         if (nse != NULL)
1287         {
1288                 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
1289                 {
1290                         old_nsstate = plpgsql_ns_setlocal(false);
1291                         nse = plpgsql_ns_lookup(cp[1], cp[0]);
1292                         plpgsql_ns_setlocal(old_nsstate);
1293
1294                         if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1295                         {
1296                                 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1297                                 result = T_DTYPE;
1298                         }
1299                 }
1300
1301                 /* Return T_ERROR if not found, otherwise T_DTYPE */
1302                 goto done;
1303         }
1304
1305         /*
1306          * First word could also be a table name
1307          */
1308         classOid = RelnameGetRelid(cp[0]);
1309         if (!OidIsValid(classOid))
1310                 goto done;
1311
1312         classtup = SearchSysCache(RELOID,
1313                                                           ObjectIdGetDatum(classOid),
1314                                                           0, 0, 0);
1315         if (!HeapTupleIsValid(classtup))
1316                 goto done;
1317
1318         /*
1319          * It must be a relation, sequence, view, or type
1320          */
1321         classStruct = (Form_pg_class) GETSTRUCT(classtup);
1322         if (classStruct->relkind != RELKIND_RELATION &&
1323                 classStruct->relkind != RELKIND_SEQUENCE &&
1324                 classStruct->relkind != RELKIND_VIEW &&
1325                 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1326                 goto done;
1327
1328         /*
1329          * Fetch the named table field and it's type
1330          */
1331         attrtup = SearchSysCacheAttName(classOid, cp[1]);
1332         if (!HeapTupleIsValid(attrtup))
1333                 goto done;
1334
1335         attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1336         typetup = SearchSysCache(TYPEOID,
1337                                                          ObjectIdGetDatum(attrStruct->atttypid),
1338                                                          0, 0, 0);
1339         if (!HeapTupleIsValid(typetup))
1340                 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1341
1342         /*
1343          * Found that - build a compiler type struct in the caller's cxt and
1344          * return it
1345          */
1346         MemoryContextSwitchTo(oldCxt);
1347         plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1348         MemoryContextSwitchTo(compile_tmp_cxt);
1349         result = T_DTYPE;
1350
1351 done:
1352         if (HeapTupleIsValid(classtup))
1353                 ReleaseSysCache(classtup);
1354         if (HeapTupleIsValid(attrtup))
1355                 ReleaseSysCache(attrtup);
1356         if (HeapTupleIsValid(typetup))
1357                 ReleaseSysCache(typetup);
1358
1359         MemoryContextSwitchTo(oldCxt);
1360         return result;
1361 }
1362
1363 /* ----------
1364  * plpgsql_parse_tripwordtype           Same lookup for word.word.word%TYPE
1365  * ----------
1366  */
1367 #define TYPE_JUNK_LEN   5
1368
1369 int
1370 plpgsql_parse_tripwordtype(char *word)
1371 {
1372         Oid                     classOid;
1373         HeapTuple       classtup = NULL;
1374         Form_pg_class classStruct;
1375         HeapTuple       attrtup = NULL;
1376         Form_pg_attribute attrStruct;
1377         HeapTuple       typetup = NULL;
1378         char       *cp[2];
1379         char       *colname[1];
1380         int                     qualified_att_len;
1381         int                     numdots = 0;
1382         int                     i;
1383         RangeVar   *relvar;
1384         MemoryContext oldCxt;
1385         int                     result = T_ERROR;
1386
1387         /* Avoid memory leaks in the long-term function context */
1388         oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1389
1390         /* Do case conversion and word separation */
1391         qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
1392         Assert(word[qualified_att_len] == '%');
1393
1394         for (i = 0; i < qualified_att_len; i++)
1395         {
1396                 if (word[i] == '.' && ++numdots == 2)
1397                         break;
1398         }
1399
1400         cp[0] = (char *) palloc((i + 1) * sizeof(char));
1401         memcpy(cp[0], word, i * sizeof(char));
1402         cp[0][i] = '\0';
1403
1404         /*
1405          * qualified_att_len - one based position + 1 (null terminator)
1406          */
1407         cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));
1408         memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));
1409         cp[1][qualified_att_len - i - 1] = '\0';
1410
1411         relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0],
1412                                                                                           "plpgsql_parse_tripwordtype"));
1413         classOid = RangeVarGetRelid(relvar, true);
1414         if (!OidIsValid(classOid))
1415                 goto done;
1416
1417         classtup = SearchSysCache(RELOID,
1418                                                           ObjectIdGetDatum(classOid),
1419                                                           0, 0, 0);
1420         if (!HeapTupleIsValid(classtup))
1421                 goto done;
1422
1423         /*
1424          * It must be a relation, sequence, view, or type
1425          */
1426         classStruct = (Form_pg_class) GETSTRUCT(classtup);
1427         if (classStruct->relkind != RELKIND_RELATION &&
1428                 classStruct->relkind != RELKIND_SEQUENCE &&
1429                 classStruct->relkind != RELKIND_VIEW &&
1430                 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1431                 goto done;
1432
1433         /*
1434          * Fetch the named table field and it's type
1435          */
1436         plpgsql_convert_ident(cp[1], colname, 1);
1437         attrtup = SearchSysCacheAttName(classOid, colname[0]);
1438         if (!HeapTupleIsValid(attrtup))
1439                 goto done;
1440
1441         attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1442         typetup = SearchSysCache(TYPEOID,
1443                                                          ObjectIdGetDatum(attrStruct->atttypid),
1444                                                          0, 0, 0);
1445         if (!HeapTupleIsValid(typetup))
1446                 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1447
1448         /*
1449          * Found that - build a compiler type struct in the caller's cxt and
1450          * return it
1451          */
1452         MemoryContextSwitchTo(oldCxt);
1453         plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1454         MemoryContextSwitchTo(compile_tmp_cxt);
1455         result = T_DTYPE;
1456
1457 done:
1458         if (HeapTupleIsValid(classtup))
1459                 ReleaseSysCache(classtup);
1460         if (HeapTupleIsValid(classtup))
1461                 ReleaseSysCache(attrtup);
1462         if (HeapTupleIsValid(typetup))
1463                 ReleaseSysCache(typetup);
1464
1465         MemoryContextSwitchTo(oldCxt);
1466         return result;
1467 }
1468
1469 /* ----------
1470  * plpgsql_parse_wordrowtype            Scanner found word%ROWTYPE.
1471  *                                      So word must be a table name.
1472  * ----------
1473  */
1474 int
1475 plpgsql_parse_wordrowtype(char *word)
1476 {
1477         Oid                     classOid;
1478         char       *cp[2];
1479         int                     i;
1480
1481         /* Do case conversion and word separation */
1482         /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1483         i = strlen(word) - 8;
1484         Assert(word[i] == '%');
1485         word[i] = '.';
1486         plpgsql_convert_ident(word, cp, 2);
1487         word[i] = '%';
1488
1489         /* Lookup the relation */
1490         classOid = RelnameGetRelid(cp[0]);
1491         if (!OidIsValid(classOid))
1492                 ereport(ERROR,
1493                                 (errcode(ERRCODE_UNDEFINED_TABLE),
1494                                  errmsg("relation \"%s\" does not exist", cp[0])));
1495
1496         /*
1497          * Build and return the row type struct
1498          */
1499         plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1500                                                                                                   -1);
1501
1502         pfree(cp[0]);
1503         pfree(cp[1]);
1504
1505         return T_DTYPE;
1506 }
1507
1508 /* ----------
1509  * plpgsql_parse_dblwordrowtype         Scanner found word.word%ROWTYPE.
1510  *                      So word must be a namespace qualified table name.
1511  * ----------
1512  */
1513 #define ROWTYPE_JUNK_LEN        8
1514
1515 int
1516 plpgsql_parse_dblwordrowtype(char *word)
1517 {
1518         Oid                     classOid;
1519         char       *cp;
1520         int                     i;
1521         RangeVar   *relvar;
1522         MemoryContext oldCxt;
1523
1524         /* Avoid memory leaks in long-term function context */
1525         oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1526
1527         /* Do case conversion and word separation */
1528         /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1529         i = strlen(word) - ROWTYPE_JUNK_LEN;
1530         Assert(word[i] == '%');
1531         word[i] = '\0';
1532         cp = pstrdup(word);
1533         word[i] = '%';
1534
1535         /* Lookup the relation */
1536         relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
1537         classOid = RangeVarGetRelid(relvar, true);
1538         if (!OidIsValid(classOid))
1539                 ereport(ERROR,
1540                                 (errcode(ERRCODE_UNDEFINED_TABLE),
1541                                  errmsg("relation \"%s\" does not exist", cp)));
1542
1543         /* Build and return the row type struct */
1544         plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1545                                                                                                   -1);
1546
1547         MemoryContextSwitchTo(oldCxt);
1548         return T_DTYPE;
1549 }
1550
1551 /*
1552  * plpgsql_build_variable - build a datum-array entry of a given
1553  * datatype
1554  *
1555  * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or
1556  * PLpgSQL_rec depending on the given datatype, and is allocated via
1557  * palloc.      The struct is automatically added to the current datum
1558  * array, and optionally to the current namespace.
1559  */
1560 PLpgSQL_variable *
1561 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type * dtype,
1562                                            bool add2namespace)
1563 {
1564         PLpgSQL_variable *result;
1565
1566         switch (dtype->ttype)
1567         {
1568                 case PLPGSQL_TTYPE_SCALAR:
1569                         {
1570                                 /* Ordinary scalar datatype */
1571                                 PLpgSQL_var *var;
1572
1573                                 var = palloc0(sizeof(PLpgSQL_var));
1574                                 var->dtype = PLPGSQL_DTYPE_VAR;
1575                                 var->refname = pstrdup(refname);
1576                                 var->lineno = lineno;
1577                                 var->datatype = dtype;
1578                                 /* other fields might be filled by caller */
1579
1580                                 /* preset to NULL */
1581                                 var->value = 0;
1582                                 var->isnull = true;
1583                                 var->freeval = false;
1584
1585                                 plpgsql_adddatum((PLpgSQL_datum *) var);
1586                                 if (add2namespace)
1587                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1588                                                                            var->varno,
1589                                                                            refname);
1590                                 result = (PLpgSQL_variable *) var;
1591                                 break;
1592                         }
1593                 case PLPGSQL_TTYPE_ROW:
1594                         {
1595                                 /* Composite type -- build a row variable */
1596                                 PLpgSQL_row *row;
1597
1598                                 row = build_row_from_class(dtype->typrelid);
1599
1600                                 row->dtype = PLPGSQL_DTYPE_ROW;
1601                                 row->refname = pstrdup(refname);
1602                                 row->lineno = lineno;
1603
1604                                 plpgsql_adddatum((PLpgSQL_datum *) row);
1605                                 if (add2namespace)
1606                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
1607                                                                            row->rowno,
1608                                                                            refname);
1609                                 result = (PLpgSQL_variable *) row;
1610                                 break;
1611                         }
1612                 case PLPGSQL_TTYPE_REC:
1613                         {
1614                                 /*
1615                                  * "record" type -- build a variable-contents record variable
1616                                  */
1617                                 PLpgSQL_rec *rec;
1618
1619                                 rec = palloc0(sizeof(PLpgSQL_rec));
1620                                 rec->dtype = PLPGSQL_DTYPE_REC;
1621                                 rec->refname = pstrdup(refname);
1622                                 rec->lineno = lineno;
1623
1624                                 plpgsql_adddatum((PLpgSQL_datum *) rec);
1625                                 if (add2namespace)
1626                                         plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
1627                                                                            rec->recno,
1628                                                                            refname);
1629                                 result = (PLpgSQL_variable *) rec;
1630                                 break;
1631                         }
1632                 case PLPGSQL_TTYPE_PSEUDO:
1633                         ereport(ERROR,
1634                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1635                                          errmsg("variable \"%s\" has pseudo-type %s",
1636                                                         refname, format_type_be(dtype->typoid))));
1637                         result = NULL;          /* keep compiler quiet */
1638                         break;
1639                 default:
1640                         elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1641                         result = NULL;          /* keep compiler quiet */
1642                         break;
1643         }
1644
1645         return result;
1646 }
1647
1648 /*
1649  * Build a row-variable data structure given the pg_class OID.
1650  */
1651 static PLpgSQL_row *
1652 build_row_from_class(Oid classOid)
1653 {
1654         PLpgSQL_row *row;
1655         Relation        rel;
1656         Form_pg_class classStruct;
1657         const char *relname;
1658         int                     i;
1659
1660         /*
1661          * Open the relation to get info.
1662          */
1663         rel = relation_open(classOid, AccessShareLock);
1664         classStruct = RelationGetForm(rel);
1665         relname = RelationGetRelationName(rel);
1666
1667         /* accept relation, sequence, view, or composite type entries */
1668         if (classStruct->relkind != RELKIND_RELATION &&
1669                 classStruct->relkind != RELKIND_SEQUENCE &&
1670                 classStruct->relkind != RELKIND_VIEW &&
1671                 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1672                 ereport(ERROR,
1673                                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1674                                  errmsg("relation \"%s\" is not a table", relname)));
1675
1676         /*
1677          * Create a row datum entry and all the required variables that it will
1678          * point to.
1679          */
1680         row = palloc0(sizeof(PLpgSQL_row));
1681         row->dtype = PLPGSQL_DTYPE_ROW;
1682         row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
1683         row->nfields = classStruct->relnatts;
1684         row->fieldnames = palloc(sizeof(char *) * row->nfields);
1685         row->varnos = palloc(sizeof(int) * row->nfields);
1686
1687         for (i = 0; i < row->nfields; i++)
1688         {
1689                 Form_pg_attribute attrStruct;
1690
1691                 /*
1692                  * Get the attribute and check for dropped column
1693                  */
1694                 attrStruct = row->rowtupdesc->attrs[i];
1695
1696                 if (!attrStruct->attisdropped)
1697                 {
1698                         char       *attname;
1699                         char            refname[(NAMEDATALEN * 2) + 100];
1700                         PLpgSQL_variable *var;
1701
1702                         attname = NameStr(attrStruct->attname);
1703                         snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
1704
1705                         /*
1706                          * Create the internal variable for the field
1707                          *
1708                          * We know if the table definitions contain a default value or if the
1709                          * field is declared in the table as NOT NULL. But it's possible
1710                          * to create a table field as NOT NULL without a default value and
1711                          * that would lead to problems later when initializing the
1712                          * variables due to entering a block at execution time. Thus we
1713                          * ignore this information for now.
1714                          */
1715                         var = plpgsql_build_variable(refname, 0,
1716                                                                  plpgsql_build_datatype(attrStruct->atttypid,
1717                                                                                                           attrStruct->atttypmod),
1718                                                                                  false);
1719
1720                         /* Add the variable to the row */
1721                         row->fieldnames[i] = attname;
1722                         row->varnos[i] = var->dno;
1723                 }
1724                 else
1725                 {
1726                         /* Leave a hole in the row structure for the dropped col */
1727                         row->fieldnames[i] = NULL;
1728                         row->varnos[i] = -1;
1729                 }
1730         }
1731
1732         relation_close(rel, AccessShareLock);
1733
1734         return row;
1735 }
1736
1737 /*
1738  * Build a row-variable data structure given the component variables.
1739  */
1740 static PLpgSQL_row *
1741 build_row_from_vars(PLpgSQL_variable ** vars, int numvars)
1742 {
1743         PLpgSQL_row *row;
1744         int                     i;
1745
1746         row = palloc0(sizeof(PLpgSQL_row));
1747         row->dtype = PLPGSQL_DTYPE_ROW;
1748         row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
1749         row->nfields = numvars;
1750         row->fieldnames = palloc(numvars * sizeof(char *));
1751         row->varnos = palloc(numvars * sizeof(int));
1752
1753         for (i = 0; i < numvars; i++)
1754         {
1755                 PLpgSQL_variable *var = vars[i];
1756                 Oid                     typoid = RECORDOID;
1757                 int32           typmod = -1;
1758
1759                 switch (var->dtype)
1760                 {
1761                         case PLPGSQL_DTYPE_VAR:
1762                                 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1763                                 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1764                                 break;
1765
1766                         case PLPGSQL_DTYPE_REC:
1767                                 break;
1768
1769                         case PLPGSQL_DTYPE_ROW:
1770                                 if (((PLpgSQL_row *) var)->rowtupdesc)
1771                                 {
1772                                         typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
1773                                         typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
1774                                 }
1775                                 break;
1776
1777                         default:
1778                                 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1779                 }
1780
1781                 row->fieldnames[i] = var->refname;
1782                 row->varnos[i] = var->dno;
1783
1784                 TupleDescInitEntry(row->rowtupdesc, i + 1,
1785                                                    var->refname,
1786                                                    typoid, typmod,
1787                                                    0);
1788         }
1789
1790         return row;
1791 }
1792
1793
1794 /* ----------
1795  * plpgsql_parse_datatype                       Scanner found something that should
1796  *                                      be a datatype name.
1797  * ----------
1798  */
1799 PLpgSQL_type *
1800 plpgsql_parse_datatype(const char *string)
1801 {
1802         Oid                     type_id;
1803         int32           typmod;
1804
1805         /* Let the main parser try to parse it under standard SQL rules */
1806         parseTypeString(string, &type_id, &typmod);
1807
1808         /* Okay, build a PLpgSQL_type data structure for it */
1809         return plpgsql_build_datatype(type_id, typmod);
1810 }
1811
1812 /*
1813  * plpgsql_build_datatype
1814  *              Build PLpgSQL_type struct given type OID and typmod.
1815  */
1816 PLpgSQL_type *
1817 plpgsql_build_datatype(Oid typeOid, int32 typmod)
1818 {
1819         HeapTuple       typeTup;
1820         PLpgSQL_type *typ;
1821
1822         typeTup = SearchSysCache(TYPEOID,
1823                                                          ObjectIdGetDatum(typeOid),
1824                                                          0, 0, 0);
1825         if (!HeapTupleIsValid(typeTup))
1826                 elog(ERROR, "cache lookup failed for type %u", typeOid);
1827
1828         typ = build_datatype(typeTup, typmod);
1829
1830         ReleaseSysCache(typeTup);
1831
1832         return typ;
1833 }
1834
1835 /*
1836  * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1837  */
1838 static PLpgSQL_type *
1839 build_datatype(HeapTuple typeTup, int32 typmod)
1840 {
1841         Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1842         PLpgSQL_type *typ;
1843
1844         if (!typeStruct->typisdefined)
1845                 ereport(ERROR,
1846                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1847                                  errmsg("type \"%s\" is only a shell",
1848                                                 NameStr(typeStruct->typname))));
1849
1850         typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
1851
1852         typ->typname = pstrdup(NameStr(typeStruct->typname));
1853         typ->typoid = HeapTupleGetOid(typeTup);
1854         switch (typeStruct->typtype)
1855         {
1856                 case 'b':                               /* base type */
1857                 case 'd':                               /* domain */
1858                         typ->ttype = PLPGSQL_TTYPE_SCALAR;
1859                         break;
1860                 case 'c':                               /* composite, ie, rowtype */
1861                         Assert(OidIsValid(typeStruct->typrelid));
1862                         typ->ttype = PLPGSQL_TTYPE_ROW;
1863                         break;
1864                 case 'p':                               /* pseudo */
1865                         if (typ->typoid == RECORDOID)
1866                                 typ->ttype = PLPGSQL_TTYPE_REC;
1867                         else
1868                                 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
1869                         break;
1870                 default:
1871                         elog(ERROR, "unrecognized typtype: %d",
1872                                  (int) typeStruct->typtype);
1873                         break;
1874         }
1875         typ->typlen = typeStruct->typlen;
1876         typ->typbyval = typeStruct->typbyval;
1877         typ->typrelid = typeStruct->typrelid;
1878         typ->typioparam = getTypeIOParam(typeTup);
1879         fmgr_info(typeStruct->typinput, &(typ->typinput));
1880         typ->atttypmod = typmod;
1881
1882         return typ;
1883 }
1884
1885 /*
1886  * plpgsql_parse_err_condition
1887  *              Generate PLpgSQL_condition entry(s) for an exception condition name
1888  *
1889  * This has to be able to return a list because there are some duplicate
1890  * names in the table of error code names.
1891  */
1892 PLpgSQL_condition *
1893 plpgsql_parse_err_condition(char *condname)
1894 {
1895         int                     i;
1896         PLpgSQL_condition *new;
1897         PLpgSQL_condition *prev;
1898
1899         /*
1900          * XXX Eventually we will want to look for user-defined exception names
1901          * here.
1902          */
1903
1904         /*
1905          * OTHERS is represented as code 0 (which would map to '00000', but we
1906          * have no need to represent that as an exception condition).
1907          */
1908         if (strcmp(condname, "others") == 0)
1909         {
1910                 new = palloc(sizeof(PLpgSQL_condition));
1911                 new->sqlerrstate = 0;
1912                 new->condname = condname;
1913                 new->next = NULL;
1914                 return new;
1915         }
1916
1917         prev = NULL;
1918         for (i = 0; exception_label_map[i].label != NULL; i++)
1919         {
1920                 if (strcmp(condname, exception_label_map[i].label) == 0)
1921                 {
1922                         new = palloc(sizeof(PLpgSQL_condition));
1923                         new->sqlerrstate = exception_label_map[i].sqlerrstate;
1924                         new->condname = condname;
1925                         new->next = prev;
1926                         prev = new;
1927                 }
1928         }
1929
1930         if (!prev)
1931                 ereport(ERROR,
1932                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1933                                  errmsg("unrecognized exception condition \"%s\"",
1934                                                 condname)));
1935
1936         return prev;
1937 }
1938
1939 /* ----------
1940  * plpgsql_adddatum                     Add a variable, record or row
1941  *                                      to the compiler's datum list.
1942  * ----------
1943  */
1944 void
1945 plpgsql_adddatum(PLpgSQL_datum * new)
1946 {
1947         if (plpgsql_nDatums == datums_alloc)
1948         {
1949                 datums_alloc *= 2;
1950                 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1951         }
1952
1953         new->dno = plpgsql_nDatums;
1954         plpgsql_Datums[plpgsql_nDatums++] = new;
1955 }
1956
1957
1958 /* ----------
1959  * plpgsql_add_initdatums               Put all datum entries created
1960  *                                      since the last call into the
1961  *                                      finishing code block so the
1962  *                                      block knows which variables to
1963  *                                      reinitialize when entered.
1964  * ----------
1965  */
1966 int
1967 plpgsql_add_initdatums(int **varnos)
1968 {
1969         int                     i;
1970         int                     n = 0;
1971
1972         for (i = datums_last; i < plpgsql_nDatums; i++)
1973         {
1974                 switch (plpgsql_Datums[i]->dtype)
1975                 {
1976                         case PLPGSQL_DTYPE_VAR:
1977                                 n++;
1978                                 break;
1979
1980                         default:
1981                                 break;
1982                 }
1983         }
1984
1985         if (varnos != NULL)
1986         {
1987                 if (n > 0)
1988                 {
1989                         *varnos = (int *) palloc(sizeof(int) * n);
1990
1991                         n = 0;
1992                         for (i = datums_last; i < plpgsql_nDatums; i++)
1993                         {
1994                                 switch (plpgsql_Datums[i]->dtype)
1995                                 {
1996                                         case PLPGSQL_DTYPE_VAR:
1997                                                 (*varnos)[n++] = plpgsql_Datums[i]->dno;
1998
1999                                         default:
2000                                                 break;
2001                                 }
2002                         }
2003                 }
2004                 else
2005                         *varnos = NULL;
2006         }
2007
2008         datums_last = plpgsql_nDatums;
2009         return n;
2010 }
2011
2012
2013 /*
2014  * Compute the hashkey for a given function invocation
2015  *
2016  * The hashkey is returned into the caller-provided storage at *hashkey.
2017  */
2018 static void
2019 compute_function_hashkey(FunctionCallInfo fcinfo,
2020                                                  Form_pg_proc procStruct,
2021                                                  PLpgSQL_func_hashkey * hashkey,
2022                                                  bool forValidator)
2023 {
2024         /* Make sure any unused bytes of the struct are zero */
2025         MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2026
2027         /* get function OID */
2028         hashkey->funcOid = fcinfo->flinfo->fn_oid;
2029
2030         /*
2031          * if trigger, get relation OID.  In validation mode we do not know what
2032          * relation is intended to be used, so we leave trigrelOid zero; the hash
2033          * entry built in this case will never really be used.
2034          */
2035         if (CALLED_AS_TRIGGER(fcinfo) && !forValidator)
2036         {
2037                 TriggerData *trigdata = (TriggerData *) fcinfo->context;
2038
2039                 hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
2040         }
2041
2042         if (procStruct->pronargs > 0)
2043         {
2044                 /* get the argument types */
2045                 memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2046                            procStruct->pronargs * sizeof(Oid));
2047
2048                 /* resolve any polymorphic argument types */
2049                 plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2050                                                                                          hashkey->argtypes,
2051                                                                                          NULL,
2052                                                                                          fcinfo->flinfo->fn_expr,
2053                                                                                          forValidator,
2054                                                                                          NameStr(procStruct->proname));
2055         }
2056 }
2057
2058 /*
2059  * This is the same as the standard resolve_polymorphic_argtypes() function,
2060  * but with a special case for validation: assume that polymorphic arguments
2061  * are integer or integer-array.  Also, we go ahead and report the error
2062  * if we can't resolve the types.
2063  */
2064 static void
2065 plpgsql_resolve_polymorphic_argtypes(int numargs,
2066                                                                          Oid *argtypes, char *argmodes,
2067                                                                          Node *call_expr, bool forValidator,
2068                                                                          const char *proname)
2069 {
2070         int                     i;
2071
2072         if (!forValidator)
2073         {
2074                 /* normal case, pass to standard routine */
2075                 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2076                                                                                   call_expr))
2077                         ereport(ERROR,
2078                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2079                                          errmsg("could not determine actual argument "
2080                                                         "type for polymorphic function \"%s\"",
2081                                                         proname)));
2082         }
2083         else
2084         {
2085                 /* special validation case */
2086                 for (i = 0; i < numargs; i++)
2087                 {
2088                         switch (argtypes[i])
2089                         {
2090                                 case ANYELEMENTOID:
2091                                         argtypes[i] = INT4OID;
2092                                         break;
2093                                 case ANYARRAYOID:
2094                                         argtypes[i] = INT4ARRAYOID;
2095                                         break;
2096                                 default:
2097                                         break;
2098                         }
2099                 }
2100         }
2101 }
2102
2103 static void
2104 delete_function(PLpgSQL_function * func)
2105 {
2106         /* remove function from hash table */
2107         plpgsql_HashTableDelete(func);
2108
2109         /* release the function's storage */
2110         MemoryContextDelete(func->fn_cxt);
2111
2112         /*
2113          * Caller should be sure not to use passed-in pointer, as it now points to
2114          * pfree'd storage
2115          */
2116 }
2117
2118 /* exported so we can call it from plpgsql_init() */
2119 void
2120 plpgsql_HashTableInit(void)
2121 {
2122         HASHCTL         ctl;
2123
2124         /* don't allow double-initialization */
2125         Assert(plpgsql_HashTable == NULL);
2126
2127         memset(&ctl, 0, sizeof(ctl));
2128         ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2129         ctl.entrysize = sizeof(plpgsql_HashEnt);
2130         ctl.hash = tag_hash;
2131         plpgsql_HashTable = hash_create("PLpgSQL function cache",
2132                                                                         FUNCS_PER_USER,
2133                                                                         &ctl,
2134                                                                         HASH_ELEM | HASH_FUNCTION);
2135 }
2136
2137 static PLpgSQL_function *
2138 plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key)
2139 {
2140         plpgsql_HashEnt *hentry;
2141
2142         hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2143                                                                                          (void *) func_key,
2144                                                                                          HASH_FIND,
2145                                                                                          NULL);
2146         if (hentry)
2147                 return hentry->function;
2148         else
2149                 return NULL;
2150 }
2151
2152 static void
2153 plpgsql_HashTableInsert(PLpgSQL_function * function,
2154                                                 PLpgSQL_func_hashkey * func_key)
2155 {
2156         plpgsql_HashEnt *hentry;
2157         bool            found;
2158
2159         hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2160                                                                                          (void *) func_key,
2161                                                                                          HASH_ENTER,
2162                                                                                          &found);
2163         if (found)
2164                 elog(WARNING, "trying to insert a function that already exists");
2165
2166         hentry->function = function;
2167         /* prepare back link from function to hashtable key */
2168         function->fn_hashkey = &hentry->key;
2169 }
2170
2171 static void
2172 plpgsql_HashTableDelete(PLpgSQL_function * function)
2173 {
2174         plpgsql_HashEnt *hentry;
2175
2176         hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2177                                                                                          (void *) function->fn_hashkey,
2178                                                                                          HASH_REMOVE,
2179                                                                                          NULL);
2180         if (hentry == NULL)
2181                 elog(WARNING, "trying to delete function that does not exist");
2182 }