1 /**********************************************************************
2 * pl_comp.c - Compiler part of the PL/pgSQL
6 * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.89 2005/05/06 17:24:55 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 /* Add the record for referencing NEW */
551 rec = palloc0(sizeof(PLpgSQL_rec));
552 rec->dtype = PLPGSQL_DTYPE_REC;
553 rec->refname = pstrdup("new");
556 rec->freetup = false;
557 plpgsql_adddatum((PLpgSQL_datum *) rec);
558 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
559 function->new_varno = rec->recno;
561 /* Add the record for referencing OLD */
562 rec = palloc0(sizeof(PLpgSQL_rec));
563 rec->dtype = PLPGSQL_DTYPE_REC;
564 rec->refname = pstrdup("old");
567 rec->freetup = false;
568 plpgsql_adddatum((PLpgSQL_datum *) rec);
569 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
570 function->old_varno = rec->recno;
572 /* Add the variable tg_name */
573 var = plpgsql_build_variable("tg_name", 0,
574 plpgsql_build_datatype(NAMEOID, -1),
576 function->tg_name_varno = var->dno;
578 /* Add the variable tg_when */
579 var = plpgsql_build_variable("tg_when", 0,
580 plpgsql_build_datatype(TEXTOID, -1),
582 function->tg_when_varno = var->dno;
584 /* Add the variable tg_level */
585 var = plpgsql_build_variable("tg_level", 0,
586 plpgsql_build_datatype(TEXTOID, -1),
588 function->tg_level_varno = var->dno;
590 /* Add the variable tg_op */
591 var = plpgsql_build_variable("tg_op", 0,
592 plpgsql_build_datatype(TEXTOID, -1),
594 function->tg_op_varno = var->dno;
596 /* Add the variable tg_relid */
597 var = plpgsql_build_variable("tg_relid", 0,
598 plpgsql_build_datatype(OIDOID, -1),
600 function->tg_relid_varno = var->dno;
602 /* Add the variable tg_relname */
603 var = plpgsql_build_variable("tg_relname", 0,
604 plpgsql_build_datatype(NAMEOID, -1),
606 function->tg_relname_varno = var->dno;
608 /* Add the variable tg_nargs */
609 var = plpgsql_build_variable("tg_nargs", 0,
610 plpgsql_build_datatype(INT4OID, -1),
612 function->tg_nargs_varno = var->dno;
617 elog(ERROR, "unrecognized function typecode: %u", functype);
621 /* Remember if function is STABLE/IMMUTABLE */
622 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
625 * Create the magic FOUND variable.
627 var = plpgsql_build_variable("found", 0,
628 plpgsql_build_datatype(BOOLOID, -1),
630 function->found_varno = var->dno;
633 * Forget about the above created variables
635 plpgsql_add_initdatums(NULL);
638 * Now parse the function's text
640 parse_rc = plpgsql_yyparse();
642 elog(ERROR, "plpgsql parser returned %d", parse_rc);
643 function->action = plpgsql_yylval.program;
645 plpgsql_scanner_finish();
649 * If it has OUT parameters or returns VOID or returns a set, we allow
650 * control to fall off the end without an explicit RETURN statement.
651 * The easiest way to implement this is to add a RETURN statement to the
652 * end of the statement list during parsing. However, if the outer block
653 * has an EXCEPTION clause, we need to make a new outer block, since the
654 * added RETURN shouldn't act like it is inside the EXCEPTION clause.
656 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
659 if (function->action->exceptions != NIL)
661 PLpgSQL_stmt_block *new;
663 new = palloc0(sizeof(PLpgSQL_stmt_block));
664 new->cmd_type = PLPGSQL_STMT_BLOCK;
665 new->body = list_make1(function->action);
667 function->action = new;
669 if (function->action->body == NIL ||
670 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
672 PLpgSQL_stmt_return *new;
674 new = palloc0(sizeof(PLpgSQL_stmt_return));
675 new->cmd_type = PLPGSQL_STMT_RETURN;
677 new->retvarno = function->out_param_varno;
679 function->action->body = lappend(function->action->body, new);
684 * Complete the function's info
686 function->fn_nargs = procStruct->pronargs;
687 for (i = 0; i < function->fn_nargs; i++)
688 function->fn_argvarnos[i] = in_arg_varnos[i];
689 function->ndatums = plpgsql_nDatums;
690 function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
691 for (i = 0; i < plpgsql_nDatums; i++)
692 function->datums[i] = plpgsql_Datums[i];
694 /* Debug dump for completed functions */
695 if (plpgsql_DumpExecTree)
696 plpgsql_dumptree(function);
699 * add it to the hash table
701 plpgsql_HashTableInsert(function, hashkey);
704 * Pop the error context stack
706 error_context_stack = plerrcontext.previous;
707 plpgsql_error_funcname = NULL;
708 plpgsql_error_lineno = 0;
710 plpgsql_check_syntax = false;
712 MemoryContextSwitchTo(compile_tmp_cxt);
713 compile_tmp_cxt = NULL;
719 * error context callback to let us supply a call-stack traceback. If
720 * we are validating, the function source is passed as an
721 * argument. This function is public only for the sake of an assertion
725 plpgsql_compile_error_callback(void *arg)
730 * Try to convert syntax error position to reference text of
731 * original CREATE FUNCTION command.
733 if (function_parse_error_transpose((const char *) arg))
737 * Done if a syntax error position was reported; otherwise we have
738 * to fall back to a "near line N" report.
742 if (plpgsql_error_funcname)
743 errcontext("compile of PL/pgSQL function \"%s\" near line %d",
744 plpgsql_error_funcname, plpgsql_error_lineno);
749 * Fetch info about the argument types, names, and IN/OUT modes from the
750 * pg_proc tuple. Return value is the number of arguments.
751 * Other results are palloc'd.
754 fetchArgInfo(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames,
757 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
758 Datum proallargtypes;
768 /* First discover the total number of parameters and get their types */
769 proallargtypes = SysCacheGetAttr(PROCOID, procTup,
770 Anum_pg_proc_proallargtypes,
775 * We expect the arrays to be 1-D arrays of the right types; verify
776 * that. For the OID and char arrays, we don't need to use
777 * deconstruct_array() since the array data is just going to look like
778 * a C array of values.
780 arr = DatumGetArrayTypeP(proallargtypes); /* ensure not toasted */
781 numargs = ARR_DIMS(arr)[0];
782 if (ARR_NDIM(arr) != 1 ||
784 ARR_ELEMTYPE(arr) != OIDOID)
785 elog(ERROR, "proallargtypes is not a 1-D Oid array");
786 Assert(numargs >= procStruct->pronargs);
787 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
788 memcpy(*p_argtypes, ARR_DATA_PTR(arr),
789 numargs * sizeof(Oid));
793 /* If no proallargtypes, use proargtypes */
794 numargs = procStruct->proargtypes.dim1;
795 Assert(numargs == procStruct->pronargs);
796 *p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
797 memcpy(*p_argtypes, procStruct->proargtypes.values,
798 numargs * sizeof(Oid));
801 /* Get argument names, if available */
802 proargnames = SysCacheGetAttr(PROCOID, procTup,
803 Anum_pg_proc_proargnames,
809 deconstruct_array(DatumGetArrayTypeP(proargnames),
810 TEXTOID, -1, false, 'i',
812 if (nelems != numargs) /* should not happen */
813 elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
814 *p_argnames = (char **) palloc(sizeof(char *) * numargs);
815 for (i = 0; i < numargs; i++)
816 (*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
820 /* Get argument modes, if available */
821 proargmodes = SysCacheGetAttr(PROCOID, procTup,
822 Anum_pg_proc_proargmodes,
828 arr = DatumGetArrayTypeP(proargmodes); /* ensure not toasted */
829 if (ARR_NDIM(arr) != 1 ||
830 ARR_DIMS(arr)[0] != numargs ||
831 ARR_ELEMTYPE(arr) != CHAROID)
832 elog(ERROR, "proargmodes is not a 1-D char array");
833 *p_argmodes = (char *) palloc(numargs * sizeof(char));
834 memcpy(*p_argmodes, ARR_DATA_PTR(arr),
835 numargs * sizeof(char));
843 * plpgsql_parse_word The scanner calls this to postparse
844 * any single word not found by a
849 plpgsql_parse_word(char *word)
854 /* Do case conversion and word separation */
855 plpgsql_convert_ident(word, cp, 1);
858 * Recognize tg_argv when compiling triggers
860 if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
862 if (strcmp(cp[0], "tg_argv") == 0)
864 bool save_spacescanned = plpgsql_SpaceScanned;
865 PLpgSQL_trigarg *trigarg;
867 trigarg = palloc0(sizeof(PLpgSQL_trigarg));
868 trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
870 if (plpgsql_yylex() != '[')
871 plpgsql_yyerror("expected \"[\"");
873 trigarg->argnum = plpgsql_read_expression(']', "]");
875 plpgsql_adddatum((PLpgSQL_datum *) trigarg);
876 plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
878 plpgsql_SpaceScanned = save_spacescanned;
885 * Do a lookup on the compilers namestack
887 nse = plpgsql_ns_lookup(cp[0], NULL);
891 switch (nse->itemtype)
893 case PLPGSQL_NSTYPE_LABEL:
896 case PLPGSQL_NSTYPE_VAR:
897 plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
900 case PLPGSQL_NSTYPE_REC:
901 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
904 case PLPGSQL_NSTYPE_ROW:
905 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
914 * Nothing found - up to now it's a word without any special meaning
923 * plpgsql_parse_dblword Same lookup for two words
924 * separated by a dot.
928 plpgsql_parse_dblword(char *word)
933 /* Do case conversion and word separation */
934 plpgsql_convert_ident(word, cp, 2);
937 * Lookup the first word
939 ns = plpgsql_ns_lookup(cp[0], NULL);
947 switch (ns->itemtype)
949 case PLPGSQL_NSTYPE_LABEL:
952 * First word is a label, so second word could be a variable,
953 * record or row in that bodies namestack. Anything else could
954 * only be something in a query given to the SPI manager and
955 * T_ERROR will get eaten up by the collector routines.
957 ns = plpgsql_ns_lookup(cp[1], cp[0]);
962 switch (ns->itemtype)
964 case PLPGSQL_NSTYPE_VAR:
965 plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
968 case PLPGSQL_NSTYPE_REC:
969 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
972 case PLPGSQL_NSTYPE_ROW:
973 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
981 case PLPGSQL_NSTYPE_REC:
984 * First word is a record name, so second word must be a
985 * field in this record.
987 PLpgSQL_recfield *new;
989 new = palloc(sizeof(PLpgSQL_recfield));
990 new->dtype = PLPGSQL_DTYPE_RECFIELD;
991 new->fieldname = pstrdup(cp[1]);
992 new->recparentno = ns->itemno;
994 plpgsql_adddatum((PLpgSQL_datum *) new);
996 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1003 case PLPGSQL_NSTYPE_ROW:
1006 * First word is a row name, so second word must be a
1007 * field in this row.
1012 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1013 for (i = 0; i < row->nfields; i++)
1015 if (row->fieldnames[i] &&
1016 strcmp(row->fieldnames[i], cp[1]) == 0)
1018 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1025 (errcode(ERRCODE_UNDEFINED_COLUMN),
1026 errmsg("row \"%s\" has no field \"%s\"",
1041 * plpgsql_parse_tripword Same lookup for three words
1042 * separated by dots.
1046 plpgsql_parse_tripword(char *word)
1051 /* Do case conversion and word separation */
1052 plpgsql_convert_ident(word, cp, 3);
1055 * Lookup the first word - it must be a label
1057 ns = plpgsql_ns_lookup(cp[0], NULL);
1065 if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
1074 * First word is a label, so second word could be a record or row
1076 ns = plpgsql_ns_lookup(cp[1], cp[0]);
1085 switch (ns->itemtype)
1087 case PLPGSQL_NSTYPE_REC:
1090 * This word is a record name, so third word must be a
1091 * field in this record.
1093 PLpgSQL_recfield *new;
1095 new = palloc(sizeof(PLpgSQL_recfield));
1096 new->dtype = PLPGSQL_DTYPE_RECFIELD;
1097 new->fieldname = pstrdup(cp[2]);
1098 new->recparentno = ns->itemno;
1100 plpgsql_adddatum((PLpgSQL_datum *) new);
1102 plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
1111 case PLPGSQL_NSTYPE_ROW:
1114 * This word is a row name, so third word must be a field
1120 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1121 for (i = 0; i < row->nfields; i++)
1123 if (row->fieldnames[i] &&
1124 strcmp(row->fieldnames[i], cp[2]) == 0)
1126 plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
1136 (errcode(ERRCODE_UNDEFINED_COLUMN),
1137 errmsg("row \"%s.%s\" has no field \"%s\"",
1138 cp[0], cp[1], cp[2])));
1153 * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
1154 * a variable name or a basetype.
1158 plpgsql_parse_wordtype(char *word)
1160 PLpgSQL_nsitem *nse;
1166 /* Do case conversion and word separation */
1167 /* We convert %type to .type momentarily to keep converter happy */
1168 i = strlen(word) - 5;
1169 Assert(word[i] == '%');
1171 plpgsql_convert_ident(word, cp, 2);
1176 * Do a lookup on the compiler's namestack. But ensure it moves up to
1179 old_nsstate = plpgsql_ns_setlocal(false);
1180 nse = plpgsql_ns_lookup(cp[0], NULL);
1181 plpgsql_ns_setlocal(old_nsstate);
1186 switch (nse->itemtype)
1188 case PLPGSQL_NSTYPE_VAR:
1189 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1192 /* XXX perhaps allow REC here? */
1200 * Word wasn't found on the namestack. Try to find a data type with
1201 * that name, but ignore pg_type entries that are in fact class types.
1203 typeOid = LookupTypeName(makeTypeName(cp[0]));
1204 if (OidIsValid(typeOid))
1208 typeTup = SearchSysCache(TYPEOID,
1209 ObjectIdGetDatum(typeOid),
1211 if (HeapTupleIsValid(typeTup))
1213 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1215 if (!typeStruct->typisdefined ||
1216 typeStruct->typrelid != InvalidOid)
1218 ReleaseSysCache(typeTup);
1223 plpgsql_yylval.dtype = build_datatype(typeTup, -1);
1225 ReleaseSysCache(typeTup);
1232 * Nothing found - up to now it's a word without any special meaning
1241 * plpgsql_parse_dblwordtype Same lookup for word.word%TYPE
1245 plpgsql_parse_dblwordtype(char *word)
1247 PLpgSQL_nsitem *nse;
1250 HeapTuple classtup = NULL;
1251 HeapTuple attrtup = NULL;
1252 HeapTuple typetup = NULL;
1253 Form_pg_class classStruct;
1254 Form_pg_attribute attrStruct;
1257 MemoryContext oldCxt;
1258 int result = T_ERROR;
1260 /* Avoid memory leaks in the long-term function context */
1261 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1263 /* Do case conversion and word separation */
1264 /* We convert %type to .type momentarily to keep converter happy */
1265 i = strlen(word) - 5;
1266 Assert(word[i] == '%');
1268 plpgsql_convert_ident(word, cp, 3);
1272 * Lookup the first word
1274 nse = plpgsql_ns_lookup(cp[0], NULL);
1277 * If this is a label lookup the second word in that label's
1282 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
1284 old_nsstate = plpgsql_ns_setlocal(false);
1285 nse = plpgsql_ns_lookup(cp[1], cp[0]);
1286 plpgsql_ns_setlocal(old_nsstate);
1288 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1290 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1295 /* Return T_ERROR if not found, otherwise T_DTYPE */
1300 * First word could also be a table name
1302 classOid = RelnameGetRelid(cp[0]);
1303 if (!OidIsValid(classOid))
1306 classtup = SearchSysCache(RELOID,
1307 ObjectIdGetDatum(classOid),
1309 if (!HeapTupleIsValid(classtup))
1313 * It must be a relation, sequence, view, or type
1315 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1316 if (classStruct->relkind != RELKIND_RELATION &&
1317 classStruct->relkind != RELKIND_SEQUENCE &&
1318 classStruct->relkind != RELKIND_VIEW &&
1319 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1323 * Fetch the named table field and it's type
1325 attrtup = SearchSysCacheAttName(classOid, cp[1]);
1326 if (!HeapTupleIsValid(attrtup))
1329 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1330 typetup = SearchSysCache(TYPEOID,
1331 ObjectIdGetDatum(attrStruct->atttypid),
1333 if (!HeapTupleIsValid(typetup))
1334 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1337 * Found that - build a compiler type struct in the caller's cxt
1340 MemoryContextSwitchTo(oldCxt);
1341 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1342 MemoryContextSwitchTo(compile_tmp_cxt);
1346 if (HeapTupleIsValid(classtup))
1347 ReleaseSysCache(classtup);
1348 if (HeapTupleIsValid(attrtup))
1349 ReleaseSysCache(attrtup);
1350 if (HeapTupleIsValid(typetup))
1351 ReleaseSysCache(typetup);
1353 MemoryContextSwitchTo(oldCxt);
1358 * plpgsql_parse_tripwordtype Same lookup for word.word.word%TYPE
1361 #define TYPE_JUNK_LEN 5
1364 plpgsql_parse_tripwordtype(char *word)
1367 HeapTuple classtup = NULL;
1368 Form_pg_class classStruct;
1369 HeapTuple attrtup = NULL;
1370 Form_pg_attribute attrStruct;
1371 HeapTuple typetup = NULL;
1374 int qualified_att_len;
1378 MemoryContext oldCxt;
1379 int result = T_ERROR;
1381 /* Avoid memory leaks in the long-term function context */
1382 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1384 /* Do case conversion and word separation */
1385 qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
1386 Assert(word[qualified_att_len] == '%');
1388 for (i = 0; i < qualified_att_len; i++)
1390 if (word[i] == '.' && ++numdots == 2)
1392 cp[0] = (char *) palloc((i + 1) * sizeof(char));
1393 memset(cp[0], 0, (i + 1) * sizeof(char));
1394 memcpy(cp[0], word, i * sizeof(char));
1397 * qualified_att_len - one based position + 1 (null
1400 cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));
1401 memset(cp[1], 0, (qualified_att_len - i) * sizeof(char));
1402 memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));
1408 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0], "plpgsql_parse_tripwordtype"));
1409 classOid = RangeVarGetRelid(relvar, true);
1410 if (!OidIsValid(classOid))
1413 classtup = SearchSysCache(RELOID,
1414 ObjectIdGetDatum(classOid),
1416 if (!HeapTupleIsValid(classtup))
1420 * It must be a relation, sequence, view, or type
1422 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1423 if (classStruct->relkind != RELKIND_RELATION &&
1424 classStruct->relkind != RELKIND_SEQUENCE &&
1425 classStruct->relkind != RELKIND_VIEW &&
1426 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1430 * Fetch the named table field and it's type
1432 plpgsql_convert_ident(cp[1], colname, 1);
1433 attrtup = SearchSysCacheAttName(classOid, colname[0]);
1434 if (!HeapTupleIsValid(attrtup))
1437 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1438 typetup = SearchSysCache(TYPEOID,
1439 ObjectIdGetDatum(attrStruct->atttypid),
1441 if (!HeapTupleIsValid(typetup))
1442 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1445 * Found that - build a compiler type struct in the caller's cxt
1448 MemoryContextSwitchTo(oldCxt);
1449 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1450 MemoryContextSwitchTo(compile_tmp_cxt);
1454 if (HeapTupleIsValid(classtup))
1455 ReleaseSysCache(classtup);
1456 if (HeapTupleIsValid(classtup))
1457 ReleaseSysCache(attrtup);
1458 if (HeapTupleIsValid(typetup))
1459 ReleaseSysCache(typetup);
1461 MemoryContextSwitchTo(oldCxt);
1466 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1467 * So word must be a table name.
1471 plpgsql_parse_wordrowtype(char *word)
1477 /* Do case conversion and word separation */
1478 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1479 i = strlen(word) - 8;
1480 Assert(word[i] == '%');
1482 plpgsql_convert_ident(word, cp, 2);
1485 /* Lookup the relation */
1486 classOid = RelnameGetRelid(cp[0]);
1487 if (!OidIsValid(classOid))
1489 (errcode(ERRCODE_UNDEFINED_TABLE),
1490 errmsg("relation \"%s\" does not exist", cp[0])));
1493 * Build and return the row type struct
1495 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1505 * plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
1506 * So word must be a namespace qualified table name.
1509 #define ROWTYPE_JUNK_LEN 8
1512 plpgsql_parse_dblwordrowtype(char *word)
1518 MemoryContext oldCxt;
1520 /* Avoid memory leaks in long-term function context */
1521 oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);
1523 /* Do case conversion and word separation */
1524 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1525 i = strlen(word) - ROWTYPE_JUNK_LEN;
1526 Assert(word[i] == '%');
1531 /* Lookup the relation */
1532 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
1533 classOid = RangeVarGetRelid(relvar, true);
1534 if (!OidIsValid(classOid))
1536 (errcode(ERRCODE_UNDEFINED_TABLE),
1537 errmsg("relation \"%s\" does not exist", cp)));
1539 /* Build and return the row type struct */
1540 plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
1543 MemoryContextSwitchTo(oldCxt);
1548 * plpgsql_build_variable - build a datum-array entry of a given
1551 * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or
1552 * PLpgSQL_rec depending on the given datatype, and is allocated via
1553 * palloc. The struct is automatically added to the current datum
1554 * array, and optionally to the current namespace.
1557 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
1560 PLpgSQL_variable *result;
1562 switch (dtype->ttype)
1564 case PLPGSQL_TTYPE_SCALAR:
1566 /* Ordinary scalar datatype */
1569 var = palloc0(sizeof(PLpgSQL_var));
1570 var->dtype = PLPGSQL_DTYPE_VAR;
1571 var->refname = pstrdup(refname);
1572 var->lineno = lineno;
1573 var->datatype = dtype;
1574 /* other fields might be filled by caller */
1576 /* preset to NULL */
1579 var->freeval = false;
1581 plpgsql_adddatum((PLpgSQL_datum *) var);
1583 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1586 result = (PLpgSQL_variable *) var;
1589 case PLPGSQL_TTYPE_ROW:
1591 /* Composite type -- build a row variable */
1594 row = build_row_from_class(dtype->typrelid);
1596 row->dtype = PLPGSQL_DTYPE_ROW;
1597 row->refname = pstrdup(refname);
1598 row->lineno = lineno;
1600 plpgsql_adddatum((PLpgSQL_datum *) row);
1602 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
1605 result = (PLpgSQL_variable *) row;
1608 case PLPGSQL_TTYPE_REC:
1611 * "record" type -- build a variable-contents record
1616 rec = palloc0(sizeof(PLpgSQL_rec));
1617 rec->dtype = PLPGSQL_DTYPE_REC;
1618 rec->refname = pstrdup(refname);
1619 rec->lineno = lineno;
1621 plpgsql_adddatum((PLpgSQL_datum *) rec);
1623 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
1626 result = (PLpgSQL_variable *) rec;
1629 case PLPGSQL_TTYPE_PSEUDO:
1631 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1632 errmsg("variable \"%s\" has pseudo-type %s",
1633 refname, format_type_be(dtype->typoid))));
1634 result = NULL; /* keep compiler quiet */
1637 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1638 result = NULL; /* keep compiler quiet */
1646 * Build a row-variable data structure given the pg_class OID.
1648 static PLpgSQL_row *
1649 build_row_from_class(Oid classOid)
1653 Form_pg_class classStruct;
1654 const char *relname;
1658 * Open the relation to get info.
1660 rel = relation_open(classOid, AccessShareLock);
1661 classStruct = RelationGetForm(rel);
1662 relname = RelationGetRelationName(rel);
1664 /* accept relation, sequence, view, or composite type entries */
1665 if (classStruct->relkind != RELKIND_RELATION &&
1666 classStruct->relkind != RELKIND_SEQUENCE &&
1667 classStruct->relkind != RELKIND_VIEW &&
1668 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1670 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1671 errmsg("relation \"%s\" is not a table", relname)));
1674 * Create a row datum entry and all the required variables that it
1677 row = palloc0(sizeof(PLpgSQL_row));
1678 row->dtype = PLPGSQL_DTYPE_ROW;
1679 row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
1680 row->nfields = classStruct->relnatts;
1681 row->fieldnames = palloc(sizeof(char *) * row->nfields);
1682 row->varnos = palloc(sizeof(int) * row->nfields);
1684 for (i = 0; i < row->nfields; i++)
1686 Form_pg_attribute attrStruct;
1689 * Get the attribute and check for dropped column
1691 attrStruct = row->rowtupdesc->attrs[i];
1693 if (!attrStruct->attisdropped)
1696 char refname[(NAMEDATALEN * 2) + 100];
1697 PLpgSQL_variable *var;
1699 attname = NameStr(attrStruct->attname);
1700 snprintf(refname, sizeof(refname), "%s.%s", relname, attname);
1703 * Create the internal variable for the field
1705 * We know if the table definitions contain a default value or if
1706 * the field is declared in the table as NOT NULL. But it's
1707 * possible to create a table field as NOT NULL without a
1708 * default value and that would lead to problems later when
1709 * initializing the variables due to entering a block at
1710 * execution time. Thus we ignore this information for now.
1712 var = plpgsql_build_variable(refname, 0,
1713 plpgsql_build_datatype(attrStruct->atttypid,
1714 attrStruct->atttypmod),
1717 /* Add the variable to the row */
1718 row->fieldnames[i] = attname;
1719 row->varnos[i] = var->dno;
1723 /* Leave a hole in the row structure for the dropped col */
1724 row->fieldnames[i] = NULL;
1725 row->varnos[i] = -1;
1729 relation_close(rel, AccessShareLock);
1735 * Build a row-variable data structure given the component variables.
1737 static PLpgSQL_row *
1738 build_row_from_vars(PLpgSQL_variable **vars, int numvars)
1743 row = palloc0(sizeof(PLpgSQL_row));
1744 row->dtype = PLPGSQL_DTYPE_ROW;
1745 row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
1746 row->nfields = numvars;
1747 row->fieldnames = palloc(numvars * sizeof(char *));
1748 row->varnos = palloc(numvars * sizeof(int));
1750 for (i = 0; i < numvars; i++)
1752 PLpgSQL_variable *var = vars[i];
1753 Oid typoid = RECORDOID;
1758 case PLPGSQL_DTYPE_VAR:
1759 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
1760 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
1763 case PLPGSQL_DTYPE_REC:
1766 case PLPGSQL_DTYPE_ROW:
1767 if (((PLpgSQL_row *) var)->rowtupdesc)
1769 typoid = ((PLpgSQL_row *) var)->rowtupdesc->tdtypeid;
1770 typmod = ((PLpgSQL_row *) var)->rowtupdesc->tdtypmod;
1775 elog(ERROR, "unrecognized dtype: %d", var->dtype);
1778 row->fieldnames[i] = var->refname;
1779 row->varnos[i] = var->dno;
1781 TupleDescInitEntry(row->rowtupdesc, i+1,
1792 * plpgsql_parse_datatype Scanner found something that should
1793 * be a datatype name.
1797 plpgsql_parse_datatype(const char *string)
1802 /* Let the main parser try to parse it under standard SQL rules */
1803 parseTypeString(string, &type_id, &typmod);
1805 /* Okay, build a PLpgSQL_type data structure for it */
1806 return plpgsql_build_datatype(type_id, typmod);
1810 * plpgsql_build_datatype
1811 * Build PLpgSQL_type struct given type OID and typmod.
1814 plpgsql_build_datatype(Oid typeOid, int32 typmod)
1819 typeTup = SearchSysCache(TYPEOID,
1820 ObjectIdGetDatum(typeOid),
1822 if (!HeapTupleIsValid(typeTup))
1823 elog(ERROR, "cache lookup failed for type %u", typeOid);
1825 typ = build_datatype(typeTup, typmod);
1827 ReleaseSysCache(typeTup);
1833 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1835 static PLpgSQL_type *
1836 build_datatype(HeapTuple typeTup, int32 typmod)
1838 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1841 if (!typeStruct->typisdefined)
1843 (errcode(ERRCODE_UNDEFINED_OBJECT),
1844 errmsg("type \"%s\" is only a shell",
1845 NameStr(typeStruct->typname))));
1847 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
1849 typ->typname = pstrdup(NameStr(typeStruct->typname));
1850 typ->typoid = HeapTupleGetOid(typeTup);
1851 switch (typeStruct->typtype)
1853 case 'b': /* base type */
1854 case 'd': /* domain */
1855 typ->ttype = PLPGSQL_TTYPE_SCALAR;
1857 case 'c': /* composite, ie, rowtype */
1858 Assert(OidIsValid(typeStruct->typrelid));
1859 typ->ttype = PLPGSQL_TTYPE_ROW;
1861 case 'p': /* pseudo */
1862 if (typ->typoid == RECORDOID)
1863 typ->ttype = PLPGSQL_TTYPE_REC;
1865 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
1868 elog(ERROR, "unrecognized typtype: %d",
1869 (int) typeStruct->typtype);
1872 typ->typlen = typeStruct->typlen;
1873 typ->typbyval = typeStruct->typbyval;
1874 typ->typrelid = typeStruct->typrelid;
1875 typ->typioparam = getTypeIOParam(typeTup);
1876 fmgr_info(typeStruct->typinput, &(typ->typinput));
1877 typ->atttypmod = typmod;
1883 * plpgsql_parse_err_condition
1884 * Generate PLpgSQL_condition entry(s) for an exception condition name
1886 * This has to be able to return a list because there are some duplicate
1887 * names in the table of error code names.
1890 plpgsql_parse_err_condition(char *condname)
1893 PLpgSQL_condition *new;
1894 PLpgSQL_condition *prev;
1897 * XXX Eventually we will want to look for user-defined exception
1902 * OTHERS is represented as code 0 (which would map to '00000', but we
1903 * have no need to represent that as an exception condition).
1905 if (strcmp(condname, "others") == 0)
1907 new = palloc(sizeof(PLpgSQL_condition));
1908 new->sqlerrstate = 0;
1909 new->condname = condname;
1915 for (i = 0; exception_label_map[i].label != NULL; i++)
1917 if (strcmp(condname, exception_label_map[i].label) == 0)
1919 new = palloc(sizeof(PLpgSQL_condition));
1920 new->sqlerrstate = exception_label_map[i].sqlerrstate;
1921 new->condname = condname;
1929 (errcode(ERRCODE_UNDEFINED_OBJECT),
1930 errmsg("unrecognized exception condition \"%s\"",
1937 * plpgsql_adddatum Add a variable, record or row
1938 * to the compilers datum list.
1942 plpgsql_adddatum(PLpgSQL_datum *new)
1944 if (plpgsql_nDatums == datums_alloc)
1947 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1950 new->dno = plpgsql_nDatums;
1951 plpgsql_Datums[plpgsql_nDatums++] = new;
1956 * plpgsql_add_initdatums Put all datum entries created
1957 * since the last call into the
1958 * finishing code block so the
1959 * block knows which variables to
1960 * reinitialize when entered.
1964 plpgsql_add_initdatums(int **varnos)
1969 for (i = datums_last; i < plpgsql_nDatums; i++)
1971 switch (plpgsql_Datums[i]->dtype)
1973 case PLPGSQL_DTYPE_VAR:
1986 *varnos = (int *) palloc(sizeof(int) * n);
1989 for (i = datums_last; i < plpgsql_nDatums; i++)
1991 switch (plpgsql_Datums[i]->dtype)
1993 case PLPGSQL_DTYPE_VAR:
1994 (*varnos)[n++] = plpgsql_Datums[i]->dno;
2005 datums_last = plpgsql_nDatums;
2011 * Compute the hashkey for a given function invocation
2013 * The hashkey is returned into the caller-provided storage at *hashkey.
2016 compute_function_hashkey(FunctionCallInfo fcinfo,
2017 Form_pg_proc procStruct,
2018 PLpgSQL_func_hashkey *hashkey,
2021 /* Make sure any unused bytes of the struct are zero */
2022 MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2024 /* get function OID */
2025 hashkey->funcOid = fcinfo->flinfo->fn_oid;
2028 * if trigger, get relation OID. In validation mode we do not know
2029 * what relation is intended to be used, so we leave trigrelOid zero;
2030 * the hash entry built in this case will never really be used.
2032 if (CALLED_AS_TRIGGER(fcinfo) && !forValidator)
2034 TriggerData *trigdata = (TriggerData *) fcinfo->context;
2036 hashkey->trigrelOid = RelationGetRelid(trigdata->tg_relation);
2039 if (procStruct->pronargs > 0)
2041 /* get the argument types */
2042 memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2043 procStruct->pronargs * sizeof(Oid));
2045 /* resolve any polymorphic argument types */
2046 plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2049 fcinfo->flinfo->fn_expr,
2051 NameStr(procStruct->proname));
2056 * This is the same as the standard resolve_polymorphic_argtypes() function,
2057 * but with a special case for validation: assume that polymorphic arguments
2058 * are integer or integer-array. Also, we go ahead and report the error
2059 * if we can't resolve the types.
2062 plpgsql_resolve_polymorphic_argtypes(int numargs,
2063 Oid *argtypes, char *argmodes,
2064 Node *call_expr, bool forValidator,
2065 const char *proname)
2071 /* normal case, pass to standard routine */
2072 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2075 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2076 errmsg("could not determine actual argument "
2077 "type for polymorphic function \"%s\"",
2082 /* special validation case */
2083 for (i = 0; i < numargs; i++)
2085 switch (argtypes[i])
2088 argtypes[i] = INT4OID;
2091 argtypes[i] = INT4ARRAYOID;
2101 delete_function(PLpgSQL_function *func)
2103 /* remove function from hash table */
2104 plpgsql_HashTableDelete(func);
2106 /* release the function's storage */
2107 MemoryContextDelete(func->fn_cxt);
2110 * Caller should be sure not to use passed-in pointer, as it now
2111 * points to pfree'd storage
2115 /* exported so we can call it from plpgsql_init() */
2117 plpgsql_HashTableInit(void)
2121 /* don't allow double-initialization */
2122 Assert(plpgsql_HashTable == NULL);
2124 memset(&ctl, 0, sizeof(ctl));
2125 ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2126 ctl.entrysize = sizeof(plpgsql_HashEnt);
2127 ctl.hash = tag_hash;
2128 plpgsql_HashTable = hash_create("PLpgSQL function cache",
2131 HASH_ELEM | HASH_FUNCTION);
2134 static PLpgSQL_function *
2135 plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
2137 plpgsql_HashEnt *hentry;
2139 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2144 return hentry->function;
2150 plpgsql_HashTableInsert(PLpgSQL_function *function,
2151 PLpgSQL_func_hashkey *func_key)
2153 plpgsql_HashEnt *hentry;
2156 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2162 (errcode(ERRCODE_OUT_OF_MEMORY),
2163 errmsg("out of memory")));
2165 elog(WARNING, "trying to insert a function that already exists");
2167 hentry->function = function;
2168 /* prepare back link from function to hashtable key */
2169 function->fn_hashkey = &hentry->key;
2173 plpgsql_HashTableDelete(PLpgSQL_function *function)
2175 plpgsql_HashEnt *hentry;
2177 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2178 (void *) function->fn_hashkey,
2182 elog(WARNING, "trying to delete function that does not exist");