1 /**********************************************************************
2 * pl_comp.c - Compiler part of the PL/pgSQL
6 * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.94 2005/10/15 02:49:49 momjian Exp $
8 * This software is copyrighted by Jan Wieck - Hamburg.
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.
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
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.
36 **********************************************************************/
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"
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"
64 * Variables in the parser that shouldn't go into plpgsql.h
67 extern PLPGSQL_YYSTYPE plpgsql_yylval;
70 * Our own local and global variables
73 static int datums_alloc;
75 PLpgSQL_datum **plpgsql_Datums;
76 static int datums_last = 0;
78 int plpgsql_error_lineno;
79 char *plpgsql_error_funcname;
80 bool plpgsql_DumpExecTree = false;
81 bool plpgsql_check_syntax = false;
83 PLpgSQL_function *plpgsql_curr_compile;
85 /* A context appropriate for short-term allocs during compilation */
86 MemoryContext compile_tmp_cxt;
89 * Hash table for compiled functions
92 static HTAB *plpgsql_HashTable = NULL;
94 typedef struct plpgsql_hashent
96 PLpgSQL_func_hashkey key;
97 PLpgSQL_function *function;
100 #define FUNCS_PER_USER 128 /* initial table size */
103 * Lookup table for EXCEPTION condition names
112 static const ExceptionLabelMap exception_label_map[] = {
113 #include "plerrcodes.h"
122 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
124 PLpgSQL_func_hashkey * hashkey,
126 static int fetchArgInfo(HeapTuple procTup,
127 Oid **p_argtypes, char ***p_argnames,
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,
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);
147 * plpgsql_compile Make an execution tree for a PL/pgSQL function.
149 * If forValidator is true, we're only compiling for validation purposes,
150 * and so some checks are skipped.
152 * Note: it's important for this to fall through quickly if the function
153 * has already been compiled.
157 plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
159 Oid funcOid = fcinfo->flinfo->fn_oid;
161 Form_pg_proc procStruct;
162 PLpgSQL_function *function;
163 PLpgSQL_func_hashkey hashkey;
164 bool hashkey_valid = false;
167 * Lookup the pg_proc tuple by Oid; we'll need it in any case
169 procTup = SearchSysCache(PROCOID,
170 ObjectIdGetDatum(funcOid),
172 if (!HeapTupleIsValid(procTup))
173 elog(ERROR, "cache lookup failed for function %u", funcOid);
174 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
177 * See if there's already a cache entry for the current FmgrInfo. If not,
178 * try to find one in the hash table.
180 function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
184 /* Compute hashkey using function signature and actual arg types */
185 compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
186 hashkey_valid = true;
188 /* And do the lookup */
189 function = plpgsql_HashTableLookup(&hashkey);
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)))
198 /* Nope, drop the function and associated storage */
199 delete_function(function);
205 * If the function wasn't found or was out-of-date, we have to compile it
210 * Calculate hashkey if we didn't already; we'll need it to store the
211 * completed function.
214 compute_function_hashkey(fcinfo, procStruct, &hashkey,
220 function = do_compile(fcinfo, procTup, &hashkey, forValidator);
223 ReleaseSysCache(procTup);
226 * Save pointer in FmgrInfo to avoid search on subsequent calls
228 fcinfo->flinfo->fn_extra = (void *) function;
231 * Finally return the compiled function
237 * This is the slow part of plpgsql_compile().
239 * While compiling a function, the CurrentMemoryContext is the
240 * per-function memory context of the function we are compiling. That
241 * means a palloc() will allocate storage with the same lifetime as
242 * the function itself.
244 * Because palloc()'d storage will not be immediately freed, temporary
245 * allocations should either be performed in a short-lived memory
246 * context or explicitly pfree'd. Since not all backend functions are
247 * careful about pfree'ing their allocations, it is also wise to
248 * switch into a short-term context before calling into the
249 * backend. An appropriate context for performing short-term
250 * allocations is the compile_tmp_cxt.
252 static PLpgSQL_function *
253 do_compile(FunctionCallInfo fcinfo,
255 PLpgSQL_func_hashkey * hashkey,
258 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
259 int functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
260 PLpgSQL_function *function;
265 Form_pg_type typeStruct;
266 PLpgSQL_variable *var;
269 ErrorContextCallback plerrcontext;
274 int num_out_args = 0;
278 int *in_arg_varnos = NULL;
279 PLpgSQL_variable **out_arg_variables;
280 MemoryContext func_cxt;
283 * Setup the scanner input and error info. We assume that this function
284 * cannot be invoked recursively, so there's no need to save and restore
285 * the static variables used here.
287 prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
288 Anum_pg_proc_prosrc, &isnull);
290 elog(ERROR, "null prosrc");
291 proc_source = DatumGetCString(DirectFunctionCall1(textout, prosrcdatum));
292 plpgsql_scanner_init(proc_source, functype);
294 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
295 plpgsql_error_lineno = 0;
298 * Setup error traceback support for ereport()
300 plerrcontext.callback = plpgsql_compile_error_callback;
301 plerrcontext.arg = forValidator ? proc_source : NULL;
302 plerrcontext.previous = error_context_stack;
303 error_context_stack = &plerrcontext;
306 * Initialize the compiler
309 plpgsql_ns_push(NULL);
310 plpgsql_DumpExecTree = false;
314 /* This is short-lived, so needn't allocate in function's cxt */
315 plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
319 * Do extra syntax checks when validating the function definition. We skip
320 * this when actually compiling functions for execution, for performance
323 plpgsql_check_syntax = forValidator;
326 * Create the new function node. We allocate the function and all of its
327 * compile-time storage (e.g. parse tree) in its own memory context. This
328 * allows us to reclaim the function's storage cleanly.
330 func_cxt = AllocSetContextCreate(TopMemoryContext,
331 "PL/PgSQL function context",
332 ALLOCSET_DEFAULT_MINSIZE,
333 ALLOCSET_DEFAULT_INITSIZE,
334 ALLOCSET_DEFAULT_MAXSIZE);
335 compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
336 function = palloc0(sizeof(*function));
337 plpgsql_curr_compile = function;
339 function->fn_name = pstrdup(NameStr(procStruct->proname));
340 function->fn_oid = fcinfo->flinfo->fn_oid;
341 function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
342 function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
343 function->fn_functype = functype;
344 function->fn_cxt = func_cxt;
345 function->out_param_varno = -1; /* set up for no OUT param */
352 * Fetch info about the procedure's parameters. Allocations aren't
353 * needed permanently, so make them in tmp cxt.
355 * We also need to resolve any polymorphic input or output argument
356 * types. In validation mode we won't be able to, so we
357 * arbitrarily assume we are dealing with integers.
359 MemoryContextSwitchTo(compile_tmp_cxt);
361 numargs = fetchArgInfo(procTup, &argtypes, &argnames, &argmodes);
363 plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
364 fcinfo->flinfo->fn_expr,
366 plpgsql_error_funcname);
368 in_arg_varnos = (int *) palloc(numargs * sizeof(int));
369 out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
371 MemoryContextSwitchTo(func_cxt);
374 * Create the variables for the procedure's parameters.
376 for (i = 0; i < numargs; i++)
379 Oid argtypeid = argtypes[i];
380 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
381 PLpgSQL_type *argdtype;
382 PLpgSQL_variable *argvariable;
385 /* Create $n name for variable */
386 snprintf(buf, sizeof(buf), "$%d", i + 1);
388 /* Create datatype info */
389 argdtype = plpgsql_build_datatype(argtypeid, -1);
391 /* Disallow pseudotype argument */
392 /* (note we already replaced ANYARRAY/ANYELEMENT) */
393 /* (build_variable would do this, but wrong message) */
394 if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
395 argdtype->ttype != PLPGSQL_TTYPE_ROW)
397 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
398 errmsg("plpgsql functions cannot take type %s",
399 format_type_be(argtypeid))));
401 /* Build variable and add to datum list */
402 argvariable = plpgsql_build_variable(buf, 0,
405 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
407 argitemtype = PLPGSQL_NSTYPE_VAR;
408 /* input argument vars are forced to be CONSTANT */
409 if (argmode == PROARGMODE_IN)
410 ((PLpgSQL_var *) argvariable)->isconst = true;
414 Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
415 argitemtype = PLPGSQL_NSTYPE_ROW;
418 /* Remember arguments in appropriate arrays */
419 if (argmode == PROARGMODE_IN || argmode == PROARGMODE_INOUT)
420 in_arg_varnos[num_in_args++] = argvariable->dno;
421 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_INOUT)
422 out_arg_variables[num_out_args++] = argvariable;
424 /* Add to namespace under the $n name */
425 plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
427 /* If there's a name for the argument, make an alias */
428 if (argnames && argnames[i][0] != '\0')
429 plpgsql_ns_additem(argitemtype, argvariable->dno,
434 * If there's just one OUT parameter, out_param_varno points
435 * directly to it. If there's more than one, build a row that
438 if (num_out_args == 1)
439 function->out_param_varno = out_arg_variables[0]->dno;
440 else if (num_out_args > 1)
442 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
445 plpgsql_adddatum((PLpgSQL_datum *) row);
446 function->out_param_varno = row->rowno;
450 * Check for a polymorphic returntype. If found, use the actual
451 * returntype type from the caller's FuncExpr node, if we have
452 * one. (In validation mode we arbitrarily assume we are dealing
455 * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
456 * work; if it doesn't we're in some context that fails to make
457 * the info available.
459 rettypeid = procStruct->prorettype;
460 if (rettypeid == ANYARRAYOID || rettypeid == ANYELEMENTOID)
464 if (rettypeid == ANYARRAYOID)
465 rettypeid = INT4ARRAYOID;
471 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
472 if (!OidIsValid(rettypeid))
474 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
475 errmsg("could not determine actual return type "
476 "for polymorphic function \"%s\"",
477 plpgsql_error_funcname)));
482 * Normal function has a defined returntype
484 function->fn_rettype = rettypeid;
485 function->fn_retset = procStruct->proretset;
488 * Lookup the function's return type
490 typeTup = SearchSysCache(TYPEOID,
491 ObjectIdGetDatum(rettypeid),
493 if (!HeapTupleIsValid(typeTup))
494 elog(ERROR, "cache lookup failed for type %u", rettypeid);
495 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
497 /* Disallow pseudotype result, except VOID or RECORD */
498 /* (note we already replaced ANYARRAY/ANYELEMENT) */
499 if (typeStruct->typtype == 'p')
501 if (rettypeid == VOIDOID ||
502 rettypeid == RECORDOID)
504 else if (rettypeid == TRIGGEROID)
506 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
507 errmsg("trigger functions may only be called as triggers")));
510 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
511 errmsg("plpgsql functions cannot return type %s",
512 format_type_be(rettypeid))));
515 if (typeStruct->typrelid != InvalidOid ||
516 rettypeid == RECORDOID)
517 function->fn_retistuple = true;
520 function->fn_retbyval = typeStruct->typbyval;
521 function->fn_rettyplen = typeStruct->typlen;
522 function->fn_rettypioparam = getTypeIOParam(typeTup);
523 fmgr_info(typeStruct->typinput, &(function->fn_retinput));
526 * install $0 reference, but only for polymorphic return
527 * types, and not when the return is specified through an
530 if ((procStruct->prorettype == ANYARRAYOID ||
531 procStruct->prorettype == ANYELEMENTOID) &&
534 (void) plpgsql_build_variable("$0", 0,
535 build_datatype(typeTup, -1),
539 ReleaseSysCache(typeTup);
543 /* Trigger procedure's return type is unknown yet */
544 function->fn_rettype = InvalidOid;
545 function->fn_retbyval = false;
546 function->fn_retistuple = true;
547 function->fn_retset = false;
549 /* shouldn't be any declared arguments */
550 if (procStruct->pronargs != 0)
552 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
553 errmsg("trigger functions cannot have declared arguments"),
554 errhint("You probably want to use TG_NARGS and TG_ARGV instead.")));
556 /* Add the record for referencing NEW */
557 rec = palloc0(sizeof(PLpgSQL_rec));
558 rec->dtype = PLPGSQL_DTYPE_REC;
559 rec->refname = pstrdup("new");
562 rec->freetup = false;
563 plpgsql_adddatum((PLpgSQL_datum *) rec);
564 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
565 function->new_varno = rec->recno;
567 /* Add the record for referencing OLD */
568 rec = palloc0(sizeof(PLpgSQL_rec));
569 rec->dtype = PLPGSQL_DTYPE_REC;
570 rec->refname = pstrdup("old");
573 rec->freetup = false;
574 plpgsql_adddatum((PLpgSQL_datum *) rec);
575 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
576 function->old_varno = rec->recno;
578 /* Add the variable tg_name */
579 var = plpgsql_build_variable("tg_name", 0,
580 plpgsql_build_datatype(NAMEOID, -1),
582 function->tg_name_varno = var->dno;
584 /* Add the variable tg_when */
585 var = plpgsql_build_variable("tg_when", 0,
586 plpgsql_build_datatype(TEXTOID, -1),
588 function->tg_when_varno = var->dno;
590 /* Add the variable tg_level */
591 var = plpgsql_build_variable("tg_level", 0,
592 plpgsql_build_datatype(TEXTOID, -1),
594 function->tg_level_varno = var->dno;
596 /* Add the variable tg_op */
597 var = plpgsql_build_variable("tg_op", 0,
598 plpgsql_build_datatype(TEXTOID, -1),
600 function->tg_op_varno = var->dno;
602 /* Add the variable tg_relid */
603 var = plpgsql_build_variable("tg_relid", 0,
604 plpgsql_build_datatype(OIDOID, -1),
606 function->tg_relid_varno = var->dno;
608 /* Add the variable tg_relname */
609 var = plpgsql_build_variable("tg_relname", 0,
610 plpgsql_build_datatype(NAMEOID, -1),
612 function->tg_relname_varno = var->dno;
614 /* Add the variable tg_nargs */
615 var = plpgsql_build_variable("tg_nargs", 0,
616 plpgsql_build_datatype(INT4OID, -1),
618 function->tg_nargs_varno = var->dno;
623 elog(ERROR, "unrecognized function typecode: %u", functype);
627 /* Remember if function is STABLE/IMMUTABLE */
628 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
631 * Create the magic FOUND variable.
633 var = plpgsql_build_variable("found", 0,
634 plpgsql_build_datatype(BOOLOID, -1),
636 function->found_varno = var->dno;
639 * Forget about the above created variables
641 plpgsql_add_initdatums(NULL);
644 * Now parse the function's text
646 parse_rc = plpgsql_yyparse();
648 elog(ERROR, "plpgsql parser returned %d", parse_rc);
649 function->action = plpgsql_yylval.program;
651 plpgsql_scanner_finish();
655 * If it has OUT parameters or returns VOID or returns a set, we allow
656 * control to fall off the end without an explicit RETURN statement. The
657 * easiest way to implement this is to add a RETURN statement to the end
658 * of the statement list during parsing. However, if the outer block has
659 * an EXCEPTION clause, we need to make a new outer block, since the added
660 * RETURN shouldn't act like it is inside the EXCEPTION clause.
662 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
665 if (function->action->exceptions != NULL)
667 PLpgSQL_stmt_block *new;
669 new = palloc0(sizeof(PLpgSQL_stmt_block));
670 new->cmd_type = PLPGSQL_STMT_BLOCK;
671 new->body = list_make1(function->action);
673 function->action = new;
675 if (function->action->body == NIL ||
676 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
678 PLpgSQL_stmt_return *new;
680 new = palloc0(sizeof(PLpgSQL_stmt_return));
681 new->cmd_type = PLPGSQL_STMT_RETURN;
683 new->retvarno = function->out_param_varno;
685 function->action->body = lappend(function->action->body, new);
690 * Complete the function's info
692 function->fn_nargs = procStruct->pronargs;
693 for (i = 0; i < function->fn_nargs; i++)
694 function->fn_argvarnos[i] = in_arg_varnos[i];
695 function->ndatums = plpgsql_nDatums;
696 function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
697 for (i = 0; i < plpgsql_nDatums; i++)
698 function->datums[i] = plpgsql_Datums[i];
700 /* Debug dump for completed functions */
701 if (plpgsql_DumpExecTree)
702 plpgsql_dumptree(function);
705 * add it to the hash table
707 plpgsql_HashTableInsert(function, hashkey);
710 * Pop the error context stack
712 error_context_stack = plerrcontext.previous;
713 plpgsql_error_funcname = NULL;
714 plpgsql_error_lineno = 0;
716 plpgsql_check_syntax = false;
718 MemoryContextSwitchTo(compile_tmp_cxt);
719 compile_tmp_cxt = NULL;
725 * error context callback to let us supply a call-stack traceback. If
726 * we are validating, the function source is passed as an
727 * argument. This function is public only for the sake of an assertion
731 plpgsql_compile_error_callback(void *arg)
736 * Try to convert syntax error position to reference text of original
737 * CREATE FUNCTION command.
739 if (function_parse_error_transpose((const char *) arg))
743 * Done if a syntax error position was reported; otherwise we have to
744 * fall back to a "near line N" report.
748 if (plpgsql_error_funcname)
749 errcontext("compile of PL/pgSQL function \"%s\" near line %d",
750 plpgsql_error_funcname, plpgsql_error_lineno);
755 * Fetch info about the argument types, names, and IN/OUT modes from the
756 * pg_proc tuple. Return value is the number of arguments.
757 * Other results are palloc'd.
760 fetchArgInfo(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames,
763 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
764 Datum proallargtypes;
774 /* First discover the total number of parameters and get their types */
775 proallargtypes = SysCacheGetAttr(PROCOID, procTup,
776 Anum_pg_proc_proallargtypes,
781 * We expect the arrays to be 1-D arrays of the right types; verify
782 * that. For the OID and char arrays, we don't need to use
783 * deconstruct_array() since the array data is just going to look like
784 * a C array of values.
786 arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
787 numargs = ARR_DIMS(arr)[0];
788 if (ARR_NDIM(arr) != 1 ||
790 ARR_ELEMTYPE(arr) != OIDOID)
791 elog(ERROR, "proallargtypes is not a 1-D Oid array");
792 Assert(numargs >= procStruct->pronargs);
793 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
794 memcpy(*p_argtypes, ARR_DATA_PTR(arr),
795 numargs * sizeof(Oid));
799 /* If no proallargtypes, use proargtypes */
800 numargs = procStruct->proargtypes.dim1;
801 Assert(numargs == procStruct->pronargs);
802 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
803 memcpy(*p_argtypes, procStruct->proargtypes.values,
804 numargs * sizeof(Oid));
807 /* Get argument names, if available */
808 proargnames = SysCacheGetAttr(PROCOID, procTup,
809 Anum_pg_proc_proargnames,
815 deconstruct_array(DatumGetArrayTypeP(proargnames),
816 TEXTOID, -1, false, 'i',
818 if (nelems != numargs) /* should not happen */
819 elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
820 *p_argnames = (char **) palloc(sizeof(char *) * numargs);
821 for (i = 0; i < numargs; i++)
822 (*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
826 /* Get argument modes, if available */
827 proargmodes = SysCacheGetAttr(PROCOID, procTup,
828 Anum_pg_proc_proargmodes,
834 arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
835 if (ARR_NDIM(arr) != 1 ||
836 ARR_DIMS(arr)[0] != numargs ||
837 ARR_ELEMTYPE(arr) != CHAROID)
838 elog(ERROR, "proargmodes is not a 1-D char array");
839 *p_argmodes = (char *) palloc(numargs * sizeof(char));
840 memcpy(*p_argmodes, ARR_DATA_PTR(arr),
841 numargs * sizeof(char));
849 * plpgsql_parse_word The scanner calls this to postparse
850 * any single word not found by a
855 plpgsql_parse_word(char *word)
860 /* Do case conversion and word separation */
861 plpgsql_convert_ident(word, cp, 1);
864 * Recognize tg_argv when compiling triggers
866 if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
868 if (strcmp(cp[0], "tg_argv") == 0)
870 bool save_spacescanned = plpgsql_SpaceScanned;
871 PLpgSQL_trigarg *trigarg;
873 trigarg = palloc0(sizeof(PLpgSQL_trigarg));
874 trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
876 if (plpgsql_yylex() != '[')
877 plpgsql_yyerror("expected \"[\"");
879 trigarg->argnum = plpgsql_read_expression(']', "]");
881 plpgsql_adddatum((PLpgSQL_datum *) trigarg);
882 plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
884 plpgsql_SpaceScanned = save_spacescanned;
891 * Do a lookup on the compiler's namestack
893 nse = plpgsql_ns_lookup(cp[0], NULL);
897 switch (nse->itemtype)
899 case PLPGSQL_NSTYPE_LABEL:
902 case PLPGSQL_NSTYPE_VAR:
903 plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
906 case PLPGSQL_NSTYPE_REC:
907 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
910 case PLPGSQL_NSTYPE_ROW:
911 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
920 * Nothing found - up to now it's a word without any special meaning for
929 * plpgsql_parse_dblword Same lookup for two words
930 * separated by a dot.
934 plpgsql_parse_dblword(char *word)
939 /* Do case conversion and word separation */
940 plpgsql_convert_ident(word, cp, 2);
943 * Lookup the first word
945 ns = plpgsql_ns_lookup(cp[0], NULL);
953 switch (ns->itemtype)
955 case PLPGSQL_NSTYPE_LABEL:
958 * First word is a label, so second word could be a variable,
959 * record or row in that bodies namestack. Anything else could
960 * only be something in a query given to the SPI manager and
961 * T_ERROR will get eaten up by the collector routines.
963 ns = plpgsql_ns_lookup(cp[1], cp[0]);
968 switch (ns->itemtype)
970 case PLPGSQL_NSTYPE_VAR:
971 plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
974 case PLPGSQL_NSTYPE_REC:
975 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
978 case PLPGSQL_NSTYPE_ROW:
979 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
987 case PLPGSQL_NSTYPE_REC:
990 * First word is a record name, so second word must be a field
993 PLpgSQL_recfield *new;
995 new = palloc(sizeof(PLpgSQL_recfield));
996 new->dtype = PLPGSQL_DTYPE_RECFIELD;
997 new->fieldname = pstrdup(cp[1]);
998 new->recparentno = ns->itemno;
1000 plpgsql_adddatum((PLpgSQL_datum *) new);
1002 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1009 case PLPGSQL_NSTYPE_ROW:
1012 * First word is a row name, so second word must be a field in
1018 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1019 for (i = 0; i < row->nfields; i++)
1021 if (row->fieldnames[i] &&
1022 strcmp(row->fieldnames[i], cp[1]) == 0)
1024 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1031 (errcode(ERRCODE_UNDEFINED_COLUMN),
1032 errmsg("row \"%s\" has no field \"%s\"",
1047 * plpgsql_parse_tripword Same lookup for three words
1048 * separated by dots.
1052 plpgsql_parse_tripword(char *word)
1057 /* Do case conversion and word separation */
1058 plpgsql_convert_ident(word, cp, 3);
1061 * Lookup the first word - it must be a label
1063 ns = plpgsql_ns_lookup(cp[0], NULL);
1071 if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
1080 * First word is a label, so second word could be a record or row
1082 ns = plpgsql_ns_lookup(cp[1], cp[0]);
1091 switch (ns->itemtype)
1093 case PLPGSQL_NSTYPE_REC:
1096 * This word is a record name, so third word must be a field
1099 PLpgSQL_recfield *new;
1101 new = palloc(sizeof(PLpgSQL_recfield));
1102 new->dtype = PLPGSQL_DTYPE_RECFIELD;
1103 new->fieldname = pstrdup(cp[2]);
1104 new->recparentno = ns->itemno;
1106 plpgsql_adddatum((PLpgSQL_datum *) new);
1108 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1117 case PLPGSQL_NSTYPE_ROW:
1120 * This word is a row name, so third word must be a field in
1126 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1127 for (i = 0; i < row->nfields; i++)
1129 if (row->fieldnames[i] &&
1130 strcmp(row->fieldnames[i], cp[2]) == 0)
1132 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1142 (errcode(ERRCODE_UNDEFINED_COLUMN),
1143 errmsg("row \"%s.%s\" has no field \"%s\"",
1144 cp[0], cp[1], cp[2])));
1159 * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
1160 * a variable name or a basetype.
1164 plpgsql_parse_wordtype(char *word)
1166 PLpgSQL_nsitem *nse;
1172 /* Do case conversion and word separation */
1173 /* We convert %type to .type momentarily to keep converter happy */
1174 i = strlen(word) - 5;
1175 Assert(word[i] == '%');
1177 plpgsql_convert_ident(word, cp, 2);
1182 * Do a lookup on the compiler's namestack. But ensure it moves up to the
1185 old_nsstate = plpgsql_ns_setlocal(false);
1186 nse = plpgsql_ns_lookup(cp[0], NULL);
1187 plpgsql_ns_setlocal(old_nsstate);
1192 switch (nse->itemtype)
1194 case PLPGSQL_NSTYPE_VAR:
1195 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1198 /* XXX perhaps allow REC here? */
1206 * Word wasn't found on the namestack. Try to find a data type with that
1207 * name, but ignore pg_type entries that are in fact class types.
1209 typeOid = LookupTypeName(makeTypeName(cp[0]));
1210 if (OidIsValid(typeOid))
1214 typeTup = SearchSysCache(TYPEOID,
1215 ObjectIdGetDatum(typeOid),
1217 if (HeapTupleIsValid(typeTup))
1219 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1221 if (!typeStruct->typisdefined ||
1222 typeStruct->typrelid != InvalidOid)
1224 ReleaseSysCache(typeTup);
1229 plpgsql_yylval.dtype = build_datatype(typeTup, -1);
1231 ReleaseSysCache(typeTup);
1238 * Nothing found - up to now it's a word without any special meaning for
1247 * plpgsql_parse_dblwordtype Same lookup for word.word%TYPE
1251 plpgsql_parse_dblwordtype(char *word)
1253 PLpgSQL_nsitem *nse;
1256 HeapTuple classtup = NULL;
1257 HeapTuple attrtup = NULL;
1258 HeapTuple typetup = NULL;
1259 Form_pg_class classStruct;
1260 Form_pg_attribute attrStruct;
1263 MemoryContext oldCxt;
1264 int result = T_ERROR;
1266 /* Avoid memory leaks in the long-term function context */
1267 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1269 /* Do case conversion and word separation */
1270 /* We convert %type to .type momentarily to keep converter happy */
1271 i = strlen(word) - 5;
1272 Assert(word[i] == '%');
1274 plpgsql_convert_ident(word, cp, 3);
1278 * Lookup the first word
1280 nse = plpgsql_ns_lookup(cp[0], NULL);
1283 * If this is a label lookup the second word in that label's namestack
1288 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
1290 old_nsstate = plpgsql_ns_setlocal(false);
1291 nse = plpgsql_ns_lookup(cp[1], cp[0]);
1292 plpgsql_ns_setlocal(old_nsstate);
1294 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1296 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1301 /* Return T_ERROR if not found, otherwise T_DTYPE */
1306 * First word could also be a table name
1308 classOid = RelnameGetRelid(cp[0]);
1309 if (!OidIsValid(classOid))
1312 classtup = SearchSysCache(RELOID,
1313 ObjectIdGetDatum(classOid),
1315 if (!HeapTupleIsValid(classtup))
1319 * It must be a relation, sequence, view, or type
1321 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1322 if (classStruct->relkind != RELKIND_RELATION &&
1323 classStruct->relkind != RELKIND_SEQUENCE &&
1324 classStruct->relkind != RELKIND_VIEW &&
1325 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1329 * Fetch the named table field and it's type
1331 attrtup = SearchSysCacheAttName(classOid, cp[1]);
1332 if (!HeapTupleIsValid(attrtup))
1335 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1336 typetup = SearchSysCache(TYPEOID,
1337 ObjectIdGetDatum(attrStruct->atttypid),
1339 if (!HeapTupleIsValid(typetup))
1340 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1343 * Found that - build a compiler type struct in the caller's cxt and
1346 MemoryContextSwitchTo(oldCxt);
1347 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1348 MemoryContextSwitchTo(compile_tmp_cxt);
1352 if (HeapTupleIsValid(classtup))
1353 ReleaseSysCache(classtup);
1354 if (HeapTupleIsValid(attrtup))
1355 ReleaseSysCache(attrtup);
1356 if (HeapTupleIsValid(typetup))
1357 ReleaseSysCache(typetup);
1359 MemoryContextSwitchTo(oldCxt);
1364 * plpgsql_parse_tripwordtype Same lookup for word.word.word%TYPE
1367 #define TYPE_JUNK_LEN 5
1370 plpgsql_parse_tripwordtype(char *word)
1373 HeapTuple classtup = NULL;
1374 Form_pg_class classStruct;
1375 HeapTuple attrtup = NULL;
1376 Form_pg_attribute attrStruct;
1377 HeapTuple typetup = NULL;
1380 int qualified_att_len;
1384 MemoryContext oldCxt;
1385 int result = T_ERROR;
1387 /* Avoid memory leaks in the long-term function context */
1388 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1390 /* Do case conversion and word separation */
1391 qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
1392 Assert(word[qualified_att_len] == '%');
1394 for (i = 0; i < qualified_att_len; i++)
1396 if (word[i] == '.' && ++numdots == 2)
1400 cp[0] = (char *) palloc((i + 1) * sizeof(char));
1401 memcpy(cp[0], word, i * sizeof(char));
1405 * qualified_att_len - one based position + 1 (null terminator)
1407 cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));
1408 memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));
1409 cp[1][qualified_att_len - i - 1] = '\0';
1411 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0],
1412 "plpgsql_parse_tripwordtype"));
1413 classOid = RangeVarGetRelid(relvar, true);
1414 if (!OidIsValid(classOid))
1417 classtup = SearchSysCache(RELOID,
1418 ObjectIdGetDatum(classOid),
1420 if (!HeapTupleIsValid(classtup))
1424 * It must be a relation, sequence, view, or type
1426 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1427 if (classStruct->relkind != RELKIND_RELATION &&
1428 classStruct->relkind != RELKIND_SEQUENCE &&
1429 classStruct->relkind != RELKIND_VIEW &&
1430 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1434 * Fetch the named table field and it's type
1436 plpgsql_convert_ident(cp[1], colname, 1);
1437 attrtup = SearchSysCacheAttName(classOid, colname[0]);
1438 if (!HeapTupleIsValid(attrtup))
1441 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1442 typetup = SearchSysCache(TYPEOID,
1443 ObjectIdGetDatum(attrStruct->atttypid),
1445 if (!HeapTupleIsValid(typetup))
1446 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1449 * Found that - build a compiler type struct in the caller's cxt and
1452 MemoryContextSwitchTo(oldCxt);
1453 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1454 MemoryContextSwitchTo(compile_tmp_cxt);
1458 if (HeapTupleIsValid(classtup))
1459 ReleaseSysCache(classtup);
1460 if (HeapTupleIsValid(classtup))
1461 ReleaseSysCache(attrtup);
1462 if (HeapTupleIsValid(typetup))
1463 ReleaseSysCache(typetup);
1465 MemoryContextSwitchTo(oldCxt);
1470 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1471 * So word must be a table name.
1475 plpgsql_parse_wordrowtype(char *word)
1481 /* Do case conversion and word separation */
1482 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1483 i = strlen(word) - 8;
1484 Assert(word[i] == '%');
1486 plpgsql_convert_ident(word, cp, 2);
1489 /* Lookup the relation */
1490 classOid = RelnameGetRelid(cp[0]);
1491 if (!OidIsValid(classOid))
1493 (errcode(ERRCODE_UNDEFINED_TABLE),
1494 errmsg("relation \"%s\" does not exist", cp[0])));
1497 * Build and return the row type struct
1499 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1509 * plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
1510 * So word must be a namespace qualified table name.
1513 #define ROWTYPE_JUNK_LEN 8
1516 plpgsql_parse_dblwordrowtype(char *word)
1522 MemoryContext oldCxt;
1524 /* Avoid memory leaks in long-term function context */
1525 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1527 /* Do case conversion and word separation */
1528 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1529 i = strlen(word) - ROWTYPE_JUNK_LEN;
1530 Assert(word[i] == '%');
1535 /* Lookup the relation */
1536 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
1537 classOid = RangeVarGetRelid(relvar, true);
1538 if (!OidIsValid(classOid))
1540 (errcode(ERRCODE_UNDEFINED_TABLE),
1541 errmsg("relation \"%s\" does not exist", cp)));
1543 /* Build and return the row type struct */
1544 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1547 MemoryContextSwitchTo(oldCxt);
1552 * plpgsql_build_variable - build a datum-array entry of a given
1555 * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or
1556 * PLpgSQL_rec depending on the given datatype, and is allocated via
1557 * palloc. The struct is automatically added to the current datum
1558 * array, and optionally to the current namespace.
1561 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type * dtype,
1564 PLpgSQL_variable *result;
1566 switch (dtype->ttype)
1568 case PLPGSQL_TTYPE_SCALAR:
1570 /* Ordinary scalar datatype */
1573 var = palloc0(sizeof(PLpgSQL_var));
1574 var->dtype = PLPGSQL_DTYPE_VAR;
1575 var->refname = pstrdup(refname);
1576 var->lineno = lineno;
1577 var->datatype = dtype;
1578 /* other fields might be filled by caller */
1580 /* preset to NULL */
1583 var->freeval = false;
1585 plpgsql_adddatum((PLpgSQL_datum *) var);
1587 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1590 result = (PLpgSQL_variable *) var;
1593 case PLPGSQL_TTYPE_ROW:
1595 /* Composite type -- build a row variable */
1598 row = build_row_from_class(dtype->typrelid);
1600 row->dtype = PLPGSQL_DTYPE_ROW;
1601 row->refname = pstrdup(refname);
1602 row->lineno = lineno;
1604 plpgsql_adddatum((PLpgSQL_datum *) row);
1606 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
1609 result = (PLpgSQL_variable *) row;
1612 case PLPGSQL_TTYPE_REC:
1615 * "record" type -- build a variable-contents record variable
1619 rec = palloc0(sizeof(PLpgSQL_rec));
1620 rec->dtype = PLPGSQL_DTYPE_REC;
1621 rec->refname = pstrdup(refname);
1622 rec->lineno = lineno;
1624 plpgsql_adddatum((PLpgSQL_datum *) rec);
1626 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
1629 result = (PLpgSQL_variable *) rec;
1632 case PLPGSQL_TTYPE_PSEUDO:
1634 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1635 errmsg("variable \"%s\" has pseudo-type %s",
1636 refname, format_type_be(dtype->typoid))));
1637 result = NULL; /* keep compiler quiet */
1640 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1641 result = NULL; /* keep compiler quiet */
1649 * Build a row-variable data structure given the pg_class OID.
1651 static PLpgSQL_row *
1652 build_row_from_class(Oid classOid)
1656 Form_pg_class classStruct;
1657 const char *relname;
1661 * Open the relation to get info.
1663 rel = relation_open(classOid, AccessShareLock);
1664 classStruct = RelationGetForm(rel);
1665 relname = RelationGetRelationName(rel);
1667 /* accept relation, sequence, view, or composite type entries */
1668 if (classStruct->relkind != RELKIND_RELATION &&
1669 classStruct->relkind != RELKIND_SEQUENCE &&
1670 classStruct->relkind != RELKIND_VIEW &&
1671 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1673 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1674 errmsg("relation \"%s\" is not a table", relname)));
1677 * Create a row datum entry and all the required variables that it will
1680 row = palloc0(sizeof(PLpgSQL_row));
1681 row->dtype = PLPGSQL_DTYPE_ROW;
1682 row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
1683 row->nfields = classStruct->relnatts;
1684 row->fieldnames = palloc(sizeof(char *) * row->nfields);
1685 row->varnos = palloc(sizeof(int) * row->nfields);
1687 for (i = 0; i < row->nfields; i++)
1689 Form_pg_attribute attrStruct;
1692 * Get the attribute and check for dropped column
1694 attrStruct = row->rowtupdesc->attrs[i];
1696 if (!attrStruct->attisdropped)
1699 char refname[(NAMEDATALEN * 2) + 100];
1700 PLpgSQL_variable *var;
1702 attname = NameStr(attrStruct->attname);
1703 snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
1706 * Create the internal variable for the field
1708 * We know if the table definitions contain a default value or if the
1709 * field is declared in the table as NOT NULL. But it's possible
1710 * to create a table field as NOT NULL without a default value and
1711 * that would lead to problems later when initializing the
1712 * variables due to entering a block at execution time. Thus we
1713 * ignore this information for now.
1715 var = plpgsql_build_variable(refname, 0,
1716 plpgsql_build_datatype(attrStruct->atttypid,
1717 attrStruct->atttypmod),
1720 /* Add the variable to the row */
1721 row->fieldnames[i] = attname;
1722 row->varnos[i] = var->dno;
1726 /* Leave a hole in the row structure for the dropped col */
1727 row->fieldnames[i] = NULL;
1728 row->varnos[i] = -1;
1732 relation_close(rel, AccessShareLock);
1738 * Build a row-variable data structure given the component variables.
1740 static PLpgSQL_row *
1741 build_row_from_vars(PLpgSQL_variable ** vars, int numvars)
1746 row = palloc0(sizeof(PLpgSQL_row));
1747 row->dtype = PLPGSQL_DTYPE_ROW;
1748 row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
1749 row->nfields = numvars;
1750 row->fieldnames = palloc(numvars * sizeof(char *));
1751 row->varnos = palloc(numvars * sizeof(int));
1753 for (i = 0; i < numvars; i++)
1755 PLpgSQL_variable *var = vars[i];
1756 Oid typoid = RECORDOID;
1761 case PLPGSQL_DTYPE_VAR:
1762 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1763 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1766 case PLPGSQL_DTYPE_REC:
1769 case PLPGSQL_DTYPE_ROW:
1770 if (((PLpgSQL_row *) var)->rowtupdesc)
1772 typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
1773 typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
1778 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1781 row->fieldnames[i] = var->refname;
1782 row->varnos[i] = var->dno;
1784 TupleDescInitEntry(row->rowtupdesc, i + 1,
1795 * plpgsql_parse_datatype Scanner found something that should
1796 * be a datatype name.
1800 plpgsql_parse_datatype(const char *string)
1805 /* Let the main parser try to parse it under standard SQL rules */
1806 parseTypeString(string, &type_id, &typmod);
1808 /* Okay, build a PLpgSQL_type data structure for it */
1809 return plpgsql_build_datatype(type_id, typmod);
1813 * plpgsql_build_datatype
1814 * Build PLpgSQL_type struct given type OID and typmod.
1817 plpgsql_build_datatype(Oid typeOid, int32 typmod)
1822 typeTup = SearchSysCache(TYPEOID,
1823 ObjectIdGetDatum(typeOid),
1825 if (!HeapTupleIsValid(typeTup))
1826 elog(ERROR, "cache lookup failed for type %u", typeOid);
1828 typ = build_datatype(typeTup, typmod);
1830 ReleaseSysCache(typeTup);
1836 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1838 static PLpgSQL_type *
1839 build_datatype(HeapTuple typeTup, int32 typmod)
1841 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1844 if (!typeStruct->typisdefined)
1846 (errcode(ERRCODE_UNDEFINED_OBJECT),
1847 errmsg("type \"%s\" is only a shell",
1848 NameStr(typeStruct->typname))));
1850 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
1852 typ->typname = pstrdup(NameStr(typeStruct->typname));
1853 typ->typoid = HeapTupleGetOid(typeTup);
1854 switch (typeStruct->typtype)
1856 case 'b': /* base type */
1857 case 'd': /* domain */
1858 typ->ttype = PLPGSQL_TTYPE_SCALAR;
1860 case 'c': /* composite, ie, rowtype */
1861 Assert(OidIsValid(typeStruct->typrelid));
1862 typ->ttype = PLPGSQL_TTYPE_ROW;
1864 case 'p': /* pseudo */
1865 if (typ->typoid == RECORDOID)
1866 typ->ttype = PLPGSQL_TTYPE_REC;
1868 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
1871 elog(ERROR, "unrecognized typtype: %d",
1872 (int) typeStruct->typtype);
1875 typ->typlen = typeStruct->typlen;
1876 typ->typbyval = typeStruct->typbyval;
1877 typ->typrelid = typeStruct->typrelid;
1878 typ->typioparam = getTypeIOParam(typeTup);
1879 fmgr_info(typeStruct->typinput, &(typ->typinput));
1880 typ->atttypmod = typmod;
1886 * plpgsql_parse_err_condition
1887 * Generate PLpgSQL_condition entry(s) for an exception condition name
1889 * This has to be able to return a list because there are some duplicate
1890 * names in the table of error code names.
1893 plpgsql_parse_err_condition(char *condname)
1896 PLpgSQL_condition *new;
1897 PLpgSQL_condition *prev;
1900 * XXX Eventually we will want to look for user-defined exception names
1905 * OTHERS is represented as code 0 (which would map to '00000', but we
1906 * have no need to represent that as an exception condition).
1908 if (strcmp(condname, "others") == 0)
1910 new = palloc(sizeof(PLpgSQL_condition));
1911 new->sqlerrstate = 0;
1912 new->condname = condname;
1918 for (i = 0; exception_label_map[i].label != NULL; i++)
1920 if (strcmp(condname, exception_label_map[i].label) == 0)
1922 new = palloc(sizeof(PLpgSQL_condition));
1923 new->sqlerrstate = exception_label_map[i].sqlerrstate;
1924 new->condname = condname;
1932 (errcode(ERRCODE_UNDEFINED_OBJECT),
1933 errmsg("unrecognized exception condition \"%s\"",
1940 * plpgsql_adddatum Add a variable, record or row
1941 * to the compiler's datum list.
1945 plpgsql_adddatum(PLpgSQL_datum * new)
1947 if (plpgsql_nDatums == datums_alloc)
1950 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1953 new->dno = plpgsql_nDatums;
1954 plpgsql_Datums[plpgsql_nDatums++] = new;
1959 * plpgsql_add_initdatums Put all datum entries created
1960 * since the last call into the
1961 * finishing code block so the
1962 * block knows which variables to
1963 * reinitialize when entered.
1967 plpgsql_add_initdatums(int **varnos)
1972 for (i = datums_last; i < plpgsql_nDatums; i++)
1974 switch (plpgsql_Datums[i]->dtype)
1976 case PLPGSQL_DTYPE_VAR:
1989 *varnos = (int *) palloc(sizeof(int) * n);
1992 for (i = datums_last; i < plpgsql_nDatums; i++)
1994 switch (plpgsql_Datums[i]->dtype)
1996 case PLPGSQL_DTYPE_VAR:
1997 (*varnos)[n++] = plpgsql_Datums[i]->dno;
2008 datums_last = plpgsql_nDatums;
2014 * Compute the hashkey for a given function invocation
2016 * The hashkey is returned into the caller-provided storage at *hashkey.
2019 compute_function_hashkey(FunctionCallInfo fcinfo,
2020 Form_pg_proc procStruct,
2021 PLpgSQL_func_hashkey * hashkey,
2024 /* Make sure any unused bytes of the struct are zero */
2025 MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2027 /* get function OID */
2028 hashkey->funcOid = fcinfo->flinfo->fn_oid;
2031 * if trigger, get relation OID. In validation mode we do not know what
2032 * relation is intended to be used, so we leave trigrelOid zero; the hash
2033 * entry built in this case will never really be used.
2035 if (CALLED_AS_TRIGGER(fcinfo) && !forValidator)
2037 TriggerData *trigdata = (TriggerData *) fcinfo->context;
2039 hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
2042 if (procStruct->pronargs > 0)
2044 /* get the argument types */
2045 memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2046 procStruct->pronargs * sizeof(Oid));
2048 /* resolve any polymorphic argument types */
2049 plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2052 fcinfo->flinfo->fn_expr,
2054 NameStr(procStruct->proname));
2059 * This is the same as the standard resolve_polymorphic_argtypes() function,
2060 * but with a special case for validation: assume that polymorphic arguments
2061 * are integer or integer-array. Also, we go ahead and report the error
2062 * if we can't resolve the types.
2065 plpgsql_resolve_polymorphic_argtypes(int numargs,
2066 Oid *argtypes, char *argmodes,
2067 Node *call_expr, bool forValidator,
2068 const char *proname)
2074 /* normal case, pass to standard routine */
2075 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2078 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2079 errmsg("could not determine actual argument "
2080 "type for polymorphic function \"%s\"",
2085 /* special validation case */
2086 for (i = 0; i < numargs; i++)
2088 switch (argtypes[i])
2091 argtypes[i] = INT4OID;
2094 argtypes[i] = INT4ARRAYOID;
2104 delete_function(PLpgSQL_function * func)
2106 /* remove function from hash table */
2107 plpgsql_HashTableDelete(func);
2109 /* release the function's storage */
2110 MemoryContextDelete(func->fn_cxt);
2113 * Caller should be sure not to use passed-in pointer, as it now points to
2118 /* exported so we can call it from plpgsql_init() */
2120 plpgsql_HashTableInit(void)
2124 /* don't allow double-initialization */
2125 Assert(plpgsql_HashTable == NULL);
2127 memset(&ctl, 0, sizeof(ctl));
2128 ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2129 ctl.entrysize = sizeof(plpgsql_HashEnt);
2130 ctl.hash = tag_hash;
2131 plpgsql_HashTable = hash_create("PLpgSQL function cache",
2134 HASH_ELEM | HASH_FUNCTION);
2137 static PLpgSQL_function *
2138 plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key)
2140 plpgsql_HashEnt *hentry;
2142 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2147 return hentry->function;
2153 plpgsql_HashTableInsert(PLpgSQL_function * function,
2154 PLpgSQL_func_hashkey * func_key)
2156 plpgsql_HashEnt *hentry;
2159 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2164 elog(WARNING, "trying to insert a function that already exists");
2166 hentry->function = function;
2167 /* prepare back link from function to hashtable key */
2168 function->fn_hashkey = &hentry->key;
2172 plpgsql_HashTableDelete(PLpgSQL_function * function)
2174 plpgsql_HashEnt *hentry;
2176 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2177 (void *) function->fn_hashkey,
2181 elog(WARNING, "trying to delete function that does not exist");