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