1 /*-------------------------------------------------------------------------
3 * pl_comp.c - Compiler part of the PL/pgSQL
6 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.101 2006/03/14 22:48:23 tgl Exp $
13 *-------------------------------------------------------------------------
22 #include "access/heapam.h"
23 #include "catalog/namespace.h"
24 #include "catalog/pg_attribute.h"
25 #include "catalog/pg_attrdef.h"
26 #include "catalog/pg_class.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_type.h"
30 #include "nodes/makefuncs.h"
31 #include "parser/gramparse.h"
32 #include "parser/parse_type.h"
33 #include "tcop/tcopprot.h"
34 #include "utils/array.h"
35 #include "utils/builtins.h"
36 #include "utils/lsyscache.h"
37 #include "utils/memutils.h"
38 #include "utils/syscache.h"
42 * Our own local and global variables
45 static int datums_alloc;
47 PLpgSQL_datum **plpgsql_Datums;
48 static int datums_last = 0;
50 int plpgsql_error_lineno;
51 char *plpgsql_error_funcname;
52 bool plpgsql_DumpExecTree = false;
53 bool plpgsql_check_syntax = false;
55 PLpgSQL_function *plpgsql_curr_compile;
57 /* A context appropriate for short-term allocs during compilation */
58 MemoryContext compile_tmp_cxt;
61 * Hash table for compiled functions
64 static HTAB *plpgsql_HashTable = NULL;
66 typedef struct plpgsql_hashent
68 PLpgSQL_func_hashkey key;
69 PLpgSQL_function *function;
72 #define FUNCS_PER_USER 128 /* initial table size */
75 * Lookup table for EXCEPTION condition names
84 static const ExceptionLabelMap exception_label_map[] = {
85 #include "plerrcodes.h"
94 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
96 PLpgSQL_func_hashkey *hashkey,
98 static PLpgSQL_row *build_row_from_class(Oid classOid);
99 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
100 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
101 static void compute_function_hashkey(FunctionCallInfo fcinfo,
102 Form_pg_proc procStruct,
103 PLpgSQL_func_hashkey *hashkey,
105 static void plpgsql_resolve_polymorphic_argtypes(int numargs,
106 Oid *argtypes, char *argmodes,
107 Node *call_expr, bool forValidator,
108 const char *proname);
109 static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
110 static void plpgsql_HashTableInsert(PLpgSQL_function *function,
111 PLpgSQL_func_hashkey *func_key);
112 static void plpgsql_HashTableDelete(PLpgSQL_function *function);
113 static void delete_function(PLpgSQL_function *func);
116 * plpgsql_compile Make an execution tree for a PL/pgSQL function.
118 * If forValidator is true, we're only compiling for validation purposes,
119 * and so some checks are skipped.
121 * Note: it's important for this to fall through quickly if the function
122 * has already been compiled.
126 plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
128 Oid funcOid = fcinfo->flinfo->fn_oid;
130 Form_pg_proc procStruct;
131 PLpgSQL_function *function;
132 PLpgSQL_func_hashkey hashkey;
133 bool hashkey_valid = false;
136 * Lookup the pg_proc tuple by Oid; we'll need it in any case
138 procTup = SearchSysCache(PROCOID,
139 ObjectIdGetDatum(funcOid),
141 if (!HeapTupleIsValid(procTup))
142 elog(ERROR, "cache lookup failed for function %u", funcOid);
143 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
146 * See if there's already a cache entry for the current FmgrInfo. If not,
147 * try to find one in the hash table.
149 function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
153 /* Compute hashkey using function signature and actual arg types */
154 compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
155 hashkey_valid = true;
157 /* And do the lookup */
158 function = plpgsql_HashTableLookup(&hashkey);
163 /* We have a compiled function, but is it still valid? */
164 if (!(function->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
165 function->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data)))
167 /* Nope, drop the function and associated storage */
168 delete_function(function);
174 * If the function wasn't found or was out-of-date, we have to compile it
179 * Calculate hashkey if we didn't already; we'll need it to store the
180 * completed function.
183 compute_function_hashkey(fcinfo, procStruct, &hashkey,
189 function = do_compile(fcinfo, procTup, &hashkey, forValidator);
192 ReleaseSysCache(procTup);
195 * Save pointer in FmgrInfo to avoid search on subsequent calls
197 fcinfo->flinfo->fn_extra = (void *) function;
200 * Finally return the compiled function
206 * This is the slow part of plpgsql_compile().
208 * While compiling a function, the CurrentMemoryContext is the
209 * per-function memory context of the function we are compiling. That
210 * means a palloc() will allocate storage with the same lifetime as
211 * the function itself.
213 * Because palloc()'d storage will not be immediately freed, temporary
214 * allocations should either be performed in a short-lived memory
215 * context or explicitly pfree'd. Since not all backend functions are
216 * careful about pfree'ing their allocations, it is also wise to
217 * switch into a short-term context before calling into the
218 * backend. An appropriate context for performing short-term
219 * allocations is the compile_tmp_cxt.
221 static PLpgSQL_function *
222 do_compile(FunctionCallInfo fcinfo,
224 PLpgSQL_func_hashkey *hashkey,
227 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
228 int functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
229 PLpgSQL_function *function;
234 Form_pg_type typeStruct;
235 PLpgSQL_variable *var;
238 ErrorContextCallback plerrcontext;
243 int num_out_args = 0;
247 int *in_arg_varnos = NULL;
248 PLpgSQL_variable **out_arg_variables;
249 MemoryContext func_cxt;
252 * Setup the scanner input and error info. We assume that this function
253 * cannot be invoked recursively, so there's no need to save and restore
254 * the static variables used here.
256 prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
257 Anum_pg_proc_prosrc, &isnull);
259 elog(ERROR, "null prosrc");
260 proc_source = DatumGetCString(DirectFunctionCall1(textout, prosrcdatum));
261 plpgsql_scanner_init(proc_source, functype);
263 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
264 plpgsql_error_lineno = 0;
267 * Setup error traceback support for ereport()
269 plerrcontext.callback = plpgsql_compile_error_callback;
270 plerrcontext.arg = forValidator ? proc_source : NULL;
271 plerrcontext.previous = error_context_stack;
272 error_context_stack = &plerrcontext;
275 * Initialize the compiler
278 plpgsql_ns_push(NULL);
279 plpgsql_DumpExecTree = false;
283 /* This is short-lived, so needn't allocate in function's cxt */
284 plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
288 * Do extra syntax checks when validating the function definition. We skip
289 * this when actually compiling functions for execution, for performance
292 plpgsql_check_syntax = forValidator;
295 * Create the new function node. We allocate the function and all of its
296 * compile-time storage (e.g. parse tree) in its own memory context. This
297 * allows us to reclaim the function's storage cleanly.
299 func_cxt = AllocSetContextCreate(TopMemoryContext,
300 "PL/PgSQL function context",
301 ALLOCSET_DEFAULT_MINSIZE,
302 ALLOCSET_DEFAULT_INITSIZE,
303 ALLOCSET_DEFAULT_MAXSIZE);
304 compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
305 function = palloc0(sizeof(*function));
306 plpgsql_curr_compile = function;
308 function->fn_name = pstrdup(NameStr(procStruct->proname));
309 function->fn_oid = fcinfo->flinfo->fn_oid;
310 function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
311 function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
312 function->fn_functype = functype;
313 function->fn_cxt = func_cxt;
314 function->out_param_varno = -1; /* set up for no OUT param */
321 * Fetch info about the procedure's parameters. Allocations aren't
322 * needed permanently, so make them in tmp cxt.
324 * We also need to resolve any polymorphic input or output
325 * argument types. In validation mode we won't be able to, so we
326 * arbitrarily assume we are dealing with integers.
328 MemoryContextSwitchTo(compile_tmp_cxt);
330 numargs = get_func_arg_info(procTup,
331 &argtypes, &argnames, &argmodes);
333 plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
334 fcinfo->flinfo->fn_expr,
336 plpgsql_error_funcname);
338 in_arg_varnos = (int *) palloc(numargs * sizeof(int));
339 out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
341 MemoryContextSwitchTo(func_cxt);
344 * Create the variables for the procedure's parameters.
346 for (i = 0; i < numargs; i++)
349 Oid argtypeid = argtypes[i];
350 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
351 PLpgSQL_type *argdtype;
352 PLpgSQL_variable *argvariable;
355 /* Create $n name for variable */
356 snprintf(buf, sizeof(buf), "$%d", i + 1);
358 /* Create datatype info */
359 argdtype = plpgsql_build_datatype(argtypeid, -1);
361 /* Disallow pseudotype argument */
362 /* (note we already replaced ANYARRAY/ANYELEMENT) */
363 /* (build_variable would do this, but wrong message) */
364 if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
365 argdtype->ttype != PLPGSQL_TTYPE_ROW)
367 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
368 errmsg("plpgsql functions cannot take type %s",
369 format_type_be(argtypeid))));
371 /* Build variable and add to datum list */
372 argvariable = plpgsql_build_variable(buf, 0,
375 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
377 argitemtype = PLPGSQL_NSTYPE_VAR;
378 /* input argument vars are forced to be CONSTANT */
379 if (argmode == PROARGMODE_IN)
380 ((PLpgSQL_var *) argvariable)->isconst = true;
384 Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
385 argitemtype = PLPGSQL_NSTYPE_ROW;
388 /* Remember arguments in appropriate arrays */
389 if (argmode == PROARGMODE_IN || argmode == PROARGMODE_INOUT)
390 in_arg_varnos[num_in_args++] = argvariable->dno;
391 if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_INOUT)
392 out_arg_variables[num_out_args++] = argvariable;
394 /* Add to namespace under the $n name */
395 plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
397 /* If there's a name for the argument, make an alias */
398 if (argnames && argnames[i][0] != '\0')
399 plpgsql_ns_additem(argitemtype, argvariable->dno,
404 * If there's just one OUT parameter, out_param_varno points
405 * directly to it. If there's more than one, build a row that
408 if (num_out_args == 1)
409 function->out_param_varno = out_arg_variables[0]->dno;
410 else if (num_out_args > 1)
412 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
415 plpgsql_adddatum((PLpgSQL_datum *) row);
416 function->out_param_varno = row->rowno;
420 * Check for a polymorphic returntype. If found, use the actual
421 * returntype type from the caller's FuncExpr node, if we have
422 * one. (In validation mode we arbitrarily assume we are dealing
425 * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
426 * work; if it doesn't we're in some context that fails to make
427 * the info available.
429 rettypeid = procStruct->prorettype;
430 if (rettypeid == ANYARRAYOID || rettypeid == ANYELEMENTOID)
434 if (rettypeid == ANYARRAYOID)
435 rettypeid = INT4ARRAYOID;
441 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
442 if (!OidIsValid(rettypeid))
444 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
445 errmsg("could not determine actual return type "
446 "for polymorphic function \"%s\"",
447 plpgsql_error_funcname)));
452 * Normal function has a defined returntype
454 function->fn_rettype = rettypeid;
455 function->fn_retset = procStruct->proretset;
458 * Lookup the function's return type
460 typeTup = SearchSysCache(TYPEOID,
461 ObjectIdGetDatum(rettypeid),
463 if (!HeapTupleIsValid(typeTup))
464 elog(ERROR, "cache lookup failed for type %u", rettypeid);
465 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
467 /* Disallow pseudotype result, except VOID or RECORD */
468 /* (note we already replaced ANYARRAY/ANYELEMENT) */
469 if (typeStruct->typtype == 'p')
471 if (rettypeid == VOIDOID ||
472 rettypeid == RECORDOID)
474 else if (rettypeid == TRIGGEROID)
476 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
477 errmsg("trigger functions may only be called as triggers")));
480 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
481 errmsg("plpgsql functions cannot return type %s",
482 format_type_be(rettypeid))));
485 if (typeStruct->typrelid != InvalidOid ||
486 rettypeid == RECORDOID)
487 function->fn_retistuple = true;
490 function->fn_retbyval = typeStruct->typbyval;
491 function->fn_rettyplen = typeStruct->typlen;
492 function->fn_rettypioparam = getTypeIOParam(typeTup);
493 fmgr_info(typeStruct->typinput, &(function->fn_retinput));
496 * install $0 reference, but only for polymorphic return
497 * types, and not when the return is specified through an
500 if ((procStruct->prorettype == ANYARRAYOID ||
501 procStruct->prorettype == ANYELEMENTOID) &&
504 (void) plpgsql_build_variable("$0", 0,
505 build_datatype(typeTup, -1),
509 ReleaseSysCache(typeTup);
513 /* Trigger procedure's return type is unknown yet */
514 function->fn_rettype = InvalidOid;
515 function->fn_retbyval = false;
516 function->fn_retistuple = true;
517 function->fn_retset = false;
519 /* shouldn't be any declared arguments */
520 if (procStruct->pronargs != 0)
522 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
523 errmsg("trigger functions cannot have declared arguments"),
524 errhint("You probably want to use TG_NARGS and TG_ARGV instead.")));
526 /* Add the record for referencing NEW */
527 rec = palloc0(sizeof(PLpgSQL_rec));
528 rec->dtype = PLPGSQL_DTYPE_REC;
529 rec->refname = pstrdup("new");
532 rec->freetup = false;
533 plpgsql_adddatum((PLpgSQL_datum *) rec);
534 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
535 function->new_varno = rec->recno;
537 /* Add the record for referencing OLD */
538 rec = palloc0(sizeof(PLpgSQL_rec));
539 rec->dtype = PLPGSQL_DTYPE_REC;
540 rec->refname = pstrdup("old");
543 rec->freetup = false;
544 plpgsql_adddatum((PLpgSQL_datum *) rec);
545 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
546 function->old_varno = rec->recno;
548 /* Add the variable tg_name */
549 var = plpgsql_build_variable("tg_name", 0,
550 plpgsql_build_datatype(NAMEOID, -1),
552 function->tg_name_varno = var->dno;
554 /* Add the variable tg_when */
555 var = plpgsql_build_variable("tg_when", 0,
556 plpgsql_build_datatype(TEXTOID, -1),
558 function->tg_when_varno = var->dno;
560 /* Add the variable tg_level */
561 var = plpgsql_build_variable("tg_level", 0,
562 plpgsql_build_datatype(TEXTOID, -1),
564 function->tg_level_varno = var->dno;
566 /* Add the variable tg_op */
567 var = plpgsql_build_variable("tg_op", 0,
568 plpgsql_build_datatype(TEXTOID, -1),
570 function->tg_op_varno = var->dno;
572 /* Add the variable tg_relid */
573 var = plpgsql_build_variable("tg_relid", 0,
574 plpgsql_build_datatype(OIDOID, -1),
576 function->tg_relid_varno = var->dno;
578 /* Add the variable tg_relname */
579 var = plpgsql_build_variable("tg_relname", 0,
580 plpgsql_build_datatype(NAMEOID, -1),
582 function->tg_relname_varno = var->dno;
584 /* Add the variable tg_nargs */
585 var = plpgsql_build_variable("tg_nargs", 0,
586 plpgsql_build_datatype(INT4OID, -1),
588 function->tg_nargs_varno = var->dno;
593 elog(ERROR, "unrecognized function typecode: %u", functype);
597 /* Remember if function is STABLE/IMMUTABLE */
598 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
601 * Create the magic FOUND variable.
603 var = plpgsql_build_variable("found", 0,
604 plpgsql_build_datatype(BOOLOID, -1),
606 function->found_varno = var->dno;
609 * Forget about the above created variables
611 plpgsql_add_initdatums(NULL);
614 * Now parse the function's text
616 parse_rc = plpgsql_yyparse();
618 elog(ERROR, "plpgsql parser returned %d", parse_rc);
619 function->action = plpgsql_yylval.program;
621 plpgsql_scanner_finish();
625 * If it has OUT parameters or returns VOID or returns a set, we allow
626 * control to fall off the end without an explicit RETURN statement. The
627 * easiest way to implement this is to add a RETURN statement to the end
628 * of the statement list during parsing. However, if the outer block has
629 * an EXCEPTION clause, we need to make a new outer block, since the added
630 * RETURN shouldn't act like it is inside the EXCEPTION clause.
632 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
635 if (function->action->exceptions != NULL)
637 PLpgSQL_stmt_block *new;
639 new = palloc0(sizeof(PLpgSQL_stmt_block));
640 new->cmd_type = PLPGSQL_STMT_BLOCK;
641 new->body = list_make1(function->action);
643 function->action = new;
645 if (function->action->body == NIL ||
646 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
648 PLpgSQL_stmt_return *new;
650 new = palloc0(sizeof(PLpgSQL_stmt_return));
651 new->cmd_type = PLPGSQL_STMT_RETURN;
653 new->retvarno = function->out_param_varno;
655 function->action->body = lappend(function->action->body, new);
660 * Complete the function's info
662 function->fn_nargs = procStruct->pronargs;
663 for (i = 0; i < function->fn_nargs; i++)
664 function->fn_argvarnos[i] = in_arg_varnos[i];
665 function->ndatums = plpgsql_nDatums;
666 function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
667 for (i = 0; i < plpgsql_nDatums; i++)
668 function->datums[i] = plpgsql_Datums[i];
670 /* Debug dump for completed functions */
671 if (plpgsql_DumpExecTree)
672 plpgsql_dumptree(function);
675 * add it to the hash table
677 plpgsql_HashTableInsert(function, hashkey);
680 * Pop the error context stack
682 error_context_stack = plerrcontext.previous;
683 plpgsql_error_funcname = NULL;
684 plpgsql_error_lineno = 0;
686 plpgsql_check_syntax = false;
688 MemoryContextSwitchTo(compile_tmp_cxt);
689 compile_tmp_cxt = NULL;
695 * error context callback to let us supply a call-stack traceback. If
696 * we are validating, the function source is passed as an
697 * argument. This function is public only for the sake of an assertion
701 plpgsql_compile_error_callback(void *arg)
706 * Try to convert syntax error position to reference text of original
707 * CREATE FUNCTION command.
709 if (function_parse_error_transpose((const char *) arg))
713 * Done if a syntax error position was reported; otherwise we have to
714 * fall back to a "near line N" report.
718 if (plpgsql_error_funcname)
719 errcontext("compile of PL/pgSQL function \"%s\" near line %d",
720 plpgsql_error_funcname, plpgsql_error_lineno);
725 * plpgsql_parse_word The scanner calls this to postparse
726 * any single word not found by a
731 plpgsql_parse_word(char *word)
736 /* Do case conversion and word separation */
737 plpgsql_convert_ident(word, cp, 1);
740 * Recognize tg_argv when compiling triggers
742 if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
744 if (strcmp(cp[0], "tg_argv") == 0)
746 bool save_spacescanned = plpgsql_SpaceScanned;
747 PLpgSQL_trigarg *trigarg;
749 trigarg = palloc0(sizeof(PLpgSQL_trigarg));
750 trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
752 if (plpgsql_yylex() != '[')
753 plpgsql_yyerror("expected \"[\"");
755 trigarg->argnum = plpgsql_read_expression(']', "]");
757 plpgsql_adddatum((PLpgSQL_datum *) trigarg);
758 plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
760 plpgsql_SpaceScanned = save_spacescanned;
767 * Do a lookup on the compiler's namestack
769 nse = plpgsql_ns_lookup(cp[0], NULL);
773 switch (nse->itemtype)
775 case PLPGSQL_NSTYPE_LABEL:
778 case PLPGSQL_NSTYPE_VAR:
779 plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
782 case PLPGSQL_NSTYPE_REC:
783 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
786 case PLPGSQL_NSTYPE_ROW:
787 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
796 * Nothing found - up to now it's a word without any special meaning for
805 * plpgsql_parse_dblword Same lookup for two words
806 * separated by a dot.
810 plpgsql_parse_dblword(char *word)
815 /* Do case conversion and word separation */
816 plpgsql_convert_ident(word, cp, 2);
819 * Lookup the first word
821 ns = plpgsql_ns_lookup(cp[0], NULL);
829 switch (ns->itemtype)
831 case PLPGSQL_NSTYPE_LABEL:
834 * First word is a label, so second word could be a variable,
835 * record or row in that bodies namestack. Anything else could
836 * only be something in a query given to the SPI manager and
837 * T_ERROR will get eaten up by the collector routines.
839 ns = plpgsql_ns_lookup(cp[1], cp[0]);
844 switch (ns->itemtype)
846 case PLPGSQL_NSTYPE_VAR:
847 plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
850 case PLPGSQL_NSTYPE_REC:
851 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
854 case PLPGSQL_NSTYPE_ROW:
855 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
863 case PLPGSQL_NSTYPE_REC:
866 * First word is a record name, so second word must be a field
869 PLpgSQL_recfield *new;
871 new = palloc(sizeof(PLpgSQL_recfield));
872 new->dtype = PLPGSQL_DTYPE_RECFIELD;
873 new->fieldname = pstrdup(cp[1]);
874 new->recparentno = ns->itemno;
876 plpgsql_adddatum((PLpgSQL_datum *) new);
878 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
885 case PLPGSQL_NSTYPE_ROW:
888 * First word is a row name, so second word must be a field in
894 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
895 for (i = 0; i < row->nfields; i++)
897 if (row->fieldnames[i] &&
898 strcmp(row->fieldnames[i], cp[1]) == 0)
900 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
907 (errcode(ERRCODE_UNDEFINED_COLUMN),
908 errmsg("row \"%s\" has no field \"%s\"",
923 * plpgsql_parse_tripword Same lookup for three words
928 plpgsql_parse_tripword(char *word)
933 /* Do case conversion and word separation */
934 plpgsql_convert_ident(word, cp, 3);
937 * Lookup the first word - it must be a label
939 ns = plpgsql_ns_lookup(cp[0], NULL);
947 if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
956 * First word is a label, so second word could be a record or row
958 ns = plpgsql_ns_lookup(cp[1], cp[0]);
967 switch (ns->itemtype)
969 case PLPGSQL_NSTYPE_REC:
972 * This word is a record name, so third word must be a field
975 PLpgSQL_recfield *new;
977 new = palloc(sizeof(PLpgSQL_recfield));
978 new->dtype = PLPGSQL_DTYPE_RECFIELD;
979 new->fieldname = pstrdup(cp[2]);
980 new->recparentno = ns->itemno;
982 plpgsql_adddatum((PLpgSQL_datum *) new);
984 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
993 case PLPGSQL_NSTYPE_ROW:
996 * This word is a row name, so third word must be a field in
1002 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1003 for (i = 0; i < row->nfields; i++)
1005 if (row->fieldnames[i] &&
1006 strcmp(row->fieldnames[i], cp[2]) == 0)
1008 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1018 (errcode(ERRCODE_UNDEFINED_COLUMN),
1019 errmsg("row \"%s.%s\" has no field \"%s\"",
1020 cp[0], cp[1], cp[2])));
1035 * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
1036 * a variable name or a basetype.
1040 plpgsql_parse_wordtype(char *word)
1042 PLpgSQL_nsitem *nse;
1048 /* Do case conversion and word separation */
1049 /* We convert %type to .type momentarily to keep converter happy */
1050 i = strlen(word) - 5;
1051 Assert(word[i] == '%');
1053 plpgsql_convert_ident(word, cp, 2);
1058 * Do a lookup on the compiler's namestack. But ensure it moves up to the
1061 old_nsstate = plpgsql_ns_setlocal(false);
1062 nse = plpgsql_ns_lookup(cp[0], NULL);
1063 plpgsql_ns_setlocal(old_nsstate);
1068 switch (nse->itemtype)
1070 case PLPGSQL_NSTYPE_VAR:
1071 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1074 /* XXX perhaps allow REC here? */
1082 * Word wasn't found on the namestack. Try to find a data type with that
1083 * name, but ignore pg_type entries that are in fact class types.
1085 typeOid = LookupTypeName(NULL, makeTypeName(cp[0]));
1086 if (OidIsValid(typeOid))
1090 typeTup = SearchSysCache(TYPEOID,
1091 ObjectIdGetDatum(typeOid),
1093 if (HeapTupleIsValid(typeTup))
1095 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1097 if (!typeStruct->typisdefined ||
1098 typeStruct->typrelid != InvalidOid)
1100 ReleaseSysCache(typeTup);
1105 plpgsql_yylval.dtype = build_datatype(typeTup, -1);
1107 ReleaseSysCache(typeTup);
1114 * Nothing found - up to now it's a word without any special meaning for
1123 * plpgsql_parse_dblwordtype Same lookup for word.word%TYPE
1127 plpgsql_parse_dblwordtype(char *word)
1129 PLpgSQL_nsitem *nse;
1132 HeapTuple classtup = NULL;
1133 HeapTuple attrtup = NULL;
1134 HeapTuple typetup = NULL;
1135 Form_pg_class classStruct;
1136 Form_pg_attribute attrStruct;
1139 MemoryContext oldCxt;
1140 int result = T_ERROR;
1142 /* Avoid memory leaks in the long-term function context */
1143 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1145 /* Do case conversion and word separation */
1146 /* We convert %type to .type momentarily to keep converter happy */
1147 i = strlen(word) - 5;
1148 Assert(word[i] == '%');
1150 plpgsql_convert_ident(word, cp, 3);
1154 * Lookup the first word
1156 nse = plpgsql_ns_lookup(cp[0], NULL);
1159 * If this is a label lookup the second word in that label's namestack
1164 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
1166 old_nsstate = plpgsql_ns_setlocal(false);
1167 nse = plpgsql_ns_lookup(cp[1], cp[0]);
1168 plpgsql_ns_setlocal(old_nsstate);
1170 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1172 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1177 /* Return T_ERROR if not found, otherwise T_DTYPE */
1182 * First word could also be a table name
1184 classOid = RelnameGetRelid(cp[0]);
1185 if (!OidIsValid(classOid))
1188 classtup = SearchSysCache(RELOID,
1189 ObjectIdGetDatum(classOid),
1191 if (!HeapTupleIsValid(classtup))
1193 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1196 * It must be a relation, sequence, view, or type
1198 if (classStruct->relkind != RELKIND_RELATION &&
1199 classStruct->relkind != RELKIND_SEQUENCE &&
1200 classStruct->relkind != RELKIND_VIEW &&
1201 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1205 * Fetch the named table field and its type
1207 attrtup = SearchSysCacheAttName(classOid, cp[1]);
1208 if (!HeapTupleIsValid(attrtup))
1210 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1212 typetup = SearchSysCache(TYPEOID,
1213 ObjectIdGetDatum(attrStruct->atttypid),
1215 if (!HeapTupleIsValid(typetup))
1216 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1219 * Found that - build a compiler type struct in the caller's cxt and
1222 MemoryContextSwitchTo(oldCxt);
1223 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1224 MemoryContextSwitchTo(compile_tmp_cxt);
1228 if (HeapTupleIsValid(classtup))
1229 ReleaseSysCache(classtup);
1230 if (HeapTupleIsValid(attrtup))
1231 ReleaseSysCache(attrtup);
1232 if (HeapTupleIsValid(typetup))
1233 ReleaseSysCache(typetup);
1235 MemoryContextSwitchTo(oldCxt);
1240 * plpgsql_parse_tripwordtype Same lookup for word.word.word%TYPE
1243 #define TYPE_JUNK_LEN 5
1246 plpgsql_parse_tripwordtype(char *word)
1249 HeapTuple classtup = NULL;
1250 HeapTuple attrtup = NULL;
1251 HeapTuple typetup = NULL;
1252 Form_pg_class classStruct;
1253 Form_pg_attribute attrStruct;
1256 int qualified_att_len;
1260 MemoryContext oldCxt;
1261 int result = T_ERROR;
1263 /* Avoid memory leaks in the long-term function context */
1264 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1266 /* Do case conversion and word separation */
1267 qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
1268 Assert(word[qualified_att_len] == '%');
1270 for (i = 0; i < qualified_att_len; i++)
1272 if (word[i] == '.' && ++numdots == 2)
1276 cp[0] = (char *) palloc((i + 1) * sizeof(char));
1277 memcpy(cp[0], word, i * sizeof(char));
1281 * qualified_att_len - one based position + 1 (null terminator)
1283 cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));
1284 memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));
1285 cp[1][qualified_att_len - i - 1] = '\0';
1287 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0],
1288 "plpgsql_parse_tripwordtype"));
1289 classOid = RangeVarGetRelid(relvar, true);
1290 if (!OidIsValid(classOid))
1293 classtup = SearchSysCache(RELOID,
1294 ObjectIdGetDatum(classOid),
1296 if (!HeapTupleIsValid(classtup))
1298 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1301 * It must be a relation, sequence, view, or type
1303 if (classStruct->relkind != RELKIND_RELATION &&
1304 classStruct->relkind != RELKIND_SEQUENCE &&
1305 classStruct->relkind != RELKIND_VIEW &&
1306 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1310 * Fetch the named table field and its type
1312 plpgsql_convert_ident(cp[1], colname, 1);
1313 attrtup = SearchSysCacheAttName(classOid, colname[0]);
1314 if (!HeapTupleIsValid(attrtup))
1316 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1318 typetup = SearchSysCache(TYPEOID,
1319 ObjectIdGetDatum(attrStruct->atttypid),
1321 if (!HeapTupleIsValid(typetup))
1322 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1325 * Found that - build a compiler type struct in the caller's cxt and
1328 MemoryContextSwitchTo(oldCxt);
1329 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1330 MemoryContextSwitchTo(compile_tmp_cxt);
1334 if (HeapTupleIsValid(classtup))
1335 ReleaseSysCache(classtup);
1336 if (HeapTupleIsValid(attrtup))
1337 ReleaseSysCache(attrtup);
1338 if (HeapTupleIsValid(typetup))
1339 ReleaseSysCache(typetup);
1341 MemoryContextSwitchTo(oldCxt);
1346 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1347 * So word must be a table name.
1351 plpgsql_parse_wordrowtype(char *word)
1357 /* Do case conversion and word separation */
1358 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1359 i = strlen(word) - 8;
1360 Assert(word[i] == '%');
1362 plpgsql_convert_ident(word, cp, 2);
1365 /* Lookup the relation */
1366 classOid = RelnameGetRelid(cp[0]);
1367 if (!OidIsValid(classOid))
1369 (errcode(ERRCODE_UNDEFINED_TABLE),
1370 errmsg("relation \"%s\" does not exist", cp[0])));
1373 * Build and return the row type struct
1375 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1385 * plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
1386 * So word must be a namespace qualified table name.
1389 #define ROWTYPE_JUNK_LEN 8
1392 plpgsql_parse_dblwordrowtype(char *word)
1398 MemoryContext oldCxt;
1400 /* Avoid memory leaks in long-term function context */
1401 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1403 /* Do case conversion and word separation */
1404 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1405 i = strlen(word) - ROWTYPE_JUNK_LEN;
1406 Assert(word[i] == '%');
1411 /* Lookup the relation */
1412 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
1413 classOid = RangeVarGetRelid(relvar, true);
1414 if (!OidIsValid(classOid))
1416 (errcode(ERRCODE_UNDEFINED_TABLE),
1417 errmsg("relation \"%s\" does not exist", cp)));
1419 /* Build and return the row type struct */
1420 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1423 MemoryContextSwitchTo(oldCxt);
1428 * plpgsql_build_variable - build a datum-array entry of a given
1431 * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or
1432 * PLpgSQL_rec depending on the given datatype, and is allocated via
1433 * palloc. The struct is automatically added to the current datum
1434 * array, and optionally to the current namespace.
1437 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
1440 PLpgSQL_variable *result;
1442 switch (dtype->ttype)
1444 case PLPGSQL_TTYPE_SCALAR:
1446 /* Ordinary scalar datatype */
1449 var = palloc0(sizeof(PLpgSQL_var));
1450 var->dtype = PLPGSQL_DTYPE_VAR;
1451 var->refname = pstrdup(refname);
1452 var->lineno = lineno;
1453 var->datatype = dtype;
1454 /* other fields might be filled by caller */
1456 /* preset to NULL */
1459 var->freeval = false;
1461 plpgsql_adddatum((PLpgSQL_datum *) var);
1463 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1466 result = (PLpgSQL_variable *) var;
1469 case PLPGSQL_TTYPE_ROW:
1471 /* Composite type -- build a row variable */
1474 row = build_row_from_class(dtype->typrelid);
1476 row->dtype = PLPGSQL_DTYPE_ROW;
1477 row->refname = pstrdup(refname);
1478 row->lineno = lineno;
1480 plpgsql_adddatum((PLpgSQL_datum *) row);
1482 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
1485 result = (PLpgSQL_variable *) row;
1488 case PLPGSQL_TTYPE_REC:
1491 * "record" type -- build a variable-contents record variable
1495 rec = palloc0(sizeof(PLpgSQL_rec));
1496 rec->dtype = PLPGSQL_DTYPE_REC;
1497 rec->refname = pstrdup(refname);
1498 rec->lineno = lineno;
1500 plpgsql_adddatum((PLpgSQL_datum *) rec);
1502 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
1505 result = (PLpgSQL_variable *) rec;
1508 case PLPGSQL_TTYPE_PSEUDO:
1510 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1511 errmsg("variable \"%s\" has pseudo-type %s",
1512 refname, format_type_be(dtype->typoid))));
1513 result = NULL; /* keep compiler quiet */
1516 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1517 result = NULL; /* keep compiler quiet */
1525 * Build a row-variable data structure given the pg_class OID.
1527 static PLpgSQL_row *
1528 build_row_from_class(Oid classOid)
1532 Form_pg_class classStruct;
1533 const char *relname;
1537 * Open the relation to get info.
1539 rel = relation_open(classOid, AccessShareLock);
1540 classStruct = RelationGetForm(rel);
1541 relname = RelationGetRelationName(rel);
1543 /* accept relation, sequence, view, or composite type entries */
1544 if (classStruct->relkind != RELKIND_RELATION &&
1545 classStruct->relkind != RELKIND_SEQUENCE &&
1546 classStruct->relkind != RELKIND_VIEW &&
1547 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1549 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1550 errmsg("relation \"%s\" is not a table", relname)));
1553 * Create a row datum entry and all the required variables that it will
1556 row = palloc0(sizeof(PLpgSQL_row));
1557 row->dtype = PLPGSQL_DTYPE_ROW;
1558 row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
1559 row->nfields = classStruct->relnatts;
1560 row->fieldnames = palloc(sizeof(char *) * row->nfields);
1561 row->varnos = palloc(sizeof(int) * row->nfields);
1563 for (i = 0; i < row->nfields; i++)
1565 Form_pg_attribute attrStruct;
1568 * Get the attribute and check for dropped column
1570 attrStruct = row->rowtupdesc->attrs[i];
1572 if (!attrStruct->attisdropped)
1575 char refname[(NAMEDATALEN * 2) + 100];
1576 PLpgSQL_variable *var;
1578 attname = NameStr(attrStruct->attname);
1579 snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
1582 * Create the internal variable for the field
1584 * We know if the table definitions contain a default value or if
1585 * the field is declared in the table as NOT NULL. But it's
1586 * possible to create a table field as NOT NULL without a default
1587 * value and that would lead to problems later when initializing
1588 * the variables due to entering a block at execution time. Thus
1589 * we ignore this information for now.
1591 var = plpgsql_build_variable(refname, 0,
1592 plpgsql_build_datatype(attrStruct->atttypid,
1593 attrStruct->atttypmod),
1596 /* Add the variable to the row */
1597 row->fieldnames[i] = attname;
1598 row->varnos[i] = var->dno;
1602 /* Leave a hole in the row structure for the dropped col */
1603 row->fieldnames[i] = NULL;
1604 row->varnos[i] = -1;
1608 relation_close(rel, AccessShareLock);
1614 * Build a row-variable data structure given the component variables.
1616 static PLpgSQL_row *
1617 build_row_from_vars(PLpgSQL_variable **vars, int numvars)
1622 row = palloc0(sizeof(PLpgSQL_row));
1623 row->dtype = PLPGSQL_DTYPE_ROW;
1624 row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
1625 row->nfields = numvars;
1626 row->fieldnames = palloc(numvars * sizeof(char *));
1627 row->varnos = palloc(numvars * sizeof(int));
1629 for (i = 0; i < numvars; i++)
1631 PLpgSQL_variable *var = vars[i];
1632 Oid typoid = RECORDOID;
1637 case PLPGSQL_DTYPE_VAR:
1638 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1639 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1642 case PLPGSQL_DTYPE_REC:
1645 case PLPGSQL_DTYPE_ROW:
1646 if (((PLpgSQL_row *) var)->rowtupdesc)
1648 typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
1649 typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
1654 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1657 row->fieldnames[i] = var->refname;
1658 row->varnos[i] = var->dno;
1660 TupleDescInitEntry(row->rowtupdesc, i + 1,
1671 * plpgsql_parse_datatype Scanner found something that should
1672 * be a datatype name.
1676 plpgsql_parse_datatype(const char *string)
1681 /* Let the main parser try to parse it under standard SQL rules */
1682 parseTypeString(string, &type_id, &typmod);
1684 /* Okay, build a PLpgSQL_type data structure for it */
1685 return plpgsql_build_datatype(type_id, typmod);
1689 * plpgsql_build_datatype
1690 * Build PLpgSQL_type struct given type OID and typmod.
1693 plpgsql_build_datatype(Oid typeOid, int32 typmod)
1698 typeTup = SearchSysCache(TYPEOID,
1699 ObjectIdGetDatum(typeOid),
1701 if (!HeapTupleIsValid(typeTup))
1702 elog(ERROR, "cache lookup failed for type %u", typeOid);
1704 typ = build_datatype(typeTup, typmod);
1706 ReleaseSysCache(typeTup);
1712 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1714 static PLpgSQL_type *
1715 build_datatype(HeapTuple typeTup, int32 typmod)
1717 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1720 if (!typeStruct->typisdefined)
1722 (errcode(ERRCODE_UNDEFINED_OBJECT),
1723 errmsg("type \"%s\" is only a shell",
1724 NameStr(typeStruct->typname))));
1726 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
1728 typ->typname = pstrdup(NameStr(typeStruct->typname));
1729 typ->typoid = HeapTupleGetOid(typeTup);
1730 switch (typeStruct->typtype)
1732 case 'b': /* base type */
1733 case 'd': /* domain */
1734 typ->ttype = PLPGSQL_TTYPE_SCALAR;
1736 case 'c': /* composite, ie, rowtype */
1737 Assert(OidIsValid(typeStruct->typrelid));
1738 typ->ttype = PLPGSQL_TTYPE_ROW;
1740 case 'p': /* pseudo */
1741 if (typ->typoid == RECORDOID)
1742 typ->ttype = PLPGSQL_TTYPE_REC;
1744 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
1747 elog(ERROR, "unrecognized typtype: %d",
1748 (int) typeStruct->typtype);
1751 typ->typlen = typeStruct->typlen;
1752 typ->typbyval = typeStruct->typbyval;
1753 typ->typrelid = typeStruct->typrelid;
1754 typ->typioparam = getTypeIOParam(typeTup);
1755 fmgr_info(typeStruct->typinput, &(typ->typinput));
1756 typ->atttypmod = typmod;
1762 * plpgsql_parse_err_condition
1763 * Generate PLpgSQL_condition entry(s) for an exception condition name
1765 * This has to be able to return a list because there are some duplicate
1766 * names in the table of error code names.
1769 plpgsql_parse_err_condition(char *condname)
1772 PLpgSQL_condition *new;
1773 PLpgSQL_condition *prev;
1776 * XXX Eventually we will want to look for user-defined exception names
1781 * OTHERS is represented as code 0 (which would map to '00000', but we
1782 * have no need to represent that as an exception condition).
1784 if (strcmp(condname, "others") == 0)
1786 new = palloc(sizeof(PLpgSQL_condition));
1787 new->sqlerrstate = 0;
1788 new->condname = condname;
1794 for (i = 0; exception_label_map[i].label != NULL; i++)
1796 if (strcmp(condname, exception_label_map[i].label) == 0)
1798 new = palloc(sizeof(PLpgSQL_condition));
1799 new->sqlerrstate = exception_label_map[i].sqlerrstate;
1800 new->condname = condname;
1808 (errcode(ERRCODE_UNDEFINED_OBJECT),
1809 errmsg("unrecognized exception condition \"%s\"",
1816 * plpgsql_adddatum Add a variable, record or row
1817 * to the compiler's datum list.
1821 plpgsql_adddatum(PLpgSQL_datum *new)
1823 if (plpgsql_nDatums == datums_alloc)
1826 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1829 new->dno = plpgsql_nDatums;
1830 plpgsql_Datums[plpgsql_nDatums++] = new;
1835 * plpgsql_add_initdatums Put all datum entries created
1836 * since the last call into the
1837 * finishing code block so the
1838 * block knows which variables to
1839 * reinitialize when entered.
1843 plpgsql_add_initdatums(int **varnos)
1848 for (i = datums_last; i < plpgsql_nDatums; i++)
1850 switch (plpgsql_Datums[i]->dtype)
1852 case PLPGSQL_DTYPE_VAR:
1865 *varnos = (int *) palloc(sizeof(int) * n);
1868 for (i = datums_last; i < plpgsql_nDatums; i++)
1870 switch (plpgsql_Datums[i]->dtype)
1872 case PLPGSQL_DTYPE_VAR:
1873 (*varnos)[n++] = plpgsql_Datums[i]->dno;
1884 datums_last = plpgsql_nDatums;
1890 * Compute the hashkey for a given function invocation
1892 * The hashkey is returned into the caller-provided storage at *hashkey.
1895 compute_function_hashkey(FunctionCallInfo fcinfo,
1896 Form_pg_proc procStruct,
1897 PLpgSQL_func_hashkey *hashkey,
1900 /* Make sure any unused bytes of the struct are zero */
1901 MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
1903 /* get function OID */
1904 hashkey->funcOid = fcinfo->flinfo->fn_oid;
1907 * if trigger, get relation OID. In validation mode we do not know what
1908 * relation is intended to be used, so we leave trigrelOid zero; the hash
1909 * entry built in this case will never really be used.
1911 if (CALLED_AS_TRIGGER(fcinfo) && !forValidator)
1913 TriggerData *trigdata = (TriggerData *) fcinfo->context;
1915 hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
1918 if (procStruct->pronargs > 0)
1920 /* get the argument types */
1921 memcpy(hashkey->argtypes, procStruct->proargtypes.values,
1922 procStruct->pronargs * sizeof(Oid));
1924 /* resolve any polymorphic argument types */
1925 plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
1928 fcinfo->flinfo->fn_expr,
1930 NameStr(procStruct->proname));
1935 * This is the same as the standard resolve_polymorphic_argtypes() function,
1936 * but with a special case for validation: assume that polymorphic arguments
1937 * are integer or integer-array. Also, we go ahead and report the error
1938 * if we can't resolve the types.
1941 plpgsql_resolve_polymorphic_argtypes(int numargs,
1942 Oid *argtypes, char *argmodes,
1943 Node *call_expr, bool forValidator,
1944 const char *proname)
1950 /* normal case, pass to standard routine */
1951 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
1954 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1955 errmsg("could not determine actual argument "
1956 "type for polymorphic function \"%s\"",
1961 /* special validation case */
1962 for (i = 0; i < numargs; i++)
1964 switch (argtypes[i])
1967 argtypes[i] = INT4OID;
1970 argtypes[i] = INT4ARRAYOID;
1980 delete_function(PLpgSQL_function *func)
1982 /* remove function from hash table */
1983 plpgsql_HashTableDelete(func);
1985 /* release the function's storage */
1986 MemoryContextDelete(func->fn_cxt);
1989 * Caller should be sure not to use passed-in pointer, as it now points to
1994 /* exported so we can call it from plpgsql_init() */
1996 plpgsql_HashTableInit(void)
2000 /* don't allow double-initialization */
2001 Assert(plpgsql_HashTable == NULL);
2003 memset(&ctl, 0, sizeof(ctl));
2004 ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2005 ctl.entrysize = sizeof(plpgsql_HashEnt);
2006 ctl.hash = tag_hash;
2007 plpgsql_HashTable = hash_create("PLpgSQL function cache",
2010 HASH_ELEM | HASH_FUNCTION);
2013 static PLpgSQL_function *
2014 plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
2016 plpgsql_HashEnt *hentry;
2018 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2023 return hentry->function;
2029 plpgsql_HashTableInsert(PLpgSQL_function *function,
2030 PLpgSQL_func_hashkey *func_key)
2032 plpgsql_HashEnt *hentry;
2035 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2040 elog(WARNING, "trying to insert a function that already exists");
2042 hentry->function = function;
2043 /* prepare back link from function to hashtable key */
2044 function->fn_hashkey = &hentry->key;
2048 plpgsql_HashTableDelete(PLpgSQL_function *function)
2050 plpgsql_HashEnt *hentry;
2052 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2053 (void *) function->fn_hashkey,
2057 elog(WARNING, "trying to delete function that does not exist");