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