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