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-2018, 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"
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  */
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 
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 
678  aggdesc = heap_open(AggregateRelationId, RowExclusiveLock);
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 aggregate support functions
777  *
778  * fnName: possibly-schema-qualified function name
779  * nargs, input_types: expected function argument types
780  * variadicArgType: type of variadic argument if any, else InvalidOid
781  *
782  * Returns OID of function, and stores its return type into *rettype
783  *
784  * NB: must not scribble on input_types[], as we may re-use those
785  */
786 static Oid
788  int nargs,
789  Oid *input_types,
790  Oid variadicArgType,
791  Oid *rettype)
792 {
793  Oid fnOid;
794  bool retset;
795  int nvargs;
796  Oid vatype;
797  Oid *true_oid_array;
798  FuncDetailCode fdresult;
799  AclResult aclresult;
800  int i;
801 
802  /*
803  * func_get_detail looks up the function in the catalogs, does
804  * disambiguation for polymorphic functions, handles inheritance, and
805  * returns the funcid and type and set or singleton status of the
806  * function's return value. it also returns the true argument types to
807  * the function.
808  */
809  fdresult = func_get_detail(fnName, NIL, NIL,
810  nargs, input_types, false, false,
811  &fnOid, rettype, &retset,
812  &nvargs, &vatype,
813  &true_oid_array, NULL);
814 
815  /* only valid case is a normal function not returning a set */
816  if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
817  ereport(ERROR,
818  (errcode(ERRCODE_UNDEFINED_FUNCTION),
819  errmsg("function %s does not exist",
820  func_signature_string(fnName, nargs,
821  NIL, input_types))));
822  if (retset)
823  ereport(ERROR,
824  (errcode(ERRCODE_DATATYPE_MISMATCH),
825  errmsg("function %s returns a set",
826  func_signature_string(fnName, nargs,
827  NIL, input_types))));
828 
829  /*
830  * If the agg is declared to take VARIADIC ANY, the underlying functions
831  * had better be declared that way too, else they may receive too many
832  * parameters; but func_get_detail would have been happy with plain ANY.
833  * (Probably nothing very bad would happen, but it wouldn't work as the
834  * user expects.) Other combinations should work without any special
835  * pushups, given that we told func_get_detail not to expand VARIADIC.
836  */
837  if (variadicArgType == ANYOID && vatype != ANYOID)
838  ereport(ERROR,
839  (errcode(ERRCODE_DATATYPE_MISMATCH),
840  errmsg("function %s must accept VARIADIC ANY to be used in this aggregate",
841  func_signature_string(fnName, nargs,
842  NIL, input_types))));
843 
844  /*
845  * If there are any polymorphic types involved, enforce consistency, and
846  * possibly refine the result type. It's OK if the result is still
847  * polymorphic at this point, though.
848  */
849  *rettype = enforce_generic_type_consistency(input_types,
850  true_oid_array,
851  nargs,
852  *rettype,
853  true);
854 
855  /*
856  * func_get_detail will find functions requiring run-time argument type
857  * coercion, but nodeAgg.c isn't prepared to deal with that
858  */
859  for (i = 0; i < nargs; i++)
860  {
861  if (!IsBinaryCoercible(input_types[i], true_oid_array[i]))
862  ereport(ERROR,
863  (errcode(ERRCODE_DATATYPE_MISMATCH),
864  errmsg("function %s requires run-time type coercion",
865  func_signature_string(fnName, nargs,
866  NIL, true_oid_array))));
867  }
868 
869  /* Check aggregate creator has permission to call the function */
870  aclresult = pg_proc_aclcheck(fnOid, GetUserId(), ACL_EXECUTE);
871  if (aclresult != ACLCHECK_OK)
872  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(fnOid));
873 
874  return fnOid;
875 }
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, 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, float4 procost, float4 prorows)
Definition: pg_proc.c:66
#define NIL
Definition: pg_list.h:69
Definition: c.h:555
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
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:46
Oid GetUserId(void)
Definition: miscinit.c:379
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
#define PointerGetDatum(X)
Definition: postgres.h:541
#define Int16GetDatum(X)
Definition: postgres.h:436
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:328
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:1074
#define heap_close(r, l)
Definition: heapam.h:97
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3662
signed int int32
Definition: c.h:313
#define FUNC_MAX_ARGS
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3349
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1397
Oid enforce_generic_type_consistency(Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:563
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
FuncDetailCode
Definition: parse_func.h:22
#define ACL_USAGE
Definition: parsenodes.h:82
#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:787
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:1953
bool IsBinaryCoercible(Oid srctype, Oid targettype)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
char * NameListToString(List *names)
Definition: namespace.c:3082
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
TupleDesc rd_att
Definition: rel.h:85
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:132
#define BoolGetDatum(X)
Definition: postgres.h:387
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
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:1312
bool func_strict(Oid funcid)
Definition: lsyscache.c:1550
#define CharGetDatum(X)
Definition: postgres.h:401
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define Int32GetDatum(X)
Definition: postgres.h:464
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define ACL_EXECUTE
Definition: parsenodes.h:81
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4651
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:95
#define elog
Definition: elog.h:219
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4739
Definition: pg_list.h:45