127{
129 int parameterCount;
130 int allParamCount;
132 char *paramModes = NULL;
138 bool nulls[Natts_pg_proc];
140 bool replaces[Natts_pg_proc];
143 bool is_update;
145 referenced,
146 temp_object;
147 char *detailmsg;
150
151
152
153
155
156 parameterCount = parameterTypes->
dim1;
159 (
errcode(ERRCODE_TOO_MANY_ARGUMENTS),
161 "functions cannot have more than %d arguments",
164
165
166
168 {
169
170
171
172
173
175
176 allParamCount =
ARR_DIMS(allParamArray)[0];
178 allParamCount <= 0 ||
181 elog(
ERROR,
"allParameterTypes is not a 1-D Oid array");
183 Assert(allParamCount >= parameterCount);
184
185 }
186 else
187 {
188 allParamCount = parameterCount;
189 allParams = parameterTypes->
values;
190 }
191
193 {
194
195
196
197
198
200
202 ARR_DIMS(modesArray)[0] != allParamCount ||
205 elog(
ERROR,
"parameterModes is not a 1-D char array");
207 }
208
209
210
211
212
215 parameterCount);
216 if (detailmsg)
218 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
219 errmsg(
"cannot determine result data type"),
221
222
223
224
225
228 parameterCount);
229 if (detailmsg)
231 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
232 errmsg(
"unsafe use of pseudo-type \"internal\""),
234
235
236
237
239 {
240 for (
i = 0;
i < allParamCount;
i++)
241 {
242 if (paramModes == NULL ||
243 paramModes[
i] == PROARGMODE_IN ||
244 paramModes[
i] == PROARGMODE_VARIADIC)
245 continue;
246
249 parameterCount);
250 if (detailmsg)
252 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
253 errmsg(
"cannot determine result data type"),
257 parameterCount);
258 if (detailmsg)
260 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
261 errmsg(
"unsafe use of pseudo-type \"internal\""),
263 }
264 }
265
266
267 if (paramModes != NULL)
268 {
269
270
271
272
273
274 for (
i = 0;
i < allParamCount;
i++)
275 {
276 switch (paramModes[
i])
277 {
278 case PROARGMODE_IN:
279 case PROARGMODE_INOUT:
281 elog(
ERROR,
"variadic parameter must be last");
282 break;
283 case PROARGMODE_OUT:
284 if (
OidIsValid(variadicType) && prokind == PROKIND_PROCEDURE)
285 elog(
ERROR,
"variadic parameter must be last");
286 break;
287 case PROARGMODE_TABLE:
288
289 break;
290 case PROARGMODE_VARIADIC:
292 elog(
ERROR,
"variadic parameter must be last");
293 switch (allParams[
i])
294 {
295 case ANYOID:
296 variadicType = ANYOID;
297 break;
298 case ANYARRAYOID:
299 variadicType = ANYELEMENTOID;
300 break;
301 case ANYCOMPATIBLEARRAYOID:
302 variadicType = ANYCOMPATIBLEOID;
303 break;
304 default:
307 elog(
ERROR,
"variadic parameter is not an array");
308 break;
309 }
310 break;
311 default:
312 elog(
ERROR,
"invalid parameter mode '%c'", paramModes[
i]);
313 break;
314 }
315 }
316 }
317
318
319
320
321
322 for (
i = 0;
i < Natts_pg_proc; ++
i)
323 {
327 }
328
350 values[Anum_pg_proc_proallargtypes - 1] = allParameterTypes;
351 else
352 nulls[Anum_pg_proc_proallargtypes - 1] = true;
354 values[Anum_pg_proc_proargmodes - 1] = parameterModes;
355 else
356 nulls[Anum_pg_proc_proargmodes - 1] = true;
358 values[Anum_pg_proc_proargnames - 1] = parameterNames;
359 else
360 nulls[Anum_pg_proc_proargnames - 1] = true;
361 if (parameterDefaults !=
NIL)
363 else
364 nulls[Anum_pg_proc_proargdefaults - 1] = true;
366 values[Anum_pg_proc_protrftypes - 1] = trftypes;
367 else
368 nulls[Anum_pg_proc_protrftypes - 1] = true;
370 if (probin)
372 else
373 nulls[Anum_pg_proc_probin - 1] = true;
374 if (prosqlbody)
376 else
377 nulls[Anum_pg_proc_prosqlbody - 1] = true;
379 values[Anum_pg_proc_proconfig - 1] = proconfig;
380 else
381 nulls[Anum_pg_proc_proconfig - 1] = true;
382
383
386
387
392
394 {
395
398 bool isnull;
399 const char *dropcmd;
400
401 if (!replace)
403 (
errcode(ERRCODE_DUPLICATE_FUNCTION),
404 errmsg(
"function \"%s\" already exists with same argument types",
405 procedureName)));
408 procedureName);
409
410
411 if (oldproc->prokind != prokind)
413 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
414 errmsg(
"cannot change routine kind"),
415 (oldproc->prokind == PROKIND_AGGREGATE ?
416 errdetail(
"\"%s\" is an aggregate function.", procedureName) :
417 oldproc->prokind == PROKIND_FUNCTION ?
418 errdetail(
"\"%s\" is a function.", procedureName) :
419 oldproc->prokind == PROKIND_PROCEDURE ?
420 errdetail(
"\"%s\" is a procedure.", procedureName) :
421 oldproc->prokind == PROKIND_WINDOW ?
422 errdetail(
"\"%s\" is a window function.", procedureName) :
423 0)));
424
425 dropcmd = (prokind == PROKIND_PROCEDURE ? "DROP PROCEDURE" :
426 prokind == PROKIND_AGGREGATE ? "DROP AGGREGATE" :
427 "DROP FUNCTION");
428
429
430
431
432
433
434
435
436
437 if (returnType != oldproc->prorettype ||
438 returnsSet != oldproc->proretset)
440 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
441 prokind == PROKIND_PROCEDURE
442 ?
errmsg(
"cannot change whether a procedure has output parameters")
443 :
errmsg(
"cannot change return type of existing function"),
444
445
446
447
448
450 dropcmd,
452
453
454
455
456
457 if (returnType == RECORDOID)
458 {
461
464 allParameterTypes,
465 parameterModes,
466 parameterNames);
467 if (olddesc == NULL && newdesc == NULL)
468 ;
469 else if (olddesc == NULL || newdesc == NULL ||
472 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
473 errmsg(
"cannot change return type of existing function"),
474 errdetail(
"Row type defined by OUT parameters is different."),
475
477 dropcmd,
479 }
480
481
482
483
484
485
487 Anum_pg_proc_proargnames,
488 &isnull);
489 if (!isnull)
490 {
492 char **old_arg_names;
493 char **new_arg_names;
494 int n_old_arg_names;
495 int n_new_arg_names;
497
499 Anum_pg_proc_proargmodes,
500 &isnull);
501 if (isnull)
503
505 proargmodes,
506 &old_arg_names);
508 parameterModes,
509 &new_arg_names);
510 for (
j = 0;
j < n_old_arg_names;
j++)
511 {
512 if (old_arg_names[
j] == NULL)
513 continue;
514 if (
j >= n_new_arg_names || new_arg_names[
j] == NULL ||
515 strcmp(old_arg_names[
j], new_arg_names[
j]) != 0)
517 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
518 errmsg(
"cannot change name of input parameter \"%s\"",
520
522 dropcmd,
524 }
525 }
526
527
528
529
530
531
532
533
534
535 if (oldproc->pronargdefaults != 0)
536 {
537 Datum proargdefaults;
541
542 if (
list_length(parameterDefaults) < oldproc->pronargdefaults)
544 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
545 errmsg(
"cannot remove parameter defaults from existing function"),
546
548 dropcmd,
550
552 Anum_pg_proc_proargdefaults);
555
556
559 oldproc->pronargdefaults);
560
561 foreach(oldlc, oldDefaults)
562 {
565
568 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
569 errmsg(
"cannot change data type of existing parameter default value"),
570
572 dropcmd,
574 newlc =
lnext(parameterDefaults, newlc);
575 }
576 }
577
578
579
580
581
582 replaces[Anum_pg_proc_oid - 1] = false;
583 replaces[Anum_pg_proc_proowner - 1] = false;
584 replaces[Anum_pg_proc_proacl - 1] = false;
585
586
589
591 is_update = true;
592 }
593 else
594 {
595
597
598
600 procNamespace);
601 if (proacl != NULL)
603 else
604 nulls[Anum_pg_proc_proacl - 1] = true;
605
607 Anum_pg_proc_oid);
611 is_update = false;
612 }
613
614
616
617
618
619
620
621
622
623 if (is_update)
625
627
629
630
633
634
637
638
641
642
643 for (
i = 0;
i < allParamCount;
i++)
644 {
647 }
648
649
651 {
654 }
655
656
658 {
661 }
662
663
664 if (languageObjectId == SQLlanguageId && prosqlbody)
666
667
668 if (parameterDefaults)
670
671
672
673
674
675
676
677
678
681 (
errmsg(
"function \"%s\" will be effectively temporary",
682 procedureName),
685
686
687
688
689
690
691
692
693
695
697
698
699 if (!is_update)
701
702
703 if (!is_update)
705 proowner, proacl);
706
707
709
711
712
714
716
717
719 {
721 int save_nestlevel = 0;
722
723
725
726
727
728
729
730
731
732
733
734
735
737 {
739 if (set_items)
740 {
746 }
747 }
748
750
751 if (set_items)
753 }
754
755
756 if (!is_update)
758
759 return myself;
760}
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 OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void collectDependenciesOfExpr(ObjectAddresses *addrs, Node *expr, List *rtable)
bool find_temp_object(const ObjectAddresses *addrs, bool local_temp_okay, ObjectAddress *foundobj)
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, const ItemPointerData *otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Oid get_element_type(Oid typid)
void namestrcpy(Name name, const char *str)
bool isTempNamespace(Oid namespaceId)
Oid exprType(const Node *expr)
#define castNode(_type_, nodeptr)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
#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)