]> granicus.if.org Git - postgresql/blob - src/backend/catalog/pg_aggregate.c
Replace heapam.h includes with {table, relation}.h where applicable.
[postgresql] / src / backend / catalog / pg_aggregate.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_aggregate.c
4  *        routines to support manipulation of the pg_aggregate relation
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/catalog/pg_aggregate.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/htup_details.h"
18 #include "access/table.h"
19 #include "catalog/dependency.h"
20 #include "catalog/indexing.h"
21 #include "catalog/pg_aggregate.h"
22 #include "catalog/pg_language.h"
23 #include "catalog/pg_operator.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_type.h"
26 #include "miscadmin.h"
27 #include "parser/parse_coerce.h"
28 #include "parser/parse_func.h"
29 #include "parser/parse_oper.h"
30 #include "utils/acl.h"
31 #include "utils/builtins.h"
32 #include "utils/lsyscache.h"
33 #include "utils/rel.h"
34 #include "utils/syscache.h"
35
36
37 static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types,
38                                         Oid variadicArgType,
39                                         Oid *rettype);
40
41
42 /*
43  * AggregateCreate
44  */
45 ObjectAddress
46 AggregateCreate(const char *aggName,
47                                 Oid aggNamespace,
48                                 char aggKind,
49                                 int numArgs,
50                                 int numDirectArgs,
51                                 oidvector *parameterTypes,
52                                 Datum allParameterTypes,
53                                 Datum parameterModes,
54                                 Datum parameterNames,
55                                 List *parameterDefaults,
56                                 Oid variadicArgType,
57                                 List *aggtransfnName,
58                                 List *aggfinalfnName,
59                                 List *aggcombinefnName,
60                                 List *aggserialfnName,
61                                 List *aggdeserialfnName,
62                                 List *aggmtransfnName,
63                                 List *aggminvtransfnName,
64                                 List *aggmfinalfnName,
65                                 bool finalfnExtraArgs,
66                                 bool mfinalfnExtraArgs,
67                                 char finalfnModify,
68                                 char mfinalfnModify,
69                                 List *aggsortopName,
70                                 Oid aggTransType,
71                                 int32 aggTransSpace,
72                                 Oid aggmTransType,
73                                 int32 aggmTransSpace,
74                                 const char *agginitval,
75                                 const char *aggminitval,
76                                 char proparallel)
77 {
78         Relation        aggdesc;
79         HeapTuple       tup;
80         bool            nulls[Natts_pg_aggregate];
81         Datum           values[Natts_pg_aggregate];
82         Form_pg_proc proc;
83         Oid                     transfn;
84         Oid                     finalfn = InvalidOid;   /* can be omitted */
85         Oid                     combinefn = InvalidOid; /* can be omitted */
86         Oid                     serialfn = InvalidOid;  /* can be omitted */
87         Oid                     deserialfn = InvalidOid;        /* can be omitted */
88         Oid                     mtransfn = InvalidOid;  /* can be omitted */
89         Oid                     minvtransfn = InvalidOid;       /* can be omitted */
90         Oid                     mfinalfn = InvalidOid;  /* can be omitted */
91         Oid                     sortop = InvalidOid;    /* can be omitted */
92         Oid                *aggArgTypes = parameterTypes->values;
93         bool            hasPolyArg;
94         bool            hasInternalArg;
95         bool            mtransIsStrict = false;
96         Oid                     rettype;
97         Oid                     finaltype;
98         Oid                     fnArgs[FUNC_MAX_ARGS];
99         int                     nargs_transfn;
100         int                     nargs_finalfn;
101         Oid                     procOid;
102         TupleDesc       tupDesc;
103         int                     i;
104         ObjectAddress myself,
105                                 referenced;
106         AclResult       aclresult;
107
108         /* sanity checks (caller should have caught these) */
109         if (!aggName)
110                 elog(ERROR, "no aggregate name supplied");
111
112         if (!aggtransfnName)
113                 elog(ERROR, "aggregate must have a transition function");
114
115         if (numDirectArgs < 0 || numDirectArgs > numArgs)
116                 elog(ERROR, "incorrect number of direct args for aggregate");
117
118         /*
119          * Aggregates can have at most FUNC_MAX_ARGS-1 args, else the transfn
120          * and/or finalfn will be unrepresentable in pg_proc.  We must check now
121          * to protect fixed-size arrays here and possibly in called functions.
122          */
123         if (numArgs < 0 || numArgs > FUNC_MAX_ARGS - 1)
124                 ereport(ERROR,
125                                 (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
126                                  errmsg_plural("aggregates cannot have more than %d argument",
127                                                            "aggregates cannot have more than %d arguments",
128                                                            FUNC_MAX_ARGS - 1,
129                                                            FUNC_MAX_ARGS - 1)));
130
131         /* check for polymorphic and INTERNAL arguments */
132         hasPolyArg = false;
133         hasInternalArg = false;
134         for (i = 0; i < numArgs; i++)
135         {
136                 if (IsPolymorphicType(aggArgTypes[i]))
137                         hasPolyArg = true;
138                 else if (aggArgTypes[i] == INTERNALOID)
139                         hasInternalArg = true;
140         }
141
142         /*
143          * If transtype is polymorphic, must have polymorphic argument also; else
144          * we will have no way to deduce the actual transtype.
145          */
146         if (IsPolymorphicType(aggTransType) && !hasPolyArg)
147                 ereport(ERROR,
148                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
149                                  errmsg("cannot determine transition data type"),
150                                  errdetail("An aggregate using a polymorphic transition type must have at least one polymorphic argument.")));
151
152         /*
153          * Likewise for moving-aggregate transtype, if any
154          */
155         if (OidIsValid(aggmTransType) &&
156                 IsPolymorphicType(aggmTransType) && !hasPolyArg)
157                 ereport(ERROR,
158                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
159                                  errmsg("cannot determine transition data type"),
160                                  errdetail("An aggregate using a polymorphic transition type must have at least one polymorphic argument.")));
161
162         /*
163          * An ordered-set aggregate that is VARIADIC must be VARIADIC ANY.  In
164          * principle we could support regular variadic types, but it would make
165          * things much more complicated because we'd have to assemble the correct
166          * subsets of arguments into array values.  Since no standard aggregates
167          * have use for such a case, we aren't bothering for now.
168          */
169         if (AGGKIND_IS_ORDERED_SET(aggKind) && OidIsValid(variadicArgType) &&
170                 variadicArgType != ANYOID)
171                 ereport(ERROR,
172                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
173                                  errmsg("a variadic ordered-set aggregate must use VARIADIC type ANY")));
174
175         /*
176          * If it's a hypothetical-set aggregate, there must be at least as many
177          * direct arguments as aggregated ones, and the last N direct arguments
178          * must match the aggregated ones in type.  (We have to check this again
179          * when the aggregate is called, in case ANY is involved, but it makes
180          * sense to reject the aggregate definition now if the declared arg types
181          * don't match up.)  It's unconditionally OK if numDirectArgs == numArgs,
182          * indicating that the grammar merged identical VARIADIC entries from both
183          * lists.  Otherwise, if the agg is VARIADIC, then we had VARIADIC only on
184          * the aggregated side, which is not OK.  Otherwise, insist on the last N
185          * parameter types on each side matching exactly.
186          */
187         if (aggKind == AGGKIND_HYPOTHETICAL &&
188                 numDirectArgs < numArgs)
189         {
190                 int                     numAggregatedArgs = numArgs - numDirectArgs;
191
192                 if (OidIsValid(variadicArgType) ||
193                         numDirectArgs < numAggregatedArgs ||
194                         memcmp(aggArgTypes + (numDirectArgs - numAggregatedArgs),
195                                    aggArgTypes + numDirectArgs,
196                                    numAggregatedArgs * sizeof(Oid)) != 0)
197                         ereport(ERROR,
198                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
199                                          errmsg("a hypothetical-set aggregate must have direct arguments matching its aggregated arguments")));
200         }
201
202         /*
203          * Find the transfn.  For ordinary aggs, it takes the transtype plus all
204          * aggregate arguments.  For ordered-set aggs, it takes the transtype plus
205          * all aggregated args, but not direct args.  However, we have to treat
206          * specially the case where a trailing VARIADIC item is considered to
207          * cover both direct and aggregated args.
208          */
209         if (AGGKIND_IS_ORDERED_SET(aggKind))
210         {
211                 if (numDirectArgs < numArgs)
212                         nargs_transfn = numArgs - numDirectArgs + 1;
213                 else
214                 {
215                         /* special case with VARIADIC last arg */
216                         Assert(variadicArgType != InvalidOid);
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         }
229         transfn = lookup_agg_function(aggtransfnName, nargs_transfn,
230                                                                   fnArgs, variadicArgType,
231                                                                   &rettype);
232
233         /*
234          * Return type of transfn (possibly after refinement by
235          * enforce_generic_type_consistency, if transtype isn't polymorphic) must
236          * exactly match declared transtype.
237          *
238          * In the non-polymorphic-transtype case, it might be okay to allow a
239          * rettype that's binary-coercible to transtype, but I'm not quite
240          * convinced that it's either safe or useful.  When transtype is
241          * polymorphic we *must* demand exact equality.
242          */
243         if (rettype != aggTransType)
244                 ereport(ERROR,
245                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
246                                  errmsg("return type of transition function %s is not %s",
247                                                 NameListToString(aggtransfnName),
248                                                 format_type_be(aggTransType))));
249
250         tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(transfn));
251         if (!HeapTupleIsValid(tup))
252                 elog(ERROR, "cache lookup failed for function %u", transfn);
253         proc = (Form_pg_proc) GETSTRUCT(tup);
254
255         /*
256          * If the transfn is strict and the initval is NULL, make sure first input
257          * type and transtype are the same (or at least binary-compatible), so
258          * that it's OK to use the first input value as the initial transValue.
259          */
260         if (proc->proisstrict && agginitval == NULL)
261         {
262                 if (numArgs < 1 ||
263                         !IsBinaryCoercible(aggArgTypes[0], aggTransType))
264                         ereport(ERROR,
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
269         ReleaseSysCache(tup);
270
271         /* handle moving-aggregate transfn, if supplied */
272         if (aggmtransfnName)
273         {
274                 /*
275                  * The arguments are the same as for the regular transfn, except that
276                  * the transition data type might be different.  So re-use the fnArgs
277                  * values set up above, except for that one.
278                  */
279                 Assert(OidIsValid(aggmTransType));
280                 fnArgs[0] = aggmTransType;
281
282                 mtransfn = lookup_agg_function(aggmtransfnName, nargs_transfn,
283                                                                            fnArgs, variadicArgType,
284                                                                            &rettype);
285
286                 /* As above, return type must exactly match declared mtranstype. */
287                 if (rettype != aggmTransType)
288                         ereport(ERROR,
289                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
290                                          errmsg("return type of transition function %s is not %s",
291                                                         NameListToString(aggmtransfnName),
292                                                         format_type_be(aggmTransType))));
293
294                 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(mtransfn));
295                 if (!HeapTupleIsValid(tup))
296                         elog(ERROR, "cache lookup failed for function %u", mtransfn);
297                 proc = (Form_pg_proc) GETSTRUCT(tup);
298
299                 /*
300                  * If the mtransfn is strict and the minitval is NULL, check first
301                  * input type and mtranstype are binary-compatible.
302                  */
303                 if (proc->proisstrict && aggminitval == NULL)
304                 {
305                         if (numArgs < 1 ||
306                                 !IsBinaryCoercible(aggArgTypes[0], aggmTransType))
307                                 ereport(ERROR,
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                 /* Remember if mtransfn is strict; we may need this below */
313                 mtransIsStrict = proc->proisstrict;
314
315                 ReleaseSysCache(tup);
316         }
317
318         /* handle minvtransfn, if supplied */
319         if (aggminvtransfnName)
320         {
321                 /*
322                  * This must have the same number of arguments with the same types as
323                  * the forward transition function, so just re-use the fnArgs data.
324                  */
325                 Assert(aggmtransfnName);
326
327                 minvtransfn = lookup_agg_function(aggminvtransfnName, nargs_transfn,
328                                                                                   fnArgs, variadicArgType,
329                                                                                   &rettype);
330
331                 /* As above, return type must exactly match declared mtranstype. */
332                 if (rettype != aggmTransType)
333                         ereport(ERROR,
334                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
335                                          errmsg("return type of inverse transition function %s is not %s",
336                                                         NameListToString(aggminvtransfnName),
337                                                         format_type_be(aggmTransType))));
338
339                 tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(minvtransfn));
340                 if (!HeapTupleIsValid(tup))
341                         elog(ERROR, "cache lookup failed for function %u", minvtransfn);
342                 proc = (Form_pg_proc) GETSTRUCT(tup);
343
344                 /*
345                  * We require the strictness settings of the forward and inverse
346                  * transition functions to agree.  This saves having to handle
347                  * assorted special cases at execution time.
348                  */
349                 if (proc->proisstrict != mtransIsStrict)
350                         ereport(ERROR,
351                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
352                                          errmsg("strictness of aggregate's forward and inverse transition functions must match")));
353
354                 ReleaseSysCache(tup);
355         }
356
357         /* handle finalfn, if supplied */
358         if (aggfinalfnName)
359         {
360                 /*
361                  * If finalfnExtraArgs is specified, the transfn takes the transtype
362                  * plus all args; otherwise, it just takes the transtype plus any
363                  * direct args.  (Non-direct args are useless at runtime, and are
364                  * actually passed as NULLs, but we may need them in the function
365                  * signature to allow resolution of a polymorphic agg's result type.)
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                                 /* variadic argument doesn't affect finalfn */
379                                 ffnVariadicArgType = InvalidOid;
380                         }
381                 }
382
383                 finalfn = lookup_agg_function(aggfinalfnName, nargs_finalfn,
384                                                                           fnArgs, ffnVariadicArgType,
385                                                                           &finaltype);
386
387                 /*
388                  * When finalfnExtraArgs is specified, the finalfn will certainly be
389                  * passed at least one null argument, so complain if it's strict.
390                  * Nothing bad would happen at runtime (you'd just get a null result),
391                  * but it's surely not what the user wants, so let's complain now.
392                  */
393                 if (finalfnExtraArgs && func_strict(finalfn))
394                         ereport(ERROR,
395                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
396                                          errmsg("final function with extra arguments must not be declared STRICT")));
397         }
398         else
399         {
400                 /*
401                  * If no finalfn, aggregate result type is type of the state value
402                  */
403                 finaltype = aggTransType;
404         }
405         Assert(OidIsValid(finaltype));
406
407         /* handle the combinefn, if supplied */
408         if (aggcombinefnName)
409         {
410                 Oid                     combineType;
411
412                 /*
413                  * Combine function must have 2 arguments, each of which is the trans
414                  * type.  VARIADIC doesn't affect it.
415                  */
416                 fnArgs[0] = aggTransType;
417                 fnArgs[1] = aggTransType;
418
419                 combinefn = lookup_agg_function(aggcombinefnName, 2,
420                                                                                 fnArgs, InvalidOid,
421                                                                                 &combineType);
422
423                 /* Ensure the return type matches the aggregate's trans type */
424                 if (combineType != aggTransType)
425                         ereport(ERROR,
426                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
427                                          errmsg("return type of combine function %s is not %s",
428                                                         NameListToString(aggcombinefnName),
429                                                         format_type_be(aggTransType))));
430
431                 /*
432                  * A combine function to combine INTERNAL states must accept nulls and
433                  * ensure that the returned state is in the correct memory context. We
434                  * cannot directly check the latter, but we can check the former.
435                  */
436                 if (aggTransType == INTERNALOID && func_strict(combinefn))
437                         ereport(ERROR,
438                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
439                                          errmsg("combine function with transition type %s must not be declared STRICT",
440                                                         format_type_be(aggTransType))));
441         }
442
443         /*
444          * Validate the serialization function, if present.
445          */
446         if (aggserialfnName)
447         {
448                 /* signature is always serialize(internal) returns bytea */
449                 fnArgs[0] = INTERNALOID;
450
451                 serialfn = lookup_agg_function(aggserialfnName, 1,
452                                                                            fnArgs, InvalidOid,
453                                                                            &rettype);
454
455                 if (rettype != BYTEAOID)
456                         ereport(ERROR,
457                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
458                                          errmsg("return type of serialization function %s is not %s",
459                                                         NameListToString(aggserialfnName),
460                                                         format_type_be(BYTEAOID))));
461         }
462
463         /*
464          * Validate the deserialization function, if present.
465          */
466         if (aggdeserialfnName)
467         {
468                 /* signature is always deserialize(bytea, internal) returns internal */
469                 fnArgs[0] = BYTEAOID;
470                 fnArgs[1] = INTERNALOID;        /* dummy argument for type safety */
471
472                 deserialfn = lookup_agg_function(aggdeserialfnName, 2,
473                                                                                  fnArgs, InvalidOid,
474                                                                                  &rettype);
475
476                 if (rettype != INTERNALOID)
477                         ereport(ERROR,
478                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
479                                          errmsg("return type of deserialization function %s is not %s",
480                                                         NameListToString(aggdeserialfnName),
481                                                         format_type_be(INTERNALOID))));
482         }
483
484         /*
485          * If finaltype (i.e. aggregate return type) is polymorphic, inputs must
486          * be polymorphic also, else parser will fail to deduce result type.
487          * (Note: given the previous test on transtype and inputs, this cannot
488          * happen, unless someone has snuck a finalfn definition into the catalogs
489          * that itself violates the rule against polymorphic result with no
490          * polymorphic input.)
491          */
492         if (IsPolymorphicType(finaltype) && !hasPolyArg)
493                 ereport(ERROR,
494                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
495                                  errmsg("cannot determine result data type"),
496                                  errdetail("An aggregate returning a polymorphic type "
497                                                    "must have at least one polymorphic argument.")));
498
499         /*
500          * Also, the return type can't be INTERNAL unless there's at least one
501          * INTERNAL argument.  This is the same type-safety restriction we enforce
502          * for regular functions, but at the level of aggregates.  We must test
503          * this explicitly because we allow INTERNAL as the transtype.
504          */
505         if (finaltype == INTERNALOID && !hasInternalArg)
506                 ereport(ERROR,
507                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
508                                  errmsg("unsafe use of pseudo-type \"internal\""),
509                                  errdetail("A function returning \"internal\" must have at least one \"internal\" argument.")));
510
511         /*
512          * If a moving-aggregate implementation is supplied, look up its finalfn
513          * if any, and check that the implied aggregate result type matches the
514          * plain implementation.
515          */
516         if (OidIsValid(aggmTransType))
517         {
518                 /* handle finalfn, if supplied */
519                 if (aggmfinalfnName)
520                 {
521                         /*
522                          * The arguments are figured the same way as for the regular
523                          * finalfn, but using aggmTransType and mfinalfnExtraArgs.
524                          */
525                         Oid                     ffnVariadicArgType = variadicArgType;
526
527                         fnArgs[0] = aggmTransType;
528                         memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
529                         if (mfinalfnExtraArgs)
530                                 nargs_finalfn = numArgs + 1;
531                         else
532                         {
533                                 nargs_finalfn = numDirectArgs + 1;
534                                 if (numDirectArgs < numArgs)
535                                 {
536                                         /* variadic argument doesn't affect finalfn */
537                                         ffnVariadicArgType = InvalidOid;
538                                 }
539                         }
540
541                         mfinalfn = lookup_agg_function(aggmfinalfnName, nargs_finalfn,
542                                                                                    fnArgs, ffnVariadicArgType,
543                                                                                    &rettype);
544
545                         /* As above, check strictness if mfinalfnExtraArgs is given */
546                         if (mfinalfnExtraArgs && func_strict(mfinalfn))
547                                 ereport(ERROR,
548                                                 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
549                                                  errmsg("final function with extra arguments must not be declared STRICT")));
550                 }
551                 else
552                 {
553                         /*
554                          * If no finalfn, aggregate result type is type of the state value
555                          */
556                         rettype = aggmTransType;
557                 }
558                 Assert(OidIsValid(rettype));
559                 if (rettype != finaltype)
560                         ereport(ERROR,
561                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
562                                          errmsg("moving-aggregate implementation returns type %s, but plain implementation returns type %s",
563                                                         format_type_be(aggmTransType),
564                                                         format_type_be(aggTransType))));
565         }
566
567         /* handle sortop, if supplied */
568         if (aggsortopName)
569         {
570                 if (numArgs != 1)
571                         ereport(ERROR,
572                                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
573                                          errmsg("sort operator can only be specified for single-argument aggregates")));
574                 sortop = LookupOperName(NULL, aggsortopName,
575                                                                 aggArgTypes[0], aggArgTypes[0],
576                                                                 false, -1);
577         }
578
579         /*
580          * permission checks on used types
581          */
582         for (i = 0; i < numArgs; i++)
583         {
584                 aclresult = pg_type_aclcheck(aggArgTypes[i], GetUserId(), ACL_USAGE);
585                 if (aclresult != ACLCHECK_OK)
586                         aclcheck_error_type(aclresult, aggArgTypes[i]);
587         }
588
589         aclresult = pg_type_aclcheck(aggTransType, GetUserId(), ACL_USAGE);
590         if (aclresult != ACLCHECK_OK)
591                 aclcheck_error_type(aclresult, aggTransType);
592
593         if (OidIsValid(aggmTransType))
594         {
595                 aclresult = pg_type_aclcheck(aggmTransType, GetUserId(), ACL_USAGE);
596                 if (aclresult != ACLCHECK_OK)
597                         aclcheck_error_type(aclresult, aggmTransType);
598         }
599
600         aclresult = pg_type_aclcheck(finaltype, GetUserId(), ACL_USAGE);
601         if (aclresult != ACLCHECK_OK)
602                 aclcheck_error_type(aclresult, finaltype);
603
604
605         /*
606          * Everything looks okay.  Try to create the pg_proc entry for the
607          * aggregate.  (This could fail if there's already a conflicting entry.)
608          */
609
610         myself = ProcedureCreate(aggName,
611                                                          aggNamespace,
612                                                          false, /* no replacement */
613                                                          false, /* doesn't return a set */
614                                                          finaltype, /* returnType */
615                                                          GetUserId(),   /* proowner */
616                                                          INTERNALlanguageId,    /* languageObjectId */
617                                                          InvalidOid,    /* no validator */
618                                                          "aggregate_dummy", /* placeholder proc */
619                                                          NULL,  /* probin */
620                                                          PROKIND_AGGREGATE,
621                                                          false, /* security invoker (currently not
622                                                                          * definable for agg) */
623                                                          false, /* isLeakProof */
624                                                          false, /* isStrict (not needed for agg) */
625                                                          PROVOLATILE_IMMUTABLE, /* volatility (not needed
626                                                                                                          * for agg) */
627                                                          proparallel,
628                                                          parameterTypes,        /* paramTypes */
629                                                          allParameterTypes, /* allParamTypes */
630                                                          parameterModes,        /* parameterModes */
631                                                          parameterNames,        /* parameterNames */
632                                                          parameterDefaults, /* parameterDefaults */
633                                                          PointerGetDatum(NULL), /* trftypes */
634                                                          PointerGetDatum(NULL), /* proconfig */
635                                                          1, /* procost */
636                                                          0);    /* prorows */
637         procOid = myself.objectId;
638
639         /*
640          * Okay to create the pg_aggregate entry.
641          */
642         aggdesc = heap_open(AggregateRelationId, RowExclusiveLock);
643         tupDesc = aggdesc->rd_att;
644
645         /* initialize nulls and values */
646         for (i = 0; i < Natts_pg_aggregate; i++)
647         {
648                 nulls[i] = false;
649                 values[i] = (Datum) NULL;
650         }
651         values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
652         values[Anum_pg_aggregate_aggkind - 1] = CharGetDatum(aggKind);
653         values[Anum_pg_aggregate_aggnumdirectargs - 1] = Int16GetDatum(numDirectArgs);
654         values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
655         values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
656         values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn);
657         values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn);
658         values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn);
659         values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
660         values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
661         values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
662         values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs);
663         values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
664         values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify);
665         values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify);
666         values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
667         values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
668         values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
669         values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
670         values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
671         if (agginitval)
672                 values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
673         else
674                 nulls[Anum_pg_aggregate_agginitval - 1] = true;
675         if (aggminitval)
676                 values[Anum_pg_aggregate_aggminitval - 1] = CStringGetTextDatum(aggminitval);
677         else
678                 nulls[Anum_pg_aggregate_aggminitval - 1] = true;
679
680         tup = heap_form_tuple(tupDesc, values, nulls);
681         CatalogTupleInsert(aggdesc, tup);
682
683         heap_close(aggdesc, RowExclusiveLock);
684
685         /*
686          * Create dependencies for the aggregate (above and beyond those already
687          * made by ProcedureCreate).  Note: we don't need an explicit dependency
688          * on aggTransType since we depend on it indirectly through transfn.
689          * Likewise for aggmTransType using the mtransfunc, if it exists.
690          */
691
692         /* Depends on transition function */
693         referenced.classId = ProcedureRelationId;
694         referenced.objectId = transfn;
695         referenced.objectSubId = 0;
696         recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
697
698         /* Depends on final function, if any */
699         if (OidIsValid(finalfn))
700         {
701                 referenced.classId = ProcedureRelationId;
702                 referenced.objectId = finalfn;
703                 referenced.objectSubId = 0;
704                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
705         }
706
707         /* Depends on combine function, if any */
708         if (OidIsValid(combinefn))
709         {
710                 referenced.classId = ProcedureRelationId;
711                 referenced.objectId = combinefn;
712                 referenced.objectSubId = 0;
713                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
714         }
715
716         /* Depends on serialization function, if any */
717         if (OidIsValid(serialfn))
718         {
719                 referenced.classId = ProcedureRelationId;
720                 referenced.objectId = serialfn;
721                 referenced.objectSubId = 0;
722                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
723         }
724
725         /* Depends on deserialization function, if any */
726         if (OidIsValid(deserialfn))
727         {
728                 referenced.classId = ProcedureRelationId;
729                 referenced.objectId = deserialfn;
730                 referenced.objectSubId = 0;
731                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
732         }
733
734         /* Depends on forward transition function, if any */
735         if (OidIsValid(mtransfn))
736         {
737                 referenced.classId = ProcedureRelationId;
738                 referenced.objectId = mtransfn;
739                 referenced.objectSubId = 0;
740                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
741         }
742
743         /* Depends on inverse transition function, if any */
744         if (OidIsValid(minvtransfn))
745         {
746                 referenced.classId = ProcedureRelationId;
747                 referenced.objectId = minvtransfn;
748                 referenced.objectSubId = 0;
749                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
750         }
751
752         /* Depends on final function, if any */
753         if (OidIsValid(mfinalfn))
754         {
755                 referenced.classId = ProcedureRelationId;
756                 referenced.objectId = mfinalfn;
757                 referenced.objectSubId = 0;
758                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
759         }
760
761         /* Depends on sort operator, if any */
762         if (OidIsValid(sortop))
763         {
764                 referenced.classId = OperatorRelationId;
765                 referenced.objectId = sortop;
766                 referenced.objectSubId = 0;
767                 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
768         }
769
770         return myself;
771 }
772
773 /*
774  * lookup_agg_function
775  * common code for finding aggregate support functions
776  *
777  * fnName: possibly-schema-qualified function name
778  * nargs, input_types: expected function argument types
779  * variadicArgType: type of variadic argument if any, else InvalidOid
780  *
781  * Returns OID of function, and stores its return type into *rettype
782  *
783  * NB: must not scribble on input_types[], as we may re-use those
784  */
785 static Oid
786 lookup_agg_function(List *fnName,
787                                         int nargs,
788                                         Oid *input_types,
789                                         Oid variadicArgType,
790                                         Oid *rettype)
791 {
792         Oid                     fnOid;
793         bool            retset;
794         int                     nvargs;
795         Oid                     vatype;
796         Oid                *true_oid_array;
797         FuncDetailCode fdresult;
798         AclResult       aclresult;
799         int                     i;
800
801         /*
802          * func_get_detail looks up the function in the catalogs, does
803          * disambiguation for polymorphic functions, handles inheritance, and
804          * returns the funcid and type and set or singleton status of the
805          * function's return value.  it also returns the true argument types to
806          * the function.
807          */
808         fdresult = func_get_detail(fnName, NIL, NIL,
809                                                            nargs, input_types, false, false,
810                                                            &fnOid, rettype, &retset,
811                                                            &nvargs, &vatype,
812                                                            &true_oid_array, NULL);
813
814         /* only valid case is a normal function not returning a set */
815         if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
816                 ereport(ERROR,
817                                 (errcode(ERRCODE_UNDEFINED_FUNCTION),
818                                  errmsg("function %s does not exist",
819                                                 func_signature_string(fnName, nargs,
820                                                                                           NIL, input_types))));
821         if (retset)
822                 ereport(ERROR,
823                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
824                                  errmsg("function %s returns a set",
825                                                 func_signature_string(fnName, nargs,
826                                                                                           NIL, input_types))));
827
828         /*
829          * If the agg is declared to take VARIADIC ANY, the underlying functions
830          * had better be declared that way too, else they may receive too many
831          * parameters; but func_get_detail would have been happy with plain ANY.
832          * (Probably nothing very bad would happen, but it wouldn't work as the
833          * user expects.)  Other combinations should work without any special
834          * pushups, given that we told func_get_detail not to expand VARIADIC.
835          */
836         if (variadicArgType == ANYOID && vatype != ANYOID)
837                 ereport(ERROR,
838                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
839                                  errmsg("function %s must accept VARIADIC ANY to be used in this aggregate",
840                                                 func_signature_string(fnName, nargs,
841                                                                                           NIL, input_types))));
842
843         /*
844          * If there are any polymorphic types involved, enforce consistency, and
845          * possibly refine the result type.  It's OK if the result is still
846          * polymorphic at this point, though.
847          */
848         *rettype = enforce_generic_type_consistency(input_types,
849                                                                                                 true_oid_array,
850                                                                                                 nargs,
851                                                                                                 *rettype,
852                                                                                                 true);
853
854         /*
855          * func_get_detail will find functions requiring run-time argument type
856          * coercion, but nodeAgg.c isn't prepared to deal with that
857          */
858         for (i = 0; i < nargs; i++)
859         {
860                 if (!IsBinaryCoercible(input_types[i], true_oid_array[i]))
861                         ereport(ERROR,
862                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
863                                          errmsg("function %s requires run-time type coercion",
864                                                         func_signature_string(fnName, nargs,
865                                                                                                   NIL, true_oid_array))));
866         }
867
868         /* Check aggregate creator has permission to call the function */
869         aclresult = pg_proc_aclcheck(fnOid, GetUserId(), ACL_EXECUTE);
870         if (aclresult != ACLCHECK_OK)
871                 aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(fnOid));
872
873         return fnOid;
874 }