1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-10 14:22:35 +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

@@ -2,18 +2,20 @@
-- AGGREGATES
--
SELECT avg(four) AS avg_1 FROM onek;
avg_1
-------
1
avg_1
--------------
1.5000000000
(1 row)
SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100;
avg_32
--------
32
avg_32
---------------
32.6666666667
(1 row)
SELECT avg(b) AS avg_107_943 FROM aggtest;
-- In 7.1, avg(float4) is computed using float8 arithmetic.
-- Round the result to 3 digits to avoid platform-specific results.
SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest;
avg_107_943
-------------
107.943
@@ -116,9 +118,9 @@ select ten, count(four), sum(DISTINCT four) from onek group by ten;
(10 rows)
SELECT newavg(four) AS avg_1 FROM onek;
avg_1
-------
1
avg_1
--------------
1.5000000000
(1 row)
SELECT newsum(four) AS sum_1500 FROM onek;

View File

@@ -3,18 +3,17 @@
--
-- all functions CREATEd
CREATE AGGREGATE newavg (
sfunc1 = int4pl, basetype = int4, stype1 = int4,
sfunc2 = int4inc, stype2 = int4,
finalfunc = int4div,
initcond1 = '0', initcond2 = '0'
sfunc = int4_accum, basetype = int4, stype = _numeric,
finalfunc = numeric_avg,
initcond1 = '{0,0,0}'
);
-- sfunc1 (value-dependent) only
-- without finalfunc; test obsolete spellings 'sfunc1' etc
CREATE AGGREGATE newsum (
sfunc1 = int4pl, basetype = int4, stype1 = int4,
initcond1 = '0'
);
-- sfunc2 (value-independent) only
-- value-independent transition function
CREATE AGGREGATE newcnt (
sfunc2 = int4inc, basetype = int4, stype2 = int4,
initcond2 = '0'
sfunc = int4inc, basetype = 'any', stype = int4,
initcond = '0'
);

View File

@@ -99,46 +99,18 @@ end;
NOTICE: COMMIT: no transaction in progress
--
-- DEFINE AGGREGATE
-- left out finalfunc
create aggregate newavg1 (sfunc1 = int4pl,
basetype = int4,
stype1 = int4,
sfunc2 = int4inc,
stype2 = int4,
initcond1 = '0',
initcond2 = '0');
ERROR: AggregateCreate: Aggregate must have final function with both transition functions
-- sfunc return type disagreement
create aggregate newavg2 (sfunc1 = int4pl,
basetype = int4,
stype1 = int4,
sfunc2 = int2inc,
stype2 = int2,
finalfunc = int4div,
initcond1 = '0',
initcond2 = '0');
ERROR: AggregateCreate: 'int4div'('int4','int2') does not exist
-- sfunc/finalfunc type disagreement
create aggregate newavg3 (sfunc1 = int4pl,
create aggregate newavg2 (sfunc = int4pl,
basetype = int4,
stype1 = int4,
sfunc2 = int4inc,
stype2 = int4,
finalfunc = int2div,
initcond1 = '0',
initcond2 = '0');
ERROR: AggregateCreate: 'int2div'('int4','int4') does not exist
stype = int4,
finalfunc = int2um,
initcond = '0');
ERROR: AggregateCreate: function 'int2um(int4)' does not exist
-- left out basetype
create aggregate newcnt1 (sfunc2 = int4inc,
stype2 = int4,
initcond2 = '0');
create aggregate newcnt1 (sfunc = int4inc,
stype = int4,
initcond = '0');
ERROR: Define: "basetype" unspecified
-- left out initcond2 (for sfunc2)
create aggregate newcnt1 (sfunc2 = int4inc,
basetype = int4,
stype2 = int4);
ERROR: AggregateCreate: transition function 2 MUST have an initial value
--
-- REMOVE INDEX

View File

@@ -1,20 +1,12 @@
--
-- This is created by pgsql/contrib/findoidjoins/make_oidjoin_check
--
SELECT oid, pg_aggregate.aggtransfn1
SELECT oid, pg_aggregate.aggtransfn
FROM pg_aggregate
WHERE pg_aggregate.aggtransfn1 != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn1);
oid | aggtransfn1
-----+-------------
(0 rows)
SELECT oid, pg_aggregate.aggtransfn2
FROM pg_aggregate
WHERE pg_aggregate.aggtransfn2 != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn2);
oid | aggtransfn2
-----+-------------
WHERE pg_aggregate.aggtransfn != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn);
oid | aggtransfn
-----+------------
(0 rows)
SELECT oid, pg_aggregate.aggfinalfn
@@ -33,20 +25,12 @@ WHERE pg_aggregate.aggbasetype != 0 AND
-----+-------------
(0 rows)
SELECT oid, pg_aggregate.aggtranstype1
SELECT oid, pg_aggregate.aggtranstype
FROM pg_aggregate
WHERE pg_aggregate.aggtranstype1 != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype1);
oid | aggtranstype1
-----+---------------
(0 rows)
SELECT oid, pg_aggregate.aggtranstype2
FROM pg_aggregate
WHERE pg_aggregate.aggtranstype2 != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype2);
oid | aggtranstype2
-----+---------------
WHERE pg_aggregate.aggtranstype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype);
oid | aggtranstype
-----+--------------
(0 rows)
SELECT oid, pg_aggregate.aggfinaltype
@@ -217,6 +201,22 @@ WHERE pg_class.relam != 0 AND
-----+-------
(0 rows)
SELECT oid, pg_class.reltoastrelid
FROM pg_class
WHERE pg_class.reltoastrelid != 0 AND
NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastrelid);
oid | reltoastrelid
-----+---------------
(0 rows)
SELECT oid, pg_class.reltoastidxid
FROM pg_class
WHERE pg_class.reltoastidxid != 0 AND
NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastidxid);
oid | reltoastidxid
-----+---------------
(0 rows)
SELECT oid, pg_index.indexrelid
FROM pg_index
WHERE pg_index.indexrelid != 0 AND

View File

@@ -84,9 +84,8 @@ WHERE p1.oid != p2.oid AND
(p1.prorettype < p2.prorettype);
prorettype | prorettype
------------+------------
18 | 25
25 | 1043
(2 rows)
(1 row)
SELECT DISTINCT p1.proargtypes[0], p2.proargtypes[0]
FROM pg_proc AS p1, pg_proc AS p2
@@ -98,8 +97,7 @@ WHERE p1.oid != p2.oid AND
proargtypes | proargtypes
-------------+-------------
25 | 1043
1042 | 1043
(2 rows)
(1 row)
SELECT DISTINCT p1.proargtypes[1], p2.proargtypes[1]
FROM pg_proc AS p1, pg_proc AS p2
@@ -434,83 +432,40 @@ WHERE p1.oprjoin = p2.oid AND
-- **************** pg_aggregate ****************
-- Look for illegal values in pg_aggregate fields.
-- aggbasetype can only be 0 if transfn1 is not present (eg, count(*))
-- or itself takes a wild-card input; we check the latter case below.
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE (p1.aggbasetype = 0 AND p1.aggtransfn1 != 0) OR aggfinaltype = 0;
WHERE aggtransfn = 0 OR aggtranstype = 0 OR aggfinaltype = 0;
oid | aggname
-----+---------
(0 rows)
-- Check combinations of transfer functions.
-- Although either transfn1 or transfn2 can be null,
-- it makes no sense for both to be. And if both are defined,
-- presumably there should be a finalfn to combine their results.
-- We also check that transtypes are null just when corresponding
-- transfns are. Also, if there is no finalfn then the output type
-- must be the transtype the result will be taken from.
-- If there is no finalfn then the output type must be the transtype.
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 = 0 AND p1.aggtransfn2 = 0;
WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
oid | aggname
-----+---------
(0 rows)
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 != 0 AND p1.aggtransfn2 = 0 AND
(p1.aggtranstype1 = 0 OR p1.aggtranstype2 != 0 OR
(p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype1));
oid | aggname
-----+---------
(0 rows)
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 = 0 AND p1.aggtransfn2 != 0 AND
(p1.aggtranstype1 != 0 OR p1.aggtranstype2 = 0 OR
(p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype2));
oid | aggname
-----+---------
(0 rows)
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 != 0 AND p1.aggtransfn2 != 0 AND
(p1.aggtranstype1 = 0 OR p1.aggtranstype2 = 0 OR
p1.aggfinalfn = 0);
oid | aggname
-----+---------
(0 rows)
-- Cross-check transfn1 (if present) against its entry in pg_proc.
-- Cross-check transfn against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
-- NOTE: in 7.1, this search finds max and min on abstime, which are
-- implemented using int4larger/int4smaller. Until we have
-- some cleaner way of dealing with binary-equivalent types, just leave
-- those two tuples in the expected output.
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn1 = p2.oid AND
(p2.proretset OR p2.pronargs != 2
-- diked out until we find a way of marking binary-compatible types
-- OR
-- p1.aggtranstype1 != p2.prorettype OR
-- p1.aggtranstype1 != p2.proargtypes[0] OR
-- p1.aggbasetype != p2.proargtypes[1]
);
oid | aggname | oid | proname
-----+---------+-----+---------
(0 rows)
-- Cross-check transfn2 (if present) against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn2 = p2.oid AND
(p2.proretset OR p1.aggtranstype2 != p2.prorettype OR
p2.pronargs != 1 OR
p1.aggtranstype2 != p2.proargtypes[0]);
oid | aggname | oid | proname
-----+---------+-----+---------
(0 rows)
WHERE p1.aggtransfn = p2.oid AND
(p2.proretset OR
p1.aggtranstype != p2.prorettype OR
p1.aggtranstype != p2.proargtypes[0] OR
NOT ((p2.pronargs = 2 AND p1.aggbasetype = p2.proargtypes[1]) OR
(p2.pronargs = 1 AND p1.aggbasetype = 0)));
oid | aggname | oid | proname
-------+---------+-----+-------------
16978 | max | 768 | int4larger
16992 | min | 769 | int4smaller
(2 rows)
-- Cross-check finalfn (if present) against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
@@ -518,9 +473,8 @@ SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggfinalfn = p2.oid AND
(p2.proretset OR p1.aggfinaltype != p2.prorettype OR
p2.pronargs != 2 OR
p1.aggtranstype1 != p2.proargtypes[0] OR
p1.aggtranstype2 != p2.proargtypes[1]);
p2.pronargs != 1 OR
p1.aggtranstype != p2.proargtypes[0]);
oid | aggname | oid | proname
-----+---------+-----+---------
(0 rows)

View File

@@ -6,7 +6,10 @@ SELECT avg(four) AS avg_1 FROM onek;
SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100;
SELECT avg(b) AS avg_107_943 FROM aggtest;
-- In 7.1, avg(float4) is computed using float8 arithmetic.
-- Round the result to 3 digits to avoid platform-specific results.
SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest;
SELECT avg(gpa) AS avg_3_4 FROM ONLY student;

View File

@@ -4,21 +4,20 @@
-- all functions CREATEd
CREATE AGGREGATE newavg (
sfunc1 = int4pl, basetype = int4, stype1 = int4,
sfunc2 = int4inc, stype2 = int4,
finalfunc = int4div,
initcond1 = '0', initcond2 = '0'
sfunc = int4_accum, basetype = int4, stype = _numeric,
finalfunc = numeric_avg,
initcond1 = '{0,0,0}'
);
-- sfunc1 (value-dependent) only
-- without finalfunc; test obsolete spellings 'sfunc1' etc
CREATE AGGREGATE newsum (
sfunc1 = int4pl, basetype = int4, stype1 = int4,
initcond1 = '0'
);
-- sfunc2 (value-independent) only
-- value-independent transition function
CREATE AGGREGATE newcnt (
sfunc2 = int4inc, basetype = int4, stype2 = int4,
initcond2 = '0'
sfunc = int4inc, basetype = 'any', stype = int4,
initcond = '0'
);

View File

@@ -114,45 +114,18 @@ end;
--
-- DEFINE AGGREGATE
-- left out finalfunc
create aggregate newavg1 (sfunc1 = int4pl,
basetype = int4,
stype1 = int4,
sfunc2 = int4inc,
stype2 = int4,
initcond1 = '0',
initcond2 = '0');
-- sfunc return type disagreement
create aggregate newavg2 (sfunc1 = int4pl,
basetype = int4,
stype1 = int4,
sfunc2 = int2inc,
stype2 = int2,
finalfunc = int4div,
initcond1 = '0',
initcond2 = '0');
-- sfunc/finalfunc type disagreement
create aggregate newavg3 (sfunc1 = int4pl,
create aggregate newavg2 (sfunc = int4pl,
basetype = int4,
stype1 = int4,
sfunc2 = int4inc,
stype2 = int4,
finalfunc = int2div,
initcond1 = '0',
initcond2 = '0');
stype = int4,
finalfunc = int2um,
initcond = '0');
-- left out basetype
create aggregate newcnt1 (sfunc2 = int4inc,
stype2 = int4,
initcond2 = '0');
-- left out initcond2 (for sfunc2)
create aggregate newcnt1 (sfunc2 = int4inc,
basetype = int4,
stype2 = int4);
create aggregate newcnt1 (sfunc = int4inc,
stype = int4,
initcond = '0');
--

View File

@@ -1,14 +1,10 @@
--
-- This is created by pgsql/contrib/findoidjoins/make_oidjoin_check
--
SELECT oid, pg_aggregate.aggtransfn1
SELECT oid, pg_aggregate.aggtransfn
FROM pg_aggregate
WHERE pg_aggregate.aggtransfn1 != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn1);
SELECT oid, pg_aggregate.aggtransfn2
FROM pg_aggregate
WHERE pg_aggregate.aggtransfn2 != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn2);
WHERE pg_aggregate.aggtransfn != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn);
SELECT oid, pg_aggregate.aggfinalfn
FROM pg_aggregate
WHERE pg_aggregate.aggfinalfn != 0 AND
@@ -17,14 +13,10 @@ SELECT oid, pg_aggregate.aggbasetype
FROM pg_aggregate
WHERE pg_aggregate.aggbasetype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggbasetype);
SELECT oid, pg_aggregate.aggtranstype1
SELECT oid, pg_aggregate.aggtranstype
FROM pg_aggregate
WHERE pg_aggregate.aggtranstype1 != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype1);
SELECT oid, pg_aggregate.aggtranstype2
FROM pg_aggregate
WHERE pg_aggregate.aggtranstype2 != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype2);
WHERE pg_aggregate.aggtranstype != 0 AND
NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype);
SELECT oid, pg_aggregate.aggfinaltype
FROM pg_aggregate
WHERE pg_aggregate.aggfinaltype != 0 AND
@@ -109,6 +101,14 @@ SELECT oid, pg_class.relam
FROM pg_class
WHERE pg_class.relam != 0 AND
NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_class.relam);
SELECT oid, pg_class.reltoastrelid
FROM pg_class
WHERE pg_class.reltoastrelid != 0 AND
NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastrelid);
SELECT oid, pg_class.reltoastidxid
FROM pg_class
WHERE pg_class.reltoastidxid != 0 AND
NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastidxid);
SELECT oid, pg_index.indexrelid
FROM pg_index
WHERE pg_index.indexrelid != 0 AND

View File

@@ -363,66 +363,32 @@ WHERE p1.oprjoin = p2.oid AND
-- **************** pg_aggregate ****************
-- Look for illegal values in pg_aggregate fields.
-- aggbasetype can only be 0 if transfn1 is not present (eg, count(*))
-- or itself takes a wild-card input; we check the latter case below.
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE (p1.aggbasetype = 0 AND p1.aggtransfn1 != 0) OR aggfinaltype = 0;
WHERE aggtransfn = 0 OR aggtranstype = 0 OR aggfinaltype = 0;
-- Check combinations of transfer functions.
-- Although either transfn1 or transfn2 can be null,
-- it makes no sense for both to be. And if both are defined,
-- presumably there should be a finalfn to combine their results.
-- We also check that transtypes are null just when corresponding
-- transfns are. Also, if there is no finalfn then the output type
-- must be the transtype the result will be taken from.
-- If there is no finalfn then the output type must be the transtype.
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 = 0 AND p1.aggtransfn2 = 0;
WHERE p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype;
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 != 0 AND p1.aggtransfn2 = 0 AND
(p1.aggtranstype1 = 0 OR p1.aggtranstype2 != 0 OR
(p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype1));
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 = 0 AND p1.aggtransfn2 != 0 AND
(p1.aggtranstype1 != 0 OR p1.aggtranstype2 = 0 OR
(p1.aggfinalfn = 0 AND p1.aggfinaltype != p1.aggtranstype2));
SELECT p1.oid, p1.aggname
FROM pg_aggregate as p1
WHERE p1.aggtransfn1 != 0 AND p1.aggtransfn2 != 0 AND
(p1.aggtranstype1 = 0 OR p1.aggtranstype2 = 0 OR
p1.aggfinalfn = 0);
-- Cross-check transfn1 (if present) against its entry in pg_proc.
-- Cross-check transfn against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
-- NOTE: in 7.1, this search finds max and min on abstime, which are
-- implemented using int4larger/int4smaller. Until we have
-- some cleaner way of dealing with binary-equivalent types, just leave
-- those two tuples in the expected output.
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn1 = p2.oid AND
(p2.proretset OR p2.pronargs != 2
-- diked out until we find a way of marking binary-compatible types
-- OR
-- p1.aggtranstype1 != p2.prorettype OR
-- p1.aggtranstype1 != p2.proargtypes[0] OR
-- p1.aggbasetype != p2.proargtypes[1]
);
-- Cross-check transfn2 (if present) against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggtransfn2 = p2.oid AND
(p2.proretset OR p1.aggtranstype2 != p2.prorettype OR
p2.pronargs != 1 OR
p1.aggtranstype2 != p2.proargtypes[0]);
WHERE p1.aggtransfn = p2.oid AND
(p2.proretset OR
p1.aggtranstype != p2.prorettype OR
p1.aggtranstype != p2.proargtypes[0] OR
NOT ((p2.pronargs = 2 AND p1.aggbasetype = p2.proargtypes[1]) OR
(p2.pronargs = 1 AND p1.aggbasetype = 0)));
-- Cross-check finalfn (if present) against its entry in pg_proc.
-- FIXME: what about binary-compatible types?
@@ -431,9 +397,8 @@ SELECT p1.oid, p1.aggname, p2.oid, p2.proname
FROM pg_aggregate AS p1, pg_proc AS p2
WHERE p1.aggfinalfn = p2.oid AND
(p2.proretset OR p1.aggfinaltype != p2.prorettype OR
p2.pronargs != 2 OR
p1.aggtranstype1 != p2.proargtypes[0] OR
p1.aggtranstype2 != p2.proargtypes[1]);
p2.pronargs != 1 OR
p1.aggtranstype != p2.proargtypes[0]);
-- **************** pg_opclass ****************