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