1 /*-------------------------------------------------------------------------
2  *
3  * pg_proc.c
4  *	  routines to support manipulation of the pg_proc relation
5  *
6  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/backend/catalog/pg_proc.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/htup_details.h"
18 #include "access/table.h"
19 #include "access/xact.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/objectaccess.h"
24 #include "catalog/pg_language.h"
25 #include "catalog/pg_namespace.h"
26 #include "catalog/pg_proc.h"
27 #include "catalog/pg_transform.h"
28 #include "catalog/pg_type.h"
29 #include "commands/defrem.h"
30 #include "executor/functions.h"
31 #include "funcapi.h"
32 #include "mb/pg_wchar.h"
33 #include "miscadmin.h"
34 #include "nodes/nodeFuncs.h"
35 #include "parser/parse_coerce.h"
36 #include "parser/parse_type.h"
37 #include "tcop/pquery.h"
38 #include "tcop/tcopprot.h"
39 #include "utils/acl.h"
40 #include "utils/builtins.h"
41 #include "utils/lsyscache.h"
42 #include "utils/regproc.h"
43 #include "utils/rel.h"
44 #include "utils/syscache.h"
45 
46 
47 typedef struct
48 {
49 	char	   *proname;
50 	char	   *prosrc;
51 } parse_error_callback_arg;
52 
53 static void sql_function_parse_error_callback(void *arg);
54 static int	match_prosrc_to_query(const char *prosrc, const char *queryText,
55 								  int cursorpos);
56 static bool match_prosrc_to_literal(const char *prosrc, const char *literal,
57 									int cursorpos, int *newcursorpos);
58 
59 
60 /* ----------------------------------------------------------------
61  *		ProcedureCreate
62  *
63  * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig
64  * are either arrays of the proper types or NULL.  We declare them Datum,
65  * not "ArrayType *", to avoid importing array.h into pg_proc.h.
66  * ----------------------------------------------------------------
67  */
68 ObjectAddress
ProcedureCreate(const char * procedureName,Oid procNamespace,bool replace,bool returnsSet,Oid returnType,Oid proowner,Oid languageObjectId,Oid languageValidator,const char * prosrc,const char * probin,char prokind,bool security_definer,bool isLeakProof,bool isStrict,char volatility,char parallel,oidvector * parameterTypes,Datum allParameterTypes,Datum parameterModes,Datum parameterNames,List * parameterDefaults,Datum trftypes,Datum proconfig,Oid prosupport,float4 procost,float4 prorows)69 ProcedureCreate(const char *procedureName,
70 				Oid procNamespace,
71 				bool replace,
72 				bool returnsSet,
73 				Oid returnType,
74 				Oid proowner,
75 				Oid languageObjectId,
76 				Oid languageValidator,
77 				const char *prosrc,
78 				const char *probin,
79 				char prokind,
80 				bool security_definer,
81 				bool isLeakProof,
82 				bool isStrict,
83 				char volatility,
84 				char parallel,
85 				oidvector *parameterTypes,
86 				Datum allParameterTypes,
87 				Datum parameterModes,
88 				Datum parameterNames,
89 				List *parameterDefaults,
90 				Datum trftypes,
91 				Datum proconfig,
92 				Oid prosupport,
93 				float4 procost,
94 				float4 prorows)
95 {
96 	Oid			retval;
97 	int			parameterCount;
98 	int			allParamCount;
99 	Oid		   *allParams;
100 	char	   *paramModes = NULL;
101 	Oid			variadicType = InvalidOid;
102 	Acl		   *proacl = NULL;
103 	Relation	rel;
104 	HeapTuple	tup;
105 	HeapTuple	oldtup;
106 	bool		nulls[Natts_pg_proc];
107 	Datum		values[Natts_pg_proc];
108 	bool		replaces[Natts_pg_proc];
109 	NameData	procname;
110 	TupleDesc	tupDesc;
111 	bool		is_update;
112 	ObjectAddress myself,
113 				referenced;
114 	char	   *detailmsg;
115 	int			i;
116 	Oid			trfid;
117 
118 	/*
119 	 * sanity checks
120 	 */
121 	Assert(PointerIsValid(prosrc));
122 
123 	parameterCount = parameterTypes->dim1;
124 	if (parameterCount < 0 || parameterCount > FUNC_MAX_ARGS)
125 		ereport(ERROR,
126 				(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
127 				 errmsg_plural("functions cannot have more than %d argument",
128 							   "functions cannot have more than %d arguments",
129 							   FUNC_MAX_ARGS,
130 							   FUNC_MAX_ARGS)));
131 	/* note: the above is correct, we do NOT count output arguments */
132 
133 	/* Deconstruct array inputs */
134 	if (allParameterTypes != PointerGetDatum(NULL))
135 	{
136 		/*
137 		 * We expect the array to be a 1-D OID array; verify that. We don't
138 		 * need to use deconstruct_array() since the array data is just going
139 		 * to look like a C array of OID values.
140 		 */
141 		ArrayType  *allParamArray = (ArrayType *) DatumGetPointer(allParameterTypes);
142 
143 		allParamCount = ARR_DIMS(allParamArray)[0];
144 		if (ARR_NDIM(allParamArray) != 1 ||
145 			allParamCount <= 0 ||
146 			ARR_HASNULL(allParamArray) ||
147 			ARR_ELEMTYPE(allParamArray) != OIDOID)
148 			elog(ERROR, "allParameterTypes is not a 1-D Oid array");
149 		allParams = (Oid *) ARR_DATA_PTR(allParamArray);
150 		Assert(allParamCount >= parameterCount);
151 		/* we assume caller got the contents right */
152 	}
153 	else
154 	{
155 		allParamCount = parameterCount;
156 		allParams = parameterTypes->values;
157 	}
158 
159 	if (parameterModes != PointerGetDatum(NULL))
160 	{
161 		/*
162 		 * We expect the array to be a 1-D CHAR array; verify that. We don't
163 		 * need to use deconstruct_array() since the array data is just going
164 		 * to look like a C array of char values.
165 		 */
166 		ArrayType  *modesArray = (ArrayType *) DatumGetPointer(parameterModes);
167 
168 		if (ARR_NDIM(modesArray) != 1 ||
169 			ARR_DIMS(modesArray)[0] != allParamCount ||
170 			ARR_HASNULL(modesArray) ||
171 			ARR_ELEMTYPE(modesArray) != CHAROID)
172 			elog(ERROR, "parameterModes is not a 1-D char array");
173 		paramModes = (char *) ARR_DATA_PTR(modesArray);
174 	}
175 
176 	/*
177 	 * Do not allow polymorphic return type unless there is a polymorphic
178 	 * input argument that we can use to deduce the actual return type.
179 	 */
180 	detailmsg = check_valid_polymorphic_signature(returnType,
181 												  parameterTypes->values,
182 												  parameterCount);
183 	if (detailmsg)
184 		ereport(ERROR,
185 				(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
186 				 errmsg("cannot determine result data type"),
187 				 errdetail_internal("%s", detailmsg)));
188 
189 	/*
190 	 * Also, do not allow return type INTERNAL unless at least one input
191 	 * argument is INTERNAL.
192 	 */
193 	detailmsg = check_valid_internal_signature(returnType,
194 											   parameterTypes->values,
195 											   parameterCount);
196 	if (detailmsg)
197 		ereport(ERROR,
198 				(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
199 				 errmsg("unsafe use of pseudo-type \"internal\""),
200 				 errdetail_internal("%s", detailmsg)));
201 
202 	/*
203 	 * Apply the same tests to any OUT arguments.
204 	 */
205 	if (allParameterTypes != PointerGetDatum(NULL))
206 	{
207 		for (i = 0; i < allParamCount; i++)
208 		{
209 			if (paramModes == NULL ||
210 				paramModes[i] == PROARGMODE_IN ||
211 				paramModes[i] == PROARGMODE_VARIADIC)
212 				continue;		/* ignore input-only params */
213 
214 			detailmsg = check_valid_polymorphic_signature(allParams[i],
215 														  parameterTypes->values,
216 														  parameterCount);
217 			if (detailmsg)
218 				ereport(ERROR,
219 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
220 						 errmsg("cannot determine result data type"),
221 						 errdetail_internal("%s", detailmsg)));
222 			detailmsg = check_valid_internal_signature(allParams[i],
223 													   parameterTypes->values,
224 													   parameterCount);
225 			if (detailmsg)
226 				ereport(ERROR,
227 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
228 						 errmsg("unsafe use of pseudo-type \"internal\""),
229 						 errdetail_internal("%s", detailmsg)));
230 		}
231 	}
232 
233 	/* Identify variadic argument type, if any */
234 	if (paramModes != NULL)
235 	{
236 		/*
237 		 * Only the last input parameter can be variadic; if it is, save its
238 		 * element type.  Errors here are just elog since caller should have
239 		 * checked this already.
240 		 */
241 		for (i = 0; i < allParamCount; i++)
242 		{
243 			switch (paramModes[i])
244 			{
245 				case PROARGMODE_IN:
246 				case PROARGMODE_INOUT:
247 					if (OidIsValid(variadicType))
248 						elog(ERROR, "variadic parameter must be last");
249 					break;
250 				case PROARGMODE_OUT:
251 				case PROARGMODE_TABLE:
252 					/* okay */
253 					break;
254 				case PROARGMODE_VARIADIC:
255 					if (OidIsValid(variadicType))
256 						elog(ERROR, "variadic parameter must be last");
257 					switch (allParams[i])
258 					{
259 						case ANYOID:
260 							variadicType = ANYOID;
261 							break;
262 						case ANYARRAYOID:
263 							variadicType = ANYELEMENTOID;
264 							break;
265 						case ANYCOMPATIBLEARRAYOID:
266 							variadicType = ANYCOMPATIBLEOID;
267 							break;
268 						default:
269 							variadicType = get_element_type(allParams[i]);
270 							if (!OidIsValid(variadicType))
271 								elog(ERROR, "variadic parameter is not an array");
272 							break;
273 					}
274 					break;
275 				default:
276 					elog(ERROR, "invalid parameter mode '%c'", paramModes[i]);
277 					break;
278 			}
279 		}
280 	}
281 
282 	/*
283 	 * All seems OK; prepare the data to be inserted into pg_proc.
284 	 */
285 
286 	for (i = 0; i < Natts_pg_proc; ++i)
287 	{
288 		nulls[i] = false;
289 		values[i] = (Datum) 0;
290 		replaces[i] = true;
291 	}
292 
293 	namestrcpy(&procname, procedureName);
294 	values[Anum_pg_proc_proname - 1] = NameGetDatum(&procname);
295 	values[Anum_pg_proc_pronamespace - 1] = ObjectIdGetDatum(procNamespace);
296 	values[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(proowner);
297 	values[Anum_pg_proc_prolang - 1] = ObjectIdGetDatum(languageObjectId);
298 	values[Anum_pg_proc_procost - 1] = Float4GetDatum(procost);
299 	values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows);
300 	values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType);
301 	values[Anum_pg_proc_prosupport - 1] = ObjectIdGetDatum(prosupport);
302 	values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind);
303 	values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer);
304 	values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof);
305 	values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict);
306 	values[Anum_pg_proc_proretset - 1] = BoolGetDatum(returnsSet);
307 	values[Anum_pg_proc_provolatile - 1] = CharGetDatum(volatility);
308 	values[Anum_pg_proc_proparallel - 1] = CharGetDatum(parallel);
309 	values[Anum_pg_proc_pronargs - 1] = UInt16GetDatum(parameterCount);
310 	values[Anum_pg_proc_pronargdefaults - 1] = UInt16GetDatum(list_length(parameterDefaults));
311 	values[Anum_pg_proc_prorettype - 1] = ObjectIdGetDatum(returnType);
312 	values[Anum_pg_proc_proargtypes - 1] = PointerGetDatum(parameterTypes);
313 	if (allParameterTypes != PointerGetDatum(NULL))
314 		values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
315 	else
316 		nulls[Anum_pg_proc_proallargtypes - 1] = true;
317 	if (parameterModes != PointerGetDatum(NULL))
318 		values[Anum_pg_proc_proargmodes - 1] = parameterModes;
319 	else
320 		nulls[Anum_pg_proc_proargmodes - 1] = true;
321 	if (parameterNames != PointerGetDatum(NULL))
322 		values[Anum_pg_proc_proargnames - 1] = parameterNames;
323 	else
324 		nulls[Anum_pg_proc_proargnames - 1] = true;
325 	if (parameterDefaults != NIL)
326 		values[Anum_pg_proc_proargdefaults - 1] = CStringGetTextDatum(nodeToString(parameterDefaults));
327 	else
328 		nulls[Anum_pg_proc_proargdefaults - 1] = true;
329 	if (trftypes != PointerGetDatum(NULL))
330 		values[Anum_pg_proc_protrftypes - 1] = trftypes;
331 	else
332 		nulls[Anum_pg_proc_protrftypes - 1] = true;
333 	values[Anum_pg_proc_prosrc - 1] = CStringGetTextDatum(prosrc);
334 	if (probin)
335 		values[Anum_pg_proc_probin - 1] = CStringGetTextDatum(probin);
336 	else
337 		nulls[Anum_pg_proc_probin - 1] = true;
338 	if (proconfig != PointerGetDatum(NULL))
339 		values[Anum_pg_proc_proconfig - 1] = proconfig;
340 	else
341 		nulls[Anum_pg_proc_proconfig - 1] = true;
342 	/* proacl will be determined later */
343 
344 	rel = table_open(ProcedureRelationId, RowExclusiveLock);
345 	tupDesc = RelationGetDescr(rel);
346 
347 	/* Check for pre-existing definition */
348 	oldtup = SearchSysCache3(PROCNAMEARGSNSP,
349 							 PointerGetDatum(procedureName),
350 							 PointerGetDatum(parameterTypes),
351 							 ObjectIdGetDatum(procNamespace));
352 
353 	if (HeapTupleIsValid(oldtup))
354 	{
355 		/* There is one; okay to replace it? */
356 		Form_pg_proc oldproc = (Form_pg_proc) GETSTRUCT(oldtup);
357 		Datum		proargnames;
358 		bool		isnull;
359 		const char *dropcmd;
360 
361 		if (!replace)
362 			ereport(ERROR,
363 					(errcode(ERRCODE_DUPLICATE_FUNCTION),
364 					 errmsg("function \"%s\" already exists with same argument types",
365 							procedureName)));
366 		if (!pg_proc_ownercheck(oldproc->oid, proowner))
367 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
368 						   procedureName);
369 
370 		/* Not okay to change routine kind */
371 		if (oldproc->prokind != prokind)
372 			ereport(ERROR,
373 					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
374 					 errmsg("cannot change routine kind"),
375 					 (oldproc->prokind == PROKIND_AGGREGATE ?
376 					  errdetail("\"%s\" is an aggregate function.", procedureName) :
377 					  oldproc->prokind == PROKIND_FUNCTION ?
378 					  errdetail("\"%s\" is a function.", procedureName) :
379 					  oldproc->prokind == PROKIND_PROCEDURE ?
380 					  errdetail("\"%s\" is a procedure.", procedureName) :
381 					  oldproc->prokind == PROKIND_WINDOW ?
382 					  errdetail("\"%s\" is a window function.", procedureName) :
383 					  0)));
384 
385 		dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" :
386 				   prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" :
387 				   "DROP FUNCTION");
388 
389 		/*
390 		 * Not okay to change the return type of the existing proc, since
391 		 * existing rules, views, etc may depend on the return type.
392 		 *
393 		 * In case of a procedure, a changing return type means that whether
394 		 * the procedure has output parameters was changed.  Since there is no
395 		 * user visible return type, we produce a more specific error message.
396 		 */
397 		if (returnType != oldproc->prorettype ||
398 			returnsSet != oldproc->proretset)
399 			ereport(ERROR,
400 					(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
401 					 prokind == PROKIND_PROCEDURE
402 					 ? errmsg("cannot change whether a procedure has output parameters")
403 					 : errmsg("cannot change return type of existing function"),
404 
405 			/*
406 			 * translator: first %s is DROP FUNCTION, DROP PROCEDURE, or DROP
407 			 * AGGREGATE
408 			 */
409 					 errhint("Use %s %s first.",
410 							 dropcmd,
411 							 format_procedure(oldproc->oid))));
412 
413 		/*
414 		 * If it returns RECORD, check for possible change of record type
415 		 * implied by OUT parameters
416 		 */
417 		if (returnType == RECORDOID)
418 		{
419 			TupleDesc	olddesc;
420 			TupleDesc	newdesc;
421 
422 			olddesc = build_function_result_tupdesc_t(oldtup);
423 			newdesc = build_function_result_tupdesc_d(prokind,
424 													  allParameterTypes,
425 													  parameterModes,
426 													  parameterNames);
427 			if (olddesc == NULL && newdesc == NULL)
428 				 /* ok, both are runtime-defined RECORDs */ ;
429 			else if (olddesc == NULL || newdesc == NULL ||
430 					 !equalTupleDescs(olddesc, newdesc))
431 				ereport(ERROR,
432 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
433 						 errmsg("cannot change return type of existing function"),
434 						 errdetail("Row type defined by OUT parameters is different."),
435 				/* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
436 						 errhint("Use %s %s first.",
437 								 dropcmd,
438 								 format_procedure(oldproc->oid))));
439 		}
440 
441 		/*
442 		 * If there were any named input parameters, check to make sure the
443 		 * names have not been changed, as this could break existing calls. We
444 		 * allow adding names to formerly unnamed parameters, though.
445 		 */
446 		proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
447 									  Anum_pg_proc_proargnames,
448 									  &isnull);
449 		if (!isnull)
450 		{
451 			Datum		proargmodes;
452 			char	  **old_arg_names;
453 			char	  **new_arg_names;
454 			int			n_old_arg_names;
455 			int			n_new_arg_names;
456 			int			j;
457 
458 			proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
459 										  Anum_pg_proc_proargmodes,
460 										  &isnull);
461 			if (isnull)
462 				proargmodes = PointerGetDatum(NULL);	/* just to be sure */
463 
464 			n_old_arg_names = get_func_input_arg_names(proargnames,
465 													   proargmodes,
466 													   &old_arg_names);
467 			n_new_arg_names = get_func_input_arg_names(parameterNames,
468 													   parameterModes,
469 													   &new_arg_names);
470 			for (j = 0; j < n_old_arg_names; j++)
471 			{
472 				if (old_arg_names[j] == NULL)
473 					continue;
474 				if (j >= n_new_arg_names || new_arg_names[j] == NULL ||
475 					strcmp(old_arg_names[j], new_arg_names[j]) != 0)
476 					ereport(ERROR,
477 							(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
478 							 errmsg("cannot change name of input parameter \"%s\"",
479 									old_arg_names[j]),
480 					/* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
481 							 errhint("Use %s %s first.",
482 									 dropcmd,
483 									 format_procedure(oldproc->oid))));
484 			}
485 		}
486 
487 		/*
488 		 * If there are existing defaults, check compatibility: redefinition
489 		 * must not remove any defaults nor change their types.  (Removing a
490 		 * default might cause a function to fail to satisfy an existing call.
491 		 * Changing type would only be possible if the associated parameter is
492 		 * polymorphic, and in such cases a change of default type might alter
493 		 * the resolved output type of existing calls.)
494 		 */
495 		if (oldproc->pronargdefaults != 0)
496 		{
497 			Datum		proargdefaults;
498 			List	   *oldDefaults;
499 			ListCell   *oldlc;
500 			ListCell   *newlc;
501 
502 			if (list_length(parameterDefaults) < oldproc->pronargdefaults)
503 				ereport(ERROR,
504 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
505 						 errmsg("cannot remove parameter defaults from existing function"),
506 				/* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
507 						 errhint("Use %s %s first.",
508 								 dropcmd,
509 								 format_procedure(oldproc->oid))));
510 
511 			proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
512 											 Anum_pg_proc_proargdefaults,
513 											 &isnull);
514 			Assert(!isnull);
515 			oldDefaults = castNode(List, stringToNode(TextDatumGetCString(proargdefaults)));
516 			Assert(list_length(oldDefaults) == oldproc->pronargdefaults);
517 
518 			/* new list can have more defaults than old, advance over 'em */
519 			newlc = list_nth_cell(parameterDefaults,
520 								  list_length(parameterDefaults) -
521 								  oldproc->pronargdefaults);
522 
523 			foreach(oldlc, oldDefaults)
524 			{
525 				Node	   *oldDef = (Node *) lfirst(oldlc);
526 				Node	   *newDef = (Node *) lfirst(newlc);
527 
528 				if (exprType(oldDef) != exprType(newDef))
529 					ereport(ERROR,
530 							(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
531 							 errmsg("cannot change data type of existing parameter default value"),
532 					/* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
533 							 errhint("Use %s %s first.",
534 									 dropcmd,
535 									 format_procedure(oldproc->oid))));
536 				newlc = lnext(parameterDefaults, newlc);
537 			}
538 		}
539 
540 		/*
541 		 * Do not change existing oid, ownership or permissions, either.  Note
542 		 * dependency-update code below has to agree with this decision.
543 		 */
544 		replaces[Anum_pg_proc_oid - 1] = false;
545 		replaces[Anum_pg_proc_proowner - 1] = false;
546 		replaces[Anum_pg_proc_proacl - 1] = false;
547 
548 		/* Okay, do it... */
549 		tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
550 		CatalogTupleUpdate(rel, &tup->t_self, tup);
551 
552 		ReleaseSysCache(oldtup);
553 		is_update = true;
554 	}
555 	else
556 	{
557 		/* Creating a new procedure */
558 		Oid			newOid;
559 
560 		/* First, get default permissions and set up proacl */
561 		proacl = get_user_default_acl(OBJECT_FUNCTION, proowner,
562 									  procNamespace);
563 		if (proacl != NULL)
564 			values[Anum_pg_proc_proacl - 1] = PointerGetDatum(proacl);
565 		else
566 			nulls[Anum_pg_proc_proacl - 1] = true;
567 
568 		newOid = GetNewOidWithIndex(rel, ProcedureOidIndexId,
569 									Anum_pg_proc_oid);
570 		values[Anum_pg_proc_oid - 1] = ObjectIdGetDatum(newOid);
571 		tup = heap_form_tuple(tupDesc, values, nulls);
572 		CatalogTupleInsert(rel, tup);
573 		is_update = false;
574 	}
575 
576 
577 	retval = ((Form_pg_proc) GETSTRUCT(tup))->oid;
578 
579 	/*
580 	 * Create dependencies for the new function.  If we are updating an
581 	 * existing function, first delete any existing pg_depend entries.
582 	 * (However, since we are not changing ownership or permissions, the
583 	 * shared dependencies do *not* need to change, and we leave them alone.)
584 	 */
585 	if (is_update)
586 		deleteDependencyRecordsFor(ProcedureRelationId, retval, true);
587 
588 	myself.classId = ProcedureRelationId;
589 	myself.objectId = retval;
590 	myself.objectSubId = 0;
591 
592 	/* dependency on namespace */
593 	referenced.classId = NamespaceRelationId;
594 	referenced.objectId = procNamespace;
595 	referenced.objectSubId = 0;
596 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
597 
598 	/* dependency on implementation language */
599 	referenced.classId = LanguageRelationId;
600 	referenced.objectId = languageObjectId;
601 	referenced.objectSubId = 0;
602 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
603 
604 	/* dependency on return type */
605 	referenced.classId = TypeRelationId;
606 	referenced.objectId = returnType;
607 	referenced.objectSubId = 0;
608 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
609 
610 	/* dependency on transform used by return type, if any */
611 	if ((trfid = get_transform_oid(returnType, languageObjectId, true)))
612 	{
613 		referenced.classId = TransformRelationId;
614 		referenced.objectId = trfid;
615 		referenced.objectSubId = 0;
616 		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
617 	}
618 
619 	/* dependency on parameter types */
620 	for (i = 0; i < allParamCount; i++)
621 	{
622 		referenced.classId = TypeRelationId;
623 		referenced.objectId = allParams[i];
624 		referenced.objectSubId = 0;
625 		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
626 
627 		/* dependency on transform used by parameter type, if any */
628 		if ((trfid = get_transform_oid(allParams[i], languageObjectId, true)))
629 		{
630 			referenced.classId = TransformRelationId;
631 			referenced.objectId = trfid;
632 			referenced.objectSubId = 0;
633 			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
634 		}
635 	}
636 
637 	/* dependency on parameter default expressions */
638 	if (parameterDefaults)
639 		recordDependencyOnExpr(&myself, (Node *) parameterDefaults,
640 							   NIL, DEPENDENCY_NORMAL);
641 
642 	/* dependency on support function, if any */
643 	if (OidIsValid(prosupport))
644 	{
645 		referenced.classId = ProcedureRelationId;
646 		referenced.objectId = prosupport;
647 		referenced.objectSubId = 0;
648 		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
649 	}
650 
651 	/* dependency on owner */
652 	if (!is_update)
653 		recordDependencyOnOwner(ProcedureRelationId, retval, proowner);
654 
655 	/* dependency on any roles mentioned in ACL */
656 	if (!is_update)
657 		recordDependencyOnNewAcl(ProcedureRelationId, retval, 0,
658 								 proowner, proacl);
659 
660 	/* dependency on extension */
661 	recordDependencyOnCurrentExtension(&myself, is_update);
662 
663 	heap_freetuple(tup);
664 
665 	/* Post creation hook for new function */
666 	InvokeObjectPostCreateHook(ProcedureRelationId, retval, 0);
667 
668 	table_close(rel, RowExclusiveLock);
669 
670 	/* Verify function body */
671 	if (OidIsValid(languageValidator))
672 	{
673 		ArrayType  *set_items = NULL;
674 		int			save_nestlevel = 0;
675 
676 		/* Advance command counter so new tuple can be seen by validator */
677 		CommandCounterIncrement();
678 
679 		/*
680 		 * Set per-function configuration parameters so that the validation is
681 		 * done with the environment the function expects.  However, if
682 		 * check_function_bodies is off, we don't do this, because that would
683 		 * create dump ordering hazards that pg_dump doesn't know how to deal
684 		 * with.  (For example, a SET clause might refer to a not-yet-created
685 		 * text search configuration.)	This means that the validator
686 		 * shouldn't complain about anything that might depend on a GUC
687 		 * parameter when check_function_bodies is off.
688 		 */
689 		if (check_function_bodies)
690 		{
691 			set_items = (ArrayType *) DatumGetPointer(proconfig);
692 			if (set_items)		/* Need a new GUC nesting level */
693 			{
694 				save_nestlevel = NewGUCNestLevel();
695 				ProcessGUCArray(set_items,
696 								(superuser() ? PGC_SUSET : PGC_USERSET),
697 								PGC_S_SESSION,
698 								GUC_ACTION_SAVE);
699 			}
700 		}
701 
702 		OidFunctionCall1(languageValidator, ObjectIdGetDatum(retval));
703 
704 		if (set_items)
705 			AtEOXact_GUC(true, save_nestlevel);
706 	}
707 
708 	return myself;
709 }
710 
711 
712 
713 /*
714  * Validator for internal functions
715  *
716  * Check that the given internal function name (the "prosrc" value) is
717  * a known builtin function.
718  */
719 Datum
fmgr_internal_validator(PG_FUNCTION_ARGS)720 fmgr_internal_validator(PG_FUNCTION_ARGS)
721 {
722 	Oid			funcoid = PG_GETARG_OID(0);
723 	HeapTuple	tuple;
724 	bool		isnull;
725 	Datum		tmp;
726 	char	   *prosrc;
727 
728 	if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
729 		PG_RETURN_VOID();
730 
731 	/*
732 	 * We do not honor check_function_bodies since it's unlikely the function
733 	 * name will be found later if it isn't there now.
734 	 */
735 
736 	tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
737 	if (!HeapTupleIsValid(tuple))
738 		elog(ERROR, "cache lookup failed for function %u", funcoid);
739 
740 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
741 	if (isnull)
742 		elog(ERROR, "null prosrc");
743 	prosrc = TextDatumGetCString(tmp);
744 
745 	if (fmgr_internal_function(prosrc) == InvalidOid)
746 		ereport(ERROR,
747 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
748 				 errmsg("there is no built-in function named \"%s\"",
749 						prosrc)));
750 
751 	ReleaseSysCache(tuple);
752 
753 	PG_RETURN_VOID();
754 }
755 
756 
757 
758 /*
759  * Validator for C language functions
760  *
761  * Make sure that the library file exists, is loadable, and contains
762  * the specified link symbol. Also check for a valid function
763  * information record.
764  */
765 Datum
fmgr_c_validator(PG_FUNCTION_ARGS)766 fmgr_c_validator(PG_FUNCTION_ARGS)
767 {
768 	Oid			funcoid = PG_GETARG_OID(0);
769 	void	   *libraryhandle;
770 	HeapTuple	tuple;
771 	bool		isnull;
772 	Datum		tmp;
773 	char	   *prosrc;
774 	char	   *probin;
775 
776 	if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
777 		PG_RETURN_VOID();
778 
779 	/*
780 	 * It'd be most consistent to skip the check if !check_function_bodies,
781 	 * but the purpose of that switch is to be helpful for pg_dump loading,
782 	 * and for pg_dump loading it's much better if we *do* check.
783 	 */
784 
785 	tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
786 	if (!HeapTupleIsValid(tuple))
787 		elog(ERROR, "cache lookup failed for function %u", funcoid);
788 
789 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
790 	if (isnull)
791 		elog(ERROR, "null prosrc for C function %u", funcoid);
792 	prosrc = TextDatumGetCString(tmp);
793 
794 	tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull);
795 	if (isnull)
796 		elog(ERROR, "null probin for C function %u", funcoid);
797 	probin = TextDatumGetCString(tmp);
798 
799 	(void) load_external_function(probin, prosrc, true, &libraryhandle);
800 	(void) fetch_finfo_record(libraryhandle, prosrc);
801 
802 	ReleaseSysCache(tuple);
803 
804 	PG_RETURN_VOID();
805 }
806 
807 
808 /*
809  * Validator for SQL language functions
810  *
811  * Parse it here in order to be sure that it contains no syntax errors.
812  */
813 Datum
fmgr_sql_validator(PG_FUNCTION_ARGS)814 fmgr_sql_validator(PG_FUNCTION_ARGS)
815 {
816 	Oid			funcoid = PG_GETARG_OID(0);
817 	HeapTuple	tuple;
818 	Form_pg_proc proc;
819 	List	   *raw_parsetree_list;
820 	List	   *querytree_list;
821 	ListCell   *lc;
822 	bool		isnull;
823 	Datum		tmp;
824 	char	   *prosrc;
825 	parse_error_callback_arg callback_arg;
826 	ErrorContextCallback sqlerrcontext;
827 	bool		haspolyarg;
828 	int			i;
829 
830 	if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
831 		PG_RETURN_VOID();
832 
833 	tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
834 	if (!HeapTupleIsValid(tuple))
835 		elog(ERROR, "cache lookup failed for function %u", funcoid);
836 	proc = (Form_pg_proc) GETSTRUCT(tuple);
837 
838 	/* Disallow pseudotype result */
839 	/* except for RECORD, VOID, or polymorphic */
840 	if (get_typtype(proc->prorettype) == TYPTYPE_PSEUDO &&
841 		proc->prorettype != RECORDOID &&
842 		proc->prorettype != VOIDOID &&
843 		!IsPolymorphicType(proc->prorettype))
844 		ereport(ERROR,
845 				(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
846 				 errmsg("SQL functions cannot return type %s",
847 						format_type_be(proc->prorettype))));
848 
849 	/* Disallow pseudotypes in arguments */
850 	/* except for polymorphic */
851 	haspolyarg = false;
852 	for (i = 0; i < proc->pronargs; i++)
853 	{
854 		if (get_typtype(proc->proargtypes.values[i]) == TYPTYPE_PSEUDO)
855 		{
856 			if (IsPolymorphicType(proc->proargtypes.values[i]))
857 				haspolyarg = true;
858 			else
859 				ereport(ERROR,
860 						(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
861 						 errmsg("SQL functions cannot have arguments of type %s",
862 								format_type_be(proc->proargtypes.values[i]))));
863 		}
864 	}
865 
866 	/* Postpone body checks if !check_function_bodies */
867 	if (check_function_bodies)
868 	{
869 		tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull);
870 		if (isnull)
871 			elog(ERROR, "null prosrc");
872 
873 		prosrc = TextDatumGetCString(tmp);
874 
875 		/*
876 		 * Setup error traceback support for ereport().
877 		 */
878 		callback_arg.proname = NameStr(proc->proname);
879 		callback_arg.prosrc = prosrc;
880 
881 		sqlerrcontext.callback = sql_function_parse_error_callback;
882 		sqlerrcontext.arg = (void *) &callback_arg;
883 		sqlerrcontext.previous = error_context_stack;
884 		error_context_stack = &sqlerrcontext;
885 
886 		/*
887 		 * We can't do full prechecking of the function definition if there
888 		 * are any polymorphic input types, because actual datatypes of
889 		 * expression results will be unresolvable.  The check will be done at
890 		 * runtime instead.
891 		 *
892 		 * We can run the text through the raw parser though; this will at
893 		 * least catch silly syntactic errors.
894 		 */
895 		raw_parsetree_list = pg_parse_query(prosrc);
896 
897 		if (!haspolyarg)
898 		{
899 			/*
900 			 * OK to do full precheck: analyze and rewrite the queries, then
901 			 * verify the result type.
902 			 */
903 			SQLFunctionParseInfoPtr pinfo;
904 			Oid			rettype;
905 			TupleDesc	rettupdesc;
906 
907 			/* But first, set up parameter information */
908 			pinfo = prepare_sql_fn_parse_info(tuple, NULL, InvalidOid);
909 
910 			querytree_list = NIL;
911 			foreach(lc, raw_parsetree_list)
912 			{
913 				RawStmt    *parsetree = lfirst_node(RawStmt, lc);
914 				List	   *querytree_sublist;
915 
916 				querytree_sublist = pg_analyze_and_rewrite_params(parsetree,
917 																  prosrc,
918 																  (ParserSetupHook) sql_fn_parser_setup,
919 																  pinfo,
920 																  NULL);
921 				querytree_list = lappend(querytree_list,
922 										 querytree_sublist);
923 			}
924 
925 			check_sql_fn_statements(querytree_list);
926 
927 			(void) get_func_result_type(funcoid, &rettype, &rettupdesc);
928 
929 			(void) check_sql_fn_retval(querytree_list,
930 									   rettype, rettupdesc,
931 									   false, NULL);
932 		}
933 
934 		error_context_stack = sqlerrcontext.previous;
935 	}
936 
937 	ReleaseSysCache(tuple);
938 
939 	PG_RETURN_VOID();
940 }
941 
942 /*
943  * Error context callback for handling errors in SQL function definitions
944  */
945 static void
sql_function_parse_error_callback(void * arg)946 sql_function_parse_error_callback(void *arg)
947 {
948 	parse_error_callback_arg *callback_arg = (parse_error_callback_arg *) arg;
949 
950 	/* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
951 	if (!function_parse_error_transpose(callback_arg->prosrc))
952 	{
953 		/* If it's not a syntax error, push info onto context stack */
954 		errcontext("SQL function \"%s\"", callback_arg->proname);
955 	}
956 }
957 
958 /*
959  * Adjust a syntax error occurring inside the function body of a CREATE
960  * FUNCTION or DO command.  This can be used by any function validator or
961  * anonymous-block handler, not only for SQL-language functions.
962  * It is assumed that the syntax error position is initially relative to the
963  * function body string (as passed in).  If possible, we adjust the position
964  * to reference the original command text; if we can't manage that, we set
965  * up an "internal query" syntax error instead.
966  *
967  * Returns true if a syntax error was processed, false if not.
968  */
969 bool
function_parse_error_transpose(const char * prosrc)970 function_parse_error_transpose(const char *prosrc)
971 {
972 	int			origerrposition;
973 	int			newerrposition;
974 	const char *queryText;
975 
976 	/*
977 	 * Nothing to do unless we are dealing with a syntax error that has a
978 	 * cursor position.
979 	 *
980 	 * Some PLs may prefer to report the error position as an internal error
981 	 * to begin with, so check that too.
982 	 */
983 	origerrposition = geterrposition();
984 	if (origerrposition <= 0)
985 	{
986 		origerrposition = getinternalerrposition();
987 		if (origerrposition <= 0)
988 			return false;
989 	}
990 
991 	/* We can get the original query text from the active portal (hack...) */
992 	Assert(ActivePortal && ActivePortal->status == PORTAL_ACTIVE);
993 	queryText = ActivePortal->sourceText;
994 
995 	/* Try to locate the prosrc in the original text */
996 	newerrposition = match_prosrc_to_query(prosrc, queryText, origerrposition);
997 
998 	if (newerrposition > 0)
999 	{
1000 		/* Successful, so fix error position to reference original query */
1001 		errposition(newerrposition);
1002 		/* Get rid of any report of the error as an "internal query" */
1003 		internalerrposition(0);
1004 		internalerrquery(NULL);
1005 	}
1006 	else
1007 	{
1008 		/*
1009 		 * If unsuccessful, convert the position to an internal position
1010 		 * marker and give the function text as the internal query.
1011 		 */
1012 		errposition(0);
1013 		internalerrposition(origerrposition);
1014 		internalerrquery(prosrc);
1015 	}
1016 
1017 	return true;
1018 }
1019 
1020 /*
1021  * Try to locate the string literal containing the function body in the
1022  * given text of the CREATE FUNCTION or DO command.  If successful, return
1023  * the character (not byte) index within the command corresponding to the
1024  * given character index within the literal.  If not successful, return 0.
1025  */
1026 static int
match_prosrc_to_query(const char * prosrc,const char * queryText,int cursorpos)1027 match_prosrc_to_query(const char *prosrc, const char *queryText,
1028 					  int cursorpos)
1029 {
1030 	/*
1031 	 * Rather than fully parsing the original command, we just scan the
1032 	 * command looking for $prosrc$ or 'prosrc'.  This could be fooled (though
1033 	 * not in any very probable scenarios), so fail if we find more than one
1034 	 * match.
1035 	 */
1036 	int			prosrclen = strlen(prosrc);
1037 	int			querylen = strlen(queryText);
1038 	int			matchpos = 0;
1039 	int			curpos;
1040 	int			newcursorpos;
1041 
1042 	for (curpos = 0; curpos < querylen - prosrclen; curpos++)
1043 	{
1044 		if (queryText[curpos] == '$' &&
1045 			strncmp(prosrc, &queryText[curpos + 1], prosrclen) == 0 &&
1046 			queryText[curpos + 1 + prosrclen] == '$')
1047 		{
1048 			/*
1049 			 * Found a $foo$ match.  Since there are no embedded quoting
1050 			 * characters in a dollar-quoted literal, we don't have to do any
1051 			 * fancy arithmetic; just offset by the starting position.
1052 			 */
1053 			if (matchpos)
1054 				return 0;		/* multiple matches, fail */
1055 			matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
1056 				+ cursorpos;
1057 		}
1058 		else if (queryText[curpos] == '\'' &&
1059 				 match_prosrc_to_literal(prosrc, &queryText[curpos + 1],
1060 										 cursorpos, &newcursorpos))
1061 		{
1062 			/*
1063 			 * Found a 'foo' match.  match_prosrc_to_literal() has adjusted
1064 			 * for any quotes or backslashes embedded in the literal.
1065 			 */
1066 			if (matchpos)
1067 				return 0;		/* multiple matches, fail */
1068 			matchpos = pg_mbstrlen_with_len(queryText, curpos + 1)
1069 				+ newcursorpos;
1070 		}
1071 	}
1072 
1073 	return matchpos;
1074 }
1075 
1076 /*
1077  * Try to match the given source text to a single-quoted literal.
1078  * If successful, adjust newcursorpos to correspond to the character
1079  * (not byte) index corresponding to cursorpos in the source text.
1080  *
1081  * At entry, literal points just past a ' character.  We must check for the
1082  * trailing quote.
1083  */
1084 static bool
match_prosrc_to_literal(const char * prosrc,const char * literal,int cursorpos,int * newcursorpos)1085 match_prosrc_to_literal(const char *prosrc, const char *literal,
1086 						int cursorpos, int *newcursorpos)
1087 {
1088 	int			newcp = cursorpos;
1089 	int			chlen;
1090 
1091 	/*
1092 	 * This implementation handles backslashes and doubled quotes in the
1093 	 * string literal.  It does not handle the SQL syntax for literals
1094 	 * continued across line boundaries.
1095 	 *
1096 	 * We do the comparison a character at a time, not a byte at a time, so
1097 	 * that we can do the correct cursorpos math.
1098 	 */
1099 	while (*prosrc)
1100 	{
1101 		cursorpos--;			/* characters left before cursor */
1102 
1103 		/*
1104 		 * Check for backslashes and doubled quotes in the literal; adjust
1105 		 * newcp when one is found before the cursor.
1106 		 */
1107 		if (*literal == '\\')
1108 		{
1109 			literal++;
1110 			if (cursorpos > 0)
1111 				newcp++;
1112 		}
1113 		else if (*literal == '\'')
1114 		{
1115 			if (literal[1] != '\'')
1116 				goto fail;
1117 			literal++;
1118 			if (cursorpos > 0)
1119 				newcp++;
1120 		}
1121 		chlen = pg_mblen(prosrc);
1122 		if (strncmp(prosrc, literal, chlen) != 0)
1123 			goto fail;
1124 		prosrc += chlen;
1125 		literal += chlen;
1126 	}
1127 
1128 	if (*literal == '\'' && literal[1] != '\'')
1129 	{
1130 		/* success */
1131 		*newcursorpos = newcp;
1132 		return true;
1133 	}
1134 
1135 fail:
1136 	/* Must set *newcursorpos to suppress compiler warning */
1137 	*newcursorpos = newcp;
1138 	return false;
1139 }
1140 
1141 List *
oid_array_to_list(Datum datum)1142 oid_array_to_list(Datum datum)
1143 {
1144 	ArrayType  *array = DatumGetArrayTypeP(datum);
1145 	Datum	   *values;
1146 	int			nelems;
1147 	int			i;
1148 	List	   *result = NIL;
1149 
1150 	deconstruct_array(array,
1151 					  OIDOID,
1152 					  sizeof(Oid), true, TYPALIGN_INT,
1153 					  &values, NULL, &nelems);
1154 	for (i = 0; i < nelems; i++)
1155 		result = lappend_oid(result, values[i]);
1156 	return result;
1157 }
1158