1 /*-------------------------------------------------------------------------
2  *
3  * pg_aggregate.c
4  *	  routines to support manipulation of the pg_aggregate relation
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/backend/catalog/pg_aggregate.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/htup_details.h"
18 #include "access/table.h"
19 #include "catalog/dependency.h"
20 #include "catalog/indexing.h"
21 #include "catalog/pg_aggregate.h"
22 #include "catalog/pg_language.h"
23 #include "catalog/pg_operator.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_type.h"
26 #include "miscadmin.h"
27 #include "parser/parse_coerce.h"
28 #include "parser/parse_func.h"
29 #include "parser/parse_oper.h"
30 #include "utils/acl.h"
31 #include "utils/builtins.h"
32 #include "utils/lsyscache.h"
33 #include "utils/rel.h"
34 #include "utils/syscache.h"
35 
36 
37 static Oid	lookup_agg_function(List *fnName, int nargs, Oid *input_types,
38 								Oid variadicArgType,
39 								Oid *rettype);
40 
41 
42 /*
43  * AggregateCreate
44  */
45 ObjectAddress
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)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(rettype),
567 							format_type_be(finaltype))));
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 mtransfunc, 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
lookup_agg_function(List * fnName,int nargs,Oid * input_types,Oid variadicArgType,Oid * rettype)837 lookup_agg_function(List *fnName,
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 }
926