78{
82 bool nulls[Natts_pg_aggregate];
84 bool replaces[Natts_pg_aggregate];
95 Oid *aggArgTypes = parameterTypes->
values;
96 bool mtransIsStrict = false;
100 int nargs_transfn;
101 int nargs_finalfn;
104 char *detailmsg;
107 referenced;
110
111
112 if (!aggName)
113 elog(
ERROR,
"no aggregate name supplied");
114
115 if (!aggtransfnName)
116 elog(
ERROR,
"aggregate must have a transition function");
117
118 if (numDirectArgs < 0 || numDirectArgs > numArgs)
119 elog(
ERROR,
"incorrect number of direct arguments for aggregate");
120
121
122
123
124
125
128 (
errcode(ERRCODE_TOO_MANY_ARGUMENTS),
129 errmsg_plural(
"aggregates cannot have more than %d argument",
130 "aggregates cannot have more than %d arguments",
133
134
135
136
137
139 aggArgTypes,
140 numArgs);
141 if (detailmsg)
143 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
144 errmsg(
"cannot determine transition data type"),
146
147
148
149
151 {
153 aggArgTypes,
154 numArgs);
155 if (detailmsg)
157 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
158 errmsg(
"cannot determine transition data type"),
160 }
161
162
163
164
165
166
167
168
169 if (AGGKIND_IS_ORDERED_SET(aggKind) &&
OidIsValid(variadicArgType) &&
170 variadicArgType != ANYOID)
172 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
173 errmsg(
"a variadic ordered-set aggregate must use VARIADIC type ANY")));
174
175
176
177
178
179
180
181
182
183
184
185
186
187 if (aggKind == AGGKIND_HYPOTHETICAL &&
188 numDirectArgs < numArgs)
189 {
190 int numAggregatedArgs = numArgs - numDirectArgs;
191
193 numDirectArgs < numAggregatedArgs ||
194 memcmp(aggArgTypes + (numDirectArgs - numAggregatedArgs),
195 aggArgTypes + numDirectArgs,
196 numAggregatedArgs *
sizeof(
Oid)) != 0)
198 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
199 errmsg(
"a hypothetical-set aggregate must have direct arguments matching its aggregated arguments")));
200 }
201
202
203
204
205
206
207
208
209 if (AGGKIND_IS_ORDERED_SET(aggKind))
210 {
211 if (numDirectArgs < numArgs)
212 nargs_transfn = numArgs - numDirectArgs + 1;
213 else
214 {
215
217 nargs_transfn = 2;
218 }
219 fnArgs[0] = aggTransType;
220 memcpy(fnArgs + 1, aggArgTypes + (numArgs - (nargs_transfn - 1)),
221 (nargs_transfn - 1) *
sizeof(
Oid));
222 }
223 else
224 {
225 nargs_transfn = numArgs + 1;
226 fnArgs[0] = aggTransType;
227 memcpy(fnArgs + 1, aggArgTypes, numArgs *
sizeof(
Oid));
228 }
230 fnArgs, variadicArgType,
231 &rettype);
232
233
234
235
236
237
238
239
240
241
242
243 if (rettype != aggTransType)
245 (
errcode(ERRCODE_DATATYPE_MISMATCH),
246 errmsg(
"return type of transition function %s is not %s",
249
252 elog(
ERROR,
"cache lookup failed for function %u", transfn);
254
255
256
257
258
259
260 if (proc->proisstrict && agginitval == NULL)
261 {
262 if (numArgs < 1 ||
265 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
266 errmsg(
"must not omit initial value when transition function is strict and transition type is not compatible with input type")));
267 }
268
270
271
272 if (aggmtransfnName)
273 {
274
275
276
277
278
280 fnArgs[0] = aggmTransType;
281
283 fnArgs, variadicArgType,
284 &rettype);
285
286
287 if (rettype != aggmTransType)
289 (
errcode(ERRCODE_DATATYPE_MISMATCH),
290 errmsg(
"return type of transition function %s is not %s",
293
296 elog(
ERROR,
"cache lookup failed for function %u", mtransfn);
298
299
300
301
302
303 if (proc->proisstrict && aggminitval == NULL)
304 {
305 if (numArgs < 1 ||
308 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
309 errmsg(
"must not omit initial value when transition function is strict and transition type is not compatible with input type")));
310 }
311
312
313 mtransIsStrict = proc->proisstrict;
314
316 }
317
318
319 if (aggminvtransfnName)
320 {
321
322
323
324
326
328 fnArgs, variadicArgType,
329 &rettype);
330
331
332 if (rettype != aggmTransType)
334 (
errcode(ERRCODE_DATATYPE_MISMATCH),
335 errmsg(
"return type of inverse transition function %s is not %s",
338
341 elog(
ERROR,
"cache lookup failed for function %u", minvtransfn);
343
344
345
346
347
348
349 if (proc->proisstrict != mtransIsStrict)
351 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
352 errmsg(
"strictness of aggregate's forward and inverse transition functions must match")));
353
355 }
356
357
358 if (aggfinalfnName)
359 {
360
361
362
363
364
365
366
367 Oid ffnVariadicArgType = variadicArgType;
368
369 fnArgs[0] = aggTransType;
370 memcpy(fnArgs + 1, aggArgTypes, numArgs *
sizeof(
Oid));
371 if (finalfnExtraArgs)
372 nargs_finalfn = numArgs + 1;
373 else
374 {
375 nargs_finalfn = numDirectArgs + 1;
376 if (numDirectArgs < numArgs)
377 {
378
380 }
381 }
382
384 fnArgs, ffnVariadicArgType,
385 &finaltype);
386
387
388
389
390
391
392
395 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
396 errmsg(
"final function with extra arguments must not be declared STRICT")));
397 }
398 else
399 {
400
401
402
403 finaltype = aggTransType;
404 }
406
407
408 if (aggcombinefnName)
409 {
411
412
413
414
415
416 fnArgs[0] = aggTransType;
417 fnArgs[1] = aggTransType;
418
421 &combineType);
422
423
424 if (combineType != aggTransType)
426 (
errcode(ERRCODE_DATATYPE_MISMATCH),
427 errmsg(
"return type of combine function %s is not %s",
430
431
432
433
434
435
436 if (aggTransType == INTERNALOID &&
func_strict(combinefn))
438 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
439 errmsg(
"combine function with transition type %s must not be declared STRICT",
441 }
442
443
444
445
446 if (aggserialfnName)
447 {
448
449 fnArgs[0] = INTERNALOID;
450
453 &rettype);
454
455 if (rettype != BYTEAOID)
457 (
errcode(ERRCODE_DATATYPE_MISMATCH),
458 errmsg(
"return type of serialization function %s is not %s",
461 }
462
463
464
465
466 if (aggdeserialfnName)
467 {
468
469 fnArgs[0] = BYTEAOID;
470 fnArgs[1] = INTERNALOID;
471
474 &rettype);
475
476 if (rettype != INTERNALOID)
478 (
errcode(ERRCODE_DATATYPE_MISMATCH),
479 errmsg(
"return type of deserialization function %s is not %s",
482 }
483
484
485
486
487
488
489
490
491
493 aggArgTypes,
494 numArgs);
495 if (detailmsg)
497 (
errcode(ERRCODE_DATATYPE_MISMATCH),
498 errmsg(
"cannot determine result data type"),
500
501
502
503
504
505
506
508 aggArgTypes,
509 numArgs);
510 if (detailmsg)
512 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
513 errmsg(
"unsafe use of pseudo-type \"internal\""),
515
516
517
518
519
520
522 {
523
524 if (aggmfinalfnName)
525 {
526
527
528
529
530 Oid ffnVariadicArgType = variadicArgType;
531
532 fnArgs[0] = aggmTransType;
533 memcpy(fnArgs + 1, aggArgTypes, numArgs *
sizeof(
Oid));
534 if (mfinalfnExtraArgs)
535 nargs_finalfn = numArgs + 1;
536 else
537 {
538 nargs_finalfn = numDirectArgs + 1;
539 if (numDirectArgs < numArgs)
540 {
541
543 }
544 }
545
547 fnArgs, ffnVariadicArgType,
548 &rettype);
549
550
553 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
554 errmsg(
"final function with extra arguments must not be declared STRICT")));
555 }
556 else
557 {
558
559
560
561 rettype = aggmTransType;
562 }
564 if (rettype != finaltype)
566 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
567 errmsg(
"moving-aggregate implementation returns type %s, but plain implementation returns type %s",
570 }
571
572
573 if (aggsortopName)
574 {
575 if (numArgs != 1)
577 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
578 errmsg(
"sort operator can only be specified for single-argument aggregates")));
580 aggArgTypes[0], aggArgTypes[0],
581 false, -1);
582 }
583
584
585
586
587 for (
i = 0;
i < numArgs;
i++)
588 {
592 }
593
597
599 {
603 }
604
608
609
610
611
612
613
614
616 aggNamespace,
617 replace,
618 false,
619 finaltype,
621 INTERNALlanguageId,
623 "aggregate_dummy",
624 NULL,
625 NULL,
626 PROKIND_AGGREGATE,
627 false,
628
629 false,
630 false,
631 PROVOLATILE_IMMUTABLE,
632
633 proparallel,
634 parameterTypes,
635 allParameterTypes,
636 parameterModes,
637 parameterNames,
638 parameterDefaults,
642 1,
643 0);
645
646
647
648
650 tupDesc = aggdesc->
rd_att;
651
652
653 for (
i = 0;
i < Natts_pg_aggregate;
i++)
654 {
658 }
679 if (agginitval)
681 else
682 nulls[Anum_pg_aggregate_agginitval - 1] = true;
683 if (aggminitval)
685 else
686 nulls[Anum_pg_aggregate_aggminitval - 1] = true;
687
688 if (replace)
690 else
691 oldtup = NULL;
692
694 {
696
697
698
699
700
701
702
703 if (aggKind != oldagg->aggkind)
705 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
706 errmsg(
"cannot change routine kind"),
707 (oldagg->aggkind == AGGKIND_NORMAL ?
708 errdetail(
"\"%s\" is an ordinary aggregate function.", aggName) :
709 oldagg->aggkind == AGGKIND_ORDERED_SET ?
710 errdetail(
"\"%s\" is an ordered-set aggregate.", aggName) :
711 oldagg->aggkind == AGGKIND_HYPOTHETICAL ?
712 errdetail(
"\"%s\" is a hypothetical-set aggregate.", aggName) :
713 0)));
714 if (numDirectArgs != oldagg->aggnumdirectargs)
716 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
717 errmsg(
"cannot change number of direct arguments of an aggregate function")));
718
719 replaces[Anum_pg_aggregate_aggfnoid - 1] = false;
720 replaces[Anum_pg_aggregate_aggkind - 1] = false;
721 replaces[Anum_pg_aggregate_aggnumdirectargs - 1] = false;
722
726 }
727 else
728 {
731 }
732
734
735
736
737
738
739
740
741
742
743
744
745
747
748
751
752
754 {
757 }
758
759
761 {
764 }
765
766
768 {
771 }
772
773
775 {
778 }
779
780
782 {
785 }
786
787
789 {
792 }
793
794
796 {
799 }
800
801
803 {
806 }
807
810 return myself;
811}
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
static Datum values[MAXATTR]
#define CStringGetTextDatum(s)
#define OidIsValid(objectId)
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, 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 errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
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)
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
bool func_strict(Oid funcid)
char * NameListToString(const List *names)
#define ObjectAddressSet(addr, class_id, object_id)
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)
bool IsBinaryCoercible(Oid srctype, Oid targettype)
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types, Oid variadicArgType, Oid *rettype)
FormData_pg_aggregate * Form_pg_aggregate
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)
FormData_pg_proc * Form_pg_proc
static Datum PointerGetDatum(const void *X)
static Datum Int16GetDatum(int16 X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Datum Int32GetDatum(int32 X)
static Datum CharGetDatum(char X)
Oid values[FLEXIBLE_ARRAY_MEMBER]
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)