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