1 /**********************************************************************
2 * pl_comp.c - Compiler part of the PL/pgSQL
6 * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.62 2003/07/27 18:38:26 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 **********************************************************************/
45 #include "access/heapam.h"
46 #include "catalog/catname.h"
47 #include "catalog/namespace.h"
48 #include "catalog/pg_attribute.h"
49 #include "catalog/pg_attrdef.h"
50 #include "catalog/pg_class.h"
51 #include "catalog/pg_proc.h"
52 #include "catalog/pg_type.h"
53 #include "nodes/makefuncs.h"
54 #include "parser/gramparse.h"
55 #include "parser/parse_type.h"
56 #include "tcop/tcopprot.h"
57 #include "utils/builtins.h"
58 #include "utils/syscache.h"
62 * Variables in the parser that shouldn't go into plpgsql.h
65 extern PLPGSQL_YYSTYPE plpgsql_yylval;
68 * Our own local and global variables
71 static int datums_alloc;
73 PLpgSQL_datum **plpgsql_Datums;
74 static int datums_last = 0;
76 int plpgsql_error_lineno;
77 char *plpgsql_error_funcname;
78 int plpgsql_DumpExecTree = 0;
80 PLpgSQL_function *plpgsql_curr_compile;
83 * Hash table for compiled functions
86 static HTAB *plpgsql_HashTable = (HTAB *) NULL;
88 typedef struct plpgsql_hashent
90 PLpgSQL_func_hashkey key;
91 PLpgSQL_function *function;
94 #define FUNCS_PER_USER 128 /* initial table size */
101 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
103 PLpgSQL_func_hashkey *hashkey);
104 static void plpgsql_compile_error_callback(void *arg);
105 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
106 static void compute_function_hashkey(FmgrInfo *flinfo,
107 Form_pg_proc procStruct,
108 PLpgSQL_func_hashkey *hashkey);
109 static void plpgsql_HashTableInit(void);
110 static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
111 static void plpgsql_HashTableInsert(PLpgSQL_function *function,
112 PLpgSQL_func_hashkey *func_key);
113 static void plpgsql_HashTableDelete(PLpgSQL_function *function);
116 * This routine is a crock, and so is everyplace that calls it. The problem
117 * is that the compiled form of a plpgsql function is allocated permanently
118 * (mostly via malloc()) and never released until backend exit. Subsidiary
119 * data structures such as fmgr info records therefore must live forever
120 * as well. A better implementation would store all this stuff in a per-
121 * function memory context that could be reclaimed at need. In the meantime,
122 * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
123 * it might allocate, and whatever the eventual function might allocate using
124 * fn_mcxt, will live forever too.
127 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
129 fmgr_info_cxt(functionId, finfo, TopMemoryContext);
134 * plpgsql_compile Make an execution tree for a PL/pgSQL function.
136 * Note: it's important for this to fall through quickly if the function
137 * has already been compiled.
141 plpgsql_compile(FunctionCallInfo fcinfo)
143 Oid funcOid = fcinfo->flinfo->fn_oid;
145 Form_pg_proc procStruct;
146 PLpgSQL_function *function;
147 PLpgSQL_func_hashkey hashkey;
148 bool hashkey_valid = false;
151 * Lookup the pg_proc tuple by Oid; we'll need it in any case
153 procTup = SearchSysCache(PROCOID,
154 ObjectIdGetDatum(funcOid),
156 if (!HeapTupleIsValid(procTup))
157 elog(ERROR, "cache lookup failed for function %u", funcOid);
158 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
161 * See if there's already a cache entry for the current FmgrInfo.
162 * If not, try to find one in the hash table.
164 function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
168 /* First time through in this backend? If so, init hashtable */
169 if (!plpgsql_HashTable)
170 plpgsql_HashTableInit();
172 /* Compute hashkey using function signature and actual arg types */
173 compute_function_hashkey(fcinfo->flinfo, procStruct, &hashkey);
174 hashkey_valid = true;
176 /* And do the lookup */
177 function = plpgsql_HashTableLookup(&hashkey);
182 /* We have a compiled function, but is it still valid? */
183 if (!(function->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
184 function->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data)))
187 * Nope, drop the hashtable entry. XXX someday, free all the
188 * subsidiary storage as well.
190 plpgsql_HashTableDelete(function);
197 * If the function wasn't found or was out-of-date, we have to compile it
202 * Calculate hashkey if we didn't already; we'll need it to store
203 * the completed function.
206 compute_function_hashkey(fcinfo->flinfo, procStruct, &hashkey);
211 function = do_compile(fcinfo, procTup, &hashkey);
214 ReleaseSysCache(procTup);
217 * Save pointer in FmgrInfo to avoid search on subsequent calls
219 fcinfo->flinfo->fn_extra = (void *) function;
222 * Finally return the compiled function
228 * This is the slow part of plpgsql_compile().
230 static PLpgSQL_function *
231 do_compile(FunctionCallInfo fcinfo,
233 PLpgSQL_func_hashkey *hashkey)
235 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
236 int functype = CALLED_AS_TRIGGER(fcinfo) ? T_TRIGGER : T_FUNCTION;
237 PLpgSQL_function *function;
240 Form_pg_type typeStruct;
245 int arg_varnos[FUNC_MAX_ARGS];
246 ErrorContextCallback plerrcontext;
251 * Setup the scanner input and error info. We assume that this
252 * function cannot be invoked recursively, so there's no need to save
253 * and restore the static variables used here.
255 proc_source = DatumGetCString(DirectFunctionCall1(textout,
256 PointerGetDatum(&procStruct->prosrc)));
257 plpgsql_scanner_init(proc_source, functype);
260 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
261 plpgsql_error_lineno = 0;
264 * Setup error traceback support for ereport()
266 plerrcontext.callback = plpgsql_compile_error_callback;
267 plerrcontext.arg = NULL;
268 plerrcontext.previous = error_context_stack;
269 error_context_stack = &plerrcontext;
272 * Initialize the compiler
275 plpgsql_ns_push(NULL);
276 plpgsql_DumpExecTree = 0;
280 plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
284 * Create the new function node
286 function = malloc(sizeof(PLpgSQL_function));
287 MemSet(function, 0, sizeof(PLpgSQL_function));
288 plpgsql_curr_compile = function;
290 function->fn_name = strdup(NameStr(procStruct->proname));
291 function->fn_oid = fcinfo->flinfo->fn_oid;
292 function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
293 function->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
294 function->fn_functype = functype;
301 * Check for a polymorphic returntype. If found, use the actual
302 * returntype type from the caller's FuncExpr node, if we
305 * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
306 * work; if it doesn't we're in some context that fails to make
307 * the info available.
309 rettypeid = procStruct->prorettype;
310 if (rettypeid == ANYARRAYOID || rettypeid == ANYELEMENTOID)
312 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
313 if (!OidIsValid(rettypeid))
315 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
316 errmsg("could not determine actual return type "
317 "for polymorphic function \"%s\"",
318 plpgsql_error_funcname)));
322 * Normal function has a defined returntype
324 function->fn_rettype = rettypeid;
325 function->fn_retset = procStruct->proretset;
328 * Lookup the functions return type
330 typeTup = SearchSysCache(TYPEOID,
331 ObjectIdGetDatum(rettypeid),
333 if (!HeapTupleIsValid(typeTup))
334 elog(ERROR, "cache lookup failed for type %u", rettypeid);
335 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
337 /* Disallow pseudotype result, except VOID or RECORD */
338 /* (note we already replaced ANYARRAY/ANYELEMENT) */
339 if (typeStruct->typtype == 'p')
341 if (rettypeid == VOIDOID ||
342 rettypeid == RECORDOID)
344 else if (rettypeid == TRIGGEROID)
346 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
347 errmsg("trigger functions may only be called as triggers")));
350 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
351 errmsg("plpgsql functions cannot return type %s",
352 format_type_be(rettypeid))));
355 if (typeStruct->typrelid != InvalidOid ||
356 rettypeid == RECORDOID)
357 function->fn_retistuple = true;
360 function->fn_retbyval = typeStruct->typbyval;
361 function->fn_rettyplen = typeStruct->typlen;
362 function->fn_rettypelem = typeStruct->typelem;
363 perm_fmgr_info(typeStruct->typinput, &(function->fn_retinput));
366 * install $0 reference, but only for polymorphic
369 if (procStruct->prorettype == ANYARRAYOID ||
370 procStruct->prorettype == ANYELEMENTOID)
374 /* name for variable */
375 snprintf(buf, sizeof(buf), "$%d", 0);
378 * Normal return values get a var node
380 var = malloc(sizeof(PLpgSQL_var));
381 memset(var, 0, sizeof(PLpgSQL_var));
383 var->dtype = PLPGSQL_DTYPE_VAR;
384 var->refname = strdup(buf);
386 var->datatype = build_datatype(typeTup, -1);
387 var->isconst = false;
388 var->notnull = false;
389 var->default_val = NULL;
394 var->freeval = false;
396 plpgsql_adddatum((PLpgSQL_datum *) var);
397 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno,
401 ReleaseSysCache(typeTup);
404 * Create the variables for the procedure's parameters
406 for (i = 0; i < procStruct->pronargs; i++)
411 /* name for variable */
412 snprintf(buf, sizeof(buf), "$%d", i + 1);
415 * Since we already did the replacement of polymorphic
416 * argument types by actual argument types while computing
417 * the hashkey, we can just use those results.
419 argtypeid = hashkey->argtypes[i];
422 * Get the parameters type
424 typeTup = SearchSysCache(TYPEOID,
425 ObjectIdGetDatum(argtypeid),
427 if (!HeapTupleIsValid(typeTup))
428 elog(ERROR, "cache lookup failed for type %u", argtypeid);
429 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
431 /* Disallow pseudotype argument */
432 /* (note we already replaced ANYARRAY/ANYELEMENT) */
433 if (typeStruct->typtype == 'p')
435 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
436 errmsg("plpgsql functions cannot take type %s",
437 format_type_be(argtypeid))));
439 if (typeStruct->typrelid != InvalidOid)
442 * For tuple type parameters, we set up a record of
445 row = plpgsql_build_rowtype(typeStruct->typrelid);
447 row->refname = strdup(buf);
449 plpgsql_adddatum((PLpgSQL_datum *) row);
450 plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, row->rowno,
453 arg_varnos[i] = row->rowno;
458 * Normal parameters get a var node
460 var = malloc(sizeof(PLpgSQL_var));
461 memset(var, 0, sizeof(PLpgSQL_var));
463 var->dtype = PLPGSQL_DTYPE_VAR;
464 var->refname = strdup(buf);
466 var->datatype = build_datatype(typeTup, -1);
468 var->notnull = false;
469 var->default_val = NULL;
471 plpgsql_adddatum((PLpgSQL_datum *) var);
472 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno,
475 arg_varnos[i] = var->varno;
477 ReleaseSysCache(typeTup);
484 * Trigger procedures return type is unknown yet
486 function->fn_rettype = InvalidOid;
487 function->fn_retbyval = false;
488 function->fn_retistuple = true;
489 function->fn_retset = false;
492 * Add the record for referencing NEW
494 rec = malloc(sizeof(PLpgSQL_rec));
495 memset(rec, 0, sizeof(PLpgSQL_rec));
496 rec->dtype = PLPGSQL_DTYPE_REC;
497 rec->refname = strdup("new");
500 rec->freetup = false;
501 plpgsql_adddatum((PLpgSQL_datum *) rec);
502 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
503 function->new_varno = rec->recno;
506 * Add the record for referencing OLD
508 rec = malloc(sizeof(PLpgSQL_rec));
509 memset(rec, 0, sizeof(PLpgSQL_rec));
510 rec->dtype = PLPGSQL_DTYPE_REC;
511 rec->refname = strdup("old");
514 rec->freetup = false;
515 plpgsql_adddatum((PLpgSQL_datum *) rec);
516 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
517 function->old_varno = rec->recno;
520 * Add the variable tg_name
522 var = malloc(sizeof(PLpgSQL_var));
523 memset(var, 0, sizeof(PLpgSQL_var));
525 var->dtype = PLPGSQL_DTYPE_VAR;
526 var->refname = strdup("tg_name");
528 var->datatype = plpgsql_parse_datatype("name");
529 var->isconst = false;
530 var->notnull = false;
531 var->default_val = NULL;
533 plpgsql_adddatum((PLpgSQL_datum *) var);
534 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
535 function->tg_name_varno = var->varno;
538 * Add the variable tg_when
540 var = malloc(sizeof(PLpgSQL_var));
541 memset(var, 0, sizeof(PLpgSQL_var));
543 var->dtype = PLPGSQL_DTYPE_VAR;
544 var->refname = strdup("tg_when");
546 var->datatype = plpgsql_parse_datatype("text");
547 var->isconst = false;
548 var->notnull = false;
549 var->default_val = NULL;
551 plpgsql_adddatum((PLpgSQL_datum *) var);
552 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
553 function->tg_when_varno = var->varno;
556 * Add the variable tg_level
558 var = malloc(sizeof(PLpgSQL_var));
559 memset(var, 0, sizeof(PLpgSQL_var));
561 var->dtype = PLPGSQL_DTYPE_VAR;
562 var->refname = strdup("tg_level");
564 var->datatype = plpgsql_parse_datatype("text");
565 var->isconst = false;
566 var->notnull = false;
567 var->default_val = NULL;
569 plpgsql_adddatum((PLpgSQL_datum *) var);
570 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
571 function->tg_level_varno = var->varno;
574 * Add the variable tg_op
576 var = malloc(sizeof(PLpgSQL_var));
577 memset(var, 0, sizeof(PLpgSQL_var));
579 var->dtype = PLPGSQL_DTYPE_VAR;
580 var->refname = strdup("tg_op");
582 var->datatype = plpgsql_parse_datatype("text");
583 var->isconst = false;
584 var->notnull = false;
585 var->default_val = NULL;
587 plpgsql_adddatum((PLpgSQL_datum *) var);
588 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
589 function->tg_op_varno = var->varno;
592 * Add the variable tg_relid
594 var = malloc(sizeof(PLpgSQL_var));
595 memset(var, 0, sizeof(PLpgSQL_var));
597 var->dtype = PLPGSQL_DTYPE_VAR;
598 var->refname = strdup("tg_relid");
600 var->datatype = plpgsql_parse_datatype("oid");
601 var->isconst = false;
602 var->notnull = false;
603 var->default_val = NULL;
605 plpgsql_adddatum((PLpgSQL_datum *) var);
606 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
607 function->tg_relid_varno = var->varno;
610 * Add the variable tg_relname
612 var = malloc(sizeof(PLpgSQL_var));
613 memset(var, 0, sizeof(PLpgSQL_var));
615 var->dtype = PLPGSQL_DTYPE_VAR;
616 var->refname = strdup("tg_relname");
618 var->datatype = plpgsql_parse_datatype("name");
619 var->isconst = false;
620 var->notnull = false;
621 var->default_val = NULL;
623 plpgsql_adddatum((PLpgSQL_datum *) var);
624 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
625 function->tg_relname_varno = var->varno;
628 * Add the variable tg_nargs
630 var = malloc(sizeof(PLpgSQL_var));
631 memset(var, 0, sizeof(PLpgSQL_var));
633 var->dtype = PLPGSQL_DTYPE_VAR;
634 var->refname = strdup("tg_nargs");
636 var->datatype = plpgsql_parse_datatype("int4");
637 var->isconst = false;
638 var->notnull = false;
639 var->default_val = NULL;
641 plpgsql_adddatum((PLpgSQL_datum *) var);
642 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
643 function->tg_nargs_varno = var->varno;
648 elog(ERROR, "unrecognized function typecode: %u", functype);
653 * Create the magic FOUND variable.
655 var = malloc(sizeof(PLpgSQL_var));
656 memset(var, 0, sizeof(PLpgSQL_var));
658 var->dtype = PLPGSQL_DTYPE_VAR;
659 var->refname = strdup("found");
661 var->datatype = plpgsql_parse_datatype("bool");
662 var->isconst = false;
663 var->notnull = false;
664 var->default_val = NULL;
666 plpgsql_adddatum((PLpgSQL_datum *) var);
667 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
668 function->found_varno = var->varno;
671 * Forget about the above created variables
673 plpgsql_add_initdatums(NULL);
676 * Now parse the functions text
678 parse_rc = plpgsql_yyparse();
680 elog(ERROR, "plpgsql parser returned %d", parse_rc);
682 plpgsql_scanner_finish();
685 * If that was successful, complete the functions info.
687 function->fn_nargs = procStruct->pronargs;
688 for (i = 0; i < function->fn_nargs; i++)
689 function->fn_argvarnos[i] = arg_varnos[i];
690 function->ndatums = plpgsql_nDatums;
691 function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
692 for (i = 0; i < plpgsql_nDatums; i++)
693 function->datums[i] = plpgsql_Datums[i];
694 function->action = plpgsql_yylval.program;
696 /* Debug dump for completed functions */
697 if (plpgsql_DumpExecTree)
698 plpgsql_dumptree(function);
701 * add it to the hash table
703 plpgsql_HashTableInsert(function, hashkey);
706 * Pop the error context stack
708 error_context_stack = plerrcontext.previous;
709 plpgsql_error_funcname = NULL;
710 plpgsql_error_lineno = 0;
717 * error context callback to let us supply a call-stack traceback
720 plpgsql_compile_error_callback(void *arg)
722 if (plpgsql_error_funcname)
723 errcontext("compile of PL/pgSQL function \"%s\" near line %d",
724 plpgsql_error_funcname, plpgsql_error_lineno);
729 * plpgsql_parse_word The scanner calls this to postparse
730 * any single word not found by a
735 plpgsql_parse_word(char *word)
740 /* Do case conversion and word separation */
741 plpgsql_convert_ident(word, cp, 1);
744 * Recognize tg_argv when compiling triggers
746 if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
748 if (strcmp(cp[0], "tg_argv") == 0)
750 int save_spacescanned = plpgsql_SpaceScanned;
751 PLpgSQL_trigarg *trigarg;
753 trigarg = malloc(sizeof(PLpgSQL_trigarg));
754 memset(trigarg, 0, sizeof(PLpgSQL_trigarg));
755 trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
757 if (plpgsql_yylex() != '[')
758 plpgsql_yyerror("expected [");
760 trigarg->argnum = plpgsql_read_expression(']', "]");
762 plpgsql_adddatum((PLpgSQL_datum *) trigarg);
763 plpgsql_yylval.variable = (PLpgSQL_datum *) trigarg;
765 plpgsql_SpaceScanned = save_spacescanned;
772 * Do a lookup on the compilers namestack
774 nse = plpgsql_ns_lookup(cp[0], NULL);
778 switch (nse->itemtype)
780 case PLPGSQL_NSTYPE_LABEL:
783 case PLPGSQL_NSTYPE_VAR:
784 plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]);
787 case PLPGSQL_NSTYPE_REC:
788 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
791 case PLPGSQL_NSTYPE_ROW:
792 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
801 * Nothing found - up to now it's a word without any special meaning
810 * plpgsql_parse_dblword Same lookup for two words
811 * separated by a dot.
815 plpgsql_parse_dblword(char *word)
820 /* Do case conversion and word separation */
821 plpgsql_convert_ident(word, cp, 2);
824 * Lookup the first word
826 ns = plpgsql_ns_lookup(cp[0], NULL);
834 switch (ns->itemtype)
836 case PLPGSQL_NSTYPE_LABEL:
839 * First word is a label, so second word could be a variable,
840 * record or row in that bodies namestack. Anything else could
841 * only be something in a query given to the SPI manager and
842 * T_ERROR will get eaten up by the collector routines.
844 ns = plpgsql_ns_lookup(cp[1], cp[0]);
849 switch (ns->itemtype)
851 case PLPGSQL_NSTYPE_VAR:
852 plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);
855 case PLPGSQL_NSTYPE_REC:
856 plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
859 case PLPGSQL_NSTYPE_ROW:
860 plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
868 case PLPGSQL_NSTYPE_REC:
871 * First word is a record name, so second word must be a
872 * field in this record.
874 PLpgSQL_recfield *new;
876 new = malloc(sizeof(PLpgSQL_recfield));
877 new->dtype = PLPGSQL_DTYPE_RECFIELD;
878 new->fieldname = strdup(cp[1]);
879 new->recparentno = ns->itemno;
881 plpgsql_adddatum((PLpgSQL_datum *) new);
883 plpgsql_yylval.variable = (PLpgSQL_datum *) new;
890 case PLPGSQL_NSTYPE_ROW:
893 * First word is a row name, so second word must be a
899 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
900 for (i = 0; i < row->nfields; i++)
902 if (strcmp(row->fieldnames[i], cp[1]) == 0)
904 plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
911 (errcode(ERRCODE_UNDEFINED_COLUMN),
912 errmsg("row \"%s\" has no field \"%s\"",
927 * plpgsql_parse_tripword Same lookup for three words
932 plpgsql_parse_tripword(char *word)
937 /* Do case conversion and word separation */
938 plpgsql_convert_ident(word, cp, 3);
941 * Lookup the first word - it must be a label
943 ns = plpgsql_ns_lookup(cp[0], NULL);
951 if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
960 * First word is a label, so second word could be a record or row
962 ns = plpgsql_ns_lookup(cp[1], cp[0]);
971 switch (ns->itemtype)
973 case PLPGSQL_NSTYPE_REC:
976 * This word is a record name, so third word must be a
977 * field in this record.
979 PLpgSQL_recfield *new;
981 new = malloc(sizeof(PLpgSQL_recfield));
982 new->dtype = PLPGSQL_DTYPE_RECFIELD;
983 new->fieldname = strdup(cp[2]);
984 new->recparentno = ns->itemno;
986 plpgsql_adddatum((PLpgSQL_datum *) new);
988 plpgsql_yylval.variable = (PLpgSQL_datum *) new;
996 case PLPGSQL_NSTYPE_ROW:
999 * This word is a row name, so third word must be a field
1005 row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
1006 for (i = 0; i < row->nfields; i++)
1008 if (strcmp(row->fieldnames[i], cp[2]) == 0)
1010 plpgsql_yylval.var = (PLpgSQL_var *) (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 compilers namestack. But ensure it moves up to
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;
1080 * Word wasn't found on the namestack. Try to find a data type with
1081 * that name, but ignore pg_type entries that are in fact class types.
1083 typeOid = LookupTypeName(makeTypeName(cp[0]));
1084 if (OidIsValid(typeOid))
1088 typeTup = SearchSysCache(TYPEOID,
1089 ObjectIdGetDatum(typeOid),
1091 if (HeapTupleIsValid(typeTup))
1093 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1095 if (!typeStruct->typisdefined ||
1096 typeStruct->typrelid != InvalidOid)
1098 ReleaseSysCache(typeTup);
1103 plpgsql_yylval.dtype = build_datatype(typeTup, -1);
1105 ReleaseSysCache(typeTup);
1112 * Nothing found - up to now it's a word without any special meaning
1121 * plpgsql_parse_dblwordtype Same lookup for word.word%TYPE
1125 plpgsql_parse_dblwordtype(char *word)
1127 PLpgSQL_nsitem *nse;
1131 Form_pg_class classStruct;
1133 Form_pg_attribute attrStruct;
1138 /* Do case conversion and word separation */
1139 /* We convert %type to .type momentarily to keep converter happy */
1140 i = strlen(word) - 5;
1141 Assert(word[i] == '%');
1143 plpgsql_convert_ident(word, cp, 3);
1148 * Lookup the first word
1150 nse = plpgsql_ns_lookup(cp[0], NULL);
1153 * If this is a label lookup the second word in that labels namestack
1158 if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
1160 old_nsstate = plpgsql_ns_setlocal(false);
1161 nse = plpgsql_ns_lookup(cp[1], cp[0]);
1162 plpgsql_ns_setlocal(old_nsstate);
1169 switch (nse->itemtype)
1171 case PLPGSQL_NSTYPE_VAR:
1172 plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1187 * First word could also be a table name
1189 classOid = RelnameGetRelid(cp[0]);
1190 if (!OidIsValid(classOid))
1196 classtup = SearchSysCache(RELOID,
1197 ObjectIdGetDatum(classOid),
1199 if (!HeapTupleIsValid(classtup))
1207 * It must be a relation, sequence, view, or type
1209 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1210 if (classStruct->relkind != RELKIND_RELATION &&
1211 classStruct->relkind != RELKIND_SEQUENCE &&
1212 classStruct->relkind != RELKIND_VIEW &&
1213 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1215 ReleaseSysCache(classtup);
1222 * Fetch the named table field and it's type
1224 attrtup = SearchSysCacheAttName(classOid, cp[1]);
1225 if (!HeapTupleIsValid(attrtup))
1227 ReleaseSysCache(classtup);
1232 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1234 typetup = SearchSysCache(TYPEOID,
1235 ObjectIdGetDatum(attrStruct->atttypid),
1237 if (!HeapTupleIsValid(typetup))
1238 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1241 * Found that - build a compiler type struct and return it
1243 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1245 ReleaseSysCache(classtup);
1246 ReleaseSysCache(attrtup);
1247 ReleaseSysCache(typetup);
1254 * plpgsql_parse_tripwordtype Same lookup for word.word.word%TYPE
1257 #define TYPE_JUNK_LEN 5
1260 plpgsql_parse_tripwordtype(char *word)
1264 Form_pg_class classStruct;
1266 Form_pg_attribute attrStruct;
1270 int qualified_att_len;
1275 /* Do case conversion and word separation */
1276 qualified_att_len = strlen(word) - TYPE_JUNK_LEN;
1277 Assert(word[qualified_att_len] == '%');
1279 for (i = 0; i < qualified_att_len; i++)
1281 if (word[i] == '.' && ++numdots == 2)
1283 cp[0] = (char *) palloc((i + 1) * sizeof(char));
1284 memset(cp[0], 0, (i + 1) * sizeof(char));
1285 memcpy(cp[0], word, i * sizeof(char));
1287 /* qualified_att_len - one based position + 1 (null terminator) */
1288 cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));
1289 memset(cp[1], 0, (qualified_att_len - i) * sizeof(char));
1290 memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));
1296 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0], "plpgsql_parse_tripwordtype"));
1297 classOid = RangeVarGetRelid(relvar, true);
1298 if (!OidIsValid(classOid))
1304 classtup = SearchSysCache(RELOID,
1305 ObjectIdGetDatum(classOid),
1307 if (!HeapTupleIsValid(classtup))
1315 * It must be a relation, sequence, view, or type
1317 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1318 if (classStruct->relkind != RELKIND_RELATION &&
1319 classStruct->relkind != RELKIND_SEQUENCE &&
1320 classStruct->relkind != RELKIND_VIEW &&
1321 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1323 ReleaseSysCache(classtup);
1330 * Fetch the named table field and it's type
1332 plpgsql_convert_ident(cp[1], colname, 1);
1333 attrtup = SearchSysCacheAttName(classOid, colname[0]);
1336 if (!HeapTupleIsValid(attrtup))
1338 ReleaseSysCache(classtup);
1343 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1345 typetup = SearchSysCache(TYPEOID,
1346 ObjectIdGetDatum(attrStruct->atttypid),
1348 if (!HeapTupleIsValid(typetup))
1349 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1352 * Found that - build a compiler type struct and return it
1354 plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
1356 ReleaseSysCache(classtup);
1357 ReleaseSysCache(attrtup);
1358 ReleaseSysCache(typetup);
1365 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1366 * So word must be a table name.
1370 plpgsql_parse_wordrowtype(char *word)
1376 /* Do case conversion and word separation */
1377 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1378 i = strlen(word) - 8;
1379 Assert(word[i] == '%');
1381 plpgsql_convert_ident(word, cp, 2);
1384 /* Lookup the relation */
1385 classOid = RelnameGetRelid(cp[0]);
1386 if (!OidIsValid(classOid))
1388 (errcode(ERRCODE_UNDEFINED_TABLE),
1389 errmsg("relation \"%s\" does not exist", cp[0])));
1392 * Build and return the complete row definition
1394 plpgsql_yylval.row = plpgsql_build_rowtype(classOid);
1403 * plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
1404 * So word must be namespace qualified a table name.
1407 #define ROWTYPE_JUNK_LEN 8
1410 plpgsql_parse_dblwordrowtype(char *word)
1417 /* Do case conversion and word separation */
1418 /* We convert %rowtype to .rowtype momentarily to keep converter happy */
1419 i = strlen(word) - ROWTYPE_JUNK_LEN;
1420 Assert(word[i] == '%');
1422 cp = (char *) palloc((i + 1) * sizeof(char));
1423 memset(cp, 0, (i + 1) * sizeof(char));
1424 memcpy(cp, word, i * sizeof(char));
1426 /* Lookup the relation */
1427 relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));
1428 classOid = RangeVarGetRelid(relvar, true);
1429 if (!OidIsValid(classOid))
1431 (errcode(ERRCODE_UNDEFINED_TABLE),
1432 errmsg("relation \"%s\" does not exist", cp)));
1435 * Build and return the complete row definition
1437 plpgsql_yylval.row = plpgsql_build_rowtype(classOid);
1445 * Build a rowtype data structure given the pg_class OID.
1448 plpgsql_build_rowtype(Oid classOid)
1452 Form_pg_class classStruct;
1453 const char *relname;
1457 * Fetch the pg_class tuple.
1459 classtup = SearchSysCache(RELOID,
1460 ObjectIdGetDatum(classOid),
1462 if (!HeapTupleIsValid(classtup))
1463 elog(ERROR, "cache lookup failed for relation %u", classOid);
1464 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1465 relname = NameStr(classStruct->relname);
1467 /* accept relation, sequence, view, or type pg_class entries */
1468 if (classStruct->relkind != RELKIND_RELATION &&
1469 classStruct->relkind != RELKIND_SEQUENCE &&
1470 classStruct->relkind != RELKIND_VIEW &&
1471 classStruct->relkind != RELKIND_COMPOSITE_TYPE)
1473 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1474 errmsg("relation \"%s\" is not a table", relname)));
1477 * Create a row datum entry and all the required variables that it
1480 row = malloc(sizeof(PLpgSQL_row));
1481 memset(row, 0, sizeof(PLpgSQL_row));
1483 row->dtype = PLPGSQL_DTYPE_ROW;
1484 row->nfields = classStruct->relnatts;
1485 row->rowtypeclass = classStruct->reltype;
1486 row->fieldnames = malloc(sizeof(char *) * row->nfields);
1487 row->varnos = malloc(sizeof(int) * row->nfields);
1489 for (i = 0; i < row->nfields; i++)
1492 Form_pg_attribute attrStruct;
1494 const char *attname;
1498 * Get the attribute and it's type
1500 attrtup = SearchSysCache(ATTNUM,
1501 ObjectIdGetDatum(classOid),
1502 Int16GetDatum(i + 1),
1504 if (!HeapTupleIsValid(attrtup))
1505 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1507 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1509 attname = NameStr(attrStruct->attname);
1511 typetup = SearchSysCache(TYPEOID,
1512 ObjectIdGetDatum(attrStruct->atttypid),
1514 if (!HeapTupleIsValid(typetup))
1515 elog(ERROR, "cache lookup failed for type %u",
1516 attrStruct->atttypid);
1519 * Create the internal variable
1521 * We know if the table definitions contain a default value or if the
1522 * field is declared in the table as NOT NULL. But it's possible
1523 * to create a table field as NOT NULL without a default value and
1524 * that would lead to problems later when initializing the
1525 * variables due to entering a block at execution time. Thus we
1526 * ignore this information for now.
1528 var = malloc(sizeof(PLpgSQL_var));
1529 memset(var, 0, sizeof(PLpgSQL_var));
1530 var->dtype = PLPGSQL_DTYPE_VAR;
1531 var->refname = malloc(strlen(relname) + strlen(attname) + 2);
1532 strcpy(var->refname, relname);
1533 strcat(var->refname, ".");
1534 strcat(var->refname, attname);
1535 var->datatype = build_datatype(typetup, attrStruct->atttypmod);
1536 var->isconst = false;
1537 var->notnull = false;
1538 var->default_val = NULL;
1539 var->value = (Datum) 0;
1541 var->freeval = false;
1543 plpgsql_adddatum((PLpgSQL_datum *) var);
1546 * Add the variable to the row.
1548 row->fieldnames[i] = strdup(attname);
1549 row->varnos[i] = var->varno;
1551 ReleaseSysCache(typetup);
1552 ReleaseSysCache(attrtup);
1555 ReleaseSysCache(classtup);
1562 * plpgsql_parse_datatype Scanner found something that should
1563 * be a datatype name.
1567 plpgsql_parse_datatype(char *string)
1574 /* Let the main parser try to parse it under standard SQL rules */
1575 parseTypeString(string, &type_id, &typmod);
1577 /* Okay, build a PLpgSQL_type data structure for it */
1578 typeTup = SearchSysCache(TYPEOID,
1579 ObjectIdGetDatum(type_id),
1581 if (!HeapTupleIsValid(typeTup))
1582 elog(ERROR, "cache lookup failed for type %u", type_id);
1584 typ = build_datatype(typeTup, typmod);
1586 ReleaseSysCache(typeTup);
1592 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
1594 static PLpgSQL_type *
1595 build_datatype(HeapTuple typeTup, int32 typmod)
1597 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1600 typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
1602 typ->typname = strdup(NameStr(typeStruct->typname));
1603 typ->typoid = HeapTupleGetOid(typeTup);
1604 typ->typlen = typeStruct->typlen;
1605 typ->typbyval = typeStruct->typbyval;
1606 typ->typrelid = typeStruct->typrelid;
1607 typ->typelem = typeStruct->typelem;
1608 perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
1609 typ->atttypmod = typmod;
1616 * plpgsql_adddatum Add a variable, record or row
1617 * to the compilers datum list.
1621 plpgsql_adddatum(PLpgSQL_datum * new)
1623 if (plpgsql_nDatums == datums_alloc)
1626 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
1629 new->dno = plpgsql_nDatums;
1630 plpgsql_Datums[plpgsql_nDatums++] = new;
1635 * plpgsql_add_initdatums Put all datum entries created
1636 * since the last call into the
1637 * finishing code block so the
1638 * block knows which variables to
1639 * reinitialize when entered.
1643 plpgsql_add_initdatums(int **varnos)
1648 for (i = datums_last; i < plpgsql_nDatums; i++)
1650 switch (plpgsql_Datums[i]->dtype)
1652 case PLPGSQL_DTYPE_VAR:
1663 *varnos = (int *) malloc(sizeof(int) * n);
1666 for (i = datums_last; i < plpgsql_nDatums; i++)
1668 switch (plpgsql_Datums[i]->dtype)
1670 case PLPGSQL_DTYPE_VAR:
1671 (*varnos)[n++] = plpgsql_Datums[i]->dno;
1679 datums_last = plpgsql_nDatums;
1685 * plpgsql_yyerror Handle parser error
1690 plpgsql_yyerror(const char *s)
1692 plpgsql_error_lineno = plpgsql_scanner_lineno();
1694 (errcode(ERRCODE_SYNTAX_ERROR),
1695 /* translator: first %s is a phrase like "syntax error" */
1696 errmsg("%s at or near \"%s\"", s, plpgsql_yytext)));
1701 * Compute the hashkey for a given function invocation
1703 * The hashkey is returned into the caller-provided storage at *hashkey.
1706 compute_function_hashkey(FmgrInfo *flinfo,
1707 Form_pg_proc procStruct,
1708 PLpgSQL_func_hashkey *hashkey)
1712 /* Make sure any unused bytes of the struct are zero */
1713 MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
1715 hashkey->funcOid = flinfo->fn_oid;
1717 /* get the argument types */
1718 for (i = 0; i < procStruct->pronargs; i++)
1720 Oid argtypeid = procStruct->proargtypes[i];
1723 * Check for polymorphic arguments. If found, use the actual
1724 * parameter type from the caller's FuncExpr node, if we
1727 * We can support arguments of type ANY the same way as normal
1728 * polymorphic arguments.
1730 if (argtypeid == ANYARRAYOID || argtypeid == ANYELEMENTOID ||
1731 argtypeid == ANYOID)
1733 argtypeid = get_fn_expr_argtype(flinfo, i);
1734 if (!OidIsValid(argtypeid))
1736 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1737 errmsg("could not determine actual argument "
1738 "type for polymorphic function \"%s\"",
1739 NameStr(procStruct->proname))));
1742 hashkey->argtypes[i] = argtypeid;
1747 plpgsql_HashTableInit(void)
1751 memset(&ctl, 0, sizeof(ctl));
1752 ctl.keysize = sizeof(PLpgSQL_func_hashkey);
1753 ctl.entrysize = sizeof(plpgsql_HashEnt);
1754 ctl.hash = tag_hash;
1755 plpgsql_HashTable = hash_create("PLpgSQL function cache",
1758 HASH_ELEM | HASH_FUNCTION);
1761 static PLpgSQL_function *
1762 plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
1764 plpgsql_HashEnt *hentry;
1766 hentry = (plpgsql_HashEnt*) hash_search(plpgsql_HashTable,
1771 return hentry->function;
1773 return (PLpgSQL_function *) NULL;
1777 plpgsql_HashTableInsert(PLpgSQL_function *function,
1778 PLpgSQL_func_hashkey *func_key)
1780 plpgsql_HashEnt *hentry;
1783 hentry = (plpgsql_HashEnt*) hash_search(plpgsql_HashTable,
1789 (errcode(ERRCODE_OUT_OF_MEMORY),
1790 errmsg("out of memory")));
1792 elog(WARNING, "trying to insert a function that already exists");
1794 hentry->function = function;
1795 /* prepare back link from function to hashtable key */
1796 function->fn_hashkey = &hentry->key;
1800 plpgsql_HashTableDelete(PLpgSQL_function *function)
1802 plpgsql_HashEnt *hentry;
1804 hentry = (plpgsql_HashEnt*) hash_search(plpgsql_HashTable,
1805 (void *) function->fn_hashkey,
1809 elog(WARNING, "trying to delete function that does not exist");