1 /*-------------------------------------------------------------------------
4 * routines to support manipulation of the pg_proc relation
6 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/catalog/pg_proc.c
13 *-------------------------------------------------------------------------
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"
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"
39 #include "rewrite/rewriteHandler.h"
40 #include "tcop/pquery.h"
41 #include "tcop/tcopprot.h"
42 #include "utils/acl.h"
43 #include "utils/builtins.h"
44 #include "utils/lsyscache.h"
45 #include "utils/regproc.h"
46 #include "utils/rel.h"
47 #include "utils/syscache.h"
54 } parse_error_callback_arg
;
56 static void sql_function_parse_error_callback(void *arg
);
57 static int match_prosrc_to_query(const char *prosrc
, const char *queryText
,
59 static bool match_prosrc_to_literal(const char *prosrc
, const char *literal
,
60 int cursorpos
, int *newcursorpos
);
63 /* ----------------------------------------------------------------
66 * Note: allParameterTypes, parameterModes, parameterNames, trftypes, and proconfig
67 * are either arrays of the proper types or NULL. We declare them Datum,
68 * not "ArrayType *", to avoid importing array.h into pg_proc.h.
69 * ----------------------------------------------------------------
72 ProcedureCreate(const char *procedureName
,
79 Oid languageValidator
,
84 bool security_definer
,
89 oidvector
*parameterTypes
,
90 Datum allParameterTypes
,
93 List
*parameterDefaults
,
104 char *paramModes
= NULL
;
105 Oid variadicType
= InvalidOid
;
110 bool nulls
[Natts_pg_proc
];
111 Datum values
[Natts_pg_proc
];
112 bool replaces
[Natts_pg_proc
];
116 ObjectAddress myself
,
121 ObjectAddresses
*addrs
;
126 Assert(PointerIsValid(prosrc
));
128 parameterCount
= parameterTypes
->dim1
;
129 if (parameterCount
< 0 || parameterCount
> FUNC_MAX_ARGS
)
131 (errcode(ERRCODE_TOO_MANY_ARGUMENTS
),
132 errmsg_plural("functions cannot have more than %d argument",
133 "functions cannot have more than %d arguments",
136 /* note: the above is correct, we do NOT count output arguments */
138 /* Deconstruct array inputs */
139 if (allParameterTypes
!= PointerGetDatum(NULL
))
142 * We expect the array to be a 1-D OID array; verify that. We don't
143 * need to use deconstruct_array() since the array data is just going
144 * to look like a C array of OID values.
146 ArrayType
*allParamArray
= (ArrayType
*) DatumGetPointer(allParameterTypes
);
148 allParamCount
= ARR_DIMS(allParamArray
)[0];
149 if (ARR_NDIM(allParamArray
) != 1 ||
150 allParamCount
<= 0 ||
151 ARR_HASNULL(allParamArray
) ||
152 ARR_ELEMTYPE(allParamArray
) != OIDOID
)
153 elog(ERROR
, "allParameterTypes is not a 1-D Oid array");
154 allParams
= (Oid
*) ARR_DATA_PTR(allParamArray
);
155 Assert(allParamCount
>= parameterCount
);
156 /* we assume caller got the contents right */
160 allParamCount
= parameterCount
;
161 allParams
= parameterTypes
->values
;
164 if (parameterModes
!= PointerGetDatum(NULL
))
167 * We expect the array to be a 1-D CHAR array; verify that. We don't
168 * need to use deconstruct_array() since the array data is just going
169 * to look like a C array of char values.
171 ArrayType
*modesArray
= (ArrayType
*) DatumGetPointer(parameterModes
);
173 if (ARR_NDIM(modesArray
) != 1 ||
174 ARR_DIMS(modesArray
)[0] != allParamCount
||
175 ARR_HASNULL(modesArray
) ||
176 ARR_ELEMTYPE(modesArray
) != CHAROID
)
177 elog(ERROR
, "parameterModes is not a 1-D char array");
178 paramModes
= (char *) ARR_DATA_PTR(modesArray
);
182 * Do not allow polymorphic return type unless there is a polymorphic
183 * input argument that we can use to deduce the actual return type.
185 detailmsg
= check_valid_polymorphic_signature(returnType
,
186 parameterTypes
->values
,
190 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
191 errmsg("cannot determine result data type"),
192 errdetail_internal("%s", detailmsg
)));
195 * Also, do not allow return type INTERNAL unless at least one input
196 * argument is INTERNAL.
198 detailmsg
= check_valid_internal_signature(returnType
,
199 parameterTypes
->values
,
203 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
204 errmsg("unsafe use of pseudo-type \"internal\""),
205 errdetail_internal("%s", detailmsg
)));
208 * Apply the same tests to any OUT arguments.
210 if (allParameterTypes
!= PointerGetDatum(NULL
))
212 for (i
= 0; i
< allParamCount
; i
++)
214 if (paramModes
== NULL
||
215 paramModes
[i
] == PROARGMODE_IN
||
216 paramModes
[i
] == PROARGMODE_VARIADIC
)
217 continue; /* ignore input-only params */
219 detailmsg
= check_valid_polymorphic_signature(allParams
[i
],
220 parameterTypes
->values
,
224 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
225 errmsg("cannot determine result data type"),
226 errdetail_internal("%s", detailmsg
)));
227 detailmsg
= check_valid_internal_signature(allParams
[i
],
228 parameterTypes
->values
,
232 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
233 errmsg("unsafe use of pseudo-type \"internal\""),
234 errdetail_internal("%s", detailmsg
)));
238 /* Identify variadic argument type, if any */
239 if (paramModes
!= NULL
)
242 * Only the last input parameter can be variadic; if it is, save its
243 * element type. Errors here are just elog since caller should have
244 * checked this already.
246 for (i
= 0; i
< allParamCount
; i
++)
248 switch (paramModes
[i
])
251 case PROARGMODE_INOUT
:
252 if (OidIsValid(variadicType
))
253 elog(ERROR
, "variadic parameter must be last");
256 if (OidIsValid(variadicType
) && prokind
== PROKIND_PROCEDURE
)
257 elog(ERROR
, "variadic parameter must be last");
259 case PROARGMODE_TABLE
:
262 case PROARGMODE_VARIADIC
:
263 if (OidIsValid(variadicType
))
264 elog(ERROR
, "variadic parameter must be last");
265 switch (allParams
[i
])
268 variadicType
= ANYOID
;
271 variadicType
= ANYELEMENTOID
;
273 case ANYCOMPATIBLEARRAYOID
:
274 variadicType
= ANYCOMPATIBLEOID
;
277 variadicType
= get_element_type(allParams
[i
]);
278 if (!OidIsValid(variadicType
))
279 elog(ERROR
, "variadic parameter is not an array");
284 elog(ERROR
, "invalid parameter mode '%c'", paramModes
[i
]);
291 * All seems OK; prepare the data to be inserted into pg_proc.
294 for (i
= 0; i
< Natts_pg_proc
; ++i
)
297 values
[i
] = (Datum
) 0;
301 namestrcpy(&procname
, procedureName
);
302 values
[Anum_pg_proc_proname
- 1] = NameGetDatum(&procname
);
303 values
[Anum_pg_proc_pronamespace
- 1] = ObjectIdGetDatum(procNamespace
);
304 values
[Anum_pg_proc_proowner
- 1] = ObjectIdGetDatum(proowner
);
305 values
[Anum_pg_proc_prolang
- 1] = ObjectIdGetDatum(languageObjectId
);
306 values
[Anum_pg_proc_procost
- 1] = Float4GetDatum(procost
);
307 values
[Anum_pg_proc_prorows
- 1] = Float4GetDatum(prorows
);
308 values
[Anum_pg_proc_provariadic
- 1] = ObjectIdGetDatum(variadicType
);
309 values
[Anum_pg_proc_prosupport
- 1] = ObjectIdGetDatum(prosupport
);
310 values
[Anum_pg_proc_prokind
- 1] = CharGetDatum(prokind
);
311 values
[Anum_pg_proc_prosecdef
- 1] = BoolGetDatum(security_definer
);
312 values
[Anum_pg_proc_proleakproof
- 1] = BoolGetDatum(isLeakProof
);
313 values
[Anum_pg_proc_proisstrict
- 1] = BoolGetDatum(isStrict
);
314 values
[Anum_pg_proc_proretset
- 1] = BoolGetDatum(returnsSet
);
315 values
[Anum_pg_proc_provolatile
- 1] = CharGetDatum(volatility
);
316 values
[Anum_pg_proc_proparallel
- 1] = CharGetDatum(parallel
);
317 values
[Anum_pg_proc_pronargs
- 1] = UInt16GetDatum(parameterCount
);
318 values
[Anum_pg_proc_pronargdefaults
- 1] = UInt16GetDatum(list_length(parameterDefaults
));
319 values
[Anum_pg_proc_prorettype
- 1] = ObjectIdGetDatum(returnType
);
320 values
[Anum_pg_proc_proargtypes
- 1] = PointerGetDatum(parameterTypes
);
321 if (allParameterTypes
!= PointerGetDatum(NULL
))
322 values
[Anum_pg_proc_proallargtypes
- 1] = allParameterTypes
;
324 nulls
[Anum_pg_proc_proallargtypes
- 1] = true;
325 if (parameterModes
!= PointerGetDatum(NULL
))
326 values
[Anum_pg_proc_proargmodes
- 1] = parameterModes
;
328 nulls
[Anum_pg_proc_proargmodes
- 1] = true;
329 if (parameterNames
!= PointerGetDatum(NULL
))
330 values
[Anum_pg_proc_proargnames
- 1] = parameterNames
;
332 nulls
[Anum_pg_proc_proargnames
- 1] = true;
333 if (parameterDefaults
!= NIL
)
334 values
[Anum_pg_proc_proargdefaults
- 1] = CStringGetTextDatum(nodeToString(parameterDefaults
));
336 nulls
[Anum_pg_proc_proargdefaults
- 1] = true;
337 if (trftypes
!= PointerGetDatum(NULL
))
338 values
[Anum_pg_proc_protrftypes
- 1] = trftypes
;
340 nulls
[Anum_pg_proc_protrftypes
- 1] = true;
341 values
[Anum_pg_proc_prosrc
- 1] = CStringGetTextDatum(prosrc
);
343 values
[Anum_pg_proc_probin
- 1] = CStringGetTextDatum(probin
);
345 nulls
[Anum_pg_proc_probin
- 1] = true;
347 values
[Anum_pg_proc_prosqlbody
- 1] = CStringGetTextDatum(nodeToString(prosqlbody
));
349 nulls
[Anum_pg_proc_prosqlbody
- 1] = true;
350 if (proconfig
!= PointerGetDatum(NULL
))
351 values
[Anum_pg_proc_proconfig
- 1] = proconfig
;
353 nulls
[Anum_pg_proc_proconfig
- 1] = true;
354 /* proacl will be determined later */
356 rel
= table_open(ProcedureRelationId
, RowExclusiveLock
);
357 tupDesc
= RelationGetDescr(rel
);
359 /* Check for pre-existing definition */
360 oldtup
= SearchSysCache3(PROCNAMEARGSNSP
,
361 PointerGetDatum(procedureName
),
362 PointerGetDatum(parameterTypes
),
363 ObjectIdGetDatum(procNamespace
));
365 if (HeapTupleIsValid(oldtup
))
367 /* There is one; okay to replace it? */
368 Form_pg_proc oldproc
= (Form_pg_proc
) GETSTRUCT(oldtup
);
375 (errcode(ERRCODE_DUPLICATE_FUNCTION
),
376 errmsg("function \"%s\" already exists with same argument types",
378 if (!object_ownercheck(ProcedureRelationId
, oldproc
->oid
, proowner
))
379 aclcheck_error(ACLCHECK_NOT_OWNER
, OBJECT_FUNCTION
,
382 /* Not okay to change routine kind */
383 if (oldproc
->prokind
!= prokind
)
385 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
386 errmsg("cannot change routine kind"),
387 (oldproc
->prokind
== PROKIND_AGGREGATE
?
388 errdetail("\"%s\" is an aggregate function.", procedureName
) :
389 oldproc
->prokind
== PROKIND_FUNCTION
?
390 errdetail("\"%s\" is a function.", procedureName
) :
391 oldproc
->prokind
== PROKIND_PROCEDURE
?
392 errdetail("\"%s\" is a procedure.", procedureName
) :
393 oldproc
->prokind
== PROKIND_WINDOW
?
394 errdetail("\"%s\" is a window function.", procedureName
) :
397 dropcmd
= (prokind
== PROKIND_PROCEDURE
? "DROP PROCEDURE" :
398 prokind
== PROKIND_AGGREGATE
? "DROP AGGREGATE" :
402 * Not okay to change the return type of the existing proc, since
403 * existing rules, views, etc may depend on the return type.
405 * In case of a procedure, a changing return type means that whether
406 * the procedure has output parameters was changed. Since there is no
407 * user visible return type, we produce a more specific error message.
409 if (returnType
!= oldproc
->prorettype
||
410 returnsSet
!= oldproc
->proretset
)
412 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
413 prokind
== PROKIND_PROCEDURE
414 ? errmsg("cannot change whether a procedure has output parameters")
415 : errmsg("cannot change return type of existing function"),
418 * translator: first %s is DROP FUNCTION, DROP PROCEDURE, or DROP
421 errhint("Use %s %s first.",
423 format_procedure(oldproc
->oid
))));
426 * If it returns RECORD, check for possible change of record type
427 * implied by OUT parameters
429 if (returnType
== RECORDOID
)
434 olddesc
= build_function_result_tupdesc_t(oldtup
);
435 newdesc
= build_function_result_tupdesc_d(prokind
,
439 if (olddesc
== NULL
&& newdesc
== NULL
)
440 /* ok, both are runtime-defined RECORDs */ ;
441 else if (olddesc
== NULL
|| newdesc
== NULL
||
442 !equalTupleDescs(olddesc
, newdesc
))
444 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
445 errmsg("cannot change return type of existing function"),
446 errdetail("Row type defined by OUT parameters is different."),
447 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
448 errhint("Use %s %s first.",
450 format_procedure(oldproc
->oid
))));
454 * If there were any named input parameters, check to make sure the
455 * names have not been changed, as this could break existing calls. We
456 * allow adding names to formerly unnamed parameters, though.
458 proargnames
= SysCacheGetAttr(PROCNAMEARGSNSP
, oldtup
,
459 Anum_pg_proc_proargnames
,
464 char **old_arg_names
;
465 char **new_arg_names
;
470 proargmodes
= SysCacheGetAttr(PROCNAMEARGSNSP
, oldtup
,
471 Anum_pg_proc_proargmodes
,
474 proargmodes
= PointerGetDatum(NULL
); /* just to be sure */
476 n_old_arg_names
= get_func_input_arg_names(proargnames
,
479 n_new_arg_names
= get_func_input_arg_names(parameterNames
,
482 for (j
= 0; j
< n_old_arg_names
; j
++)
484 if (old_arg_names
[j
] == NULL
)
486 if (j
>= n_new_arg_names
|| new_arg_names
[j
] == NULL
||
487 strcmp(old_arg_names
[j
], new_arg_names
[j
]) != 0)
489 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
490 errmsg("cannot change name of input parameter \"%s\"",
492 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
493 errhint("Use %s %s first.",
495 format_procedure(oldproc
->oid
))));
500 * If there are existing defaults, check compatibility: redefinition
501 * must not remove any defaults nor change their types. (Removing a
502 * default might cause a function to fail to satisfy an existing call.
503 * Changing type would only be possible if the associated parameter is
504 * polymorphic, and in such cases a change of default type might alter
505 * the resolved output type of existing calls.)
507 if (oldproc
->pronargdefaults
!= 0)
509 Datum proargdefaults
;
514 if (list_length(parameterDefaults
) < oldproc
->pronargdefaults
)
516 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
517 errmsg("cannot remove parameter defaults from existing function"),
518 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
519 errhint("Use %s %s first.",
521 format_procedure(oldproc
->oid
))));
523 proargdefaults
= SysCacheGetAttr(PROCNAMEARGSNSP
, oldtup
,
524 Anum_pg_proc_proargdefaults
,
527 oldDefaults
= castNode(List
, stringToNode(TextDatumGetCString(proargdefaults
)));
528 Assert(list_length(oldDefaults
) == oldproc
->pronargdefaults
);
530 /* new list can have more defaults than old, advance over 'em */
531 newlc
= list_nth_cell(parameterDefaults
,
532 list_length(parameterDefaults
) -
533 oldproc
->pronargdefaults
);
535 foreach(oldlc
, oldDefaults
)
537 Node
*oldDef
= (Node
*) lfirst(oldlc
);
538 Node
*newDef
= (Node
*) lfirst(newlc
);
540 if (exprType(oldDef
) != exprType(newDef
))
542 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
543 errmsg("cannot change data type of existing parameter default value"),
544 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
545 errhint("Use %s %s first.",
547 format_procedure(oldproc
->oid
))));
548 newlc
= lnext(parameterDefaults
, newlc
);
553 * Do not change existing oid, ownership or permissions, either. Note
554 * dependency-update code below has to agree with this decision.
556 replaces
[Anum_pg_proc_oid
- 1] = false;
557 replaces
[Anum_pg_proc_proowner
- 1] = false;
558 replaces
[Anum_pg_proc_proacl
- 1] = false;
561 tup
= heap_modify_tuple(oldtup
, tupDesc
, values
, nulls
, replaces
);
562 CatalogTupleUpdate(rel
, &tup
->t_self
, tup
);
564 ReleaseSysCache(oldtup
);
569 /* Creating a new procedure */
572 /* First, get default permissions and set up proacl */
573 proacl
= get_user_default_acl(OBJECT_FUNCTION
, proowner
,
576 values
[Anum_pg_proc_proacl
- 1] = PointerGetDatum(proacl
);
578 nulls
[Anum_pg_proc_proacl
- 1] = true;
580 newOid
= GetNewOidWithIndex(rel
, ProcedureOidIndexId
,
582 values
[Anum_pg_proc_oid
- 1] = ObjectIdGetDatum(newOid
);
583 tup
= heap_form_tuple(tupDesc
, values
, nulls
);
584 CatalogTupleInsert(rel
, tup
);
589 retval
= ((Form_pg_proc
) GETSTRUCT(tup
))->oid
;
592 * Create dependencies for the new function. If we are updating an
593 * existing function, first delete any existing pg_depend entries.
594 * (However, since we are not changing ownership or permissions, the
595 * shared dependencies do *not* need to change, and we leave them alone.)
598 deleteDependencyRecordsFor(ProcedureRelationId
, retval
, true);
600 addrs
= new_object_addresses();
602 ObjectAddressSet(myself
, ProcedureRelationId
, retval
);
604 /* dependency on namespace */
605 ObjectAddressSet(referenced
, NamespaceRelationId
, procNamespace
);
606 add_exact_object_address(&referenced
, addrs
);
608 /* dependency on implementation language */
609 ObjectAddressSet(referenced
, LanguageRelationId
, languageObjectId
);
610 add_exact_object_address(&referenced
, addrs
);
612 /* dependency on return type */
613 ObjectAddressSet(referenced
, TypeRelationId
, returnType
);
614 add_exact_object_address(&referenced
, addrs
);
616 /* dependency on transform used by return type, if any */
617 if ((trfid
= get_transform_oid(returnType
, languageObjectId
, true)))
619 ObjectAddressSet(referenced
, TransformRelationId
, trfid
);
620 add_exact_object_address(&referenced
, addrs
);
623 /* dependency on parameter types */
624 for (i
= 0; i
< allParamCount
; i
++)
626 ObjectAddressSet(referenced
, TypeRelationId
, allParams
[i
]);
627 add_exact_object_address(&referenced
, addrs
);
629 /* dependency on transform used by parameter type, if any */
630 if ((trfid
= get_transform_oid(allParams
[i
], languageObjectId
, true)))
632 ObjectAddressSet(referenced
, TransformRelationId
, trfid
);
633 add_exact_object_address(&referenced
, addrs
);
637 /* dependency on support function, if any */
638 if (OidIsValid(prosupport
))
640 ObjectAddressSet(referenced
, ProcedureRelationId
, prosupport
);
641 add_exact_object_address(&referenced
, addrs
);
644 record_object_address_dependencies(&myself
, addrs
, DEPENDENCY_NORMAL
);
645 free_object_addresses(addrs
);
647 /* dependency on SQL routine body */
648 if (languageObjectId
== SQLlanguageId
&& prosqlbody
)
649 recordDependencyOnExpr(&myself
, prosqlbody
, NIL
, DEPENDENCY_NORMAL
);
651 /* dependency on parameter default expressions */
652 if (parameterDefaults
)
653 recordDependencyOnExpr(&myself
, (Node
*) parameterDefaults
,
654 NIL
, DEPENDENCY_NORMAL
);
656 /* dependency on owner */
658 recordDependencyOnOwner(ProcedureRelationId
, retval
, proowner
);
660 /* dependency on any roles mentioned in ACL */
662 recordDependencyOnNewAcl(ProcedureRelationId
, retval
, 0,
665 /* dependency on extension */
666 recordDependencyOnCurrentExtension(&myself
, is_update
);
670 /* Post creation hook for new function */
671 InvokeObjectPostCreateHook(ProcedureRelationId
, retval
, 0);
673 table_close(rel
, RowExclusiveLock
);
675 /* Verify function body */
676 if (OidIsValid(languageValidator
))
678 ArrayType
*set_items
= NULL
;
679 int save_nestlevel
= 0;
681 /* Advance command counter so new tuple can be seen by validator */
682 CommandCounterIncrement();
685 * Set per-function configuration parameters so that the validation is
686 * done with the environment the function expects. However, if
687 * check_function_bodies is off, we don't do this, because that would
688 * create dump ordering hazards that pg_dump doesn't know how to deal
689 * with. (For example, a SET clause might refer to a not-yet-created
690 * text search configuration.) This means that the validator
691 * shouldn't complain about anything that might depend on a GUC
692 * parameter when check_function_bodies is off.
694 if (check_function_bodies
)
696 set_items
= (ArrayType
*) DatumGetPointer(proconfig
);
697 if (set_items
) /* Need a new GUC nesting level */
699 save_nestlevel
= NewGUCNestLevel();
700 ProcessGUCArray(set_items
,
701 (superuser() ? PGC_SUSET
: PGC_USERSET
),
707 OidFunctionCall1(languageValidator
, ObjectIdGetDatum(retval
));
710 AtEOXact_GUC(true, save_nestlevel
);
713 /* ensure that stats are dropped if transaction aborts */
715 pgstat_create_function(retval
);
723 * Validator for internal functions
725 * Check that the given internal function name (the "prosrc" value) is
726 * a known builtin function.
729 fmgr_internal_validator(PG_FUNCTION_ARGS
)
731 Oid funcoid
= PG_GETARG_OID(0);
737 if (!CheckFunctionValidatorAccess(fcinfo
->flinfo
->fn_oid
, funcoid
))
741 * We do not honor check_function_bodies since it's unlikely the function
742 * name will be found later if it isn't there now.
745 tuple
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcoid
));
746 if (!HeapTupleIsValid(tuple
))
747 elog(ERROR
, "cache lookup failed for function %u", funcoid
);
749 tmp
= SysCacheGetAttr(PROCOID
, tuple
, Anum_pg_proc_prosrc
, &isnull
);
751 elog(ERROR
, "null prosrc");
752 prosrc
= TextDatumGetCString(tmp
);
754 if (fmgr_internal_function(prosrc
) == InvalidOid
)
756 (errcode(ERRCODE_UNDEFINED_FUNCTION
),
757 errmsg("there is no built-in function named \"%s\"",
760 ReleaseSysCache(tuple
);
768 * Validator for C language functions
770 * Make sure that the library file exists, is loadable, and contains
771 * the specified link symbol. Also check for a valid function
772 * information record.
775 fmgr_c_validator(PG_FUNCTION_ARGS
)
777 Oid funcoid
= PG_GETARG_OID(0);
785 if (!CheckFunctionValidatorAccess(fcinfo
->flinfo
->fn_oid
, funcoid
))
789 * It'd be most consistent to skip the check if !check_function_bodies,
790 * but the purpose of that switch is to be helpful for pg_dump loading,
791 * and for pg_dump loading it's much better if we *do* check.
794 tuple
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcoid
));
795 if (!HeapTupleIsValid(tuple
))
796 elog(ERROR
, "cache lookup failed for function %u", funcoid
);
798 tmp
= SysCacheGetAttr(PROCOID
, tuple
, Anum_pg_proc_prosrc
, &isnull
);
800 elog(ERROR
, "null prosrc for C function %u", funcoid
);
801 prosrc
= TextDatumGetCString(tmp
);
803 tmp
= SysCacheGetAttr(PROCOID
, tuple
, Anum_pg_proc_probin
, &isnull
);
805 elog(ERROR
, "null probin for C function %u", funcoid
);
806 probin
= TextDatumGetCString(tmp
);
808 (void) load_external_function(probin
, prosrc
, true, &libraryhandle
);
809 (void) fetch_finfo_record(libraryhandle
, prosrc
);
811 ReleaseSysCache(tuple
);
818 * Validator for SQL language functions
820 * Parse it here in order to be sure that it contains no syntax errors.
823 fmgr_sql_validator(PG_FUNCTION_ARGS
)
825 Oid funcoid
= PG_GETARG_OID(0);
828 List
*raw_parsetree_list
;
829 List
*querytree_list
;
834 parse_error_callback_arg callback_arg
;
835 ErrorContextCallback sqlerrcontext
;
839 if (!CheckFunctionValidatorAccess(fcinfo
->flinfo
->fn_oid
, funcoid
))
842 tuple
= SearchSysCache1(PROCOID
, ObjectIdGetDatum(funcoid
));
843 if (!HeapTupleIsValid(tuple
))
844 elog(ERROR
, "cache lookup failed for function %u", funcoid
);
845 proc
= (Form_pg_proc
) GETSTRUCT(tuple
);
847 /* Disallow pseudotype result */
848 /* except for RECORD, VOID, or polymorphic */
849 if (get_typtype(proc
->prorettype
) == TYPTYPE_PSEUDO
&&
850 proc
->prorettype
!= RECORDOID
&&
851 proc
->prorettype
!= VOIDOID
&&
852 !IsPolymorphicType(proc
->prorettype
))
854 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
855 errmsg("SQL functions cannot return type %s",
856 format_type_be(proc
->prorettype
))));
858 /* Disallow pseudotypes in arguments */
859 /* except for polymorphic */
861 for (i
= 0; i
< proc
->pronargs
; i
++)
863 if (get_typtype(proc
->proargtypes
.values
[i
]) == TYPTYPE_PSEUDO
)
865 if (IsPolymorphicType(proc
->proargtypes
.values
[i
]))
869 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
870 errmsg("SQL functions cannot have arguments of type %s",
871 format_type_be(proc
->proargtypes
.values
[i
]))));
875 /* Postpone body checks if !check_function_bodies */
876 if (check_function_bodies
)
878 tmp
= SysCacheGetAttr(PROCOID
, tuple
, Anum_pg_proc_prosrc
, &isnull
);
880 elog(ERROR
, "null prosrc");
882 prosrc
= TextDatumGetCString(tmp
);
885 * Setup error traceback support for ereport().
887 callback_arg
.proname
= NameStr(proc
->proname
);
888 callback_arg
.prosrc
= prosrc
;
890 sqlerrcontext
.callback
= sql_function_parse_error_callback
;
891 sqlerrcontext
.arg
= (void *) &callback_arg
;
892 sqlerrcontext
.previous
= error_context_stack
;
893 error_context_stack
= &sqlerrcontext
;
895 /* If we have prosqlbody, pay attention to that not prosrc */
896 tmp
= SysCacheGetAttr(PROCOID
, tuple
, Anum_pg_proc_prosqlbody
, &isnull
);
900 List
*stored_query_list
;
902 n
= stringToNode(TextDatumGetCString(tmp
));
904 stored_query_list
= linitial(castNode(List
, n
));
906 stored_query_list
= list_make1(n
);
908 querytree_list
= NIL
;
909 foreach(lc
, stored_query_list
)
911 Query
*parsetree
= lfirst_node(Query
, lc
);
912 List
*querytree_sublist
;
915 * Typically, we'd have acquired locks already while parsing
916 * the body of the CREATE FUNCTION command. However, a
917 * validator function cannot assume that it's only called in
920 AcquireRewriteLocks(parsetree
, true, false);
921 querytree_sublist
= pg_rewrite_query(parsetree
);
922 querytree_list
= lappend(querytree_list
, querytree_sublist
);
928 * We can't do full prechecking of the function definition if
929 * there are any polymorphic input types, because actual datatypes
930 * of expression results will be unresolvable. The check will be
931 * done at runtime instead.
933 * We can run the text through the raw parser though; this will at
934 * least catch silly syntactic errors.
936 raw_parsetree_list
= pg_parse_query(prosrc
);
937 querytree_list
= NIL
;
942 * OK to do full precheck: analyze and rewrite the queries,
943 * then verify the result type.
945 SQLFunctionParseInfoPtr pinfo
;
947 /* But first, set up parameter information */
948 pinfo
= prepare_sql_fn_parse_info(tuple
, NULL
, InvalidOid
);
950 foreach(lc
, raw_parsetree_list
)
952 RawStmt
*parsetree
= lfirst_node(RawStmt
, lc
);
953 List
*querytree_sublist
;
955 querytree_sublist
= pg_analyze_and_rewrite_withcb(parsetree
,
957 (ParserSetupHook
) sql_fn_parser_setup
,
960 querytree_list
= lappend(querytree_list
,
969 TupleDesc rettupdesc
;
971 check_sql_fn_statements(querytree_list
);
973 (void) get_func_result_type(funcoid
, &rettype
, &rettupdesc
);
975 (void) check_sql_fn_retval(querytree_list
,
980 error_context_stack
= sqlerrcontext
.previous
;
983 ReleaseSysCache(tuple
);
989 * Error context callback for handling errors in SQL function definitions
992 sql_function_parse_error_callback(void *arg
)
994 parse_error_callback_arg
*callback_arg
= (parse_error_callback_arg
*) arg
;
996 /* See if it's a syntax error; if so, transpose to CREATE FUNCTION */
997 if (!function_parse_error_transpose(callback_arg
->prosrc
))
999 /* If it's not a syntax error, push info onto context stack */
1000 errcontext("SQL function \"%s\"", callback_arg
->proname
);
1005 * Adjust a syntax error occurring inside the function body of a CREATE
1006 * FUNCTION or DO command. This can be used by any function validator or
1007 * anonymous-block handler, not only for SQL-language functions.
1008 * It is assumed that the syntax error position is initially relative to the
1009 * function body string (as passed in). If possible, we adjust the position
1010 * to reference the original command text; if we can't manage that, we set
1011 * up an "internal query" syntax error instead.
1013 * Returns true if a syntax error was processed, false if not.
1016 function_parse_error_transpose(const char *prosrc
)
1018 int origerrposition
;
1022 * Nothing to do unless we are dealing with a syntax error that has a
1025 * Some PLs may prefer to report the error position as an internal error
1026 * to begin with, so check that too.
1028 origerrposition
= geterrposition();
1029 if (origerrposition
<= 0)
1031 origerrposition
= getinternalerrposition();
1032 if (origerrposition
<= 0)
1036 /* We can get the original query text from the active portal (hack...) */
1037 if (ActivePortal
&& ActivePortal
->status
== PORTAL_ACTIVE
)
1039 const char *queryText
= ActivePortal
->sourceText
;
1041 /* Try to locate the prosrc in the original text */
1042 newerrposition
= match_prosrc_to_query(prosrc
, queryText
,
1048 * Quietly give up if no ActivePortal. This is an unusual situation
1049 * but it can happen in, e.g., logical replication workers.
1051 newerrposition
= -1;
1054 if (newerrposition
> 0)
1056 /* Successful, so fix error position to reference original query */
1057 errposition(newerrposition
);
1058 /* Get rid of any report of the error as an "internal query" */
1059 internalerrposition(0);
1060 internalerrquery(NULL
);
1065 * If unsuccessful, convert the position to an internal position
1066 * marker and give the function text as the internal query.
1069 internalerrposition(origerrposition
);
1070 internalerrquery(prosrc
);
1077 * Try to locate the string literal containing the function body in the
1078 * given text of the CREATE FUNCTION or DO command. If successful, return
1079 * the character (not byte) index within the command corresponding to the
1080 * given character index within the literal. If not successful, return 0.
1083 match_prosrc_to_query(const char *prosrc
, const char *queryText
,
1087 * Rather than fully parsing the original command, we just scan the
1088 * command looking for $prosrc$ or 'prosrc'. This could be fooled (though
1089 * not in any very probable scenarios), so fail if we find more than one
1092 int prosrclen
= strlen(prosrc
);
1093 int querylen
= strlen(queryText
);
1098 for (curpos
= 0; curpos
< querylen
- prosrclen
; curpos
++)
1100 if (queryText
[curpos
] == '$' &&
1101 strncmp(prosrc
, &queryText
[curpos
+ 1], prosrclen
) == 0 &&
1102 queryText
[curpos
+ 1 + prosrclen
] == '$')
1105 * Found a $foo$ match. Since there are no embedded quoting
1106 * characters in a dollar-quoted literal, we don't have to do any
1107 * fancy arithmetic; just offset by the starting position.
1110 return 0; /* multiple matches, fail */
1111 matchpos
= pg_mbstrlen_with_len(queryText
, curpos
+ 1)
1114 else if (queryText
[curpos
] == '\'' &&
1115 match_prosrc_to_literal(prosrc
, &queryText
[curpos
+ 1],
1116 cursorpos
, &newcursorpos
))
1119 * Found a 'foo' match. match_prosrc_to_literal() has adjusted
1120 * for any quotes or backslashes embedded in the literal.
1123 return 0; /* multiple matches, fail */
1124 matchpos
= pg_mbstrlen_with_len(queryText
, curpos
+ 1)
1133 * Try to match the given source text to a single-quoted literal.
1134 * If successful, adjust newcursorpos to correspond to the character
1135 * (not byte) index corresponding to cursorpos in the source text.
1137 * At entry, literal points just past a ' character. We must check for the
1141 match_prosrc_to_literal(const char *prosrc
, const char *literal
,
1142 int cursorpos
, int *newcursorpos
)
1144 int newcp
= cursorpos
;
1148 * This implementation handles backslashes and doubled quotes in the
1149 * string literal. It does not handle the SQL syntax for literals
1150 * continued across line boundaries.
1152 * We do the comparison a character at a time, not a byte at a time, so
1153 * that we can do the correct cursorpos math.
1157 cursorpos
--; /* characters left before cursor */
1160 * Check for backslashes and doubled quotes in the literal; adjust
1161 * newcp when one is found before the cursor.
1163 if (*literal
== '\\')
1169 else if (*literal
== '\'')
1171 if (literal
[1] != '\'')
1177 chlen
= pg_mblen(prosrc
);
1178 if (strncmp(prosrc
, literal
, chlen
) != 0)
1184 if (*literal
== '\'' && literal
[1] != '\'')
1187 *newcursorpos
= newcp
;
1192 /* Must set *newcursorpos to suppress compiler warning */
1193 *newcursorpos
= newcp
;
1198 oid_array_to_list(Datum datum
)
1200 ArrayType
*array
= DatumGetArrayTypeP(datum
);
1206 deconstruct_array_builtin(array
, OIDOID
, &values
, NULL
, &nelems
);
1207 for (i
= 0; i
< nelems
; i
++)
1208 result
= lappend_oid(result
, values
[i
]);