126{
128 int parameterCount;
129 int allParamCount;
131 char *paramModes = NULL;
137 bool nulls[Natts_pg_proc];
139 bool replaces[Natts_pg_proc];
142 bool is_update;
144 referenced;
145 char *detailmsg;
148
149
150
151
153
154 parameterCount = parameterTypes->
dim1;
157 (
errcode(ERRCODE_TOO_MANY_ARGUMENTS),
159 "functions cannot have more than %d arguments",
162
163
164
166 {
167
168
169
170
171
173
174 allParamCount =
ARR_DIMS(allParamArray)[0];
176 allParamCount <= 0 ||
179 elog(
ERROR,
"allParameterTypes is not a 1-D Oid array");
181 Assert(allParamCount >= parameterCount);
182
183 }
184 else
185 {
186 allParamCount = parameterCount;
187 allParams = parameterTypes->
values;
188 }
189
191 {
192
193
194
195
196
198
200 ARR_DIMS(modesArray)[0] != allParamCount ||
203 elog(
ERROR,
"parameterModes is not a 1-D char array");
205 }
206
207
208
209
210
213 parameterCount);
214 if (detailmsg)
216 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
217 errmsg(
"cannot determine result data type"),
219
220
221
222
223
226 parameterCount);
227 if (detailmsg)
229 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
230 errmsg(
"unsafe use of pseudo-type \"internal\""),
232
233
234
235
237 {
238 for (
i = 0;
i < allParamCount;
i++)
239 {
240 if (paramModes == NULL ||
241 paramModes[
i] == PROARGMODE_IN ||
242 paramModes[
i] == PROARGMODE_VARIADIC)
243 continue;
244
247 parameterCount);
248 if (detailmsg)
250 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
251 errmsg(
"cannot determine result data type"),
255 parameterCount);
256 if (detailmsg)
258 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
259 errmsg(
"unsafe use of pseudo-type \"internal\""),
261 }
262 }
263
264
265 if (paramModes != NULL)
266 {
267
268
269
270
271
272 for (
i = 0;
i < allParamCount;
i++)
273 {
274 switch (paramModes[
i])
275 {
276 case PROARGMODE_IN:
277 case PROARGMODE_INOUT:
279 elog(
ERROR,
"variadic parameter must be last");
280 break;
281 case PROARGMODE_OUT:
282 if (
OidIsValid(variadicType) && prokind == PROKIND_PROCEDURE)
283 elog(
ERROR,
"variadic parameter must be last");
284 break;
285 case PROARGMODE_TABLE:
286
287 break;
288 case PROARGMODE_VARIADIC:
290 elog(
ERROR,
"variadic parameter must be last");
291 switch (allParams[
i])
292 {
293 case ANYOID:
294 variadicType = ANYOID;
295 break;
296 case ANYARRAYOID:
297 variadicType = ANYELEMENTOID;
298 break;
299 case ANYCOMPATIBLEARRAYOID:
300 variadicType = ANYCOMPATIBLEOID;
301 break;
302 default:
305 elog(
ERROR,
"variadic parameter is not an array");
306 break;
307 }
308 break;
309 default:
310 elog(
ERROR,
"invalid parameter mode '%c'", paramModes[
i]);
311 break;
312 }
313 }
314 }
315
316
317
318
319
320 for (
i = 0;
i < Natts_pg_proc; ++
i)
321 {
325 }
326
348 values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
349 else
350 nulls[Anum_pg_proc_proallargtypes - 1] = true;
352 values[Anum_pg_proc_proargmodes - 1] = parameterModes;
353 else
354 nulls[Anum_pg_proc_proargmodes - 1] = true;
356 values[Anum_pg_proc_proargnames - 1] = parameterNames;
357 else
358 nulls[Anum_pg_proc_proargnames - 1] = true;
359 if (parameterDefaults !=
NIL)
361 else
362 nulls[Anum_pg_proc_proargdefaults - 1] = true;
364 values[Anum_pg_proc_protrftypes - 1] = trftypes;
365 else
366 nulls[Anum_pg_proc_protrftypes - 1] = true;
368 if (probin)
370 else
371 nulls[Anum_pg_proc_probin - 1] = true;
372 if (prosqlbody)
374 else
375 nulls[Anum_pg_proc_prosqlbody - 1] = true;
377 values[Anum_pg_proc_proconfig - 1] = proconfig;
378 else
379 nulls[Anum_pg_proc_proconfig - 1] = true;
380
381
384
385
390
392 {
393
396 bool isnull;
397 const char *dropcmd;
398
399 if (!replace)
401 (
errcode(ERRCODE_DUPLICATE_FUNCTION),
402 errmsg(
"function \"%s\" already exists with same argument types",
403 procedureName)));
406 procedureName);
407
408
409 if (oldproc->prokind != prokind)
411 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
412 errmsg(
"cannot change routine kind"),
413 (oldproc->prokind == PROKIND_AGGREGATE ?
414 errdetail(
"\"%s\" is an aggregate function.", procedureName) :
415 oldproc->prokind == PROKIND_FUNCTION ?
416 errdetail(
"\"%s\" is a function.", procedureName) :
417 oldproc->prokind == PROKIND_PROCEDURE ?
418 errdetail(
"\"%s\" is a procedure.", procedureName) :
419 oldproc->prokind == PROKIND_WINDOW ?
420 errdetail(
"\"%s\" is a window function.", procedureName) :
421 0)));
422
423 dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" :
424 prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" :
425 "DROP FUNCTION");
426
427
428
429
430
431
432
433
434
435 if (returnType != oldproc->prorettype ||
436 returnsSet != oldproc->proretset)
438 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
439 prokind == PROKIND_PROCEDURE
440 ?
errmsg(
"cannot change whether a procedure has output parameters")
441 :
errmsg(
"cannot change return type of existing function"),
442
443
444
445
446
448 dropcmd,
450
451
452
453
454
455 if (returnType == RECORDOID)
456 {
459
462 allParameterTypes,
463 parameterModes,
464 parameterNames);
465 if (olddesc == NULL && newdesc == NULL)
466 ;
467 else if (olddesc == NULL || newdesc == NULL ||
470 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
471 errmsg(
"cannot change return type of existing function"),
472 errdetail(
"Row type defined by OUT parameters is different."),
473
475 dropcmd,
477 }
478
479
480
481
482
483
485 Anum_pg_proc_proargnames,
486 &isnull);
487 if (!isnull)
488 {
490 char **old_arg_names;
491 char **new_arg_names;
492 int n_old_arg_names;
493 int n_new_arg_names;
495
497 Anum_pg_proc_proargmodes,
498 &isnull);
499 if (isnull)
501
503 proargmodes,
504 &old_arg_names);
506 parameterModes,
507 &new_arg_names);
508 for (
j = 0;
j < n_old_arg_names;
j++)
509 {
510 if (old_arg_names[
j] == NULL)
511 continue;
512 if (
j >= n_new_arg_names || new_arg_names[
j] == NULL ||
513 strcmp(old_arg_names[
j], new_arg_names[
j]) != 0)
515 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
516 errmsg(
"cannot change name of input parameter \"%s\"",
518
520 dropcmd,
522 }
523 }
524
525
526
527
528
529
530
531
532
533 if (oldproc->pronargdefaults != 0)
534 {
535 Datum proargdefaults;
539
540 if (
list_length(parameterDefaults) < oldproc->pronargdefaults)
542 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
543 errmsg(
"cannot remove parameter defaults from existing function"),
544
546 dropcmd,
548
550 Anum_pg_proc_proargdefaults);
553
554
557 oldproc->pronargdefaults);
558
559 foreach(oldlc, oldDefaults)
560 {
563
566 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
567 errmsg(
"cannot change data type of existing parameter default value"),
568
570 dropcmd,
572 newlc =
lnext(parameterDefaults, newlc);
573 }
574 }
575
576
577
578
579
580 replaces[Anum_pg_proc_oid - 1] = false;
581 replaces[Anum_pg_proc_proowner - 1] = false;
582 replaces[Anum_pg_proc_proacl - 1] = false;
583
584
587
589 is_update = true;
590 }
591 else
592 {
593
595
596
598 procNamespace);
599 if (proacl != NULL)
601 else
602 nulls[Anum_pg_proc_proacl - 1] = true;
603
605 Anum_pg_proc_oid);
609 is_update = false;
610 }
611
612
614
615
616
617
618
619
620
621 if (is_update)
623
625
627
628
631
632
635
636
639
640
641 for (
i = 0;
i < allParamCount;
i++)
642 {
645 }
646
647
649 {
652 }
653
654
656 {
659 }
660
663
664
665 if (languageObjectId == SQLlanguageId && prosqlbody)
667
668
669 if (parameterDefaults)
672
673
674 if (!is_update)
676
677
678 if (!is_update)
680 proowner, proacl);
681
682
684
686
687
689
691
692
694 {
696 int save_nestlevel = 0;
697
698
700
701
702
703
704
705
706
707
708
709
710
712 {
714 if (set_items)
715 {
721 }
722 }
723
725
726 if (set_items)
728 }
729
730
731 if (!is_update)
733
734 return myself;
735}
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 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)
int NewGUCNestLevel(void)
void ProcessGUCArray(ArrayType *array, GucContext context, GucSource source, GucAction action)
void AtEOXact_GUC(bool isCommit, int nestLevel)
bool check_function_bodies
Assert(PointerIsAligned(start, uint64))
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)
static void * GETSTRUCT(const HeapTupleData *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)
#define foreach_oid(var, lst)
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)