1 /**********************************************************************
2 * pl_comp.c - Compiler part of the PL/pgSQL
6 * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.93 2005/09/24 22:54:44 tgl 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
178 * not, 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
211 * Calculate hashkey if we didn't already; we'll need it to store
212 * the completed function.
215 compute_function_hashkey(fcinfo, procStruct, &hashkey,
221 function = do_compile(fcinfo, procTup, &hashkey, forValidator);
224 ReleaseSysCache(procTup);
227 * Save pointer in FmgrInfo to avoid search on subsequent calls
229 fcinfo->flinfo->fn_extra = (void *) function;
232 * Finally return the compiled function
238 * This is the slow part of plpgsql_compile().
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.
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.
253 static PLpgSQL_function *
254 do_compile(FunctionCallInfo fcinfo,
256 PLpgSQL_func_hashkey *hashkey,
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;
266 Form_pg_type typeStruct;
267 PLpgSQL_variable *var;
270 ErrorContextCallback plerrcontext;
275 int num_out_args = 0;
279 int *in_arg_varnos = NULL;
280 PLpgSQL_variable **out_arg_variables;
281 MemoryContext func_cxt;
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.
288 prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
289 Anum_pg_proc_prosrc, &isnull);
291 elog(ERROR, "null prosrc");
292 proc_source = DatumGetCString(DirectFunctionCall1(textout, prosrcdatum));
293 plpgsql_scanner_init(proc_source, functype);
295 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
296 plpgsql_error_lineno = 0;
299 * Setup error traceback support for ereport()
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;
307 * Initialize the compiler
310 plpgsql_ns_push(NULL);
311 plpgsql_DumpExecTree = false;
315 /* This is short-lived, so needn't allocate in function's cxt */
316 plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
320 * Do extra syntax checks when validating the function
321 * definition. We skip this when actually compiling functions for
322 * execution, for performance reasons.
324 plpgsql_check_syntax = forValidator;
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
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;
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 */
353 * Fetch info about the procedure's parameters. Allocations
354 * aren't needed permanently, so make them in tmp cxt.
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.
360 MemoryContextSwitchTo(compile_tmp_cxt);
362 numargs = fetchArgInfo(procTup, &argtypes, &argnames, &argmodes);
364 plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
365 fcinfo->flinfo->fn_expr,
367 plpgsql_error_funcname);
369 in_arg_varnos = (int *) palloc(numargs * sizeof(int));
370 out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
372 MemoryContextSwitchTo(func_cxt);
375 * Create the variables for the procedure's parameters.
377 for (i = 0; i < numargs; i++)
380 Oid argtypeid = argtypes[i];
381 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
382 PLpgSQL_type *argdtype;
383 PLpgSQL_variable *argvariable;
386 /* Create $n name for variable */
387 snprintf(buf, sizeof(buf), "$%d", i + 1);
389 /* Create datatype info */
390 argdtype = plpgsql_build_datatype(argtypeid, -1);
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)
398 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
399 errmsg("plpgsql functions cannot take type %s",
400 format_type_be(argtypeid))));
402 /* Build variable and add to datum list */
403 argvariable = plpgsql_build_variable(buf, 0,
406 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
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;
415 Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
416 argitemtype = PLPGSQL_NSTYPE_ROW;
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;
425 /* Add to namespace under the $n name */
426 plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
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,
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.
439 if (num_out_args == 1)
440 function->out_param_varno = out_arg_variables[0]->dno;
441 else if (num_out_args > 1)
443 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
446 plpgsql_adddatum((PLpgSQL_datum *) row);
447 function->out_param_varno = row->rowno;
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.)
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.
460 rettypeid = procStruct->prorettype;
461 if (rettypeid == ANYARRAYOID || rettypeid == ANYELEMENTOID)
465 if (rettypeid == ANYARRAYOID)
466 rettypeid = INT4ARRAYOID;
472 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
473 if (!OidIsValid(rettypeid))
475 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
476 errmsg("could not determine actual return type "
477 "for polymorphic function \"%s\"",
478 plpgsql_error_funcname)));
483 * Normal function has a defined returntype
485 function->fn_rettype = rettypeid;
486 function->fn_retset = procStruct->proretset;
489 * Lookup the function's return type
491 typeTup = SearchSysCache(TYPEOID,
492 ObjectIdGetDatum(rettypeid),
494 if (!HeapTupleIsValid(typeTup))
495 elog(ERROR, "cache lookup failed for type %u", rettypeid);
496 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
498 /* Disallow pseudotype result, except VOID or RECORD */
499 /* (note we already replaced ANYARRAY/ANYELEMENT) */
500 if (typeStruct->typtype == 'p')
502 if (rettypeid == VOIDOID ||
503 rettypeid == RECORDOID)
505 else if (rettypeid == TRIGGEROID)
507 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
508 errmsg("trigger functions may only be called as triggers")));
511 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
512 errmsg("plpgsql functions cannot return type %s",
513 format_type_be(rettypeid))));
516 if (typeStruct->typrelid != InvalidOid ||
517 rettypeid == RECORDOID)
518 function->fn_retistuple = true;
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));
527 * install $0 reference, but only for polymorphic return
528 * types, and not when the return is specified through an
531 if ((procStruct->prorettype == ANYARRAYOID ||
532 procStruct->prorettype == ANYELEMENTOID) &&
535 (void) plpgsql_build_variable("$0", 0,
536 build_datatype(typeTup, -1),
540 ReleaseSysCache(typeTup);
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;
550 /* shouldn't be any declared arguments */
551 if (procStruct->pronargs != 0)
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.")));
557 /* Add the record for referencing NEW */
558 rec = palloc0(sizeof(PLpgSQL_rec));
559 rec->dtype = PLPGSQL_DTYPE_REC;
560 rec->refname = pstrdup("new");
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;
568 /* Add the record for referencing OLD */
569 rec = palloc0(sizeof(PLpgSQL_rec));
570 rec->dtype = PLPGSQL_DTYPE_REC;
571 rec->refname = pstrdup("old");
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;
579 /* Add the variable tg_name */
580 var = plpgsql_build_variable("tg_name", 0,
581 plpgsql_build_datatype(NAMEOID, -1),
583 function->tg_name_varno = var->dno;
585 /* Add the variable tg_when */
586 var = plpgsql_build_variable("tg_when", 0,
587 plpgsql_build_datatype(TEXTOID, -1),
589 function->tg_when_varno = var->dno;
591 /* Add the variable tg_level */
592 var = plpgsql_build_variable("tg_level", 0,
593 plpgsql_build_datatype(TEXTOID, -1),
595 function->tg_level_varno = var->dno;
597 /* Add the variable tg_op */
598 var = plpgsql_build_variable("tg_op", 0,
599 plpgsql_build_datatype(TEXTOID, -1),
601 function->tg_op_varno = var->dno;
603 /* Add the variable tg_relid */
604 var = plpgsql_build_variable("tg_relid", 0,
605 plpgsql_build_datatype(OIDOID, -1),
607 function->tg_relid_varno = var->dno;
609 /* Add the variable tg_relname */
610 var = plpgsql_build_variable("tg_relname", 0,
611 plpgsql_build_datatype(NAMEOID, -1),
613 function->tg_relname_varno = var->dno;
615 /* Add the variable tg_nargs */
616 var = plpgsql_build_variable("tg_nargs", 0,
617 plpgsql_build_datatype(INT4OID, -1),
619 function->tg_nargs_varno = var->dno;
624 elog(ERROR, "unrecognized function typecode: %u", functype);
628 /* Remember if function is STABLE/IMMUTABLE */
629 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
632 * Create the magic FOUND variable.
634 var = plpgsql_build_variable("found", 0,
635 plpgsql_build_datatype(BOOLOID, -1),
637 function->found_varno = var->dno;
640 * Forget about the above created variables
642 plpgsql_add_initdatums(NULL);
645 * Now parse the function's text
647 parse_rc = plpgsql_yyparse();
649 elog(ERROR, "plpgsql parser returned %d", parse_rc);
650 function->action = plpgsql_yylval.program;
652 plpgsql_scanner_finish();
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.
663 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
666 if (function->action->exceptions != NULL)
668 PLpgSQL_stmt_block *new;
670 new = palloc0(sizeof(PLpgSQL_stmt_block));
671 new->cmd_type = PLPGSQL_STMT_BLOCK;
672 new->body = list_make1(function->action);
674 function->action = new;
676 if (function->action->body == NIL ||
677 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
679 PLpgSQL_stmt_return *new;
681 new = palloc0(sizeof(PLpgSQL_stmt_return));
682 new->cmd_type = PLPGSQL_STMT_RETURN;
684 new->retvarno = function->out_param_varno;
686 function->action->body = lappend(function->action->body, new);
691 * Complete the function's info
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];
701 /* Debug dump for completed functions */
702 if (plpgsql_DumpExecTree)
703 plpgsql_dumptree(function);
706 * add it to the hash table
708 plpgsql_HashTableInsert(function, hashkey);
711 * Pop the error context stack
713 error_context_stack = plerrcontext.previous;
714 plpgsql_error_funcname = NULL;
715 plpgsql_error_lineno = 0;
717 plpgsql_check_syntax = false;
719 MemoryContextSwitchTo(compile_tmp_cxt);
720 compile_tmp_cxt = NULL;
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
732 plpgsql_compile_error_callback(void *arg)
737 * Try to convert syntax error position to reference text of
738 * original CREATE FUNCTION command.
740 if (function_parse_error_transpose((const char *) arg))
744 * Done if a syntax error position was reported; otherwise we have
745 * to fall back to a "near line N" report.
749 if (plpgsql_error_funcname)
750 errcontext("compile of PL/pgSQL function \"%s\" near line %d",
751 plpgsql_error_funcname, plpgsql_error_lineno);
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.
761 fetchArgInfo(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames,
764 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
765 Datum proallargtypes;
775 /* First discover the total number of parameters and get their types */
776 proallargtypes = SysCacheGetAttr(PROCOID, procTup,
777 Anum_pg_proc_proallargtypes,
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.
787 arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
788 numargs = ARR_DIMS(arr)[0];
789 if (ARR_NDIM(arr) != 1 ||
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));
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));
808 /* Get argument names, if available */
809 proargnames = SysCacheGetAttr(PROCOID, procTup,
810 Anum_pg_proc_proargnames,
816 deconstruct_array(DatumGetArrayTypeP(proargnames),
817 TEXTOID, -1, false, 'i',
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,
827 /* Get argument modes, if available */
828 proargmodes = SysCacheGetAttr(PROCOID, procTup,
829 Anum_pg_proc_proargmodes,
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));
850 * plpgsql_parse_word The scanner calls this to postparse
851 * any single word not found by a
856 plpgsql_parse_word(char *word)
861 /* Do case conversion and word separation */
862 plpgsql_convert_ident(word, cp, 1);
865 * Recognize tg_argv when compiling triggers
867 if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
869 if (strcmp(cp[0], "tg_argv") == 0)
871 bool save_spacescanned = plpgsql_SpaceScanned;
872 PLpgSQL_trigarg *trigarg;
874 trigarg = palloc0(sizeof(PLpgSQL_trigarg));
875 trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
877 if (plpgsql_yylex() != '[')
878 plpgsql_yyerror("expected \"[\"");
880 trigarg->argnum = plpgsql_read_expression(']', "]");
882 plpgsql_adddatum((PLpgSQL_datum *) trigarg);
883 plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
885 plpgsql_SpaceScanned = save_spacescanned;
892 * Do a lookup on the compiler's namestack
894 nse = plpgsql_ns_lookup(cp[0], NULL);
898 switch (nse->itemtype)
900 case PLPGSQL_NSTYPE_LABEL:
903 case PLPGSQL_NSTYPE_VAR:
904 plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
907 case PLPGSQL_NSTYPE_REC:
908 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
911 case PLPGSQL_NSTYPE_ROW:
912 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
921 * Nothing found - up to now it's a word without any special meaning
930 * plpgsql_parse_dblword Same lookup for two words
931 * separated by a dot.
935 plpgsql_parse_dblword(char *word)
940 /* Do case conversion and word separation */
941 plpgsql_convert_ident(word, cp, 2);
944 * Lookup the first word
946 ns = plpgsql_ns_lookup(cp[0], NULL);
954 switch (ns->itemtype)
956 case PLPGSQL_NSTYPE_LABEL:
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.
964 ns = plpgsql_ns_lookup(cp[1], cp[0]);
969 switch (ns->itemtype)
971 case PLPGSQL_NSTYPE_VAR:
972 plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
975 case PLPGSQL_NSTYPE_REC:
976 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
979 case PLPGSQL_NSTYPE_ROW:
980 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
988 case PLPGSQL_NSTYPE_REC:
991 * First word is a record name, so second word must be a
992 * field in this record.
994 PLpgSQL_recfield *new;
996 new = palloc(sizeof(PLpgSQL_recfield));
997 new->dtype = PLPGSQL_DTYPE_RECFIELD;
998 new->fieldname = pstrdup(cp[1]);
999 new->recparentno = ns->itemno;
1001 plpgsql_adddatum((PLpgSQL_datum *) new);
1003 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1010 case PLPGSQL_NSTYPE_ROW:
1013 * First word is a row name, so second word must be a
1014 * field in this row.
1019 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1020 for (i = 0; i < row->nfields; i++)
1022 if (row->fieldnames[i] &&
1023 strcmp(row->fieldnames[i], cp[1]) == 0)
1025 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1032 (errcode(ERRCODE_UNDEFINED_COLUMN),
1033 errmsg("row \"%s\" has no field \"%s\"",
1048 * plpgsql_parse_tripword Same lookup for three words
1049 * separated by dots.
1053 plpgsql_parse_tripword(char *word)
1058 /* Do case conversion and word separation */
1059 plpgsql_convert_ident(word, cp, 3);
1062 * Lookup the first word - it must be a label
1064 ns = plpgsql_ns_lookup(cp[0], NULL);
1072 if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
1081 * First word is a label, so second word could be a record or row
1083 ns = plpgsql_ns_lookup(cp[1], cp[0]);
1092 switch (ns->itemtype)
1094 case PLPGSQL_NSTYPE_REC:
1097 * This word is a record name, so third word must be a
1098 * field in this record.
1100 PLpgSQL_recfield *new;
1102 new = palloc(sizeof(PLpgSQL_recfield));
1103 new->dtype = PLPGSQL_DTYPE_RECFIELD;
1104 new->fieldname = pstrdup(cp[2]);
1105 new->recparentno = ns->itemno;
1107 plpgsql_adddatum((PLpgSQL_datum *) new);
1109 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1118 case PLPGSQL_NSTYPE_ROW:
1121 * This word is a row name, so third word must be a field
1127 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1128 for (i = 0; i < row->nfields; i++)
1130 if (row->fieldnames[i] &&
1131 strcmp(row->fieldnames[i], cp[2]) == 0)
1133 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1143 (errcode(ERRCODE_UNDEFINED_COLUMN),
1144 errmsg("row \"%s.%s\" has no field \"%s\"",
1145 cp[0], cp[1], cp[2])));
1160 * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
1161 * a variable name or a basetype.
1165 plpgsql_parse_wordtype(char *word)
1167 PLpgSQL_nsitem *nse;
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] == '%');
1178 plpgsql_convert_ident(word, cp, 2);
1183 * Do a lookup on the compiler's namestack. But ensure it moves up to
1186 old_nsstate = plpgsql_ns_setlocal(false);
1187 nse = plpgsql_ns_lookup(cp[0], NULL);
1188 plpgsql_ns_setlocal(old_nsstate);
1193 switch (nse->itemtype)
1195 case PLPGSQL_NSTYPE_VAR:
1196 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1199 /* XXX perhaps allow REC here? */
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.
1210 typeOid = LookupTypeName(makeTypeName(cp[0]));
1211 if (OidIsValid(typeOid))
1215 typeTup = SearchSysCache(TYPEOID,
1216 ObjectIdGetDatum(typeOid),
1218 if (HeapTupleIsValid(typeTup))
1220 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1222 if (!typeStruct->typisdefined ||
1223 typeStruct->typrelid != InvalidOid)
1225 ReleaseSysCache(typeTup);
1230 plpgsql_yylval.dtype = build_datatype(typeTup, -1);
1232 ReleaseSysCache(typeTup);
1239 * Nothing found - up to now it's a word without any special meaning
1248 * plpgsql_parse_dblwordtype Same lookup for word.word%TYPE
1252 plpgsql_parse_dblwordtype(char *word)
1254 PLpgSQL_nsitem *nse;
1257 HeapTuple classtup = NULL;
1258 HeapTuple attrtup = NULL;
1259 HeapTuple typetup = NULL;
1260 Form_pg_class classStruct;
1261 Form_pg_attribute attrStruct;
1264 MemoryContext oldCxt;
1265 int result = T_ERROR;
1267 /* Avoid memory leaks in the long-term function context */
1268 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
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] == '%');
1275 plpgsql_convert_ident(word, cp, 3);
1279 * Lookup the first word
1281 nse = plpgsql_ns_lookup(cp[0], NULL);
1284 * If this is a label lookup the second word in that label's
1289 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
1291 old_nsstate = plpgsql_ns_setlocal(false);
1292 nse = plpgsql_ns_lookup(cp[1], cp[0]);
1293 plpgsql_ns_setlocal(old_nsstate);
1295 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1297 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1302 /* Return T_ERROR if not found, otherwise T_DTYPE */
1307 * First word could also be a table name
1309 classOid = RelnameGetRelid(cp[0]);
1310 if (!OidIsValid(classOid))
1313 classtup = SearchSysCache(RELOID,
1314 ObjectIdGetDatum(classOid),
1316 if (!HeapTupleIsValid(classtup))
1320 * It must be a relation, sequence, view, or type
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)
1330 * Fetch the named table field and it's type
1332 attrtup = SearchSysCacheAttName(classOid, cp[1]);
1333 if (!HeapTupleIsValid(attrtup))
1336 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1337 typetup = SearchSysCache(TYPEOID,
1338 ObjectIdGetDatum(attrStruct->atttypid),
1340 if (!HeapTupleIsValid(typetup))
1341 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1344 * Found that - build a compiler type struct in the caller's cxt
1347 MemoryContextSwitchTo(oldCxt);
1348 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1349 MemoryContextSwitchTo(compile_tmp_cxt);
1353 if (HeapTupleIsValid(classtup))
1354 ReleaseSysCache(classtup);
1355 if (HeapTupleIsValid(attrtup))
1356 ReleaseSysCache(attrtup);
1357 if (HeapTupleIsValid(typetup))
1358 ReleaseSysCache(typetup);
1360 MemoryContextSwitchTo(oldCxt);
1365 * plpgsql_parse_tripwordtype Same lookup for word.word.word%TYPE
1368 #define TYPE_JUNK_LEN 5
1371 plpgsql_parse_tripwordtype(char *word)
1374 HeapTuple classtup = NULL;
1375 Form_pg_class classStruct;
1376 HeapTuple attrtup = NULL;
1377 Form_pg_attribute attrStruct;
1378 HeapTuple typetup = NULL;
1381 int qualified_att_len;
1385 MemoryContext oldCxt;
1386 int result = T_ERROR;
1388 /* Avoid memory leaks in the long-term function context */
1389 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1391 /* Do case conversion and word separation */
1392 qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
1393 Assert(word[qualified_att_len] == '%');
1395 for (i = 0; i < qualified_att_len; i++)
1397 if (word[i] == '.' && ++numdots == 2)
1401 cp[0] = (char *) palloc((i + 1) * sizeof(char));
1402 memcpy(cp[0], word, i * sizeof(char));
1406 * qualified_att_len - one based position + 1 (null terminator)
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';
1412 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0],
1413 "plpgsql_parse_tripwordtype"));
1414 classOid = RangeVarGetRelid(relvar, true);
1415 if (!OidIsValid(classOid))
1418 classtup = SearchSysCache(RELOID,
1419 ObjectIdGetDatum(classOid),
1421 if (!HeapTupleIsValid(classtup))
1425 * It must be a relation, sequence, view, or type
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)
1435 * Fetch the named table field and it's type
1437 plpgsql_convert_ident(cp[1], colname, 1);
1438 attrtup = SearchSysCacheAttName(classOid, colname[0]);
1439 if (!HeapTupleIsValid(attrtup))
1442 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1443 typetup = SearchSysCache(TYPEOID,
1444 ObjectIdGetDatum(attrStruct->atttypid),
1446 if (!HeapTupleIsValid(typetup))
1447 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1450 * Found that - build a compiler type struct in the caller's cxt
1453 MemoryContextSwitchTo(oldCxt);
1454 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1455 MemoryContextSwitchTo(compile_tmp_cxt);
1459 if (HeapTupleIsValid(classtup))
1460 ReleaseSysCache(classtup);
1461 if (HeapTupleIsValid(classtup))
1462 ReleaseSysCache(attrtup);
1463 if (HeapTupleIsValid(typetup))
1464 ReleaseSysCache(typetup);
1466 MemoryContextSwitchTo(oldCxt);
1471 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1472 * So word must be a table name.
1476 plpgsql_parse_wordrowtype(char *word)
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] == '%');
1487 plpgsql_convert_ident(word, cp, 2);
1490 /* Lookup the relation */
1491 classOid = RelnameGetRelid(cp[0]);
1492 if (!OidIsValid(classOid))
1494 (errcode(ERRCODE_UNDEFINED_TABLE),
1495 errmsg("relation \"%s\" does not exist", cp[0])));
1498 * Build and return the row type struct
1500 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1510 * plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
1511 * So word must be a namespace qualified table name.
1514 #define ROWTYPE_JUNK_LEN 8
1517 plpgsql_parse_dblwordrowtype(char *word)
1523 MemoryContext oldCxt;
1525 /* Avoid memory leaks in long-term function context */
1526 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
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] == '%');
1536 /* Lookup the relation */
1537 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
1538 classOid = RangeVarGetRelid(relvar, true);
1539 if (!OidIsValid(classOid))
1541 (errcode(ERRCODE_UNDEFINED_TABLE),
1542 errmsg("relation \"%s\" does not exist", cp)));
1544 /* Build and return the row type struct */
1545 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1548 MemoryContextSwitchTo(oldCxt);
1553 * plpgsql_build_variable - build a datum-array entry of a given
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.
1562 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
1565 PLpgSQL_variable *result;
1567 switch (dtype->ttype)
1569 case PLPGSQL_TTYPE_SCALAR:
1571 /* Ordinary scalar datatype */
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 */
1581 /* preset to NULL */
1584 var->freeval = false;
1586 plpgsql_adddatum((PLpgSQL_datum *) var);
1588 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1591 result = (PLpgSQL_variable *) var;
1594 case PLPGSQL_TTYPE_ROW:
1596 /* Composite type -- build a row variable */
1599 row = build_row_from_class(dtype->typrelid);
1601 row->dtype = PLPGSQL_DTYPE_ROW;
1602 row->refname = pstrdup(refname);
1603 row->lineno = lineno;
1605 plpgsql_adddatum((PLpgSQL_datum *) row);
1607 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
1610 result = (PLpgSQL_variable *) row;
1613 case PLPGSQL_TTYPE_REC:
1616 * "record" type -- build a variable-contents record
1621 rec = palloc0(sizeof(PLpgSQL_rec));
1622 rec->dtype = PLPGSQL_DTYPE_REC;
1623 rec->refname = pstrdup(refname);
1624 rec->lineno = lineno;
1626 plpgsql_adddatum((PLpgSQL_datum *) rec);
1628 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
1631 result = (PLpgSQL_variable *) rec;
1634 case PLPGSQL_TTYPE_PSEUDO:
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 */
1642 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1643 result = NULL; /* keep compiler quiet */
1651 * Build a row-variable data structure given the pg_class OID.
1653 static PLpgSQL_row *
1654 build_row_from_class(Oid classOid)
1658 Form_pg_class classStruct;
1659 const char *relname;
1663 * Open the relation to get info.
1665 rel = relation_open(classOid, AccessShareLock);
1666 classStruct = RelationGetForm(rel);
1667 relname = RelationGetRelationName(rel);
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)
1675 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1676 errmsg("relation \"%s\" is not a table", relname)));
1679 * Create a row datum entry and all the required variables that it
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);
1689 for (i = 0; i < row->nfields; i++)
1691 Form_pg_attribute attrStruct;
1694 * Get the attribute and check for dropped column
1696 attrStruct = row->rowtupdesc->attrs[i];
1698 if (!attrStruct->attisdropped)
1701 char refname[(NAMEDATALEN * 2) + 100];
1702 PLpgSQL_variable *var;
1704 attname = NameStr(attrStruct->attname);
1705 snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
1708 * Create the internal variable for the field
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.
1717 var = plpgsql_build_variable(refname, 0,
1718 plpgsql_build_datatype(attrStruct->atttypid,
1719 attrStruct->atttypmod),
1722 /* Add the variable to the row */
1723 row->fieldnames[i] = attname;
1724 row->varnos[i] = var->dno;
1728 /* Leave a hole in the row structure for the dropped col */
1729 row->fieldnames[i] = NULL;
1730 row->varnos[i] = -1;
1734 relation_close(rel, AccessShareLock);
1740 * Build a row-variable data structure given the component variables.
1742 static PLpgSQL_row *
1743 build_row_from_vars(PLpgSQL_variable **vars, int numvars)
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));
1755 for (i = 0; i < numvars; i++)
1757 PLpgSQL_variable *var = vars[i];
1758 Oid typoid = RECORDOID;
1763 case PLPGSQL_DTYPE_VAR:
1764 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1765 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1768 case PLPGSQL_DTYPE_REC:
1771 case PLPGSQL_DTYPE_ROW:
1772 if (((PLpgSQL_row *) var)->rowtupdesc)
1774 typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
1775 typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
1780 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1783 row->fieldnames[i] = var->refname;
1784 row->varnos[i] = var->dno;
1786 TupleDescInitEntry(row->rowtupdesc, i+1,
1797 * plpgsql_parse_datatype Scanner found something that should
1798 * be a datatype name.
1802 plpgsql_parse_datatype(const char *string)
1807 /* Let the main parser try to parse it under standard SQL rules */
1808 parseTypeString(string, &type_id, &typmod);
1810 /* Okay, build a PLpgSQL_type data structure for it */
1811 return plpgsql_build_datatype(type_id, typmod);
1815 * plpgsql_build_datatype
1816 * Build PLpgSQL_type struct given type OID and typmod.
1819 plpgsql_build_datatype(Oid typeOid, int32 typmod)
1824 typeTup = SearchSysCache(TYPEOID,
1825 ObjectIdGetDatum(typeOid),
1827 if (!HeapTupleIsValid(typeTup))
1828 elog(ERROR, "cache lookup failed for type %u", typeOid);
1830 typ = build_datatype(typeTup, typmod);
1832 ReleaseSysCache(typeTup);
1838 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1840 static PLpgSQL_type *
1841 build_datatype(HeapTuple typeTup, int32 typmod)
1843 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1846 if (!typeStruct->typisdefined)
1848 (errcode(ERRCODE_UNDEFINED_OBJECT),
1849 errmsg("type \"%s\" is only a shell",
1850 NameStr(typeStruct->typname))));
1852 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
1854 typ->typname = pstrdup(NameStr(typeStruct->typname));
1855 typ->typoid = HeapTupleGetOid(typeTup);
1856 switch (typeStruct->typtype)
1858 case 'b': /* base type */
1859 case 'd': /* domain */
1860 typ->ttype = PLPGSQL_TTYPE_SCALAR;
1862 case 'c': /* composite, ie, rowtype */
1863 Assert(OidIsValid(typeStruct->typrelid));
1864 typ->ttype = PLPGSQL_TTYPE_ROW;
1866 case 'p': /* pseudo */
1867 if (typ->typoid == RECORDOID)
1868 typ->ttype = PLPGSQL_TTYPE_REC;
1870 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
1873 elog(ERROR, "unrecognized typtype: %d",
1874 (int) typeStruct->typtype);
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;
1888 * plpgsql_parse_err_condition
1889 * Generate PLpgSQL_condition entry(s) for an exception condition name
1891 * This has to be able to return a list because there are some duplicate
1892 * names in the table of error code names.
1895 plpgsql_parse_err_condition(char *condname)
1898 PLpgSQL_condition *new;
1899 PLpgSQL_condition *prev;
1902 * XXX Eventually we will want to look for user-defined exception
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).
1910 if (strcmp(condname, "others") == 0)
1912 new = palloc(sizeof(PLpgSQL_condition));
1913 new->sqlerrstate = 0;
1914 new->condname = condname;
1920 for (i = 0; exception_label_map[i].label != NULL; i++)
1922 if (strcmp(condname, exception_label_map[i].label) == 0)
1924 new = palloc(sizeof(PLpgSQL_condition));
1925 new->sqlerrstate = exception_label_map[i].sqlerrstate;
1926 new->condname = condname;
1934 (errcode(ERRCODE_UNDEFINED_OBJECT),
1935 errmsg("unrecognized exception condition \"%s\"",
1942 * plpgsql_adddatum Add a variable, record or row
1943 * to the compiler's datum list.
1947 plpgsql_adddatum(PLpgSQL_datum *new)
1949 if (plpgsql_nDatums == datums_alloc)
1952 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1955 new->dno = plpgsql_nDatums;
1956 plpgsql_Datums[plpgsql_nDatums++] = new;
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.
1969 plpgsql_add_initdatums(int **varnos)
1974 for (i = datums_last; i < plpgsql_nDatums; i++)
1976 switch (plpgsql_Datums[i]->dtype)
1978 case PLPGSQL_DTYPE_VAR:
1991 *varnos = (int *) palloc(sizeof(int) * n);
1994 for (i = datums_last; i < plpgsql_nDatums; i++)
1996 switch (plpgsql_Datums[i]->dtype)
1998 case PLPGSQL_DTYPE_VAR:
1999 (*varnos)[n++] = plpgsql_Datums[i]->dno;
2010 datums_last = plpgsql_nDatums;
2016 * Compute the hashkey for a given function invocation
2018 * The hashkey is returned into the caller-provided storage at *hashkey.
2021 compute_function_hashkey(FunctionCallInfo fcinfo,
2022 Form_pg_proc procStruct,
2023 PLpgSQL_func_hashkey *hashkey,
2026 /* Make sure any unused bytes of the struct are zero */
2027 MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2029 /* get function OID */
2030 hashkey->funcOid = fcinfo->flinfo->fn_oid;
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.
2037 if (CALLED_AS_TRIGGER(fcinfo) && !forValidator)
2039 TriggerData *trigdata = (TriggerData *) fcinfo->context;
2041 hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
2044 if (procStruct->pronargs > 0)
2046 /* get the argument types */
2047 memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2048 procStruct->pronargs * sizeof(Oid));
2050 /* resolve any polymorphic argument types */
2051 plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2054 fcinfo->flinfo->fn_expr,
2056 NameStr(procStruct->proname));
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.
2067 plpgsql_resolve_polymorphic_argtypes(int numargs,
2068 Oid *argtypes, char *argmodes,
2069 Node *call_expr, bool forValidator,
2070 const char *proname)
2076 /* normal case, pass to standard routine */
2077 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2080 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2081 errmsg("could not determine actual argument "
2082 "type for polymorphic function \"%s\"",
2087 /* special validation case */
2088 for (i = 0; i < numargs; i++)
2090 switch (argtypes[i])
2093 argtypes[i] = INT4OID;
2096 argtypes[i] = INT4ARRAYOID;
2106 delete_function(PLpgSQL_function *func)
2108 /* remove function from hash table */
2109 plpgsql_HashTableDelete(func);
2111 /* release the function's storage */
2112 MemoryContextDelete(func->fn_cxt);
2115 * Caller should be sure not to use passed-in pointer, as it now
2116 * points to pfree'd storage
2120 /* exported so we can call it from plpgsql_init() */
2122 plpgsql_HashTableInit(void)
2126 /* don't allow double-initialization */
2127 Assert(plpgsql_HashTable == NULL);
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",
2136 HASH_ELEM | HASH_FUNCTION);
2139 static PLpgSQL_function *
2140 plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
2142 plpgsql_HashEnt *hentry;
2144 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2149 return hentry->function;
2155 plpgsql_HashTableInsert(PLpgSQL_function *function,
2156 PLpgSQL_func_hashkey *func_key)
2158 plpgsql_HashEnt *hentry;
2161 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2166 elog(WARNING, "trying to insert a function that already exists");
2168 hentry->function = function;
2169 /* prepare back link from function to hashtable key */
2170 function->fn_hashkey = &hentry->key;
2174 plpgsql_HashTableDelete(PLpgSQL_function *function)
2176 plpgsql_HashEnt *hentry;
2178 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2179 (void *) function->fn_hashkey,
2183 elog(WARNING, "trying to delete function that does not exist");