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