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:
@@ -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;
|
||||
|
||||
@@ -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'
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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'
|
||||
);
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
--
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ****************
|
||||
|
||||
|
||||
Reference in New Issue
Block a user