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