static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types,
Oid variadicArgType,
Oid *rettype);
/* *AggregateCreate
*/
ObjectAddress
AggregateCreate(constchar *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, constchar *agginitval, constchar *aggminitval, char proparallel)
{
Relation aggdesc;
HeapTuple tup;
HeapTuple oldtup; bool nulls[Natts_pg_aggregate];
Datum values[Natts_pg_aggregate]; bool replaces[Natts_pg_aggregate];
Form_pg_proc proc;
Oid transfn;
Oid finalfn = InvalidOid; /* can be omitted */
Oid combinefn = InvalidOid; /* can be omitted */
Oid serialfn = InvalidOid; /* can be omitted */
Oid deserialfn = InvalidOid; /* can be omitted */
Oid mtransfn = InvalidOid; /* can be omitted */
Oid minvtransfn = InvalidOid; /* can be omitted */
Oid mfinalfn = InvalidOid; /* can be omitted */
Oid sortop = InvalidOid; /* can be omitted */
Oid *aggArgTypes = parameterTypes->values; bool mtransIsStrict = false;
Oid rettype;
Oid finaltype;
Oid fnArgs[FUNC_MAX_ARGS]; int nargs_transfn; int nargs_finalfn;
Oid procOid;
TupleDesc tupDesc; char *detailmsg; int i;
ObjectAddress myself,
referenced;
ObjectAddresses *addrs;
AclResult aclresult;
/* sanity checks (caller should have caught these) */ if (!aggName)
elog(ERROR, "no aggregate name supplied");
if (!aggtransfnName)
elog(ERROR, "aggregate must have a transition function");
if (numDirectArgs < 0 || numDirectArgs > numArgs)
elog(ERROR, "incorrect number of direct arguments for aggregate");
/* *AggregatescanhaveatmostFUNC_MAX_ARGS-1args,elsethetransfn *and/orfinalfnwillbeunrepresentableinpg_proc.Wemustchecknow *toprotectfixed-sizearrayshereandpossiblyincalledfunctions.
*/ if (numArgs < 0 || numArgs > FUNC_MAX_ARGS - 1)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg_plural("aggregates cannot have more than %d argument", "aggregates cannot have more than %d arguments",
FUNC_MAX_ARGS - 1,
FUNC_MAX_ARGS - 1)));
/* *Iftranstypeispolymorphic,musthavepolymorphicargumentalso;else *wewillhavenowaytodeducetheactualtranstype.
*/
detailmsg = check_valid_polymorphic_signature(aggTransType,
aggArgTypes,
numArgs); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot determine transition data type"),
errdetail_internal("%s", detailmsg)));
/* *Likewiseformoving-aggregatetranstype,ifany
*/ if (OidIsValid(aggmTransType))
{
detailmsg = check_valid_polymorphic_signature(aggmTransType,
aggArgTypes,
numArgs); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("cannot determine transition data type"),
errdetail_internal("%s", detailmsg)));
}
/* *Anordered-setaggregatethatisVARIADICmustbeVARIADICANY.In *principlewecouldsupportregularvariadictypes,butitwouldmake *thingsmuchmorecomplicatedbecausewe'dhavetoassemblethecorrect *subsetsofargumentsintoarrayvalues.Sincenostandardaggregates *haveuseforsuchacase,wearen'tbotheringfornow.
*/ if (AGGKIND_IS_ORDERED_SET(aggKind) && OidIsValid(variadicArgType) &&
variadicArgType != ANYOID)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("a variadic ordered-set aggregate must use VARIADIC type ANY")));
/* *Returntypeoftransfn(possiblyafterrefinementby *enforce_generic_type_consistency,iftranstypeisn'tpolymorphic)must *exactlymatchdeclaredtranstype. * *Inthenon-polymorphic-transtypecase,itmightbeokaytoallowa *rettypethat'sbinary-coercibletotranstype,butI'mnotquite *convincedthatit'seithersafeoruseful.Whentranstypeis *polymorphicwe*must*demandexactequality.
*/ if (rettype != aggTransType)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of transition function %s is not %s",
NameListToString(aggtransfnName),
format_type_be(aggTransType))));
tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(transfn)); if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", transfn);
proc = (Form_pg_proc) GETSTRUCT(tup);
/* *IfthetransfnisstrictandtheinitvalisNULL,makesurefirstinput *typeandtranstypearethesame(oratleastbinary-compatible),so *thatit'sOKtousethefirstinputvalueastheinitialtransValue.
*/ if (proc->proisstrict && agginitval == NULL)
{ if (numArgs < 1 ||
!IsBinaryCoercible(aggArgTypes[0], aggTransType))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("must not omit initial value when transition function is strict and transition type is not compatible with input type")));
}
ReleaseSysCache(tup);
/* handle moving-aggregate transfn, if supplied */ if (aggmtransfnName)
{ /* *Theargumentsarethesameasfortheregulartransfn,exceptthat *thetransitiondatatypemightbedifferent.Sore-usethefnArgs *valuessetupabove,exceptforthatone.
*/
Assert(OidIsValid(aggmTransType));
fnArgs[0] = aggmTransType;
/* As above, return type must exactly match declared mtranstype. */ if (rettype != aggmTransType)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of transition function %s is not %s",
NameListToString(aggmtransfnName),
format_type_be(aggmTransType))));
tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(mtransfn)); if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", mtransfn);
proc = (Form_pg_proc) GETSTRUCT(tup);
/* *IfthemtransfnisstrictandtheminitvalisNULL,checkfirst *inputtypeandmtranstypearebinary-compatible.
*/ if (proc->proisstrict && aggminitval == NULL)
{ if (numArgs < 1 ||
!IsBinaryCoercible(aggArgTypes[0], aggmTransType))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("must not omit initial value when transition function is strict and transition type is not compatible with input type")));
}
/* Remember if mtransfn is strict; we may need this below */
mtransIsStrict = proc->proisstrict;
ReleaseSysCache(tup);
}
/* handle minvtransfn, if supplied */ if (aggminvtransfnName)
{ /* *Thismusthavethesamenumberofargumentswiththesametypesas *theforwardtransitionfunction,sojustre-usethefnArgsdata.
*/
Assert(aggmtransfnName);
/* As above, return type must exactly match declared mtranstype. */ if (rettype != aggmTransType)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of inverse transition function %s is not %s",
NameListToString(aggminvtransfnName),
format_type_be(aggmTransType))));
tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(minvtransfn)); if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", minvtransfn);
proc = (Form_pg_proc) GETSTRUCT(tup);
/* *Werequirethestrictnesssettingsoftheforwardandinverse *transitionfunctionstoagree.Thissaveshavingtohandle *assortedspecialcasesatexecutiontime.
*/ if (proc->proisstrict != mtransIsStrict)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("strictness of aggregate's forward and inverse transition functions must match")));
ReleaseSysCache(tup);
}
/* handle finalfn, if supplied */ if (aggfinalfnName)
{ /* *IffinalfnExtraArgsisspecified,thetransfntakesthetranstype *plusallargs;otherwise,itjusttakesthetranstypeplusany *directargs.(Non-directargsareuselessatruntime,andare *actuallypassedasNULLs,butwemayneedtheminthefunction *signaturetoallowresolutionofapolymorphicagg'sresulttype.)
*/
Oid ffnVariadicArgType = variadicArgType;
/* *WhenfinalfnExtraArgsisspecified,thefinalfnwillcertainlybe *passedatleastonenullargument,socomplainifit'sstrict. *Nothingbadwouldhappenatruntime(you'djustgetanullresult), *butit'ssurelynotwhattheuserwants,solet'scomplainnow.
*/ if (finalfnExtraArgs && func_strict(finalfn))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("final function with extra arguments must not be declared STRICT")));
} else
{ /* *Ifnofinalfn,aggregateresulttypeistypeofthestatevalue
*/
finaltype = aggTransType;
}
Assert(OidIsValid(finaltype));
/* handle the combinefn, if supplied */ if (aggcombinefnName)
{
Oid combineType;
/* Ensure the return type matches the aggregate's trans type */ if (combineType != aggTransType)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of combine function %s is not %s",
NameListToString(aggcombinefnName),
format_type_be(aggTransType))));
/* *AcombinefunctiontocombineINTERNALstatesmustacceptnullsand *ensurethatthereturnedstateisinthecorrectmemorycontext.We *cannotdirectlycheckthelatter,butwecanchecktheformer.
*/ if (aggTransType == INTERNALOID && func_strict(combinefn))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("combine function with transition type %s must not be declared STRICT",
format_type_be(aggTransType))));
}
/* *Validatetheserializationfunction,ifpresent.
*/ if (aggserialfnName)
{ /* signature is always serialize(internal) returns bytea */
fnArgs[0] = INTERNALOID;
if (rettype != BYTEAOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of serialization function %s is not %s",
NameListToString(aggserialfnName),
format_type_be(BYTEAOID))));
}
/* *Validatethedeserializationfunction,ifpresent.
*/ if (aggdeserialfnName)
{ /* signature is always deserialize(bytea, internal) returns internal */
fnArgs[0] = BYTEAOID;
fnArgs[1] = INTERNALOID; /* dummy argument for type safety */
if (rettype != INTERNALOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("return type of deserialization function %s is not %s",
NameListToString(aggdeserialfnName),
format_type_be(INTERNALOID))));
}
/* *Iffinaltype(i.e.aggregatereturntype)ispolymorphic,inputsmust *bepolymorphicalso,elseparserwillfailtodeduceresulttype. *(Note:giventheprevioustestontranstypeandinputs,thiscannot *happen,unlesssomeonehassnuckafinalfndefinitionintothecatalogs *thatitselfviolatestheruleagainstpolymorphicresultwithno *polymorphicinput.)
*/
detailmsg = check_valid_polymorphic_signature(finaltype,
aggArgTypes,
numArgs); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot determine result data type"),
errdetail_internal("%s", detailmsg)));
/* *Also,thereturntypecan'tbeINTERNALunlessthere'satleastone *INTERNALargument.Thisisthesametype-safetyrestrictionweenforce *forregularfunctions,butatthelevelofaggregates.Wemusttest *thisexplicitlybecauseweallowINTERNALasthetranstype.
*/
detailmsg = check_valid_internal_signature(finaltype,
aggArgTypes,
numArgs); if (detailmsg)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("unsafe use of pseudo-type \"internal\""),
errdetail_internal("%s", detailmsg)));
/* *Ifamoving-aggregateimplementationissupplied,lookupitsfinalfn *ifany,andcheckthattheimpliedaggregateresulttypematchesthe *plainimplementation.
*/ if (OidIsValid(aggmTransType))
{ /* handle finalfn, if supplied */ if (aggmfinalfnName)
{ /* *Theargumentsarefiguredthesamewayasfortheregular *finalfn,butusingaggmTransTypeandmfinalfnExtraArgs.
*/
Oid ffnVariadicArgType = variadicArgType;
/* As above, check strictness if mfinalfnExtraArgs is given */ if (mfinalfnExtraArgs && func_strict(mfinalfn))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("final function with extra arguments must not be declared STRICT")));
} else
{ /* *Ifnofinalfn,aggregateresulttypeistypeofthestatevalue
*/
rettype = aggmTransType;
}
Assert(OidIsValid(rettype)); if (rettype != finaltype)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("moving-aggregate implementation returns type %s, but plain implementation returns type %s",
format_type_be(rettype),
format_type_be(finaltype))));
}
/* handle sortop, if supplied */ if (aggsortopName)
{ if (numArgs != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("sort operator can only be specified for single-argument aggregates")));
sortop = LookupOperName(NULL, aggsortopName,
aggArgTypes[0], aggArgTypes[0], false, -1);
}
/* *permissionchecksonusedtypes
*/ for (i = 0; i < numArgs; i++)
{
aclresult = object_aclcheck(TypeRelationId, aggArgTypes[i], GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK)
aclcheck_error_type(aclresult, aggArgTypes[i]);
}
/* Depends on transition function */
ObjectAddressSet(referenced, ProcedureRelationId, transfn);
add_exact_object_address(&referenced, addrs);
/* Depends on final function, if any */ if (OidIsValid(finalfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, finalfn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on combine function, if any */ if (OidIsValid(combinefn))
{
ObjectAddressSet(referenced, ProcedureRelationId, combinefn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on serialization function, if any */ if (OidIsValid(serialfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, serialfn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on deserialization function, if any */ if (OidIsValid(deserialfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, deserialfn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on forward transition function, if any */ if (OidIsValid(mtransfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, mtransfn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on inverse transition function, if any */ if (OidIsValid(minvtransfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, minvtransfn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on final function, if any */ if (OidIsValid(mfinalfn))
{
ObjectAddressSet(referenced, ProcedureRelationId, mfinalfn);
add_exact_object_address(&referenced, addrs);
}
/* Depends on sort operator, if any */ if (OidIsValid(sortop))
{
ObjectAddressSet(referenced, OperatorRelationId, sortop);
add_exact_object_address(&referenced, addrs);
}
/* *lookup_agg_function *commoncodeforfindingaggregatesupportfunctions * *fnName:possibly-schema-qualifiedfunctionname *nargs,input_types:expectedfunctionargumenttypes *variadicArgType:typeofvariadicargumentifany,elseInvalidOid * *ReturnsOIDoffunction,andstoresitsreturntypeinto*rettype * *NB:mustnotscribbleoninput_types[],aswemayre-usethose
*/ static Oid
lookup_agg_function(List *fnName, int nargs,
Oid *input_types,
Oid variadicArgType,
Oid *rettype)
{
Oid fnOid; bool retset; int nvargs;
Oid vatype;
Oid *true_oid_array;
FuncDetailCode fdresult;
AclResult aclresult; int i;
/* only valid case is a normal function not returning a set */ if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function %s does not exist",
func_signature_string(fnName, nargs,
NIL, input_types)))); if (retset)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function %s returns a set",
func_signature_string(fnName, nargs,
NIL, input_types))));
/* *IftheaggisdeclaredtotakeVARIADICANY,theunderlyingfunctions *hadbetterbedeclaredthatwaytoo,elsetheymayreceivetoomany *parameters;butfunc_get_detailwouldhavebeenhappywithplainANY. *(Probablynothingverybadwouldhappen,butitwouldn'tworkasthe *userexpects.)Othercombinationsshouldworkwithoutanyspecial *pushups,giventhatwetoldfunc_get_detailnottoexpandVARIADIC.
*/ if (variadicArgType == ANYOID && vatype != ANYOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function %s must accept VARIADIC ANY to be used in this aggregate",
func_signature_string(fnName, nargs,
NIL, input_types))));
/* *func_get_detailwillfindfunctionsrequiringrun-timeargumenttype *coercion,butnodeAgg.cisn'tpreparedtodealwiththat
*/ for (i = 0; i < nargs; i++)
{ if (!IsBinaryCoercible(input_types[i], true_oid_array[i]))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("function %s requires run-time type coercion",
func_signature_string(fnName, nargs,
NIL, true_oid_array))));
}
/* Check aggregate creator has permission to call the function */
aclresult = object_aclcheck(ProcedureRelationId, fnOid, GetUserId(), ACL_EXECUTE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_FUNCTION, get_func_name(fnOid));
return fnOid;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.35Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.