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