97{
99 int parameterCount;
100 int allParamCount;
102 char *paramModes = NULL;
108 bool nulls[Natts_pg_proc];
110 bool replaces[Natts_pg_proc];
113 bool is_update;
115 referenced;
116 char *detailmsg;
120
121
122
123
125
126 parameterCount = parameterTypes->
dim1;
129 (
errcode(ERRCODE_TOO_MANY_ARGUMENTS),
131 "functions cannot have more than %d arguments",
134
135
136
138 {
139
140
141
142
143
145
146 allParamCount =
ARR_DIMS(allParamArray)[0];
148 allParamCount <= 0 ||
151 elog(
ERROR,
"allParameterTypes is not a 1-D Oid array");
153 Assert(allParamCount >= parameterCount);
154
155 }
156 else
157 {
158 allParamCount = parameterCount;
159 allParams = parameterTypes->
values;
160 }
161
163 {
164
165
166
167
168
170
172 ARR_DIMS(modesArray)[0] != allParamCount ||
175 elog(
ERROR,
"parameterModes is not a 1-D char array");
177 }
178
179
180
181
182
185 parameterCount);
186 if (detailmsg)
188 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
189 errmsg(
"cannot determine result data type"),
191
192
193
194
195
198 parameterCount);
199 if (detailmsg)
201 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
202 errmsg(
"unsafe use of pseudo-type \"internal\""),
204
205
206
207
209 {
210 for (
i = 0;
i < allParamCount;
i++)
211 {
212 if (paramModes == NULL ||
213 paramModes[
i] == PROARGMODE_IN ||
214 paramModes[
i] == PROARGMODE_VARIADIC)
215 continue;
216
219 parameterCount);
220 if (detailmsg)
222 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
223 errmsg(
"cannot determine result data type"),
227 parameterCount);
228 if (detailmsg)
230 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
231 errmsg(
"unsafe use of pseudo-type \"internal\""),
233 }
234 }
235
236
237 if (paramModes != NULL)
238 {
239
240
241
242
243
244 for (
i = 0;
i < allParamCount;
i++)
245 {
246 switch (paramModes[
i])
247 {
248 case PROARGMODE_IN:
249 case PROARGMODE_INOUT:
251 elog(
ERROR,
"variadic parameter must be last");
252 break;
253 case PROARGMODE_OUT:
254 if (
OidIsValid(variadicType) && prokind == PROKIND_PROCEDURE)
255 elog(
ERROR,
"variadic parameter must be last");
256 break;
257 case PROARGMODE_TABLE:
258
259 break;
260 case PROARGMODE_VARIADIC:
262 elog(
ERROR,
"variadic parameter must be last");
263 switch (allParams[
i])
264 {
265 case ANYOID:
266 variadicType = ANYOID;
267 break;
268 case ANYARRAYOID:
269 variadicType = ANYELEMENTOID;
270 break;
271 case ANYCOMPATIBLEARRAYOID:
272 variadicType = ANYCOMPATIBLEOID;
273 break;
274 default:
277 elog(
ERROR,
"variadic parameter is not an array");
278 break;
279 }
280 break;
281 default:
282 elog(
ERROR,
"invalid parameter mode '%c'", paramModes[
i]);
283 break;
284 }
285 }
286 }
287
288
289
290
291
292 for (
i = 0;
i < Natts_pg_proc; ++
i)
293 {
297 }
298
320 values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
321 else
322 nulls[Anum_pg_proc_proallargtypes - 1] = true;
324 values[Anum_pg_proc_proargmodes - 1] = parameterModes;
325 else
326 nulls[Anum_pg_proc_proargmodes - 1] = true;
328 values[Anum_pg_proc_proargnames - 1] = parameterNames;
329 else
330 nulls[Anum_pg_proc_proargnames - 1] = true;
331 if (parameterDefaults !=
NIL)
333 else
334 nulls[Anum_pg_proc_proargdefaults - 1] = true;
336 values[Anum_pg_proc_protrftypes - 1] = trftypes;
337 else
338 nulls[Anum_pg_proc_protrftypes - 1] = true;
340 if (probin)
342 else
343 nulls[Anum_pg_proc_probin - 1] = true;
344 if (prosqlbody)
346 else
347 nulls[Anum_pg_proc_prosqlbody - 1] = true;
349 values[Anum_pg_proc_proconfig - 1] = proconfig;
350 else
351 nulls[Anum_pg_proc_proconfig - 1] = true;
352
353
356
357
362
364 {
365
368 bool isnull;
369 const char *dropcmd;
370
371 if (!replace)
373 (
errcode(ERRCODE_DUPLICATE_FUNCTION),
374 errmsg(
"function \"%s\" already exists with same argument types",
375 procedureName)));
378 procedureName);
379
380
381 if (oldproc->prokind != prokind)
383 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
384 errmsg(
"cannot change routine kind"),
385 (oldproc->prokind == PROKIND_AGGREGATE ?
386 errdetail(
"\"%s\" is an aggregate function.", procedureName) :
387 oldproc->prokind == PROKIND_FUNCTION ?
388 errdetail(
"\"%s\" is a function.", procedureName) :
389 oldproc->prokind == PROKIND_PROCEDURE ?
390 errdetail(
"\"%s\" is a procedure.", procedureName) :
391 oldproc->prokind == PROKIND_WINDOW ?
392 errdetail(
"\"%s\" is a window function.", procedureName) :
393 0)));
394
395 dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" :
396 prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" :
397 "DROP FUNCTION");
398
399
400
401
402
403
404
405
406
407 if (returnType != oldproc->prorettype ||
408 returnsSet != oldproc->proretset)
410 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
411 prokind == PROKIND_PROCEDURE
412 ?
errmsg(
"cannot change whether a procedure has output parameters")
413 :
errmsg(
"cannot change return type of existing function"),
414
415
416
417
418
420 dropcmd,
422
423
424
425
426
427 if (returnType == RECORDOID)
428 {
431
434 allParameterTypes,
435 parameterModes,
436 parameterNames);
437 if (olddesc == NULL && newdesc == NULL)
438 ;
439 else if (olddesc == NULL || newdesc == NULL ||
442 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
443 errmsg(
"cannot change return type of existing function"),
444 errdetail(
"Row type defined by OUT parameters is different."),
445
447 dropcmd,
449 }
450
451
452
453
454
455
457 Anum_pg_proc_proargnames,
458 &isnull);
459 if (!isnull)
460 {
462 char **old_arg_names;
463 char **new_arg_names;
464 int n_old_arg_names;
465 int n_new_arg_names;
467
469 Anum_pg_proc_proargmodes,
470 &isnull);
471 if (isnull)
473
475 proargmodes,
476 &old_arg_names);
478 parameterModes,
479 &new_arg_names);
480 for (
j = 0;
j < n_old_arg_names;
j++)
481 {
482 if (old_arg_names[
j] == NULL)
483 continue;
484 if (
j >= n_new_arg_names || new_arg_names[
j] == NULL ||
485 strcmp(old_arg_names[
j], new_arg_names[
j]) != 0)
487 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
488 errmsg(
"cannot change name of input parameter \"%s\"",
490
492 dropcmd,
494 }
495 }
496
497
498
499
500
501
502
503
504
505 if (oldproc->pronargdefaults != 0)
506 {
507 Datum proargdefaults;
511
512 if (
list_length(parameterDefaults) < oldproc->pronargdefaults)
514 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
515 errmsg(
"cannot remove parameter defaults from existing function"),
516
518 dropcmd,
520
522 Anum_pg_proc_proargdefaults);
525
526
529 oldproc->pronargdefaults);
530
531 foreach(oldlc, oldDefaults)
532 {
535
538 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
539 errmsg(
"cannot change data type of existing parameter default value"),
540
542 dropcmd,
544 newlc =
lnext(parameterDefaults, newlc);
545 }
546 }
547
548
549
550
551
552 replaces[Anum_pg_proc_oid - 1] = false;
553 replaces[Anum_pg_proc_proowner - 1] = false;
554 replaces[Anum_pg_proc_proacl - 1] = false;
555
556
559
561 is_update = true;
562 }
563 else
564 {
565
567
568
570 procNamespace);
571 if (proacl != NULL)
573 else
574 nulls[Anum_pg_proc_proacl - 1] = true;
575
577 Anum_pg_proc_oid);
581 is_update = false;
582 }
583
584
586
587
588
589
590
591
592
593 if (is_update)
595
597
599
600
603
604
607
608
611
612
614 {
617 }
618
619
620 for (
i = 0;
i < allParamCount;
i++)
621 {
624
625
627 {
630 }
631 }
632
633
635 {
638 }
639
642
643
644 if (languageObjectId == SQLlanguageId && prosqlbody)
646
647
648 if (parameterDefaults)
651
652
653 if (!is_update)
655
656
657 if (!is_update)
659 proowner, proacl);
660
661
663
665
666
668
670
671
673 {
675 int save_nestlevel = 0;
676
677
679
680
681
682
683
684
685
686
687
688
689
691 {
693 if (set_items)
694 {
700 }
701 }
702
704
705 if (set_items)
707 }
708
709
710 if (!is_update)
712
713 return myself;
714}
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
#define Assert(condition)
#define PointerIsValid(pointer)
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
int errdetail_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define OidFunctionCall1(functionId, arg1)
TupleDesc build_function_result_tupdesc_t(HeapTuple procTuple)
TupleDesc build_function_result_tupdesc_d(char prokind, Datum proallargtypes, Datum proargmodes, Datum proargnames)
int get_func_input_arg_names(Datum proargnames, Datum proargmodes, char ***arg_names)
Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok)
int NewGUCNestLevel(void)
void ProcessGUCArray(ArrayType *array, GucContext context, GucSource source, GucAction action)
void AtEOXact_GUC(bool isCommit, int nestLevel)
bool check_function_bodies
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Oid get_element_type(Oid typid)
void namestrcpy(Name name, const char *str)
Oid exprType(const Node *expr)
#define castNode(_type_, nodeptr)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define ObjectAddressSet(addr, class_id, object_id)
char * nodeToString(const void *obj)
char * check_valid_internal_signature(Oid ret_type, const Oid *declared_arg_types, int nargs)
char * check_valid_polymorphic_signature(Oid ret_type, const Oid *declared_arg_types, int nargs)
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
static int list_length(const List *l)
static ListCell * list_nth_cell(const List *list, int n)
static ListCell * lnext(const List *l, const ListCell *c)
FormData_pg_proc * Form_pg_proc
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
void pgstat_create_function(Oid proid)
static Datum PointerGetDatum(const void *X)
static Datum Float4GetDatum(float4 X)
static Datum UInt16GetDatum(uint16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum NameGetDatum(const NameData *X)
static Pointer DatumGetPointer(Datum X)
static Datum CharGetDatum(char X)
void * stringToNode(const char *str)
char * format_procedure(Oid procedure_oid)
#define RelationGetDescr(relation)
Oid values[FLEXIBLE_ARRAY_MEMBER]
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
bool equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2)
void CommandCounterIncrement(void)