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