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