1 /*-------------------------------------------------------------------------
2 *
3 * pl_comp.c - Compiler part of the PL/pgSQL
4 * procedural language
5 *
6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/pl/plpgsql/src/pl_comp.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16 #include "postgres.h"
17
18 #include <ctype.h>
19
20 #include "access/htup_details.h"
21 #include "catalog/namespace.h"
22 #include "catalog/pg_proc.h"
23 #include "catalog/pg_type.h"
24 #include "funcapi.h"
25 #include "nodes/makefuncs.h"
26 #include "parser/parse_type.h"
27 #include "plpgsql.h"
28 #include "utils/builtins.h"
29 #include "utils/fmgroids.h"
30 #include "utils/guc.h"
31 #include "utils/lsyscache.h"
32 #include "utils/memutils.h"
33 #include "utils/regproc.h"
34 #include "utils/rel.h"
35 #include "utils/syscache.h"
36 #include "utils/typcache.h"
37
38 /* ----------
39 * Our own local and global variables
40 * ----------
41 */
42 PLpgSQL_stmt_block *plpgsql_parse_result;
43
44 static int datums_alloc;
45 int plpgsql_nDatums;
46 PLpgSQL_datum **plpgsql_Datums;
47 static int datums_last;
48
49 char *plpgsql_error_funcname;
50 bool plpgsql_DumpExecTree = false;
51 bool plpgsql_check_syntax = false;
52
53 PLpgSQL_function *plpgsql_curr_compile;
54
55 /* A context appropriate for short-term allocs during compilation */
56 MemoryContext plpgsql_compile_tmp_cxt;
57
58 /* ----------
59 * Hash table for compiled functions
60 * ----------
61 */
62 static HTAB *plpgsql_HashTable = NULL;
63
64 typedef struct plpgsql_hashent
65 {
66 PLpgSQL_func_hashkey key;
67 PLpgSQL_function *function;
68 } plpgsql_HashEnt;
69
70 #define FUNCS_PER_USER 128 /* initial table size */
71
72 /* ----------
73 * Lookup table for EXCEPTION condition names
74 * ----------
75 */
76 typedef struct
77 {
78 const char *label;
79 int sqlerrstate;
80 } ExceptionLabelMap;
81
82 static const ExceptionLabelMap exception_label_map[] = {
83 #include "plerrcodes.h" /* pgrminclude ignore */
84 {NULL, 0}
85 };
86
87
88 /* ----------
89 * static prototypes
90 * ----------
91 */
92 static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
93 HeapTuple procTup,
94 PLpgSQL_function *function,
95 PLpgSQL_func_hashkey *hashkey,
96 bool forValidator);
97 static void plpgsql_compile_error_callback(void *arg);
98 static void add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name);
99 static void add_dummy_return(PLpgSQL_function *function);
100 static Node *plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref);
101 static Node *plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var);
102 static Node *plpgsql_param_ref(ParseState *pstate, ParamRef *pref);
103 static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
104 ColumnRef *cref, bool error_if_no_field);
105 static Node *make_datum_param(PLpgSQL_expr *expr, int dno, int location);
106 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
107 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod,
108 Oid collation, TypeName *origtypname);
109 static void plpgsql_start_datums(void);
110 static void plpgsql_finish_datums(PLpgSQL_function *function);
111 static void compute_function_hashkey(FunctionCallInfo fcinfo,
112 Form_pg_proc procStruct,
113 PLpgSQL_func_hashkey *hashkey,
114 bool forValidator);
115 static void plpgsql_resolve_polymorphic_argtypes(int numargs,
116 Oid *argtypes, char *argmodes,
117 Node *call_expr, bool forValidator,
118 const char *proname);
119 static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
120 static void plpgsql_HashTableInsert(PLpgSQL_function *function,
121 PLpgSQL_func_hashkey *func_key);
122 static void plpgsql_HashTableDelete(PLpgSQL_function *function);
123 static void delete_function(PLpgSQL_function *func);
124
125 /* ----------
126 * plpgsql_compile Make an execution tree for a PL/pgSQL function.
127 *
128 * If forValidator is true, we're only compiling for validation purposes,
129 * and so some checks are skipped.
130 *
131 * Note: it's important for this to fall through quickly if the function
132 * has already been compiled.
133 * ----------
134 */
135 PLpgSQL_function *
plpgsql_compile(FunctionCallInfo fcinfo,bool forValidator)136 plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator)
137 {
138 Oid funcOid = fcinfo->flinfo->fn_oid;
139 HeapTuple procTup;
140 Form_pg_proc procStruct;
141 PLpgSQL_function *function;
142 PLpgSQL_func_hashkey hashkey;
143 bool function_valid = false;
144 bool hashkey_valid = false;
145
146 /*
147 * Lookup the pg_proc tuple by Oid; we'll need it in any case
148 */
149 procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
150 if (!HeapTupleIsValid(procTup))
151 elog(ERROR, "cache lookup failed for function %u", funcOid);
152 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
153
154 /*
155 * See if there's already a cache entry for the current FmgrInfo. If not,
156 * try to find one in the hash table.
157 */
158 function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
159
160 recheck:
161 if (!function)
162 {
163 /* Compute hashkey using function signature and actual arg types */
164 compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
165 hashkey_valid = true;
166
167 /* And do the lookup */
168 function = plpgsql_HashTableLookup(&hashkey);
169 }
170
171 if (function)
172 {
173 /* We have a compiled function, but is it still valid? */
174 if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
175 ItemPointerEquals(&function->fn_tid, &procTup->t_self))
176 function_valid = true;
177 else
178 {
179 /*
180 * Nope, so remove it from hashtable and try to drop associated
181 * storage (if not done already).
182 */
183 delete_function(function);
184
185 /*
186 * If the function isn't in active use then we can overwrite the
187 * func struct with new data, allowing any other existing fn_extra
188 * pointers to make use of the new definition on their next use.
189 * If it is in use then just leave it alone and make a new one.
190 * (The active invocations will run to completion using the
191 * previous definition, and then the cache entry will just be
192 * leaked; doesn't seem worth adding code to clean it up, given
193 * what a corner case this is.)
194 *
195 * If we found the function struct via fn_extra then it's possible
196 * a replacement has already been made, so go back and recheck the
197 * hashtable.
198 */
199 if (function->use_count != 0)
200 {
201 function = NULL;
202 if (!hashkey_valid)
203 goto recheck;
204 }
205 }
206 }
207
208 /*
209 * If the function wasn't found or was out-of-date, we have to compile it
210 */
211 if (!function_valid)
212 {
213 /*
214 * Calculate hashkey if we didn't already; we'll need it to store the
215 * completed function.
216 */
217 if (!hashkey_valid)
218 compute_function_hashkey(fcinfo, procStruct, &hashkey,
219 forValidator);
220
221 /*
222 * Do the hard part.
223 */
224 function = do_compile(fcinfo, procTup, function,
225 &hashkey, forValidator);
226 }
227
228 ReleaseSysCache(procTup);
229
230 /*
231 * Save pointer in FmgrInfo to avoid search on subsequent calls
232 */
233 fcinfo->flinfo->fn_extra = (void *) function;
234
235 /*
236 * Finally return the compiled function
237 */
238 return function;
239 }
240
241 /*
242 * This is the slow part of plpgsql_compile().
243 *
244 * The passed-in "function" pointer is either NULL or an already-allocated
245 * function struct to overwrite.
246 *
247 * While compiling a function, the CurrentMemoryContext is the
248 * per-function memory context of the function we are compiling. That
249 * means a palloc() will allocate storage with the same lifetime as
250 * the function itself.
251 *
252 * Because palloc()'d storage will not be immediately freed, temporary
253 * allocations should either be performed in a short-lived memory
254 * context or explicitly pfree'd. Since not all backend functions are
255 * careful about pfree'ing their allocations, it is also wise to
256 * switch into a short-term context before calling into the
257 * backend. An appropriate context for performing short-term
258 * allocations is the plpgsql_compile_tmp_cxt.
259 *
260 * NB: this code is not re-entrant. We assume that nothing we do here could
261 * result in the invocation of another plpgsql function.
262 */
263 static PLpgSQL_function *
do_compile(FunctionCallInfo fcinfo,HeapTuple procTup,PLpgSQL_function * function,PLpgSQL_func_hashkey * hashkey,bool forValidator)264 do_compile(FunctionCallInfo fcinfo,
265 HeapTuple procTup,
266 PLpgSQL_function *function,
267 PLpgSQL_func_hashkey *hashkey,
268 bool forValidator)
269 {
270 Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
271 bool is_dml_trigger = CALLED_AS_TRIGGER(fcinfo);
272 bool is_event_trigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
273 Datum prosrcdatum;
274 bool isnull;
275 char *proc_source;
276 HeapTuple typeTup;
277 Form_pg_type typeStruct;
278 PLpgSQL_variable *var;
279 PLpgSQL_rec *rec;
280 int i;
281 ErrorContextCallback plerrcontext;
282 int parse_rc;
283 Oid rettypeid;
284 int numargs;
285 int num_in_args = 0;
286 int num_out_args = 0;
287 Oid *argtypes;
288 char **argnames;
289 char *argmodes;
290 int *in_arg_varnos = NULL;
291 PLpgSQL_variable **out_arg_variables;
292 MemoryContext func_cxt;
293
294 /*
295 * Setup the scanner input and error info. We assume that this function
296 * cannot be invoked recursively, so there's no need to save and restore
297 * the static variables used here.
298 */
299 prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
300 Anum_pg_proc_prosrc, &isnull);
301 if (isnull)
302 elog(ERROR, "null prosrc");
303 proc_source = TextDatumGetCString(prosrcdatum);
304 plpgsql_scanner_init(proc_source);
305
306 plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
307
308 /*
309 * Setup error traceback support for ereport()
310 */
311 plerrcontext.callback = plpgsql_compile_error_callback;
312 plerrcontext.arg = forValidator ? proc_source : NULL;
313 plerrcontext.previous = error_context_stack;
314 error_context_stack = &plerrcontext;
315
316 /*
317 * Do extra syntax checks when validating the function definition. We skip
318 * this when actually compiling functions for execution, for performance
319 * reasons.
320 */
321 plpgsql_check_syntax = forValidator;
322
323 /*
324 * Create the new function struct, if not done already. The function
325 * structs are never thrown away, so keep them in TopMemoryContext.
326 */
327 if (function == NULL)
328 {
329 function = (PLpgSQL_function *)
330 MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function));
331 }
332 else
333 {
334 /* re-using a previously existing struct, so clear it out */
335 memset(function, 0, sizeof(PLpgSQL_function));
336 }
337 plpgsql_curr_compile = function;
338
339 /*
340 * All the permanent output of compilation (e.g. parse tree) is kept in a
341 * per-function memory context, so it can be reclaimed easily.
342 */
343 func_cxt = AllocSetContextCreate(TopMemoryContext,
344 "PL/pgSQL function",
345 ALLOCSET_DEFAULT_SIZES);
346 plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
347
348 function->fn_signature = format_procedure(fcinfo->flinfo->fn_oid);
349 MemoryContextSetIdentifier(func_cxt, function->fn_signature);
350 function->fn_oid = fcinfo->flinfo->fn_oid;
351 function->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
352 function->fn_tid = procTup->t_self;
353 function->fn_input_collation = fcinfo->fncollation;
354 function->fn_cxt = func_cxt;
355 function->out_param_varno = -1; /* set up for no OUT param */
356 function->resolve_option = plpgsql_variable_conflict;
357 function->print_strict_params = plpgsql_print_strict_params;
358 /* only promote extra warnings and errors at CREATE FUNCTION time */
359 function->extra_warnings = forValidator ? plpgsql_extra_warnings : 0;
360 function->extra_errors = forValidator ? plpgsql_extra_errors : 0;
361
362 if (is_dml_trigger)
363 function->fn_is_trigger = PLPGSQL_DML_TRIGGER;
364 else if (is_event_trigger)
365 function->fn_is_trigger = PLPGSQL_EVENT_TRIGGER;
366 else
367 function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
368
369 function->fn_prokind = procStruct->prokind;
370
371 function->nstatements = 0;
372 function->requires_procedure_resowner = false;
373
374 /*
375 * Initialize the compiler, particularly the namespace stack. The
376 * outermost namespace contains function parameters and other special
377 * variables (such as FOUND), and is named after the function itself.
378 */
379 plpgsql_ns_init();
380 plpgsql_ns_push(NameStr(procStruct->proname), PLPGSQL_LABEL_BLOCK);
381 plpgsql_DumpExecTree = false;
382 plpgsql_start_datums();
383
384 switch (function->fn_is_trigger)
385 {
386 case PLPGSQL_NOT_TRIGGER:
387
388 /*
389 * Fetch info about the procedure's parameters. Allocations aren't
390 * needed permanently, so make them in tmp cxt.
391 *
392 * We also need to resolve any polymorphic input or output
393 * argument types. In validation mode we won't be able to, so we
394 * arbitrarily assume we are dealing with integers.
395 */
396 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
397
398 numargs = get_func_arg_info(procTup,
399 &argtypes, &argnames, &argmodes);
400
401 plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
402 fcinfo->flinfo->fn_expr,
403 forValidator,
404 plpgsql_error_funcname);
405
406 in_arg_varnos = (int *) palloc(numargs * sizeof(int));
407 out_arg_variables = (PLpgSQL_variable **) palloc(numargs * sizeof(PLpgSQL_variable *));
408
409 MemoryContextSwitchTo(func_cxt);
410
411 /*
412 * Create the variables for the procedure's parameters.
413 */
414 for (i = 0; i < numargs; i++)
415 {
416 char buf[32];
417 Oid argtypeid = argtypes[i];
418 char argmode = argmodes ? argmodes[i] : PROARGMODE_IN;
419 PLpgSQL_type *argdtype;
420 PLpgSQL_variable *argvariable;
421 PLpgSQL_nsitem_type argitemtype;
422
423 /* Create $n name for variable */
424 snprintf(buf, sizeof(buf), "$%d", i + 1);
425
426 /* Create datatype info */
427 argdtype = plpgsql_build_datatype(argtypeid,
428 -1,
429 function->fn_input_collation,
430 NULL);
431
432 /* Disallow pseudotype argument */
433 /* (note we already replaced polymorphic types) */
434 /* (build_variable would do this, but wrong message) */
435 if (argdtype->ttype == PLPGSQL_TTYPE_PSEUDO)
436 ereport(ERROR,
437 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
438 errmsg("PL/pgSQL functions cannot accept type %s",
439 format_type_be(argtypeid))));
440
441 /*
442 * Build variable and add to datum list. If there's a name
443 * for the argument, use that as refname, else use $n name.
444 */
445 argvariable = plpgsql_build_variable((argnames &&
446 argnames[i][0] != '\0') ?
447 argnames[i] : buf,
448 0, argdtype, false);
449
450 if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
451 {
452 argitemtype = PLPGSQL_NSTYPE_VAR;
453 }
454 else
455 {
456 Assert(argvariable->dtype == PLPGSQL_DTYPE_REC);
457 argitemtype = PLPGSQL_NSTYPE_REC;
458 }
459
460 /* Remember arguments in appropriate arrays */
461 if (argmode == PROARGMODE_IN ||
462 argmode == PROARGMODE_INOUT ||
463 argmode == PROARGMODE_VARIADIC)
464 in_arg_varnos[num_in_args++] = argvariable->dno;
465 if (argmode == PROARGMODE_OUT ||
466 argmode == PROARGMODE_INOUT ||
467 argmode == PROARGMODE_TABLE)
468 out_arg_variables[num_out_args++] = argvariable;
469
470 /* Add to namespace under the $n name */
471 add_parameter_name(argitemtype, argvariable->dno, buf);
472
473 /* If there's a name for the argument, make an alias */
474 if (argnames && argnames[i][0] != '\0')
475 add_parameter_name(argitemtype, argvariable->dno,
476 argnames[i]);
477 }
478
479 /*
480 * If there's just one OUT parameter, out_param_varno points
481 * directly to it. If there's more than one, build a row that
482 * holds all of them. Procedures return a row even for one OUT
483 * parameter.
484 */
485 if (num_out_args > 1 ||
486 (num_out_args == 1 && function->fn_prokind == PROKIND_PROCEDURE))
487 {
488 PLpgSQL_row *row = build_row_from_vars(out_arg_variables,
489 num_out_args);
490
491 plpgsql_adddatum((PLpgSQL_datum *) row);
492 function->out_param_varno = row->dno;
493 }
494 else if (num_out_args == 1)
495 function->out_param_varno = out_arg_variables[0]->dno;
496
497 /*
498 * Check for a polymorphic returntype. If found, use the actual
499 * returntype type from the caller's FuncExpr node, if we have
500 * one. (In validation mode we arbitrarily assume we are dealing
501 * with integers.)
502 *
503 * Note: errcode is FEATURE_NOT_SUPPORTED because it should always
504 * work; if it doesn't we're in some context that fails to make
505 * the info available.
506 */
507 rettypeid = procStruct->prorettype;
508 if (IsPolymorphicType(rettypeid))
509 {
510 if (forValidator)
511 {
512 if (rettypeid == ANYARRAYOID ||
513 rettypeid == ANYCOMPATIBLEARRAYOID)
514 rettypeid = INT4ARRAYOID;
515 else if (rettypeid == ANYRANGEOID ||
516 rettypeid == ANYCOMPATIBLERANGEOID)
517 rettypeid = INT4RANGEOID;
518 else if (rettypeid == ANYMULTIRANGEOID)
519 rettypeid = INT4MULTIRANGEOID;
520 else /* ANYELEMENT or ANYNONARRAY or ANYCOMPATIBLE */
521 rettypeid = INT4OID;
522 /* XXX what could we use for ANYENUM? */
523 }
524 else
525 {
526 rettypeid = get_fn_expr_rettype(fcinfo->flinfo);
527 if (!OidIsValid(rettypeid))
528 ereport(ERROR,
529 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
530 errmsg("could not determine actual return type "
531 "for polymorphic function \"%s\"",
532 plpgsql_error_funcname)));
533 }
534 }
535
536 /*
537 * Normal function has a defined returntype
538 */
539 function->fn_rettype = rettypeid;
540 function->fn_retset = procStruct->proretset;
541
542 /*
543 * Lookup the function's return type
544 */
545 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettypeid));
546 if (!HeapTupleIsValid(typeTup))
547 elog(ERROR, "cache lookup failed for type %u", rettypeid);
548 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
549
550 /* Disallow pseudotype result, except VOID or RECORD */
551 /* (note we already replaced polymorphic types) */
552 if (typeStruct->typtype == TYPTYPE_PSEUDO)
553 {
554 if (rettypeid == VOIDOID ||
555 rettypeid == RECORDOID)
556 /* okay */ ;
557 else if (rettypeid == TRIGGEROID || rettypeid == EVENT_TRIGGEROID)
558 ereport(ERROR,
559 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
560 errmsg("trigger functions can only be called as triggers")));
561 else
562 ereport(ERROR,
563 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
564 errmsg("PL/pgSQL functions cannot return type %s",
565 format_type_be(rettypeid))));
566 }
567
568 function->fn_retistuple = type_is_rowtype(rettypeid);
569 function->fn_retisdomain = (typeStruct->typtype == TYPTYPE_DOMAIN);
570 function->fn_retbyval = typeStruct->typbyval;
571 function->fn_rettyplen = typeStruct->typlen;
572
573 /*
574 * install $0 reference, but only for polymorphic return types,
575 * and not when the return is specified through an output
576 * parameter.
577 */
578 if (IsPolymorphicType(procStruct->prorettype) &&
579 num_out_args == 0)
580 {
581 (void) plpgsql_build_variable("$0", 0,
582 build_datatype(typeTup,
583 -1,
584 function->fn_input_collation,
585 NULL),
586 true);
587 }
588
589 ReleaseSysCache(typeTup);
590 break;
591
592 case PLPGSQL_DML_TRIGGER:
593 /* Trigger procedure's return type is unknown yet */
594 function->fn_rettype = InvalidOid;
595 function->fn_retbyval = false;
596 function->fn_retistuple = true;
597 function->fn_retisdomain = false;
598 function->fn_retset = false;
599
600 /* shouldn't be any declared arguments */
601 if (procStruct->pronargs != 0)
602 ereport(ERROR,
603 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
604 errmsg("trigger functions cannot have declared arguments"),
605 errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead.")));
606
607 /* Add the record for referencing NEW ROW */
608 rec = plpgsql_build_record("new", 0, NULL, RECORDOID, true);
609 function->new_varno = rec->dno;
610
611 /* Add the record for referencing OLD ROW */
612 rec = plpgsql_build_record("old", 0, NULL, RECORDOID, true);
613 function->old_varno = rec->dno;
614
615 /* Add the variable tg_name */
616 var = plpgsql_build_variable("tg_name", 0,
617 plpgsql_build_datatype(NAMEOID,
618 -1,
619 function->fn_input_collation,
620 NULL),
621 true);
622 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
623 var->dtype = PLPGSQL_DTYPE_PROMISE;
624 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NAME;
625
626 /* Add the variable tg_when */
627 var = plpgsql_build_variable("tg_when", 0,
628 plpgsql_build_datatype(TEXTOID,
629 -1,
630 function->fn_input_collation,
631 NULL),
632 true);
633 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
634 var->dtype = PLPGSQL_DTYPE_PROMISE;
635 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_WHEN;
636
637 /* Add the variable tg_level */
638 var = plpgsql_build_variable("tg_level", 0,
639 plpgsql_build_datatype(TEXTOID,
640 -1,
641 function->fn_input_collation,
642 NULL),
643 true);
644 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
645 var->dtype = PLPGSQL_DTYPE_PROMISE;
646 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_LEVEL;
647
648 /* Add the variable tg_op */
649 var = plpgsql_build_variable("tg_op", 0,
650 plpgsql_build_datatype(TEXTOID,
651 -1,
652 function->fn_input_collation,
653 NULL),
654 true);
655 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
656 var->dtype = PLPGSQL_DTYPE_PROMISE;
657 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_OP;
658
659 /* Add the variable tg_relid */
660 var = plpgsql_build_variable("tg_relid", 0,
661 plpgsql_build_datatype(OIDOID,
662 -1,
663 InvalidOid,
664 NULL),
665 true);
666 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
667 var->dtype = PLPGSQL_DTYPE_PROMISE;
668 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_RELID;
669
670 /* Add the variable tg_relname */
671 var = plpgsql_build_variable("tg_relname", 0,
672 plpgsql_build_datatype(NAMEOID,
673 -1,
674 function->fn_input_collation,
675 NULL),
676 true);
677 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
678 var->dtype = PLPGSQL_DTYPE_PROMISE;
679 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
680
681 /* tg_table_name is now preferred to tg_relname */
682 var = plpgsql_build_variable("tg_table_name", 0,
683 plpgsql_build_datatype(NAMEOID,
684 -1,
685 function->fn_input_collation,
686 NULL),
687 true);
688 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
689 var->dtype = PLPGSQL_DTYPE_PROMISE;
690 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_NAME;
691
692 /* add the variable tg_table_schema */
693 var = plpgsql_build_variable("tg_table_schema", 0,
694 plpgsql_build_datatype(NAMEOID,
695 -1,
696 function->fn_input_collation,
697 NULL),
698 true);
699 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
700 var->dtype = PLPGSQL_DTYPE_PROMISE;
701 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TABLE_SCHEMA;
702
703 /* Add the variable tg_nargs */
704 var = plpgsql_build_variable("tg_nargs", 0,
705 plpgsql_build_datatype(INT4OID,
706 -1,
707 InvalidOid,
708 NULL),
709 true);
710 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
711 var->dtype = PLPGSQL_DTYPE_PROMISE;
712 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_NARGS;
713
714 /* Add the variable tg_argv */
715 var = plpgsql_build_variable("tg_argv", 0,
716 plpgsql_build_datatype(TEXTARRAYOID,
717 -1,
718 function->fn_input_collation,
719 NULL),
720 true);
721 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
722 var->dtype = PLPGSQL_DTYPE_PROMISE;
723 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_ARGV;
724
725 break;
726
727 case PLPGSQL_EVENT_TRIGGER:
728 function->fn_rettype = VOIDOID;
729 function->fn_retbyval = false;
730 function->fn_retistuple = true;
731 function->fn_retisdomain = false;
732 function->fn_retset = false;
733
734 /* shouldn't be any declared arguments */
735 if (procStruct->pronargs != 0)
736 ereport(ERROR,
737 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
738 errmsg("event trigger functions cannot have declared arguments")));
739
740 /* Add the variable tg_event */
741 var = plpgsql_build_variable("tg_event", 0,
742 plpgsql_build_datatype(TEXTOID,
743 -1,
744 function->fn_input_collation,
745 NULL),
746 true);
747 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
748 var->dtype = PLPGSQL_DTYPE_PROMISE;
749 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_EVENT;
750
751 /* Add the variable tg_tag */
752 var = plpgsql_build_variable("tg_tag", 0,
753 plpgsql_build_datatype(TEXTOID,
754 -1,
755 function->fn_input_collation,
756 NULL),
757 true);
758 Assert(var->dtype == PLPGSQL_DTYPE_VAR);
759 var->dtype = PLPGSQL_DTYPE_PROMISE;
760 ((PLpgSQL_var *) var)->promise = PLPGSQL_PROMISE_TG_TAG;
761
762 break;
763
764 default:
765 elog(ERROR, "unrecognized function typecode: %d",
766 (int) function->fn_is_trigger);
767 break;
768 }
769
770 /* Remember if function is STABLE/IMMUTABLE */
771 function->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
772
773 /*
774 * Create the magic FOUND variable.
775 */
776 var = plpgsql_build_variable("found", 0,
777 plpgsql_build_datatype(BOOLOID,
778 -1,
779 InvalidOid,
780 NULL),
781 true);
782 function->found_varno = var->dno;
783
784 /*
785 * Now parse the function's text
786 */
787 parse_rc = plpgsql_yyparse();
788 if (parse_rc != 0)
789 elog(ERROR, "plpgsql parser returned %d", parse_rc);
790 function->action = plpgsql_parse_result;
791
792 plpgsql_scanner_finish();
793 pfree(proc_source);
794
795 /*
796 * If it has OUT parameters or returns VOID or returns a set, we allow
797 * control to fall off the end without an explicit RETURN statement. The
798 * easiest way to implement this is to add a RETURN statement to the end
799 * of the statement list during parsing.
800 */
801 if (num_out_args > 0 || function->fn_rettype == VOIDOID ||
802 function->fn_retset)
803 add_dummy_return(function);
804
805 /*
806 * Complete the function's info
807 */
808 function->fn_nargs = procStruct->pronargs;
809 for (i = 0; i < function->fn_nargs; i++)
810 function->fn_argvarnos[i] = in_arg_varnos[i];
811
812 plpgsql_finish_datums(function);
813
814 /* Debug dump for completed functions */
815 if (plpgsql_DumpExecTree)
816 plpgsql_dumptree(function);
817
818 /*
819 * add it to the hash table
820 */
821 plpgsql_HashTableInsert(function, hashkey);
822
823 /*
824 * Pop the error context stack
825 */
826 error_context_stack = plerrcontext.previous;
827 plpgsql_error_funcname = NULL;
828
829 plpgsql_check_syntax = false;
830
831 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
832 plpgsql_compile_tmp_cxt = NULL;
833 return function;
834 }
835
836 /* ----------
837 * plpgsql_compile_inline Make an execution tree for an anonymous code block.
838 *
839 * Note: this is generally parallel to do_compile(); is it worth trying to
840 * merge the two?
841 *
842 * Note: we assume the block will be thrown away so there is no need to build
843 * persistent data structures.
844 * ----------
845 */
846 PLpgSQL_function *
plpgsql_compile_inline(char * proc_source)847 plpgsql_compile_inline(char *proc_source)
848 {
849 char *func_name = "inline_code_block";
850 PLpgSQL_function *function;
851 ErrorContextCallback plerrcontext;
852 PLpgSQL_variable *var;
853 int parse_rc;
854 MemoryContext func_cxt;
855
856 /*
857 * Setup the scanner input and error info. We assume that this function
858 * cannot be invoked recursively, so there's no need to save and restore
859 * the static variables used here.
860 */
861 plpgsql_scanner_init(proc_source);
862
863 plpgsql_error_funcname = func_name;
864
865 /*
866 * Setup error traceback support for ereport()
867 */
868 plerrcontext.callback = plpgsql_compile_error_callback;
869 plerrcontext.arg = proc_source;
870 plerrcontext.previous = error_context_stack;
871 error_context_stack = &plerrcontext;
872
873 /* Do extra syntax checking if check_function_bodies is on */
874 plpgsql_check_syntax = check_function_bodies;
875
876 /* Function struct does not live past current statement */
877 function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
878
879 plpgsql_curr_compile = function;
880
881 /*
882 * All the rest of the compile-time storage (e.g. parse tree) is kept in
883 * its own memory context, so it can be reclaimed easily.
884 */
885 func_cxt = AllocSetContextCreate(CurrentMemoryContext,
886 "PL/pgSQL inline code context",
887 ALLOCSET_DEFAULT_SIZES);
888 plpgsql_compile_tmp_cxt = MemoryContextSwitchTo(func_cxt);
889
890 function->fn_signature = pstrdup(func_name);
891 function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
892 function->fn_input_collation = InvalidOid;
893 function->fn_cxt = func_cxt;
894 function->out_param_varno = -1; /* set up for no OUT param */
895 function->resolve_option = plpgsql_variable_conflict;
896 function->print_strict_params = plpgsql_print_strict_params;
897
898 /*
899 * don't do extra validation for inline code as we don't want to add spam
900 * at runtime
901 */
902 function->extra_warnings = 0;
903 function->extra_errors = 0;
904
905 function->nstatements = 0;
906 function->requires_procedure_resowner = false;
907
908 plpgsql_ns_init();
909 plpgsql_ns_push(func_name, PLPGSQL_LABEL_BLOCK);
910 plpgsql_DumpExecTree = false;
911 plpgsql_start_datums();
912
913 /* Set up as though in a function returning VOID */
914 function->fn_rettype = VOIDOID;
915 function->fn_retset = false;
916 function->fn_retistuple = false;
917 function->fn_retisdomain = false;
918 function->fn_prokind = PROKIND_FUNCTION;
919 /* a bit of hardwired knowledge about type VOID here */
920 function->fn_retbyval = true;
921 function->fn_rettyplen = sizeof(int32);
922
923 /*
924 * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
925 * set this true inside a read-only transaction? Not clear.
926 */
927 function->fn_readonly = false;
928
929 /*
930 * Create the magic FOUND variable.
931 */
932 var = plpgsql_build_variable("found", 0,
933 plpgsql_build_datatype(BOOLOID,
934 -1,
935 InvalidOid,
936 NULL),
937 true);
938 function->found_varno = var->dno;
939
940 /*
941 * Now parse the function's text
942 */
943 parse_rc = plpgsql_yyparse();
944 if (parse_rc != 0)
945 elog(ERROR, "plpgsql parser returned %d", parse_rc);
946 function->action = plpgsql_parse_result;
947
948 plpgsql_scanner_finish();
949
950 /*
951 * If it returns VOID (always true at the moment), we allow control to
952 * fall off the end without an explicit RETURN statement.
953 */
954 if (function->fn_rettype == VOIDOID)
955 add_dummy_return(function);
956
957 /*
958 * Complete the function's info
959 */
960 function->fn_nargs = 0;
961
962 plpgsql_finish_datums(function);
963
964 /*
965 * Pop the error context stack
966 */
967 error_context_stack = plerrcontext.previous;
968 plpgsql_error_funcname = NULL;
969
970 plpgsql_check_syntax = false;
971
972 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
973 plpgsql_compile_tmp_cxt = NULL;
974 return function;
975 }
976
977
978 /*
979 * error context callback to let us supply a call-stack traceback.
980 * If we are validating or executing an anonymous code block, the function
981 * source text is passed as an argument.
982 */
983 static void
plpgsql_compile_error_callback(void * arg)984 plpgsql_compile_error_callback(void *arg)
985 {
986 if (arg)
987 {
988 /*
989 * Try to convert syntax error position to reference text of original
990 * CREATE FUNCTION or DO command.
991 */
992 if (function_parse_error_transpose((const char *) arg))
993 return;
994
995 /*
996 * Done if a syntax error position was reported; otherwise we have to
997 * fall back to a "near line N" report.
998 */
999 }
1000
1001 if (plpgsql_error_funcname)
1002 errcontext("compilation of PL/pgSQL function \"%s\" near line %d",
1003 plpgsql_error_funcname, plpgsql_latest_lineno());
1004 }
1005
1006
1007 /*
1008 * Add a name for a function parameter to the function's namespace
1009 */
1010 static void
add_parameter_name(PLpgSQL_nsitem_type itemtype,int itemno,const char * name)1011 add_parameter_name(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
1012 {
1013 /*
1014 * Before adding the name, check for duplicates. We need this even though
1015 * functioncmds.c has a similar check, because that code explicitly
1016 * doesn't complain about conflicting IN and OUT parameter names. In
1017 * plpgsql, such names are in the same namespace, so there is no way to
1018 * disambiguate.
1019 */
1020 if (plpgsql_ns_lookup(plpgsql_ns_top(), true,
1021 name, NULL, NULL,
1022 NULL) != NULL)
1023 ereport(ERROR,
1024 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1025 errmsg("parameter name \"%s\" used more than once",
1026 name)));
1027
1028 /* OK, add the name */
1029 plpgsql_ns_additem(itemtype, itemno, name);
1030 }
1031
1032 /*
1033 * Add a dummy RETURN statement to the given function's body
1034 */
1035 static void
add_dummy_return(PLpgSQL_function * function)1036 add_dummy_return(PLpgSQL_function *function)
1037 {
1038 /*
1039 * If the outer block has an EXCEPTION clause, we need to make a new outer
1040 * block, since the added RETURN shouldn't act like it is inside the
1041 * EXCEPTION clause. Likewise, if it has a label, wrap it in a new outer
1042 * block so that EXIT doesn't skip the RETURN.
1043 */
1044 if (function->action->exceptions != NULL ||
1045 function->action->label != NULL)
1046 {
1047 PLpgSQL_stmt_block *new;
1048
1049 new = palloc0(sizeof(PLpgSQL_stmt_block));
1050 new->cmd_type = PLPGSQL_STMT_BLOCK;
1051 new->stmtid = ++function->nstatements;
1052 new->body = list_make1(function->action);
1053
1054 function->action = new;
1055 }
1056 if (function->action->body == NIL ||
1057 ((PLpgSQL_stmt *) llast(function->action->body))->cmd_type != PLPGSQL_STMT_RETURN)
1058 {
1059 PLpgSQL_stmt_return *new;
1060
1061 new = palloc0(sizeof(PLpgSQL_stmt_return));
1062 new->cmd_type = PLPGSQL_STMT_RETURN;
1063 new->stmtid = ++function->nstatements;
1064 new->expr = NULL;
1065 new->retvarno = function->out_param_varno;
1066
1067 function->action->body = lappend(function->action->body, new);
1068 }
1069 }
1070
1071
1072 /*
1073 * plpgsql_parser_setup set up parser hooks for dynamic parameters
1074 *
1075 * Note: this routine, and the hook functions it prepares for, are logically
1076 * part of plpgsql parsing. But they actually run during function execution,
1077 * when we are ready to evaluate a SQL query or expression that has not
1078 * previously been parsed and planned.
1079 */
1080 void
plpgsql_parser_setup(struct ParseState * pstate,PLpgSQL_expr * expr)1081 plpgsql_parser_setup(struct ParseState *pstate, PLpgSQL_expr *expr)
1082 {
1083 pstate->p_pre_columnref_hook = plpgsql_pre_column_ref;
1084 pstate->p_post_columnref_hook = plpgsql_post_column_ref;
1085 pstate->p_paramref_hook = plpgsql_param_ref;
1086 /* no need to use p_coerce_param_hook */
1087 pstate->p_ref_hook_state = (void *) expr;
1088 }
1089
1090 /*
1091 * plpgsql_pre_column_ref parser callback before parsing a ColumnRef
1092 */
1093 static Node *
plpgsql_pre_column_ref(ParseState * pstate,ColumnRef * cref)1094 plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
1095 {
1096 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1097
1098 if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
1099 return resolve_column_ref(pstate, expr, cref, false);
1100 else
1101 return NULL;
1102 }
1103
1104 /*
1105 * plpgsql_post_column_ref parser callback after parsing a ColumnRef
1106 */
1107 static Node *
plpgsql_post_column_ref(ParseState * pstate,ColumnRef * cref,Node * var)1108 plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
1109 {
1110 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1111 Node *myvar;
1112
1113 if (expr->func->resolve_option == PLPGSQL_RESOLVE_VARIABLE)
1114 return NULL; /* we already found there's no match */
1115
1116 if (expr->func->resolve_option == PLPGSQL_RESOLVE_COLUMN && var != NULL)
1117 return NULL; /* there's a table column, prefer that */
1118
1119 /*
1120 * If we find a record/row variable but can't match a field name, throw
1121 * error if there was no core resolution for the ColumnRef either. In
1122 * that situation, the reference is inevitably going to fail, and
1123 * complaining about the record/row variable is likely to be more on-point
1124 * than the core parser's error message. (It's too bad we don't have
1125 * access to transformColumnRef's internal crerr state here, as in case of
1126 * a conflict with a table name this could still be less than the most
1127 * helpful error message possible.)
1128 */
1129 myvar = resolve_column_ref(pstate, expr, cref, (var == NULL));
1130
1131 if (myvar != NULL && var != NULL)
1132 {
1133 /*
1134 * We could leave it to the core parser to throw this error, but we
1135 * can add a more useful detail message than the core could.
1136 */
1137 ereport(ERROR,
1138 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
1139 errmsg("column reference \"%s\" is ambiguous",
1140 NameListToString(cref->fields)),
1141 errdetail("It could refer to either a PL/pgSQL variable or a table column."),
1142 parser_errposition(pstate, cref->location)));
1143 }
1144
1145 return myvar;
1146 }
1147
1148 /*
1149 * plpgsql_param_ref parser callback for ParamRefs ($n symbols)
1150 */
1151 static Node *
plpgsql_param_ref(ParseState * pstate,ParamRef * pref)1152 plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
1153 {
1154 PLpgSQL_expr *expr = (PLpgSQL_expr *) pstate->p_ref_hook_state;
1155 char pname[32];
1156 PLpgSQL_nsitem *nse;
1157
1158 snprintf(pname, sizeof(pname), "$%d", pref->number);
1159
1160 nse = plpgsql_ns_lookup(expr->ns, false,
1161 pname, NULL, NULL,
1162 NULL);
1163
1164 if (nse == NULL)
1165 return NULL; /* name not known to plpgsql */
1166
1167 return make_datum_param(expr, nse->itemno, pref->location);
1168 }
1169
1170 /*
1171 * resolve_column_ref attempt to resolve a ColumnRef as a plpgsql var
1172 *
1173 * Returns the translated node structure, or NULL if name not found
1174 *
1175 * error_if_no_field tells whether to throw error or quietly return NULL if
1176 * we are able to match a record/row name but don't find a field name match.
1177 */
1178 static Node *
resolve_column_ref(ParseState * pstate,PLpgSQL_expr * expr,ColumnRef * cref,bool error_if_no_field)1179 resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
1180 ColumnRef *cref, bool error_if_no_field)
1181 {
1182 PLpgSQL_execstate *estate;
1183 PLpgSQL_nsitem *nse;
1184 const char *name1;
1185 const char *name2 = NULL;
1186 const char *name3 = NULL;
1187 const char *colname = NULL;
1188 int nnames;
1189 int nnames_scalar = 0;
1190 int nnames_wholerow = 0;
1191 int nnames_field = 0;
1192
1193 /*
1194 * We use the function's current estate to resolve parameter data types.
1195 * This is really pretty bogus because there is no provision for updating
1196 * plans when those types change ...
1197 */
1198 estate = expr->func->cur_estate;
1199
1200 /*----------
1201 * The allowed syntaxes are:
1202 *
1203 * A Scalar variable reference, or whole-row record reference.
1204 * A.B Qualified scalar or whole-row reference, or field reference.
1205 * A.B.C Qualified record field reference.
1206 * A.* Whole-row record reference.
1207 * A.B.* Qualified whole-row record reference.
1208 *----------
1209 */
1210 switch (list_length(cref->fields))
1211 {
1212 case 1:
1213 {
1214 Node *field1 = (Node *) linitial(cref->fields);
1215
1216 Assert(IsA(field1, String));
1217 name1 = strVal(field1);
1218 nnames_scalar = 1;
1219 nnames_wholerow = 1;
1220 break;
1221 }
1222 case 2:
1223 {
1224 Node *field1 = (Node *) linitial(cref->fields);
1225 Node *field2 = (Node *) lsecond(cref->fields);
1226
1227 Assert(IsA(field1, String));
1228 name1 = strVal(field1);
1229
1230 /* Whole-row reference? */
1231 if (IsA(field2, A_Star))
1232 {
1233 /* Set name2 to prevent matches to scalar variables */
1234 name2 = "*";
1235 nnames_wholerow = 1;
1236 break;
1237 }
1238
1239 Assert(IsA(field2, String));
1240 name2 = strVal(field2);
1241 colname = name2;
1242 nnames_scalar = 2;
1243 nnames_wholerow = 2;
1244 nnames_field = 1;
1245 break;
1246 }
1247 case 3:
1248 {
1249 Node *field1 = (Node *) linitial(cref->fields);
1250 Node *field2 = (Node *) lsecond(cref->fields);
1251 Node *field3 = (Node *) lthird(cref->fields);
1252
1253 Assert(IsA(field1, String));
1254 name1 = strVal(field1);
1255 Assert(IsA(field2, String));
1256 name2 = strVal(field2);
1257
1258 /* Whole-row reference? */
1259 if (IsA(field3, A_Star))
1260 {
1261 /* Set name3 to prevent matches to scalar variables */
1262 name3 = "*";
1263 nnames_wholerow = 2;
1264 break;
1265 }
1266
1267 Assert(IsA(field3, String));
1268 name3 = strVal(field3);
1269 colname = name3;
1270 nnames_field = 2;
1271 break;
1272 }
1273 default:
1274 /* too many names, ignore */
1275 return NULL;
1276 }
1277
1278 nse = plpgsql_ns_lookup(expr->ns, false,
1279 name1, name2, name3,
1280 &nnames);
1281
1282 if (nse == NULL)
1283 return NULL; /* name not known to plpgsql */
1284
1285 switch (nse->itemtype)
1286 {
1287 case PLPGSQL_NSTYPE_VAR:
1288 if (nnames == nnames_scalar)
1289 return make_datum_param(expr, nse->itemno, cref->location);
1290 break;
1291 case PLPGSQL_NSTYPE_REC:
1292 if (nnames == nnames_wholerow)
1293 return make_datum_param(expr, nse->itemno, cref->location);
1294 if (nnames == nnames_field)
1295 {
1296 /* colname could be a field in this record */
1297 PLpgSQL_rec *rec = (PLpgSQL_rec *) estate->datums[nse->itemno];
1298 int i;
1299
1300 /* search for a datum referencing this field */
1301 i = rec->firstfield;
1302 while (i >= 0)
1303 {
1304 PLpgSQL_recfield *fld = (PLpgSQL_recfield *) estate->datums[i];
1305
1306 Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
1307 fld->recparentno == nse->itemno);
1308 if (strcmp(fld->fieldname, colname) == 0)
1309 {
1310 return make_datum_param(expr, i, cref->location);
1311 }
1312 i = fld->nextfield;
1313 }
1314
1315 /*
1316 * We should not get here, because a RECFIELD datum should
1317 * have been built at parse time for every possible qualified
1318 * reference to fields of this record. But if we do, handle
1319 * it like field-not-found: throw error or return NULL.
1320 */
1321 if (error_if_no_field)
1322 ereport(ERROR,
1323 (errcode(ERRCODE_UNDEFINED_COLUMN),
1324 errmsg("record \"%s\" has no field \"%s\"",
1325 (nnames_field == 1) ? name1 : name2,
1326 colname),
1327 parser_errposition(pstate, cref->location)));
1328 }
1329 break;
1330 default:
1331 elog(ERROR, "unrecognized plpgsql itemtype: %d", nse->itemtype);
1332 }
1333
1334 /* Name format doesn't match the plpgsql variable type */
1335 return NULL;
1336 }
1337
1338 /*
1339 * Helper for columnref parsing: build a Param referencing a plpgsql datum,
1340 * and make sure that that datum is listed in the expression's paramnos.
1341 */
1342 static Node *
make_datum_param(PLpgSQL_expr * expr,int dno,int location)1343 make_datum_param(PLpgSQL_expr *expr, int dno, int location)
1344 {
1345 PLpgSQL_execstate *estate;
1346 PLpgSQL_datum *datum;
1347 Param *param;
1348 MemoryContext oldcontext;
1349
1350 /* see comment in resolve_column_ref */
1351 estate = expr->func->cur_estate;
1352 Assert(dno >= 0 && dno < estate->ndatums);
1353 datum = estate->datums[dno];
1354
1355 /*
1356 * Bitmapset must be allocated in function's permanent memory context
1357 */
1358 oldcontext = MemoryContextSwitchTo(expr->func->fn_cxt);
1359 expr->paramnos = bms_add_member(expr->paramnos, dno);
1360 MemoryContextSwitchTo(oldcontext);
1361
1362 param = makeNode(Param);
1363 param->paramkind = PARAM_EXTERN;
1364 param->paramid = dno + 1;
1365 plpgsql_exec_get_datum_type_info(estate,
1366 datum,
1367 ¶m->paramtype,
1368 ¶m->paramtypmod,
1369 ¶m->paramcollid);
1370 param->location = location;
1371
1372 return (Node *) param;
1373 }
1374
1375
1376 /* ----------
1377 * plpgsql_parse_word The scanner calls this to postparse
1378 * any single word that is not a reserved keyword.
1379 *
1380 * word1 is the downcased/dequoted identifier; it must be palloc'd in the
1381 * function's long-term memory context.
1382 *
1383 * yytxt is the original token text; we need this to check for quoting,
1384 * so that later checks for unreserved keywords work properly.
1385 *
1386 * We attempt to recognize the token as a variable only if lookup is true
1387 * and the plpgsql_IdentifierLookup context permits it.
1388 *
1389 * If recognized as a variable, fill in *wdatum and return true;
1390 * if not recognized, fill in *word and return false.
1391 * (Note: those two pointers actually point to members of the same union,
1392 * but for notational reasons we pass them separately.)
1393 * ----------
1394 */
1395 bool
plpgsql_parse_word(char * word1,const char * yytxt,bool lookup,PLwdatum * wdatum,PLword * word)1396 plpgsql_parse_word(char *word1, const char *yytxt, bool lookup,
1397 PLwdatum *wdatum, PLword *word)
1398 {
1399 PLpgSQL_nsitem *ns;
1400
1401 /*
1402 * We should not lookup variables in DECLARE sections. In SQL
1403 * expressions, there's no need to do so either --- lookup will happen
1404 * when the expression is compiled.
1405 */
1406 if (lookup && plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
1407 {
1408 /*
1409 * Do a lookup in the current namespace stack
1410 */
1411 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1412 word1, NULL, NULL,
1413 NULL);
1414
1415 if (ns != NULL)
1416 {
1417 switch (ns->itemtype)
1418 {
1419 case PLPGSQL_NSTYPE_VAR:
1420 case PLPGSQL_NSTYPE_REC:
1421 wdatum->datum = plpgsql_Datums[ns->itemno];
1422 wdatum->ident = word1;
1423 wdatum->quoted = (yytxt[0] == '"');
1424 wdatum->idents = NIL;
1425 return true;
1426
1427 default:
1428 /* plpgsql_ns_lookup should never return anything else */
1429 elog(ERROR, "unrecognized plpgsql itemtype: %d",
1430 ns->itemtype);
1431 }
1432 }
1433 }
1434
1435 /*
1436 * Nothing found - up to now it's a word without any special meaning for
1437 * us.
1438 */
1439 word->ident = word1;
1440 word->quoted = (yytxt[0] == '"');
1441 return false;
1442 }
1443
1444
1445 /* ----------
1446 * plpgsql_parse_dblword Same lookup for two words
1447 * separated by a dot.
1448 * ----------
1449 */
1450 bool
plpgsql_parse_dblword(char * word1,char * word2,PLwdatum * wdatum,PLcword * cword)1451 plpgsql_parse_dblword(char *word1, char *word2,
1452 PLwdatum *wdatum, PLcword *cword)
1453 {
1454 PLpgSQL_nsitem *ns;
1455 List *idents;
1456 int nnames;
1457
1458 idents = list_make2(makeString(word1),
1459 makeString(word2));
1460
1461 /*
1462 * We should do nothing in DECLARE sections. In SQL expressions, we
1463 * really only need to make sure that RECFIELD datums are created when
1464 * needed. In all the cases handled by this function, returning a T_DATUM
1465 * with a two-word idents string is the right thing.
1466 */
1467 if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
1468 {
1469 /*
1470 * Do a lookup in the current namespace stack
1471 */
1472 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1473 word1, word2, NULL,
1474 &nnames);
1475 if (ns != NULL)
1476 {
1477 switch (ns->itemtype)
1478 {
1479 case PLPGSQL_NSTYPE_VAR:
1480 /* Block-qualified reference to scalar variable. */
1481 wdatum->datum = plpgsql_Datums[ns->itemno];
1482 wdatum->ident = NULL;
1483 wdatum->quoted = false; /* not used */
1484 wdatum->idents = idents;
1485 return true;
1486
1487 case PLPGSQL_NSTYPE_REC:
1488 if (nnames == 1)
1489 {
1490 /*
1491 * First word is a record name, so second word could
1492 * be a field in this record. We build a RECFIELD
1493 * datum whether it is or not --- any error will be
1494 * detected later.
1495 */
1496 PLpgSQL_rec *rec;
1497 PLpgSQL_recfield *new;
1498
1499 rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1500 new = plpgsql_build_recfield(rec, word2);
1501
1502 wdatum->datum = (PLpgSQL_datum *) new;
1503 }
1504 else
1505 {
1506 /* Block-qualified reference to record variable. */
1507 wdatum->datum = plpgsql_Datums[ns->itemno];
1508 }
1509 wdatum->ident = NULL;
1510 wdatum->quoted = false; /* not used */
1511 wdatum->idents = idents;
1512 return true;
1513
1514 default:
1515 break;
1516 }
1517 }
1518 }
1519
1520 /* Nothing found */
1521 cword->idents = idents;
1522 return false;
1523 }
1524
1525
1526 /* ----------
1527 * plpgsql_parse_tripword Same lookup for three words
1528 * separated by dots.
1529 * ----------
1530 */
1531 bool
plpgsql_parse_tripword(char * word1,char * word2,char * word3,PLwdatum * wdatum,PLcword * cword)1532 plpgsql_parse_tripword(char *word1, char *word2, char *word3,
1533 PLwdatum *wdatum, PLcword *cword)
1534 {
1535 PLpgSQL_nsitem *ns;
1536 List *idents;
1537 int nnames;
1538
1539 /*
1540 * We should do nothing in DECLARE sections. In SQL expressions, we need
1541 * to make sure that RECFIELD datums are created when needed, and we need
1542 * to be careful about how many names are reported as belonging to the
1543 * T_DATUM: the third word could be a sub-field reference, which we don't
1544 * care about here.
1545 */
1546 if (plpgsql_IdentifierLookup != IDENTIFIER_LOOKUP_DECLARE)
1547 {
1548 /*
1549 * Do a lookup in the current namespace stack. Must find a record
1550 * reference, else ignore.
1551 */
1552 ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1553 word1, word2, word3,
1554 &nnames);
1555 if (ns != NULL)
1556 {
1557 switch (ns->itemtype)
1558 {
1559 case PLPGSQL_NSTYPE_REC:
1560 {
1561 PLpgSQL_rec *rec;
1562 PLpgSQL_recfield *new;
1563
1564 rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1565 if (nnames == 1)
1566 {
1567 /*
1568 * First word is a record name, so second word
1569 * could be a field in this record (and the third,
1570 * a sub-field). We build a RECFIELD datum
1571 * whether it is or not --- any error will be
1572 * detected later.
1573 */
1574 new = plpgsql_build_recfield(rec, word2);
1575 idents = list_make2(makeString(word1),
1576 makeString(word2));
1577 }
1578 else
1579 {
1580 /* Block-qualified reference to record variable. */
1581 new = plpgsql_build_recfield(rec, word3);
1582 idents = list_make3(makeString(word1),
1583 makeString(word2),
1584 makeString(word3));
1585 }
1586 wdatum->datum = (PLpgSQL_datum *) new;
1587 wdatum->ident = NULL;
1588 wdatum->quoted = false; /* not used */
1589 wdatum->idents = idents;
1590 return true;
1591 }
1592
1593 default:
1594 break;
1595 }
1596 }
1597 }
1598
1599 /* Nothing found */
1600 idents = list_make3(makeString(word1),
1601 makeString(word2),
1602 makeString(word3));
1603 cword->idents = idents;
1604 return false;
1605 }
1606
1607
1608 /* ----------
1609 * plpgsql_parse_wordtype The scanner found word%TYPE. word can be
1610 * a variable name or a basetype.
1611 *
1612 * Returns datatype struct, or NULL if no match found for word.
1613 * ----------
1614 */
1615 PLpgSQL_type *
plpgsql_parse_wordtype(char * ident)1616 plpgsql_parse_wordtype(char *ident)
1617 {
1618 PLpgSQL_type *dtype;
1619 PLpgSQL_nsitem *nse;
1620 TypeName *typeName;
1621 HeapTuple typeTup;
1622
1623 /*
1624 * Do a lookup in the current namespace stack
1625 */
1626 nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1627 ident, NULL, NULL,
1628 NULL);
1629
1630 if (nse != NULL)
1631 {
1632 switch (nse->itemtype)
1633 {
1634 case PLPGSQL_NSTYPE_VAR:
1635 return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1636
1637 /* XXX perhaps allow REC/ROW here? */
1638
1639 default:
1640 return NULL;
1641 }
1642 }
1643
1644 /*
1645 * Word wasn't found in the namespace stack. Try to find a data type with
1646 * that name, but ignore shell types and complex types.
1647 */
1648 typeName = makeTypeName(ident);
1649 typeTup = LookupTypeName(NULL, typeName, NULL, false);
1650 if (typeTup)
1651 {
1652 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1653
1654 if (!typeStruct->typisdefined ||
1655 typeStruct->typrelid != InvalidOid)
1656 {
1657 ReleaseSysCache(typeTup);
1658 return NULL;
1659 }
1660
1661 dtype = build_datatype(typeTup, -1,
1662 plpgsql_curr_compile->fn_input_collation,
1663 typeName);
1664
1665 ReleaseSysCache(typeTup);
1666 return dtype;
1667 }
1668
1669 /*
1670 * Nothing found - up to now it's a word without any special meaning for
1671 * us.
1672 */
1673 return NULL;
1674 }
1675
1676
1677 /* ----------
1678 * plpgsql_parse_cwordtype Same lookup for compositeword%TYPE
1679 * ----------
1680 */
1681 PLpgSQL_type *
plpgsql_parse_cwordtype(List * idents)1682 plpgsql_parse_cwordtype(List *idents)
1683 {
1684 PLpgSQL_type *dtype = NULL;
1685 PLpgSQL_nsitem *nse;
1686 const char *fldname;
1687 Oid classOid;
1688 HeapTuple classtup = NULL;
1689 HeapTuple attrtup = NULL;
1690 HeapTuple typetup = NULL;
1691 Form_pg_class classStruct;
1692 Form_pg_attribute attrStruct;
1693 MemoryContext oldCxt;
1694
1695 /* Avoid memory leaks in the long-term function context */
1696 oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1697
1698 if (list_length(idents) == 2)
1699 {
1700 /*
1701 * Do a lookup in the current namespace stack. We don't need to check
1702 * number of names matched, because we will only consider scalar
1703 * variables.
1704 */
1705 nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1706 strVal(linitial(idents)),
1707 strVal(lsecond(idents)),
1708 NULL,
1709 NULL);
1710
1711 if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1712 {
1713 dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1714 goto done;
1715 }
1716
1717 /*
1718 * First word could also be a table name
1719 */
1720 classOid = RelnameGetRelid(strVal(linitial(idents)));
1721 if (!OidIsValid(classOid))
1722 goto done;
1723 fldname = strVal(lsecond(idents));
1724 }
1725 else if (list_length(idents) == 3)
1726 {
1727 RangeVar *relvar;
1728
1729 relvar = makeRangeVar(strVal(linitial(idents)),
1730 strVal(lsecond(idents)),
1731 -1);
1732 /* Can't lock relation - we might not have privileges. */
1733 classOid = RangeVarGetRelid(relvar, NoLock, true);
1734 if (!OidIsValid(classOid))
1735 goto done;
1736 fldname = strVal(lthird(idents));
1737 }
1738 else
1739 goto done;
1740
1741 classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(classOid));
1742 if (!HeapTupleIsValid(classtup))
1743 goto done;
1744 classStruct = (Form_pg_class) GETSTRUCT(classtup);
1745
1746 /*
1747 * It must be a relation, sequence, view, materialized view, composite
1748 * type, or foreign table
1749 */
1750 if (classStruct->relkind != RELKIND_RELATION &&
1751 classStruct->relkind != RELKIND_SEQUENCE &&
1752 classStruct->relkind != RELKIND_VIEW &&
1753 classStruct->relkind != RELKIND_MATVIEW &&
1754 classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
1755 classStruct->relkind != RELKIND_FOREIGN_TABLE &&
1756 classStruct->relkind != RELKIND_PARTITIONED_TABLE)
1757 goto done;
1758
1759 /*
1760 * Fetch the named table field and its type
1761 */
1762 attrtup = SearchSysCacheAttName(classOid, fldname);
1763 if (!HeapTupleIsValid(attrtup))
1764 goto done;
1765 attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1766
1767 typetup = SearchSysCache1(TYPEOID,
1768 ObjectIdGetDatum(attrStruct->atttypid));
1769 if (!HeapTupleIsValid(typetup))
1770 elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1771
1772 /*
1773 * Found that - build a compiler type struct in the caller's cxt and
1774 * return it. Note that we treat the type as being found-by-OID; no
1775 * attempt to re-look-up the type name will happen during invalidations.
1776 */
1777 MemoryContextSwitchTo(oldCxt);
1778 dtype = build_datatype(typetup,
1779 attrStruct->atttypmod,
1780 attrStruct->attcollation,
1781 NULL);
1782 MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1783
1784 done:
1785 if (HeapTupleIsValid(classtup))
1786 ReleaseSysCache(classtup);
1787 if (HeapTupleIsValid(attrtup))
1788 ReleaseSysCache(attrtup);
1789 if (HeapTupleIsValid(typetup))
1790 ReleaseSysCache(typetup);
1791
1792 MemoryContextSwitchTo(oldCxt);
1793 return dtype;
1794 }
1795
1796 /* ----------
1797 * plpgsql_parse_wordrowtype Scanner found word%ROWTYPE.
1798 * So word must be a table name.
1799 * ----------
1800 */
1801 PLpgSQL_type *
plpgsql_parse_wordrowtype(char * ident)1802 plpgsql_parse_wordrowtype(char *ident)
1803 {
1804 Oid classOid;
1805 Oid typOid;
1806
1807 /*
1808 * Look up the relation. Note that because relation rowtypes have the
1809 * same names as their relations, this could be handled as a type lookup
1810 * equally well; we use the relation lookup code path only because the
1811 * errors thrown here have traditionally referred to relations not types.
1812 * But we'll make a TypeName in case we have to do re-look-up of the type.
1813 */
1814 classOid = RelnameGetRelid(ident);
1815 if (!OidIsValid(classOid))
1816 ereport(ERROR,
1817 (errcode(ERRCODE_UNDEFINED_TABLE),
1818 errmsg("relation \"%s\" does not exist", ident)));
1819
1820 /* Some relkinds lack type OIDs */
1821 typOid = get_rel_type_id(classOid);
1822 if (!OidIsValid(typOid))
1823 ereport(ERROR,
1824 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1825 errmsg("relation \"%s\" does not have a composite type",
1826 ident)));
1827
1828 /* Build and return the row type struct */
1829 return plpgsql_build_datatype(typOid, -1, InvalidOid,
1830 makeTypeName(ident));
1831 }
1832
1833 /* ----------
1834 * plpgsql_parse_cwordrowtype Scanner found compositeword%ROWTYPE.
1835 * So word must be a namespace qualified table name.
1836 * ----------
1837 */
1838 PLpgSQL_type *
plpgsql_parse_cwordrowtype(List * idents)1839 plpgsql_parse_cwordrowtype(List *idents)
1840 {
1841 Oid classOid;
1842 Oid typOid;
1843 RangeVar *relvar;
1844 MemoryContext oldCxt;
1845
1846 /*
1847 * As above, this is a relation lookup but could be a type lookup if we
1848 * weren't being backwards-compatible about error wording.
1849 */
1850 if (list_length(idents) != 2)
1851 return NULL;
1852
1853 /* Avoid memory leaks in long-term function context */
1854 oldCxt = MemoryContextSwitchTo(plpgsql_compile_tmp_cxt);
1855
1856 /* Look up relation name. Can't lock it - we might not have privileges. */
1857 relvar = makeRangeVar(strVal(linitial(idents)),
1858 strVal(lsecond(idents)),
1859 -1);
1860 classOid = RangeVarGetRelid(relvar, NoLock, false);
1861
1862 /* Some relkinds lack type OIDs */
1863 typOid = get_rel_type_id(classOid);
1864 if (!OidIsValid(typOid))
1865 ereport(ERROR,
1866 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1867 errmsg("relation \"%s\" does not have a composite type",
1868 strVal(lsecond(idents)))));
1869
1870 MemoryContextSwitchTo(oldCxt);
1871
1872 /* Build and return the row type struct */
1873 return plpgsql_build_datatype(typOid, -1, InvalidOid,
1874 makeTypeNameFromNameList(idents));
1875 }
1876
1877 /*
1878 * plpgsql_build_variable - build a datum-array entry of a given
1879 * datatype
1880 *
1881 * The returned struct may be a PLpgSQL_var or PLpgSQL_rec
1882 * depending on the given datatype, and is allocated via
1883 * palloc. The struct is automatically added to the current datum
1884 * array, and optionally to the current namespace.
1885 */
1886 PLpgSQL_variable *
plpgsql_build_variable(const char * refname,int lineno,PLpgSQL_type * dtype,bool add2namespace)1887 plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,
1888 bool add2namespace)
1889 {
1890 PLpgSQL_variable *result;
1891
1892 switch (dtype->ttype)
1893 {
1894 case PLPGSQL_TTYPE_SCALAR:
1895 {
1896 /* Ordinary scalar datatype */
1897 PLpgSQL_var *var;
1898
1899 var = palloc0(sizeof(PLpgSQL_var));
1900 var->dtype = PLPGSQL_DTYPE_VAR;
1901 var->refname = pstrdup(refname);
1902 var->lineno = lineno;
1903 var->datatype = dtype;
1904 /* other fields are left as 0, might be changed by caller */
1905
1906 /* preset to NULL */
1907 var->value = 0;
1908 var->isnull = true;
1909 var->freeval = false;
1910
1911 plpgsql_adddatum((PLpgSQL_datum *) var);
1912 if (add2namespace)
1913 plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
1914 var->dno,
1915 refname);
1916 result = (PLpgSQL_variable *) var;
1917 break;
1918 }
1919 case PLPGSQL_TTYPE_REC:
1920 {
1921 /* Composite type -- build a record variable */
1922 PLpgSQL_rec *rec;
1923
1924 rec = plpgsql_build_record(refname, lineno,
1925 dtype, dtype->typoid,
1926 add2namespace);
1927 result = (PLpgSQL_variable *) rec;
1928 break;
1929 }
1930 case PLPGSQL_TTYPE_PSEUDO:
1931 ereport(ERROR,
1932 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1933 errmsg("variable \"%s\" has pseudo-type %s",
1934 refname, format_type_be(dtype->typoid))));
1935 result = NULL; /* keep compiler quiet */
1936 break;
1937 default:
1938 elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1939 result = NULL; /* keep compiler quiet */
1940 break;
1941 }
1942
1943 return result;
1944 }
1945
1946 /*
1947 * Build empty named record variable, and optionally add it to namespace
1948 */
1949 PLpgSQL_rec *
plpgsql_build_record(const char * refname,int lineno,PLpgSQL_type * dtype,Oid rectypeid,bool add2namespace)1950 plpgsql_build_record(const char *refname, int lineno,
1951 PLpgSQL_type *dtype, Oid rectypeid,
1952 bool add2namespace)
1953 {
1954 PLpgSQL_rec *rec;
1955
1956 rec = palloc0(sizeof(PLpgSQL_rec));
1957 rec->dtype = PLPGSQL_DTYPE_REC;
1958 rec->refname = pstrdup(refname);
1959 rec->lineno = lineno;
1960 /* other fields are left as 0, might be changed by caller */
1961 rec->datatype = dtype;
1962 rec->rectypeid = rectypeid;
1963 rec->firstfield = -1;
1964 rec->erh = NULL;
1965 plpgsql_adddatum((PLpgSQL_datum *) rec);
1966 if (add2namespace)
1967 plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->dno, rec->refname);
1968
1969 return rec;
1970 }
1971
1972 /*
1973 * Build a row-variable data structure given the component variables.
1974 * Include a rowtupdesc, since we will need to materialize the row result.
1975 */
1976 static PLpgSQL_row *
build_row_from_vars(PLpgSQL_variable ** vars,int numvars)1977 build_row_from_vars(PLpgSQL_variable **vars, int numvars)
1978 {
1979 PLpgSQL_row *row;
1980 int i;
1981
1982 row = palloc0(sizeof(PLpgSQL_row));
1983 row->dtype = PLPGSQL_DTYPE_ROW;
1984 row->refname = "(unnamed row)";
1985 row->lineno = -1;
1986 row->rowtupdesc = CreateTemplateTupleDesc(numvars);
1987 row->nfields = numvars;
1988 row->fieldnames = palloc(numvars * sizeof(char *));
1989 row->varnos = palloc(numvars * sizeof(int));
1990
1991 for (i = 0; i < numvars; i++)
1992 {
1993 PLpgSQL_variable *var = vars[i];
1994 Oid typoid;
1995 int32 typmod;
1996 Oid typcoll;
1997
1998 /* Member vars of a row should never be const */
1999 Assert(!var->isconst);
2000
2001 switch (var->dtype)
2002 {
2003 case PLPGSQL_DTYPE_VAR:
2004 case PLPGSQL_DTYPE_PROMISE:
2005 typoid = ((PLpgSQL_var *) var)->datatype->typoid;
2006 typmod = ((PLpgSQL_var *) var)->datatype->atttypmod;
2007 typcoll = ((PLpgSQL_var *) var)->datatype->collation;
2008 break;
2009
2010 case PLPGSQL_DTYPE_REC:
2011 /* shouldn't need to revalidate rectypeid already... */
2012 typoid = ((PLpgSQL_rec *) var)->rectypeid;
2013 typmod = -1; /* don't know typmod, if it's used at all */
2014 typcoll = InvalidOid; /* composite types have no collation */
2015 break;
2016
2017 default:
2018 elog(ERROR, "unrecognized dtype: %d", var->dtype);
2019 typoid = InvalidOid; /* keep compiler quiet */
2020 typmod = 0;
2021 typcoll = InvalidOid;
2022 break;
2023 }
2024
2025 row->fieldnames[i] = var->refname;
2026 row->varnos[i] = var->dno;
2027
2028 TupleDescInitEntry(row->rowtupdesc, i + 1,
2029 var->refname,
2030 typoid, typmod,
2031 0);
2032 TupleDescInitEntryCollation(row->rowtupdesc, i + 1, typcoll);
2033 }
2034
2035 return row;
2036 }
2037
2038 /*
2039 * Build a RECFIELD datum for the named field of the specified record variable
2040 *
2041 * If there's already such a datum, just return it; we don't need duplicates.
2042 */
2043 PLpgSQL_recfield *
plpgsql_build_recfield(PLpgSQL_rec * rec,const char * fldname)2044 plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
2045 {
2046 PLpgSQL_recfield *recfield;
2047 int i;
2048
2049 /* search for an existing datum referencing this field */
2050 i = rec->firstfield;
2051 while (i >= 0)
2052 {
2053 PLpgSQL_recfield *fld = (PLpgSQL_recfield *) plpgsql_Datums[i];
2054
2055 Assert(fld->dtype == PLPGSQL_DTYPE_RECFIELD &&
2056 fld->recparentno == rec->dno);
2057 if (strcmp(fld->fieldname, fldname) == 0)
2058 return fld;
2059 i = fld->nextfield;
2060 }
2061
2062 /* nope, so make a new one */
2063 recfield = palloc0(sizeof(PLpgSQL_recfield));
2064 recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2065 recfield->fieldname = pstrdup(fldname);
2066 recfield->recparentno = rec->dno;
2067 recfield->rectupledescid = INVALID_TUPLEDESC_IDENTIFIER;
2068
2069 plpgsql_adddatum((PLpgSQL_datum *) recfield);
2070
2071 /* now we can link it into the parent's chain */
2072 recfield->nextfield = rec->firstfield;
2073 rec->firstfield = recfield->dno;
2074
2075 return recfield;
2076 }
2077
2078 /*
2079 * plpgsql_build_datatype
2080 * Build PLpgSQL_type struct given type OID, typmod, collation,
2081 * and type's parsed name.
2082 *
2083 * If collation is not InvalidOid then it overrides the type's default
2084 * collation. But collation is ignored if the datatype is non-collatable.
2085 *
2086 * origtypname is the parsed form of what the user wrote as the type name.
2087 * It can be NULL if the type could not be a composite type, or if it was
2088 * identified by OID to begin with (e.g., it's a function argument type).
2089 */
2090 PLpgSQL_type *
plpgsql_build_datatype(Oid typeOid,int32 typmod,Oid collation,TypeName * origtypname)2091 plpgsql_build_datatype(Oid typeOid, int32 typmod,
2092 Oid collation, TypeName *origtypname)
2093 {
2094 HeapTuple typeTup;
2095 PLpgSQL_type *typ;
2096
2097 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2098 if (!HeapTupleIsValid(typeTup))
2099 elog(ERROR, "cache lookup failed for type %u", typeOid);
2100
2101 typ = build_datatype(typeTup, typmod, collation, origtypname);
2102
2103 ReleaseSysCache(typeTup);
2104
2105 return typ;
2106 }
2107
2108 /*
2109 * Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
2110 * and additional details (see comments for plpgsql_build_datatype).
2111 */
2112 static PLpgSQL_type *
build_datatype(HeapTuple typeTup,int32 typmod,Oid collation,TypeName * origtypname)2113 build_datatype(HeapTuple typeTup, int32 typmod,
2114 Oid collation, TypeName *origtypname)
2115 {
2116 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
2117 PLpgSQL_type *typ;
2118
2119 if (!typeStruct->typisdefined)
2120 ereport(ERROR,
2121 (errcode(ERRCODE_UNDEFINED_OBJECT),
2122 errmsg("type \"%s\" is only a shell",
2123 NameStr(typeStruct->typname))));
2124
2125 typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
2126
2127 typ->typname = pstrdup(NameStr(typeStruct->typname));
2128 typ->typoid = typeStruct->oid;
2129 switch (typeStruct->typtype)
2130 {
2131 case TYPTYPE_BASE:
2132 case TYPTYPE_ENUM:
2133 case TYPTYPE_RANGE:
2134 case TYPTYPE_MULTIRANGE:
2135 typ->ttype = PLPGSQL_TTYPE_SCALAR;
2136 break;
2137 case TYPTYPE_COMPOSITE:
2138 typ->ttype = PLPGSQL_TTYPE_REC;
2139 break;
2140 case TYPTYPE_DOMAIN:
2141 if (type_is_rowtype(typeStruct->typbasetype))
2142 typ->ttype = PLPGSQL_TTYPE_REC;
2143 else
2144 typ->ttype = PLPGSQL_TTYPE_SCALAR;
2145 break;
2146 case TYPTYPE_PSEUDO:
2147 if (typ->typoid == RECORDOID)
2148 typ->ttype = PLPGSQL_TTYPE_REC;
2149 else
2150 typ->ttype = PLPGSQL_TTYPE_PSEUDO;
2151 break;
2152 default:
2153 elog(ERROR, "unrecognized typtype: %d",
2154 (int) typeStruct->typtype);
2155 break;
2156 }
2157 typ->typlen = typeStruct->typlen;
2158 typ->typbyval = typeStruct->typbyval;
2159 typ->typtype = typeStruct->typtype;
2160 typ->collation = typeStruct->typcollation;
2161 if (OidIsValid(collation) && OidIsValid(typ->collation))
2162 typ->collation = collation;
2163 /* Detect if type is true array, or domain thereof */
2164 /* NB: this is only used to decide whether to apply expand_array */
2165 if (typeStruct->typtype == TYPTYPE_BASE)
2166 {
2167 /*
2168 * This test should include what get_element_type() checks. We also
2169 * disallow non-toastable array types (i.e. oidvector and int2vector).
2170 */
2171 typ->typisarray = (IsTrueArrayType(typeStruct) &&
2172 typeStruct->typstorage != TYPSTORAGE_PLAIN);
2173 }
2174 else if (typeStruct->typtype == TYPTYPE_DOMAIN)
2175 {
2176 /* we can short-circuit looking up base types if it's not varlena */
2177 typ->typisarray = (typeStruct->typlen == -1 &&
2178 typeStruct->typstorage != TYPSTORAGE_PLAIN &&
2179 OidIsValid(get_base_element_type(typeStruct->typbasetype)));
2180 }
2181 else
2182 typ->typisarray = false;
2183 typ->atttypmod = typmod;
2184
2185 /*
2186 * If it's a named composite type (or domain over one), find the typcache
2187 * entry and record the current tupdesc ID, so we can detect changes
2188 * (including drops). We don't currently support on-the-fly replacement
2189 * of non-composite types, else we might want to do this for them too.
2190 */
2191 if (typ->ttype == PLPGSQL_TTYPE_REC && typ->typoid != RECORDOID)
2192 {
2193 TypeCacheEntry *typentry;
2194
2195 typentry = lookup_type_cache(typ->typoid,
2196 TYPECACHE_TUPDESC |
2197 TYPECACHE_DOMAIN_BASE_INFO);
2198 if (typentry->typtype == TYPTYPE_DOMAIN)
2199 typentry = lookup_type_cache(typentry->domainBaseType,
2200 TYPECACHE_TUPDESC);
2201 if (typentry->tupDesc == NULL)
2202 ereport(ERROR,
2203 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
2204 errmsg("type %s is not composite",
2205 format_type_be(typ->typoid))));
2206
2207 typ->origtypname = origtypname;
2208 typ->tcache = typentry;
2209 typ->tupdesc_id = typentry->tupDesc_identifier;
2210 }
2211 else
2212 {
2213 typ->origtypname = NULL;
2214 typ->tcache = NULL;
2215 typ->tupdesc_id = 0;
2216 }
2217
2218 return typ;
2219 }
2220
2221 /*
2222 * plpgsql_recognize_err_condition
2223 * Check condition name and translate it to SQLSTATE.
2224 *
2225 * Note: there are some cases where the same condition name has multiple
2226 * entries in the table. We arbitrarily return the first match.
2227 */
2228 int
plpgsql_recognize_err_condition(const char * condname,bool allow_sqlstate)2229 plpgsql_recognize_err_condition(const char *condname, bool allow_sqlstate)
2230 {
2231 int i;
2232
2233 if (allow_sqlstate)
2234 {
2235 if (strlen(condname) == 5 &&
2236 strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2237 return MAKE_SQLSTATE(condname[0],
2238 condname[1],
2239 condname[2],
2240 condname[3],
2241 condname[4]);
2242 }
2243
2244 for (i = 0; exception_label_map[i].label != NULL; i++)
2245 {
2246 if (strcmp(condname, exception_label_map[i].label) == 0)
2247 return exception_label_map[i].sqlerrstate;
2248 }
2249
2250 ereport(ERROR,
2251 (errcode(ERRCODE_UNDEFINED_OBJECT),
2252 errmsg("unrecognized exception condition \"%s\"",
2253 condname)));
2254 return 0; /* keep compiler quiet */
2255 }
2256
2257 /*
2258 * plpgsql_parse_err_condition
2259 * Generate PLpgSQL_condition entry(s) for an exception condition name
2260 *
2261 * This has to be able to return a list because there are some duplicate
2262 * names in the table of error code names.
2263 */
2264 PLpgSQL_condition *
plpgsql_parse_err_condition(char * condname)2265 plpgsql_parse_err_condition(char *condname)
2266 {
2267 int i;
2268 PLpgSQL_condition *new;
2269 PLpgSQL_condition *prev;
2270
2271 /*
2272 * XXX Eventually we will want to look for user-defined exception names
2273 * here.
2274 */
2275
2276 /*
2277 * OTHERS is represented as code 0 (which would map to '00000', but we
2278 * have no need to represent that as an exception condition).
2279 */
2280 if (strcmp(condname, "others") == 0)
2281 {
2282 new = palloc(sizeof(PLpgSQL_condition));
2283 new->sqlerrstate = 0;
2284 new->condname = condname;
2285 new->next = NULL;
2286 return new;
2287 }
2288
2289 prev = NULL;
2290 for (i = 0; exception_label_map[i].label != NULL; i++)
2291 {
2292 if (strcmp(condname, exception_label_map[i].label) == 0)
2293 {
2294 new = palloc(sizeof(PLpgSQL_condition));
2295 new->sqlerrstate = exception_label_map[i].sqlerrstate;
2296 new->condname = condname;
2297 new->next = prev;
2298 prev = new;
2299 }
2300 }
2301
2302 if (!prev)
2303 ereport(ERROR,
2304 (errcode(ERRCODE_UNDEFINED_OBJECT),
2305 errmsg("unrecognized exception condition \"%s\"",
2306 condname)));
2307
2308 return prev;
2309 }
2310
2311 /* ----------
2312 * plpgsql_start_datums Initialize datum list at compile startup.
2313 * ----------
2314 */
2315 static void
plpgsql_start_datums(void)2316 plpgsql_start_datums(void)
2317 {
2318 datums_alloc = 128;
2319 plpgsql_nDatums = 0;
2320 /* This is short-lived, so needn't allocate in function's cxt */
2321 plpgsql_Datums = MemoryContextAlloc(plpgsql_compile_tmp_cxt,
2322 sizeof(PLpgSQL_datum *) * datums_alloc);
2323 /* datums_last tracks what's been seen by plpgsql_add_initdatums() */
2324 datums_last = 0;
2325 }
2326
2327 /* ----------
2328 * plpgsql_adddatum Add a variable, record or row
2329 * to the compiler's datum list.
2330 * ----------
2331 */
2332 void
plpgsql_adddatum(PLpgSQL_datum * newdatum)2333 plpgsql_adddatum(PLpgSQL_datum *newdatum)
2334 {
2335 if (plpgsql_nDatums == datums_alloc)
2336 {
2337 datums_alloc *= 2;
2338 plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
2339 }
2340
2341 newdatum->dno = plpgsql_nDatums;
2342 plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2343 }
2344
2345 /* ----------
2346 * plpgsql_finish_datums Copy completed datum info into function struct.
2347 * ----------
2348 */
2349 static void
plpgsql_finish_datums(PLpgSQL_function * function)2350 plpgsql_finish_datums(PLpgSQL_function *function)
2351 {
2352 Size copiable_size = 0;
2353 int i;
2354
2355 function->ndatums = plpgsql_nDatums;
2356 function->datums = palloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
2357 for (i = 0; i < plpgsql_nDatums; i++)
2358 {
2359 function->datums[i] = plpgsql_Datums[i];
2360
2361 /* This must agree with copy_plpgsql_datums on what is copiable */
2362 switch (function->datums[i]->dtype)
2363 {
2364 case PLPGSQL_DTYPE_VAR:
2365 case PLPGSQL_DTYPE_PROMISE:
2366 copiable_size += MAXALIGN(sizeof(PLpgSQL_var));
2367 break;
2368 case PLPGSQL_DTYPE_REC:
2369 copiable_size += MAXALIGN(sizeof(PLpgSQL_rec));
2370 break;
2371 default:
2372 break;
2373 }
2374 }
2375 function->copiable_size = copiable_size;
2376 }
2377
2378
2379 /* ----------
2380 * plpgsql_add_initdatums Make an array of the datum numbers of
2381 * all the initializable datums created since the last call
2382 * to this function.
2383 *
2384 * If varnos is NULL, we just forget any datum entries created since the
2385 * last call.
2386 *
2387 * This is used around a DECLARE section to create a list of the datums
2388 * that have to be initialized at block entry. Note that datums can also
2389 * be created elsewhere than DECLARE, eg by a FOR-loop, but it is then
2390 * the responsibility of special-purpose code to initialize them.
2391 * ----------
2392 */
2393 int
plpgsql_add_initdatums(int ** varnos)2394 plpgsql_add_initdatums(int **varnos)
2395 {
2396 int i;
2397 int n = 0;
2398
2399 /*
2400 * The set of dtypes recognized here must match what exec_stmt_block()
2401 * cares about (re)initializing at block entry.
2402 */
2403 for (i = datums_last; i < plpgsql_nDatums; i++)
2404 {
2405 switch (plpgsql_Datums[i]->dtype)
2406 {
2407 case PLPGSQL_DTYPE_VAR:
2408 case PLPGSQL_DTYPE_REC:
2409 n++;
2410 break;
2411
2412 default:
2413 break;
2414 }
2415 }
2416
2417 if (varnos != NULL)
2418 {
2419 if (n > 0)
2420 {
2421 *varnos = (int *) palloc(sizeof(int) * n);
2422
2423 n = 0;
2424 for (i = datums_last; i < plpgsql_nDatums; i++)
2425 {
2426 switch (plpgsql_Datums[i]->dtype)
2427 {
2428 case PLPGSQL_DTYPE_VAR:
2429 case PLPGSQL_DTYPE_REC:
2430 (*varnos)[n++] = plpgsql_Datums[i]->dno;
2431
2432 default:
2433 break;
2434 }
2435 }
2436 }
2437 else
2438 *varnos = NULL;
2439 }
2440
2441 datums_last = plpgsql_nDatums;
2442 return n;
2443 }
2444
2445
2446 /*
2447 * Compute the hashkey for a given function invocation
2448 *
2449 * The hashkey is returned into the caller-provided storage at *hashkey.
2450 */
2451 static void
compute_function_hashkey(FunctionCallInfo fcinfo,Form_pg_proc procStruct,PLpgSQL_func_hashkey * hashkey,bool forValidator)2452 compute_function_hashkey(FunctionCallInfo fcinfo,
2453 Form_pg_proc procStruct,
2454 PLpgSQL_func_hashkey *hashkey,
2455 bool forValidator)
2456 {
2457 /* Make sure any unused bytes of the struct are zero */
2458 MemSet(hashkey, 0, sizeof(PLpgSQL_func_hashkey));
2459
2460 /* get function OID */
2461 hashkey->funcOid = fcinfo->flinfo->fn_oid;
2462
2463 /* get call context */
2464 hashkey->isTrigger = CALLED_AS_TRIGGER(fcinfo);
2465 hashkey->isEventTrigger = CALLED_AS_EVENT_TRIGGER(fcinfo);
2466
2467 /*
2468 * If DML trigger, include trigger's OID in the hash, so that each trigger
2469 * usage gets a different hash entry, allowing for e.g. different relation
2470 * rowtypes or transition table names. In validation mode we do not know
2471 * what relation or transition table names are intended to be used, so we
2472 * leave trigOid zero; the hash entry built in this case will never be
2473 * used for any actual calls.
2474 *
2475 * We don't currently need to distinguish different event trigger usages
2476 * in the same way, since the special parameter variables don't vary in
2477 * type in that case.
2478 */
2479 if (hashkey->isTrigger && !forValidator)
2480 {
2481 TriggerData *trigdata = (TriggerData *) fcinfo->context;
2482
2483 hashkey->trigOid = trigdata->tg_trigger->tgoid;
2484 }
2485
2486 /* get input collation, if known */
2487 hashkey->inputCollation = fcinfo->fncollation;
2488
2489 if (procStruct->pronargs > 0)
2490 {
2491 /* get the argument types */
2492 memcpy(hashkey->argtypes, procStruct->proargtypes.values,
2493 procStruct->pronargs * sizeof(Oid));
2494
2495 /* resolve any polymorphic argument types */
2496 plpgsql_resolve_polymorphic_argtypes(procStruct->pronargs,
2497 hashkey->argtypes,
2498 NULL,
2499 fcinfo->flinfo->fn_expr,
2500 forValidator,
2501 NameStr(procStruct->proname));
2502 }
2503 }
2504
2505 /*
2506 * This is the same as the standard resolve_polymorphic_argtypes() function,
2507 * but with a special case for validation: assume that polymorphic arguments
2508 * are integer, integer-array or integer-range. Also, we go ahead and report
2509 * the error if we can't resolve the types.
2510 */
2511 static void
plpgsql_resolve_polymorphic_argtypes(int numargs,Oid * argtypes,char * argmodes,Node * call_expr,bool forValidator,const char * proname)2512 plpgsql_resolve_polymorphic_argtypes(int numargs,
2513 Oid *argtypes, char *argmodes,
2514 Node *call_expr, bool forValidator,
2515 const char *proname)
2516 {
2517 int i;
2518
2519 if (!forValidator)
2520 {
2521 /* normal case, pass to standard routine */
2522 if (!resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
2523 call_expr))
2524 ereport(ERROR,
2525 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2526 errmsg("could not determine actual argument "
2527 "type for polymorphic function \"%s\"",
2528 proname)));
2529 }
2530 else
2531 {
2532 /* special validation case */
2533 for (i = 0; i < numargs; i++)
2534 {
2535 switch (argtypes[i])
2536 {
2537 case ANYELEMENTOID:
2538 case ANYNONARRAYOID:
2539 case ANYENUMOID: /* XXX dubious */
2540 case ANYCOMPATIBLEOID:
2541 case ANYCOMPATIBLENONARRAYOID:
2542 argtypes[i] = INT4OID;
2543 break;
2544 case ANYARRAYOID:
2545 case ANYCOMPATIBLEARRAYOID:
2546 argtypes[i] = INT4ARRAYOID;
2547 break;
2548 case ANYRANGEOID:
2549 case ANYCOMPATIBLERANGEOID:
2550 argtypes[i] = INT4RANGEOID;
2551 break;
2552 case ANYMULTIRANGEOID:
2553 argtypes[i] = INT4MULTIRANGEOID;
2554 break;
2555 default:
2556 break;
2557 }
2558 }
2559 }
2560 }
2561
2562 /*
2563 * delete_function - clean up as much as possible of a stale function cache
2564 *
2565 * We can't release the PLpgSQL_function struct itself, because of the
2566 * possibility that there are fn_extra pointers to it. We can release
2567 * the subsidiary storage, but only if there are no active evaluations
2568 * in progress. Otherwise we'll just leak that storage. Since the
2569 * case would only occur if a pg_proc update is detected during a nested
2570 * recursive call on the function, a leak seems acceptable.
2571 *
2572 * Note that this can be called more than once if there are multiple fn_extra
2573 * pointers to the same function cache. Hence be careful not to do things
2574 * twice.
2575 */
2576 static void
delete_function(PLpgSQL_function * func)2577 delete_function(PLpgSQL_function *func)
2578 {
2579 /* remove function from hash table (might be done already) */
2580 plpgsql_HashTableDelete(func);
2581
2582 /* release the function's storage if safe and not done already */
2583 if (func->use_count == 0)
2584 plpgsql_free_function_memory(func);
2585 }
2586
2587 /* exported so we can call it from _PG_init() */
2588 void
plpgsql_HashTableInit(void)2589 plpgsql_HashTableInit(void)
2590 {
2591 HASHCTL ctl;
2592
2593 /* don't allow double-initialization */
2594 Assert(plpgsql_HashTable == NULL);
2595
2596 ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2597 ctl.entrysize = sizeof(plpgsql_HashEnt);
2598 plpgsql_HashTable = hash_create("PLpgSQL function hash",
2599 FUNCS_PER_USER,
2600 &ctl,
2601 HASH_ELEM | HASH_BLOBS);
2602 }
2603
2604 static PLpgSQL_function *
plpgsql_HashTableLookup(PLpgSQL_func_hashkey * func_key)2605 plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
2606 {
2607 plpgsql_HashEnt *hentry;
2608
2609 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2610 (void *) func_key,
2611 HASH_FIND,
2612 NULL);
2613 if (hentry)
2614 return hentry->function;
2615 else
2616 return NULL;
2617 }
2618
2619 static void
plpgsql_HashTableInsert(PLpgSQL_function * function,PLpgSQL_func_hashkey * func_key)2620 plpgsql_HashTableInsert(PLpgSQL_function *function,
2621 PLpgSQL_func_hashkey *func_key)
2622 {
2623 plpgsql_HashEnt *hentry;
2624 bool found;
2625
2626 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2627 (void *) func_key,
2628 HASH_ENTER,
2629 &found);
2630 if (found)
2631 elog(WARNING, "trying to insert a function that already exists");
2632
2633 hentry->function = function;
2634 /* prepare back link from function to hashtable key */
2635 function->fn_hashkey = &hentry->key;
2636 }
2637
2638 static void
plpgsql_HashTableDelete(PLpgSQL_function * function)2639 plpgsql_HashTableDelete(PLpgSQL_function *function)
2640 {
2641 plpgsql_HashEnt *hentry;
2642
2643 /* do nothing if not in table */
2644 if (function->fn_hashkey == NULL)
2645 return;
2646
2647 hentry = (plpgsql_HashEnt *) hash_search(plpgsql_HashTable,
2648 (void *) function->fn_hashkey,
2649 HASH_REMOVE,
2650 NULL);
2651 if (hentry == NULL)
2652 elog(WARNING, "trying to delete function that does not exist");
2653
2654 /* remove back link, which no longer points to allocated storage */
2655 function->fn_hashkey = NULL;
2656 }
2657