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