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-2020, 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  */
46 AggregateCreate(const char *aggName,
47  Oid aggNamespace,
48  bool replace,
49  char aggKind,
50  int numArgs,
51  int numDirectArgs,
52  oidvector *parameterTypes,
53  Datum allParameterTypes,
54  Datum parameterModes,
55  Datum parameterNames,
56  List *parameterDefaults,
57  Oid variadicArgType,
58  List *aggtransfnName,
59  List *aggfinalfnName,
60  List *aggcombinefnName,
61  List *aggserialfnName,
62  List *aggdeserialfnName,
63  List *aggmtransfnName,
64  List *aggminvtransfnName,
65  List *aggmfinalfnName,
66  bool finalfnExtraArgs,
67  bool mfinalfnExtraArgs,
68  char finalfnModify,
69  char mfinalfnModify,
70  List *aggsortopName,
71  Oid aggTransType,
72  int32 aggTransSpace,
73  Oid aggmTransType,
74  int32 aggmTransSpace,
75  const char *agginitval,
76  const char *aggminitval,
77  char proparallel)
78 {
79  Relation aggdesc;
80  HeapTuple tup;
81  HeapTuple oldtup;
82  bool nulls[Natts_pg_aggregate];
83  Datum values[Natts_pg_aggregate];
84  bool replaces[Natts_pg_aggregate];
85  Form_pg_proc proc;
86  Oid transfn;
87  Oid finalfn = InvalidOid; /* can be omitted */
88  Oid combinefn = InvalidOid; /* can be omitted */
89  Oid serialfn = InvalidOid; /* can be omitted */
90  Oid deserialfn = InvalidOid; /* can be omitted */
91  Oid mtransfn = InvalidOid; /* can be omitted */
92  Oid minvtransfn = InvalidOid; /* can be omitted */
93  Oid mfinalfn = InvalidOid; /* can be omitted */
94  Oid sortop = InvalidOid; /* can be omitted */
95  Oid *aggArgTypes = parameterTypes->values;
96  bool mtransIsStrict = false;
97  Oid rettype;
98  Oid finaltype;
99  Oid fnArgs[FUNC_MAX_ARGS];
100  int nargs_transfn;
101  int nargs_finalfn;
102  Oid procOid;
103  TupleDesc tupDesc;
104  char *detailmsg;
105  int i;
106  ObjectAddress myself,
107  referenced;
108  ObjectAddresses *addrs;
109  AclResult aclresult;
110 
111  /* sanity checks (caller should have caught these) */
112  if (!aggName)
113  elog(ERROR, "no aggregate name supplied");
114 
115  if (!aggtransfnName)
116  elog(ERROR, "aggregate must have a transition function");
117 
118  if (numDirectArgs < 0 || numDirectArgs > numArgs)
119  elog(ERROR, "incorrect number of direct arguments for aggregate");
120 
121  /*
122  * Aggregates can have at most FUNC_MAX_ARGS-1 args, else the transfn
123  * and/or finalfn will be unrepresentable in pg_proc. We must check now
124  * to protect fixed-size arrays here and possibly in called functions.
125  */
126  if (numArgs < 0 || numArgs > FUNC_MAX_ARGS - 1)
127  ereport(ERROR,
128  (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
129  errmsg_plural("aggregates cannot have more than %d argument",
130  "aggregates cannot have more than %d arguments",
131  FUNC_MAX_ARGS - 1,
132  FUNC_MAX_ARGS - 1)));
133 
134  /*
135  * If transtype is polymorphic, must have polymorphic argument also; else
136  * we will have no way to deduce the actual transtype.
137  */
138  detailmsg = check_valid_polymorphic_signature(aggTransType,
139  aggArgTypes,
140  numArgs);
141  if (detailmsg)
142  ereport(ERROR,
143  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
144  errmsg("cannot determine transition data type"),
145  errdetail_internal("%s", detailmsg)));
146 
147  /*
148  * Likewise for moving-aggregate transtype, if any
149  */
150  if (OidIsValid(aggmTransType))
151  {
152  detailmsg = check_valid_polymorphic_signature(aggmTransType,
153  aggArgTypes,
154  numArgs);
155  if (detailmsg)
156  ereport(ERROR,
157  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
158  errmsg("cannot determine transition data type"),
159  errdetail_internal("%s", detailmsg)));
160  }
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  detailmsg = check_valid_polymorphic_signature(finaltype,
493  aggArgTypes,
494  numArgs);
495  if (detailmsg)
496  ereport(ERROR,
497  (errcode(ERRCODE_DATATYPE_MISMATCH),
498  errmsg("cannot determine result data type"),
499  errdetail_internal("%s", detailmsg)));
500 
501  /*
502  * Also, the return type can't be INTERNAL unless there's at least one
503  * INTERNAL argument. This is the same type-safety restriction we enforce
504  * for regular functions, but at the level of aggregates. We must test
505  * this explicitly because we allow INTERNAL as the transtype.
506  */
507  detailmsg = check_valid_internal_signature(finaltype,
508  aggArgTypes,
509  numArgs);
510  if (detailmsg)
511  ereport(ERROR,
512  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
513  errmsg("unsafe use of pseudo-type \"internal\""),
514  errdetail_internal("%s", detailmsg)));
515 
516  /*
517  * If a moving-aggregate implementation is supplied, look up its finalfn
518  * if any, and check that the implied aggregate result type matches the
519  * plain implementation.
520  */
521  if (OidIsValid(aggmTransType))
522  {
523  /* handle finalfn, if supplied */
524  if (aggmfinalfnName)
525  {
526  /*
527  * The arguments are figured the same way as for the regular
528  * finalfn, but using aggmTransType and mfinalfnExtraArgs.
529  */
530  Oid ffnVariadicArgType = variadicArgType;
531 
532  fnArgs[0] = aggmTransType;
533  memcpy(fnArgs + 1, aggArgTypes, numArgs * sizeof(Oid));
534  if (mfinalfnExtraArgs)
535  nargs_finalfn = numArgs + 1;
536  else
537  {
538  nargs_finalfn = numDirectArgs + 1;
539  if (numDirectArgs < numArgs)
540  {
541  /* variadic argument doesn't affect finalfn */
542  ffnVariadicArgType = InvalidOid;
543  }
544  }
545 
546  mfinalfn = lookup_agg_function(aggmfinalfnName, nargs_finalfn,
547  fnArgs, ffnVariadicArgType,
548  &rettype);
549 
550  /* As above, check strictness if mfinalfnExtraArgs is given */
551  if (mfinalfnExtraArgs && func_strict(mfinalfn))
552  ereport(ERROR,
553  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
554  errmsg("final function with extra arguments must not be declared STRICT")));
555  }
556  else
557  {
558  /*
559  * If no finalfn, aggregate result type is type of the state value
560  */
561  rettype = aggmTransType;
562  }
563  Assert(OidIsValid(rettype));
564  if (rettype != finaltype)
565  ereport(ERROR,
566  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
567  errmsg("moving-aggregate implementation returns type %s, but plain implementation returns type %s",
568  format_type_be(rettype),
569  format_type_be(finaltype))));
570  }
571 
572  /* handle sortop, if supplied */
573  if (aggsortopName)
574  {
575  if (numArgs != 1)
576  ereport(ERROR,
577  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
578  errmsg("sort operator can only be specified for single-argument aggregates")));
579  sortop = LookupOperName(NULL, aggsortopName,
580  aggArgTypes[0], aggArgTypes[0],
581  false, -1);
582  }
583 
584  /*
585  * permission checks on used types
586  */
587  for (i = 0; i < numArgs; i++)
588  {
589  aclresult = pg_type_aclcheck(aggArgTypes[i], GetUserId(), ACL_USAGE);
590  if (aclresult != ACLCHECK_OK)
591  aclcheck_error_type(aclresult, aggArgTypes[i]);
592  }
593 
594  aclresult = pg_type_aclcheck(aggTransType, GetUserId(), ACL_USAGE);
595  if (aclresult != ACLCHECK_OK)
596  aclcheck_error_type(aclresult, aggTransType);
597 
598  if (OidIsValid(aggmTransType))
599  {
600  aclresult = pg_type_aclcheck(aggmTransType, GetUserId(), ACL_USAGE);
601  if (aclresult != ACLCHECK_OK)
602  aclcheck_error_type(aclresult, aggmTransType);
603  }
604 
605  aclresult = pg_type_aclcheck(finaltype, GetUserId(), ACL_USAGE);
606  if (aclresult != ACLCHECK_OK)
607  aclcheck_error_type(aclresult, finaltype);
608 
609 
610  /*
611  * Everything looks okay. Try to create the pg_proc entry for the
612  * aggregate. (This could fail if there's already a conflicting entry.)
613  */
614 
615  myself = ProcedureCreate(aggName,
616  aggNamespace,
617  replace, /* maybe replacement */
618  false, /* doesn't return a set */
619  finaltype, /* returnType */
620  GetUserId(), /* proowner */
621  INTERNALlanguageId, /* languageObjectId */
622  InvalidOid, /* no validator */
623  "aggregate_dummy", /* placeholder proc */
624  NULL, /* probin */
625  PROKIND_AGGREGATE,
626  false, /* security invoker (currently not
627  * definable for agg) */
628  false, /* isLeakProof */
629  false, /* isStrict (not needed for agg) */
630  PROVOLATILE_IMMUTABLE, /* volatility (not needed
631  * for agg) */
632  proparallel,
633  parameterTypes, /* paramTypes */
634  allParameterTypes, /* allParamTypes */
635  parameterModes, /* parameterModes */
636  parameterNames, /* parameterNames */
637  parameterDefaults, /* parameterDefaults */
638  PointerGetDatum(NULL), /* trftypes */
639  PointerGetDatum(NULL), /* proconfig */
640  InvalidOid, /* no prosupport */
641  1, /* procost */
642  0); /* prorows */
643  procOid = myself.objectId;
644 
645  /*
646  * Okay to create the pg_aggregate entry.
647  */
648  aggdesc = table_open(AggregateRelationId, RowExclusiveLock);
649  tupDesc = aggdesc->rd_att;
650 
651  /* initialize nulls and values */
652  for (i = 0; i < Natts_pg_aggregate; i++)
653  {
654  nulls[i] = false;
655  values[i] = (Datum) NULL;
656  replaces[i] = true;
657  }
658  values[Anum_pg_aggregate_aggfnoid - 1] = ObjectIdGetDatum(procOid);
659  values[Anum_pg_aggregate_aggkind - 1] = CharGetDatum(aggKind);
660  values[Anum_pg_aggregate_aggnumdirectargs - 1] = Int16GetDatum(numDirectArgs);
661  values[Anum_pg_aggregate_aggtransfn - 1] = ObjectIdGetDatum(transfn);
662  values[Anum_pg_aggregate_aggfinalfn - 1] = ObjectIdGetDatum(finalfn);
663  values[Anum_pg_aggregate_aggcombinefn - 1] = ObjectIdGetDatum(combinefn);
664  values[Anum_pg_aggregate_aggserialfn - 1] = ObjectIdGetDatum(serialfn);
665  values[Anum_pg_aggregate_aggdeserialfn - 1] = ObjectIdGetDatum(deserialfn);
666  values[Anum_pg_aggregate_aggmtransfn - 1] = ObjectIdGetDatum(mtransfn);
667  values[Anum_pg_aggregate_aggminvtransfn - 1] = ObjectIdGetDatum(minvtransfn);
668  values[Anum_pg_aggregate_aggmfinalfn - 1] = ObjectIdGetDatum(mfinalfn);
669  values[Anum_pg_aggregate_aggfinalextra - 1] = BoolGetDatum(finalfnExtraArgs);
670  values[Anum_pg_aggregate_aggmfinalextra - 1] = BoolGetDatum(mfinalfnExtraArgs);
671  values[Anum_pg_aggregate_aggfinalmodify - 1] = CharGetDatum(finalfnModify);
672  values[Anum_pg_aggregate_aggmfinalmodify - 1] = CharGetDatum(mfinalfnModify);
673  values[Anum_pg_aggregate_aggsortop - 1] = ObjectIdGetDatum(sortop);
674  values[Anum_pg_aggregate_aggtranstype - 1] = ObjectIdGetDatum(aggTransType);
675  values[Anum_pg_aggregate_aggtransspace - 1] = Int32GetDatum(aggTransSpace);
676  values[Anum_pg_aggregate_aggmtranstype - 1] = ObjectIdGetDatum(aggmTransType);
677  values[Anum_pg_aggregate_aggmtransspace - 1] = Int32GetDatum(aggmTransSpace);
678  if (agginitval)
679  values[Anum_pg_aggregate_agginitval - 1] = CStringGetTextDatum(agginitval);
680  else
681  nulls[Anum_pg_aggregate_agginitval - 1] = true;
682  if (aggminitval)
683  values[Anum_pg_aggregate_aggminitval - 1] = CStringGetTextDatum(aggminitval);
684  else
685  nulls[Anum_pg_aggregate_aggminitval - 1] = true;
686 
687  if (replace)
688  oldtup = SearchSysCache1(AGGFNOID, ObjectIdGetDatum(procOid));
689  else
690  oldtup = NULL;
691 
692  if (HeapTupleIsValid(oldtup))
693  {
694  Form_pg_aggregate oldagg = (Form_pg_aggregate) GETSTRUCT(oldtup);
695 
696  /*
697  * If we're replacing an existing entry, we need to validate that
698  * we're not changing anything that would break callers. Specifically
699  * we must not change aggkind or aggnumdirectargs, which affect how an
700  * aggregate call is treated in parse analysis.
701  */
702  if (aggKind != oldagg->aggkind)
703  ereport(ERROR,
704  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
705  errmsg("cannot change routine kind"),
706  (oldagg->aggkind == AGGKIND_NORMAL ?
707  errdetail("\"%s\" is an ordinary aggregate function.", aggName) :
708  oldagg->aggkind == AGGKIND_ORDERED_SET ?
709  errdetail("\"%s\" is an ordered-set aggregate.", aggName) :
710  oldagg->aggkind == AGGKIND_HYPOTHETICAL ?
711  errdetail("\"%s\" is a hypothetical-set aggregate.", aggName) :
712  0)));
713  if (numDirectArgs != oldagg->aggnumdirectargs)
714  ereport(ERROR,
715  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
716  errmsg("cannot change number of direct arguments of an aggregate function")));
717 
718  replaces[Anum_pg_aggregate_aggfnoid - 1] = false;
719  replaces[Anum_pg_aggregate_aggkind - 1] = false;
720  replaces[Anum_pg_aggregate_aggnumdirectargs - 1] = false;
721 
722  tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
723  CatalogTupleUpdate(aggdesc, &tup->t_self, tup);
724  ReleaseSysCache(oldtup);
725  }
726  else
727  {
728  tup = heap_form_tuple(tupDesc, values, nulls);
729  CatalogTupleInsert(aggdesc, tup);
730  }
731 
732  table_close(aggdesc, RowExclusiveLock);
733 
734  /*
735  * Create dependencies for the aggregate (above and beyond those already
736  * made by ProcedureCreate). Note: we don't need an explicit dependency
737  * on aggTransType since we depend on it indirectly through transfn.
738  * Likewise for aggmTransType using the mtransfn, if it exists.
739  *
740  * If we're replacing an existing definition, ProcedureCreate deleted all
741  * our existing dependencies, so we have to do the same things here either
742  * way.
743  */
744 
745  addrs = new_object_addresses();
746 
747  /* Depends on transition function */
748  ObjectAddressSet(referenced, ProcedureRelationId, transfn);
749  add_exact_object_address(&referenced, addrs);
750 
751  /* Depends on final function, if any */
752  if (OidIsValid(finalfn))
753  {
754  ObjectAddressSet(referenced, ProcedureRelationId, finalfn);
755  add_exact_object_address(&referenced, addrs);
756  }
757 
758  /* Depends on combine function, if any */
759  if (OidIsValid(combinefn))
760  {
761  ObjectAddressSet(referenced, ProcedureRelationId, combinefn);
762  add_exact_object_address(&referenced, addrs);
763  }
764 
765  /* Depends on serialization function, if any */
766  if (OidIsValid(serialfn))
767  {
768  ObjectAddressSet(referenced, ProcedureRelationId, serialfn);
769  add_exact_object_address(&referenced, addrs);
770  }
771 
772  /* Depends on deserialization function, if any */
773  if (OidIsValid(deserialfn))
774  {
775  ObjectAddressSet(referenced, ProcedureRelationId, deserialfn);
776  add_exact_object_address(&referenced, addrs);
777  }
778 
779  /* Depends on forward transition function, if any */
780  if (OidIsValid(mtransfn))
781  {
782  ObjectAddressSet(referenced, ProcedureRelationId, mtransfn);
783  add_exact_object_address(&referenced, addrs);
784  }
785 
786  /* Depends on inverse transition function, if any */
787  if (OidIsValid(minvtransfn))
788  {
789  ObjectAddressSet(referenced, ProcedureRelationId, minvtransfn);
790  add_exact_object_address(&referenced, addrs);
791  }
792 
793  /* Depends on final function, if any */
794  if (OidIsValid(mfinalfn))
795  {
796  ObjectAddressSet(referenced, ProcedureRelationId, mfinalfn);
797  add_exact_object_address(&referenced, addrs);
798  }
799 
800  /* Depends on sort operator, if any */
801  if (OidIsValid(sortop))
802  {
803  ObjectAddressSet(referenced, OperatorRelationId, sortop);
804  add_exact_object_address(&referenced, addrs);
805  }
806 
808  free_object_addresses(addrs);
809  return myself;
810 }
811 
812 /*
813  * lookup_agg_function
814  * common code for finding aggregate support functions
815  *
816  * fnName: possibly-schema-qualified function name
817  * nargs, input_types: expected function argument types
818  * variadicArgType: type of variadic argument if any, else InvalidOid
819  *
820  * Returns OID of function, and stores its return type into *rettype
821  *
822  * NB: must not scribble on input_types[], as we may re-use those
823  */
824 static Oid
826  int nargs,
827  Oid *input_types,
828  Oid variadicArgType,
829  Oid *rettype)
830 {
831  Oid fnOid;
832  bool retset;
833  int nvargs;
834  Oid vatype;
835  Oid *true_oid_array;
836  FuncDetailCode fdresult;
837  AclResult aclresult;
838  int i;
839 
840  /*
841  * func_get_detail looks up the function in the catalogs, does
842  * disambiguation for polymorphic functions, handles inheritance, and
843  * returns the funcid and type and set or singleton status of the
844  * function's return value. it also returns the true argument types to
845  * the function.
846  */
847  fdresult = func_get_detail(fnName, NIL, NIL,
848  nargs, input_types, false, false,
849  &fnOid, rettype, &retset,
850  &nvargs, &vatype,
851  &true_oid_array, NULL);
852 
853  /* only valid case is a normal function not returning a set */
854  if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
855  ereport(ERROR,
856  (errcode(ERRCODE_UNDEFINED_FUNCTION),
857  errmsg("function %s does not exist",
858  func_signature_string(fnName, nargs,
859  NIL, input_types))));
860  if (retset)
861  ereport(ERROR,
862  (errcode(ERRCODE_DATATYPE_MISMATCH),
863  errmsg("function %s returns a set",
864  func_signature_string(fnName, nargs,
865  NIL, input_types))));
866 
867  /*
868  * If the agg is declared to take VARIADIC ANY, the underlying functions
869  * had better be declared that way too, else they may receive too many
870  * parameters; but func_get_detail would have been happy with plain ANY.
871  * (Probably nothing very bad would happen, but it wouldn't work as the
872  * user expects.) Other combinations should work without any special
873  * pushups, given that we told func_get_detail not to expand VARIADIC.
874  */
875  if (variadicArgType == ANYOID && vatype != ANYOID)
876  ereport(ERROR,
877  (errcode(ERRCODE_DATATYPE_MISMATCH),
878  errmsg("function %s must accept VARIADIC ANY to be used in this aggregate",
879  func_signature_string(fnName, nargs,
880  NIL, input_types))));
881 
882  /*
883  * If there are any polymorphic types involved, enforce consistency, and
884  * possibly refine the result type. It's OK if the result is still
885  * polymorphic at this point, though.
886  */
887  *rettype = enforce_generic_type_consistency(input_types,
888  true_oid_array,
889  nargs,
890  *rettype,
891  true);
892 
893  /*
894  * func_get_detail will find functions requiring run-time argument type
895  * coercion, but nodeAgg.c isn't prepared to deal with that
896  */
897  for (i = 0; i < nargs; i++)
898  {
899  if (!IsBinaryCoercible(input_types[i], true_oid_array[i]))
900  ereport(ERROR,
901  (errcode(ERRCODE_DATATYPE_MISMATCH),
902  errmsg("function %s requires run-time type coercion",
903  func_signature_string(fnName, nargs,
904  NIL, true_oid_array))));
905  }
906 
907  /* Check aggregate creator has permission to call the function */
908  aclresult = pg_proc_aclcheck(fnOid, GetUserId(), ACL_EXECUTE);
909  if (aclresult != ACLCHECK_OK)
910  aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(fnOid));
911 
912  return fnOid;
913 }
#define NIL
Definition: pg_list.h:65
Definition: c.h:601
Oid enforce_generic_type_consistency(const Oid *actual_arg_types, Oid *declared_arg_types, int nargs, Oid rettype, bool allow_poly)
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
char * check_valid_polymorphic_signature(Oid ret_type, const Oid *declared_arg_types, int nargs)
Oid GetUserId(void)
Definition: miscinit.c:476
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:934
#define PointerGetDatum(X)
Definition: postgres.h:556
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2676
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, Oid prosupport, float4 procost, float4 prorows)
Definition: pg_proc.c:69
#define Int16GetDatum(X)
Definition: postgres.h:451
int errcode(int sqlerrcode)
Definition: elog.c:610
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
Oid LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright, bool noError, int location)
Definition: parse_oper.c:101
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2467
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2412
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2707
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:651
void aclcheck_error_type(AclResult aclerr, Oid typeOid)
Definition: aclchk.c:3607
signed int int32
Definition: c.h:362
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
#define FUNC_MAX_ARGS
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1520
ItemPointerData t_self
Definition: htup.h:65
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:609
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:957
FuncDetailCode
Definition: parse_func.h:22
#define ACL_USAGE
Definition: parsenodes.h:82
static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types, Oid variadicArgType, Oid *rettype)
Definition: pg_aggregate.c:825
const char * func_signature_string(List *funcname, int nargs, List *argnames, const Oid *argtypes)
Definition: parse_func.c:2015
bool IsBinaryCoercible(Oid srctype, Oid targettype)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
char * NameListToString(List *names)
Definition: namespace.c:3101
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
TupleDesc rd_att
Definition: rel.h:110
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
#define BoolGetDatum(X)
Definition: postgres.h:402
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:144
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:745
char * check_valid_internal_signature(Oid ret_type, const Oid *declared_arg_types, int nargs)
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:109
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
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:1382
bool func_strict(Oid funcid)
Definition: lsyscache.c:1673
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:416
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define Int32GetDatum(X)
Definition: postgres.h:479
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:214
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4587
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:86
ObjectAddress AggregateCreate(const char *aggName, Oid aggNamespace, bool replace, 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
AclResult pg_type_aclcheck(Oid type_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4675
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
Definition: pg_list.h:50
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221