1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-17 17:02:08 +03:00

Revise aggregate functions per earlier discussions in pghackers.

There's now only one transition value and transition function.
NULL handling in aggregates is a lot cleaner.  Also, use Numeric
accumulators instead of integer accumulators for sum/avg on integer
datatypes --- this avoids overflow at the cost of being a little slower.
Implement VARIANCE() and STDDEV() aggregates in the standard backend.

Also, enable new LIKE selectivity estimators by default.  Unrelated
change, but as long as I had to force initdb anyway...
This commit is contained in:
Tom Lane
2000-07-17 03:05:41 +00:00
parent 139f19c302
commit bec98a31c5
55 changed files with 1949 additions and 1813 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.38 2000/06/15 03:32:19 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.39 2000/07/17 03:05:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -189,18 +189,16 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
{
HeapTuple theAggTuple;
Form_pg_aggregate aggform;
Oid fintype;
Oid xfn1;
Oid vartype;
Aggref *aggref;
bool usenulls = false;
theAggTuple = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggname),
ObjectIdGetDatum(basetype),
0, 0);
/* shouldn't happen --- caller should have checked already */
if (!HeapTupleIsValid(theAggTuple))
elog(ERROR, "Aggregate %s does not exist", aggname);
agg_error("ParseAgg", aggname, basetype);
aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
/*
* There used to be a really ugly hack for count(*) here.
@ -209,43 +207,18 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
* does the right thing. (It didn't use to do the right thing,
* because the optimizer had the wrong ideas about semantics of
* queries without explicit variables. Fixed as of Oct 1999 --- tgl.)
*
* Since "1" never evaluates as null, we currently have no need of the
* "usenulls" flag, but it should be kept around; in fact, we should
* extend the pg_aggregate table to let usenulls be specified as an
* attribute of user-defined aggregates. In the meantime, usenulls is
* just always set to "false".
*/
aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
fintype = aggform->aggfinaltype;
xfn1 = aggform->aggtransfn1;
/* only aggregates with transfn1 need a base type */
if (OidIsValid(xfn1))
{
basetype = aggform->aggbasetype;
vartype = exprType(lfirst(args));
if ((basetype != vartype)
&& (!IS_BINARY_COMPATIBLE(basetype, vartype)))
{
Type tp1,
tp2;
tp1 = typeidType(basetype);
tp2 = typeidType(vartype);
elog(ERROR, "Aggregate type mismatch"
"\n\t%s() works on %s, not on %s",
aggname, typeTypeName(tp1), typeTypeName(tp2));
}
}
/*
* We assume caller has already checked that given args are compatible
* with the agg's basetype.
*/
aggref = makeNode(Aggref);
aggref->aggname = pstrdup(aggname);
aggref->basetype = aggform->aggbasetype;
aggref->aggtype = fintype;
aggref->aggtype = aggform->aggfinaltype;
aggref->target = lfirst(args);
aggref->usenulls = usenulls;
aggref->aggstar = agg_star;
aggref->aggdistinct = agg_distinct;
@ -268,10 +241,9 @@ agg_error(char *caller, char *aggname, Oid basetypeID)
*/
if (basetypeID == InvalidOid)
elog(ERROR, "%s: aggregate '%s' for all types does not exist", caller, aggname);
elog(ERROR, "%s: aggregate '%s' for all types does not exist",
caller, aggname);
else
{
elog(ERROR, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
typeidTypeName(basetypeID));
}
elog(ERROR, "%s: aggregate '%s' for '%s' does not exist",
caller, aggname, typeidTypeName(basetypeID));
}