summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAshutosh Bapat2012-04-02 10:09:32 +0000
committerAshutosh Bapat2012-04-02 10:09:32 +0000
commita40e4ef8d222bf9cdc3952e7af668864949b0d00 (patch)
treeeca0d806a9d9b7b452f855b03f78cb40419066d7 /src
parentd7134501525dd2a3d7c8fc30a8f29fdaab110d98 (diff)
Any data exchange between coordinator and datanode happens in the form of text,
obtained by calling I/O functions for datatypes. For float4 and float8 we used float*out function which limit the number of digits in the string to DBL_DIG/FLT_DIG (both 16) + extra_float_digits (GUC). By default the later value is 0. Rest of the digits are truncated. Thus we see a difference at the 16th digit when we add up truncated floating point transition results from datanodes. The fix here is really to move from text based data exchange to binary data exchange between coordinator and datanode, which will preserve the precision of floating point. This is basic change and might be risky to apply just before the release. Hence adding alternate output file. The test aggregates has EXPLAIN outputs specific to PostgreSQL. Those outputs are not valid in Postgres-XC. Hence updating the expected output with EXPLAIN outputs obtained in Postgres-XC.
Diffstat (limited to 'src')
-rw-r--r--src/test/regress/expected/aggregates.out255
-rw-r--r--src/test/regress/expected/aggregates_1.out1018
-rw-r--r--src/test/regress/sql/aggregates.sql30
3 files changed, 1138 insertions, 165 deletions
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index e2d3bc9c8a..dd20688519 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -445,19 +445,19 @@ FROM bool_test;
--
-- Test cases that should be optimized into indexscans instead of
-- the generic aggregate implementation.
+-- In Postgres-XC, plans printed by explain are the ones created on the
+-- coordinator. Coordinator does not generate index scan plans.
--
analyze tenk1; -- ensure we get consistent plans here
-- Basic cases
-explain (costs off)
+explain (costs off, nodes off)
select min(unique1) from tenk1;
- QUERY PLAN
--------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan using tenk1_unique1 on tenk1
- Index Cond: (unique1 IS NOT NULL)
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select min(unique1) from tenk1;
min
@@ -465,16 +465,14 @@ select min(unique1) from tenk1;
0
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1;
- QUERY PLAN
-----------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique1 on tenk1
- Index Cond: (unique1 IS NOT NULL)
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select max(unique1) from tenk1;
max
@@ -482,16 +480,14 @@ select max(unique1) from tenk1;
9999
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1 where unique1 < 42;
- QUERY PLAN
-------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 < 42))
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select max(unique1) from tenk1 where unique1 < 42;
max
@@ -499,16 +495,14 @@ select max(unique1) from tenk1 where unique1 < 42;
41
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1 where unique1 > 42;
- QUERY PLAN
-------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42))
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select max(unique1) from tenk1 where unique1 > 42;
max
@@ -516,16 +510,14 @@ select max(unique1) from tenk1 where unique1 > 42;
9999
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1 where unique1 > 42000;
- QUERY PLAN
----------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000))
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select max(unique1) from tenk1 where unique1 > 42000;
max
@@ -534,16 +526,14 @@ select max(unique1) from tenk1 where unique1 > 42000;
(1 row)
-- multi-column index (uses tenk1_thous_tenthous)
-explain (costs off)
+explain (costs off, nodes off)
select max(tenthous) from tenk1 where thousand = 33;
- QUERY PLAN
---------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_thous_tenthous on tenk1
- Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select max(tenthous) from tenk1 where thousand = 33;
max
@@ -551,16 +541,14 @@ select max(tenthous) from tenk1 where thousand = 33;
9033
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select min(tenthous) from tenk1 where thousand = 33;
- QUERY PLAN
---------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan using tenk1_thous_tenthous on tenk1
- Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
-(5 rows)
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
select min(tenthous) from tenk1 where thousand = 33;
min
@@ -569,19 +557,18 @@ select min(tenthous) from tenk1 where thousand = 33;
(1 row)
-- check parameter propagation into an indexscan subquery
-explain (costs off)
+explain (costs off, nodes off)
select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
from int4_tbl;
- QUERY PLAN
------------------------------------------------------------------------------------------
- Seq Scan on int4_tbl
- SubPlan 2
- -> Result
- InitPlan 1 (returns $1)
- -> Limit
- -> Index Scan using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1))
-(7 rows)
+ QUERY PLAN
+------------------------------------------------------------
+ Result
+ -> Data Node Scan on int4_tbl
+ SubPlan 1
+ -> Aggregate
+ -> Data Node Scan on tenk1
+ Coordinator quals: (unique1 > int4_tbl.f1)
+(6 rows)
select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
from int4_tbl
@@ -596,17 +583,14 @@ order by f1;
(5 rows)
-- check some cases that were handled incorrectly in 8.3.0
-explain (costs off)
+explain (costs off, nodes off)
select distinct max(unique2) from tenk1;
- QUERY PLAN
-----------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------
HashAggregate
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
-(6 rows)
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(3 rows)
select distinct max(unique2) from tenk1;
max
@@ -614,18 +598,15 @@ select distinct max(unique2) from tenk1;
9999
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2) from tenk1 order by 1;
- QUERY PLAN
-----------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------
Sort
- Sort Key: ($0)
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
-(7 rows)
+ Sort Key: (max(unique2))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
select max(unique2) from tenk1 order by 1;
max
@@ -633,18 +614,15 @@ select max(unique2) from tenk1 order by 1;
9999
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2) from tenk1 order by max(unique2);
- QUERY PLAN
-----------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------
Sort
- Sort Key: ($0)
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
-(7 rows)
+ Sort Key: (max(unique2))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
select max(unique2) from tenk1 order by max(unique2);
max
@@ -652,18 +630,15 @@ select max(unique2) from tenk1 order by max(unique2);
9999
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2) from tenk1 order by max(unique2)+1;
- QUERY PLAN
-----------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------
Sort
- Sort Key: (($0 + 1))
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
-(7 rows)
+ Sort Key: ((max(unique2) + 1))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
select max(unique2) from tenk1 order by max(unique2)+1;
max
@@ -671,18 +646,15 @@ select max(unique2) from tenk1 order by max(unique2)+1;
9999
(1 row)
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
- QUERY PLAN
-----------------------------------------------------------------
+ QUERY PLAN
+-------------------------------------
Sort
Sort Key: (generate_series(1, 3))
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
-(7 rows)
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
max | g
@@ -705,36 +677,17 @@ insert into minmaxtest values(11), (12);
insert into minmaxtest1 values(13), (14);
insert into minmaxtest2 values(15), (16);
insert into minmaxtest3 values(17), (18);
-explain (costs off)
+explain (costs off, nodes off)
select min(f1), max(f1) from minmaxtest;
- QUERY PLAN
---------------------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Merge Append
- Sort Key: public.minmaxtest.f1
- -> Index Scan using minmaxtesti on minmaxtest
- Index Cond: (f1 IS NOT NULL)
- -> Index Scan using minmaxtest1i on minmaxtest1 minmaxtest
- Index Cond: (f1 IS NOT NULL)
- -> Index Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest
- Index Cond: (f1 IS NOT NULL)
- -> Index Scan using minmaxtest3i on minmaxtest3 minmaxtest
- Index Cond: (f1 IS NOT NULL)
- InitPlan 2 (returns $1)
- -> Limit
- -> Merge Append
- Sort Key: public.minmaxtest.f1
- -> Index Scan Backward using minmaxtesti on minmaxtest
- Index Cond: (f1 IS NOT NULL)
- -> Index Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest
- Index Cond: (f1 IS NOT NULL)
- -> Index Scan using minmaxtest2i on minmaxtest2 minmaxtest
- Index Cond: (f1 IS NOT NULL)
- -> Index Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest
- Index Cond: (f1 IS NOT NULL)
-(25 rows)
+ QUERY PLAN
+------------------------------------------
+ Aggregate
+ -> Append
+ -> Data Node Scan on minmaxtest
+ -> Data Node Scan on minmaxtest
+ -> Data Node Scan on minmaxtest
+ -> Data Node Scan on minmaxtest
+(6 rows)
select min(f1), max(f1) from minmaxtest;
min | max
diff --git a/src/test/regress/expected/aggregates_1.out b/src/test/regress/expected/aggregates_1.out
new file mode 100644
index 0000000000..12be7c64c2
--- /dev/null
+++ b/src/test/regress/expected/aggregates_1.out
@@ -0,0 +1,1018 @@
+--
+-- AGGREGATES
+--
+SELECT avg(four) AS avg_1 FROM onek;
+ avg_1
+--------------------
+ 1.5000000000000000
+(1 row)
+
+SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100;
+ avg_32
+---------------------
+ 32.6666666666666667
+(1 row)
+
+-- 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
+(1 row)
+
+SELECT avg(gpa) AS avg_3_4 FROM ONLY student;
+ avg_3_4
+---------
+ 3.4
+(1 row)
+
+SELECT sum(four) AS sum_1500 FROM onek;
+ sum_1500
+----------
+ 1500
+(1 row)
+
+SELECT sum(a) AS sum_198 FROM aggtest;
+ sum_198
+---------
+ 198
+(1 row)
+
+SELECT sum(b) AS avg_431_773 FROM aggtest;
+ avg_431_773
+-------------
+ 431.773
+(1 row)
+
+SELECT sum(gpa) AS avg_6_8 FROM ONLY student;
+ avg_6_8
+---------
+ 6.8
+(1 row)
+
+SELECT max(four) AS max_3 FROM onek;
+ max_3
+-------
+ 3
+(1 row)
+
+SELECT max(a) AS max_100 FROM aggtest;
+ max_100
+---------
+ 100
+(1 row)
+
+SELECT max(aggtest.b) AS max_324_78 FROM aggtest;
+ max_324_78
+------------
+ 324.78
+(1 row)
+
+SELECT max(student.gpa) AS max_3_7 FROM student;
+ max_3_7
+---------
+ 3.7
+(1 row)
+
+SELECT stddev_pop(b) FROM aggtest;
+ stddev_pop
+------------------
+ 131.107032318951
+(1 row)
+
+SELECT stddev_samp(b) FROM aggtest;
+ stddev_samp
+------------------
+ 151.389360803998
+(1 row)
+
+SELECT var_pop(b) FROM aggtest;
+ var_pop
+------------------
+ 17189.0539234824
+(1 row)
+
+SELECT var_samp(b) FROM aggtest;
+ var_samp
+------------------
+ 22918.7385646432
+(1 row)
+
+SELECT stddev_pop(b::numeric) FROM aggtest;
+ stddev_pop
+------------------
+ 131.107032862199
+(1 row)
+
+SELECT stddev_samp(b::numeric) FROM aggtest;
+ stddev_samp
+------------------
+ 151.389361431288
+(1 row)
+
+SELECT var_pop(b::numeric) FROM aggtest;
+ var_pop
+--------------------
+ 17189.054065929769
+(1 row)
+
+SELECT var_samp(b::numeric) FROM aggtest;
+ var_samp
+--------------------
+ 22918.738754573025
+(1 row)
+
+-- population variance is defined for a single tuple, sample variance
+-- is not
+SELECT var_pop(1.0), var_samp(2.0);
+ var_pop | var_samp
+---------+----------
+ 0 |
+(1 row)
+
+SELECT stddev_pop(3.0::numeric), stddev_samp(4.0::numeric);
+ stddev_pop | stddev_samp
+------------+-------------
+ 0 |
+(1 row)
+
+-- SQL2003 binary aggregates
+SELECT regr_count(b, a) FROM aggtest;
+ regr_count
+------------
+ 4
+(1 row)
+
+SELECT regr_sxx(b, a) FROM aggtest;
+ regr_sxx
+----------
+ 5099
+(1 row)
+
+SELECT regr_syy(b, a) FROM aggtest;
+ regr_syy
+------------------
+ 68756.2156939297
+(1 row)
+
+SELECT regr_sxy(b, a) FROM aggtest;
+ regr_sxy
+------------------
+ 2614.51582155001
+(1 row)
+
+SELECT regr_avgx(b, a), regr_avgy(b, a) FROM aggtest;
+ regr_avgx | regr_avgy
+-----------+------------------
+ 49.5 | 107.943152273074
+(1 row)
+
+SELECT regr_r2(b, a) FROM aggtest;
+ regr_r2
+--------------------
+ 0.0194977982031797
+(1 row)
+
+SELECT regr_slope(b, a), regr_intercept(b, a) FROM aggtest;
+ regr_slope | regr_intercept
+-------------------+------------------
+ 0.512750700441265 | 82.5619926012313
+(1 row)
+
+SELECT covar_pop(b, a), covar_samp(b, a) FROM aggtest;
+ covar_pop | covar_samp
+------------------+------------------
+ 653.628955387502 | 871.505273850003
+(1 row)
+
+SELECT corr(b, a) FROM aggtest;
+ corr
+-------------------
+ 0.139634516517871
+(1 row)
+
+SELECT count(four) AS cnt_1000 FROM onek;
+ cnt_1000
+----------
+ 1000
+(1 row)
+
+SELECT count(DISTINCT four) AS cnt_4 FROM onek;
+ cnt_4
+-------
+ 4
+(1 row)
+
+select ten, count(*), sum(four) from onek
+group by ten order by ten;
+ ten | count | sum
+-----+-------+-----
+ 0 | 100 | 100
+ 1 | 100 | 200
+ 2 | 100 | 100
+ 3 | 100 | 200
+ 4 | 100 | 100
+ 5 | 100 | 200
+ 6 | 100 | 100
+ 7 | 100 | 200
+ 8 | 100 | 100
+ 9 | 100 | 200
+(10 rows)
+
+select ten, count(four), sum(DISTINCT four) from onek
+group by ten order by ten;
+ ten | count | sum
+-----+-------+-----
+ 0 | 100 | 2
+ 1 | 100 | 4
+ 2 | 100 | 2
+ 3 | 100 | 4
+ 4 | 100 | 2
+ 5 | 100 | 4
+ 6 | 100 | 2
+ 7 | 100 | 4
+ 8 | 100 | 2
+ 9 | 100 | 4
+(10 rows)
+
+-- user-defined aggregates
+SELECT newavg(four) AS avg_1 FROM onek;
+ avg_1
+--------------------
+ 1.5000000000000000
+(1 row)
+
+SELECT newsum(four) AS sum_1500 FROM onek;
+ sum_1500
+----------
+ 1500
+(1 row)
+
+SELECT newcnt(four) AS cnt_1000 FROM onek;
+ cnt_1000
+----------
+ 1000
+(1 row)
+
+SELECT newcnt(*) AS cnt_1000 FROM onek;
+ cnt_1000
+----------
+ 1000
+(1 row)
+
+SELECT oldcnt(*) AS cnt_1000 FROM onek;
+ cnt_1000
+----------
+ 1000
+(1 row)
+
+SELECT sum2(q1,q2) FROM int8_tbl;
+ sum2
+-------------------
+ 18271560493827981
+(1 row)
+
+-- test for outer-level aggregates
+-- this should work
+select ten, sum(distinct four) from onek a
+group by ten
+having exists (select 1 from onek b where sum(distinct a.four) = b.four)
+order by ten;
+ ten | sum
+-----+-----
+ 0 | 2
+ 2 | 2
+ 4 | 2
+ 6 | 2
+ 8 | 2
+(5 rows)
+
+-- this should fail because subquery has an agg of its own in WHERE
+select ten, sum(distinct four) from onek a
+group by ten
+having exists (select 1 from onek b
+ where sum(distinct a.four + b.four) = b.four);
+ERROR: aggregates not allowed in WHERE clause
+LINE 4: where sum(distinct a.four + b.four) = b.four)...
+ ^
+-- Test handling of sublinks within outer-level aggregates.
+-- Per bug report from Daniel Grace.
+select
+ (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)))
+from tenk1 o;
+ ?column?
+----------
+ 9999
+(1 row)
+
+--
+-- test for bitwise integer aggregates
+--
+CREATE TEMPORARY TABLE bitwise_test(
+ i2 INT2,
+ i4 INT4,
+ i8 INT8,
+ i INTEGER,
+ x INT2,
+ y BIT(4)
+);
+-- empty case
+SELECT
+ BIT_AND(i2) AS "?",
+ BIT_OR(i4) AS "?"
+FROM bitwise_test;
+ ? | ?
+---+---
+ |
+(1 row)
+
+COPY bitwise_test FROM STDIN NULL 'null';
+SELECT
+ BIT_AND(i2) AS "1",
+ BIT_AND(i4) AS "1",
+ BIT_AND(i8) AS "1",
+ BIT_AND(i) AS "?",
+ BIT_AND(x) AS "0",
+ BIT_AND(y) AS "0100",
+ BIT_OR(i2) AS "7",
+ BIT_OR(i4) AS "7",
+ BIT_OR(i8) AS "7",
+ BIT_OR(i) AS "?",
+ BIT_OR(x) AS "7",
+ BIT_OR(y) AS "1101"
+FROM bitwise_test;
+ 1 | 1 | 1 | ? | 0 | 0100 | 7 | 7 | 7 | ? | 7 | 1101
+---+---+---+---+---+------+---+---+---+---+---+------
+ 1 | 1 | 1 | 1 | 0 | 0100 | 7 | 7 | 7 | 3 | 7 | 1101
+(1 row)
+
+--
+-- test boolean aggregates
+--
+-- first test all possible transition and final states
+SELECT
+ -- boolean and transitions
+ -- null because strict
+ booland_statefunc(NULL, NULL) IS NULL AS "t",
+ booland_statefunc(TRUE, NULL) IS NULL AS "t",
+ booland_statefunc(FALSE, NULL) IS NULL AS "t",
+ booland_statefunc(NULL, TRUE) IS NULL AS "t",
+ booland_statefunc(NULL, FALSE) IS NULL AS "t",
+ -- and actual computations
+ booland_statefunc(TRUE, TRUE) AS "t",
+ NOT booland_statefunc(TRUE, FALSE) AS "t",
+ NOT booland_statefunc(FALSE, TRUE) AS "t",
+ NOT booland_statefunc(FALSE, FALSE) AS "t";
+ t | t | t | t | t | t | t | t | t
+---+---+---+---+---+---+---+---+---
+ t | t | t | t | t | t | t | t | t
+(1 row)
+
+SELECT
+ -- boolean or transitions
+ -- null because strict
+ boolor_statefunc(NULL, NULL) IS NULL AS "t",
+ boolor_statefunc(TRUE, NULL) IS NULL AS "t",
+ boolor_statefunc(FALSE, NULL) IS NULL AS "t",
+ boolor_statefunc(NULL, TRUE) IS NULL AS "t",
+ boolor_statefunc(NULL, FALSE) IS NULL AS "t",
+ -- actual computations
+ boolor_statefunc(TRUE, TRUE) AS "t",
+ boolor_statefunc(TRUE, FALSE) AS "t",
+ boolor_statefunc(FALSE, TRUE) AS "t",
+ NOT boolor_statefunc(FALSE, FALSE) AS "t";
+ t | t | t | t | t | t | t | t | t
+---+---+---+---+---+---+---+---+---
+ t | t | t | t | t | t | t | t | t
+(1 row)
+
+CREATE TEMPORARY TABLE bool_test(
+ b1 BOOL,
+ b2 BOOL,
+ b3 BOOL,
+ b4 BOOL);
+-- empty case
+SELECT
+ BOOL_AND(b1) AS "n",
+ BOOL_OR(b3) AS "n"
+FROM bool_test;
+ n | n
+---+---
+ |
+(1 row)
+
+COPY bool_test FROM STDIN NULL 'null';
+SELECT
+ BOOL_AND(b1) AS "f",
+ BOOL_AND(b2) AS "t",
+ BOOL_AND(b3) AS "f",
+ BOOL_AND(b4) AS "n",
+ BOOL_AND(NOT b2) AS "f",
+ BOOL_AND(NOT b3) AS "t"
+FROM bool_test;
+ f | t | f | n | f | t
+---+---+---+---+---+---
+ f | t | f | | f | t
+(1 row)
+
+SELECT
+ EVERY(b1) AS "f",
+ EVERY(b2) AS "t",
+ EVERY(b3) AS "f",
+ EVERY(b4) AS "n",
+ EVERY(NOT b2) AS "f",
+ EVERY(NOT b3) AS "t"
+FROM bool_test;
+ f | t | f | n | f | t
+---+---+---+---+---+---
+ f | t | f | | f | t
+(1 row)
+
+SELECT
+ BOOL_OR(b1) AS "t",
+ BOOL_OR(b2) AS "t",
+ BOOL_OR(b3) AS "f",
+ BOOL_OR(b4) AS "n",
+ BOOL_OR(NOT b2) AS "f",
+ BOOL_OR(NOT b3) AS "t"
+FROM bool_test;
+ t | t | f | n | f | t
+---+---+---+---+---+---
+ t | t | f | | f | t
+(1 row)
+
+--
+-- Test cases that should be optimized into indexscans instead of
+-- the generic aggregate implementation.
+-- In Postgres-XC, plans printed by explain are the ones created on the
+-- coordinator. Coordinator does not generate index scan plans.
+--
+analyze tenk1; -- ensure we get consistent plans here
+-- Basic cases
+explain (costs off, nodes off)
+ select min(unique1) from tenk1;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select min(unique1) from tenk1;
+ min
+-----
+ 0
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique1) from tenk1;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select max(unique1) from tenk1;
+ max
+------
+ 9999
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique1) from tenk1 where unique1 < 42;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select max(unique1) from tenk1 where unique1 < 42;
+ max
+-----
+ 41
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique1) from tenk1 where unique1 > 42;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select max(unique1) from tenk1 where unique1 > 42;
+ max
+------
+ 9999
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique1) from tenk1 where unique1 > 42000;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select max(unique1) from tenk1 where unique1 > 42000;
+ max
+-----
+
+(1 row)
+
+-- multi-column index (uses tenk1_thous_tenthous)
+explain (costs off, nodes off)
+ select max(tenthous) from tenk1 where thousand = 33;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select max(tenthous) from tenk1 where thousand = 33;
+ max
+------
+ 9033
+(1 row)
+
+explain (costs off, nodes off)
+ select min(tenthous) from tenk1 where thousand = 33;
+ QUERY PLAN
+--------------------------------------------------------
+ Aggregate
+ -> Materialize
+ -> Data Node Scan on "__REMOTE_GROUP_QUERY__"
+(3 rows)
+
+select min(tenthous) from tenk1 where thousand = 33;
+ min
+-----
+ 33
+(1 row)
+
+-- check parameter propagation into an indexscan subquery
+explain (costs off, nodes off)
+ select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
+ from int4_tbl;
+ QUERY PLAN
+------------------------------------------------------------
+ Result
+ -> Data Node Scan on int4_tbl
+ SubPlan 1
+ -> Aggregate
+ -> Data Node Scan on tenk1
+ Coordinator quals: (unique1 > int4_tbl.f1)
+(6 rows)
+
+select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
+from int4_tbl
+order by f1;
+ f1 | gt
+-------------+----
+ -2147483647 | 0
+ -123456 | 0
+ 0 | 1
+ 123456 |
+ 2147483647 |
+(5 rows)
+
+-- check some cases that were handled incorrectly in 8.3.0
+explain (costs off, nodes off)
+ select distinct max(unique2) from tenk1;
+ QUERY PLAN
+-------------------------------------
+ HashAggregate
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(3 rows)
+
+select distinct max(unique2) from tenk1;
+ max
+------
+ 9999
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique2) from tenk1 order by 1;
+ QUERY PLAN
+-------------------------------------
+ Sort
+ Sort Key: (max(unique2))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
+
+select max(unique2) from tenk1 order by 1;
+ max
+------
+ 9999
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique2) from tenk1 order by max(unique2);
+ QUERY PLAN
+-------------------------------------
+ Sort
+ Sort Key: (max(unique2))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
+
+select max(unique2) from tenk1 order by max(unique2);
+ max
+------
+ 9999
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique2) from tenk1 order by max(unique2)+1;
+ QUERY PLAN
+-------------------------------------
+ Sort
+ Sort Key: ((max(unique2) + 1))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
+
+select max(unique2) from tenk1 order by max(unique2)+1;
+ max
+------
+ 9999
+(1 row)
+
+explain (costs off, nodes off)
+ select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
+ QUERY PLAN
+-------------------------------------
+ Sort
+ Sort Key: (generate_series(1, 3))
+ -> Aggregate
+ -> Data Node Scan on tenk1
+(4 rows)
+
+select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
+ max | g
+------+---
+ 9999 | 3
+ 9999 | 2
+ 9999 | 1
+(3 rows)
+
+-- try it on an inheritance tree
+create table minmaxtest(f1 int);
+create table minmaxtest1() inherits (minmaxtest);
+create table minmaxtest2() inherits (minmaxtest);
+create table minmaxtest3() inherits (minmaxtest);
+create index minmaxtesti on minmaxtest(f1);
+create index minmaxtest1i on minmaxtest1(f1);
+create index minmaxtest2i on minmaxtest2(f1 desc);
+create index minmaxtest3i on minmaxtest3(f1) where f1 is not null;
+insert into minmaxtest values(11), (12);
+insert into minmaxtest1 values(13), (14);
+insert into minmaxtest2 values(15), (16);
+insert into minmaxtest3 values(17), (18);
+explain (costs off, nodes off)
+ select min(f1), max(f1) from minmaxtest;
+ QUERY PLAN
+------------------------------------------
+ Aggregate
+ -> Append
+ -> Data Node Scan on minmaxtest
+ -> Data Node Scan on minmaxtest
+ -> Data Node Scan on minmaxtest
+ -> Data Node Scan on minmaxtest
+(6 rows)
+
+select min(f1), max(f1) from minmaxtest;
+ min | max
+-----+-----
+ 11 | 18
+(1 row)
+
+drop table minmaxtest cascade;
+NOTICE: drop cascades to 3 other objects
+DETAIL: drop cascades to table minmaxtest1
+drop cascades to table minmaxtest2
+drop cascades to table minmaxtest3
+--
+-- Test combinations of DISTINCT and/or ORDER BY
+--
+select array_agg(a order by b)
+ from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
+ array_agg
+-----------
+ {3,4,2,1}
+(1 row)
+
+select array_agg(a order by a)
+ from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
+ array_agg
+-----------
+ {1,2,3,4}
+(1 row)
+
+select array_agg(a order by a desc)
+ from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
+ array_agg
+-----------
+ {4,3,2,1}
+(1 row)
+
+select array_agg(b order by a desc)
+ from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
+ array_agg
+-----------
+ {2,1,3,4}
+(1 row)
+
+select array_agg(distinct a)
+ from (values (1),(2),(1),(3),(null),(2)) v(a);
+ array_agg
+--------------
+ {1,2,3,NULL}
+(1 row)
+
+select array_agg(distinct a order by a)
+ from (values (1),(2),(1),(3),(null),(2)) v(a);
+ array_agg
+--------------
+ {1,2,3,NULL}
+(1 row)
+
+select array_agg(distinct a order by a desc)
+ from (values (1),(2),(1),(3),(null),(2)) v(a);
+ array_agg
+--------------
+ {NULL,3,2,1}
+(1 row)
+
+select array_agg(distinct a order by a desc nulls last)
+ from (values (1),(2),(1),(3),(null),(2)) v(a);
+ array_agg
+--------------
+ {3,2,1,NULL}
+(1 row)
+
+-- multi-arg aggs, strict/nonstrict, distinct/order by
+select aggfstr(a,b,c)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
+ aggfstr
+---------------------------------------
+ {"(1,3,foo)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select aggfns(a,b,c)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
+ aggfns
+-----------------------------------------------
+ {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select aggfstr(distinct a,b,c)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,3) i;
+ aggfstr
+---------------------------------------
+ {"(1,3,foo)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select aggfns(distinct a,b,c)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,3) i;
+ aggfns
+-----------------------------------------------
+ {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select aggfstr(distinct a,b,c order by b)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,3) i;
+ aggfstr
+---------------------------------------
+ {"(3,1,baz)","(2,2,bar)","(1,3,foo)"}
+(1 row)
+
+select aggfns(distinct a,b,c order by b)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,3) i;
+ aggfns
+-----------------------------------------------
+ {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"}
+(1 row)
+
+-- test specific code paths
+select aggfns(distinct a,a,c order by c using ~<~,a)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,2) i;
+ aggfns
+------------------------------------------------
+ {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"}
+(1 row)
+
+select aggfns(distinct a,a,c order by c using ~<~)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,2) i;
+ aggfns
+------------------------------------------------
+ {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"}
+(1 row)
+
+select aggfns(distinct a,a,c order by a)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,2) i;
+ aggfns
+------------------------------------------------
+ {"(0,0,)","(1,1,foo)","(2,2,bar)","(3,3,baz)"}
+(1 row)
+
+select aggfns(distinct a,b,c order by a,c using ~<~,b)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,2) i;
+ aggfns
+-----------------------------------------------
+ {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+-- check node I/O via view creation and usage, also deparsing logic
+create view agg_view1 as
+ select aggfns(a,b,c)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
+select * from agg_view1;
+ aggfns
+-----------------------------------------------
+ {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+--------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(v.a, v.b, v.c) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
+(1 row)
+
+create or replace view agg_view1 as
+ select aggfns(distinct a,b,c)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,3) i;
+select * from agg_view1;
+ aggfns
+-----------------------------------------------
+ {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(DISTINCT v.a, v.b, v.c) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c), generate_series(1, 3) i(i);
+(1 row)
+
+create or replace view agg_view1 as
+ select aggfns(distinct a,b,c order by b)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,3) i;
+select * from agg_view1;
+ aggfns
+-----------------------------------------------
+ {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.b) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c), generate_series(1, 3) i(i);
+(1 row)
+
+create or replace view agg_view1 as
+ select aggfns(a,b,c order by b+1)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
+select * from agg_view1;
+ aggfns
+-----------------------------------------------
+ {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(v.a, v.b, v.c ORDER BY (v.b + 1)) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
+(1 row)
+
+create or replace view agg_view1 as
+ select aggfns(a,a,c order by b)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
+select * from agg_view1;
+ aggfns
+------------------------------------------------
+ {"(3,3,baz)","(2,2,bar)","(1,1,foo)","(0,0,)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(v.a, v.a, v.c ORDER BY v.b) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
+(1 row)
+
+create or replace view agg_view1 as
+ select aggfns(a,b,c order by c using ~<~)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
+select * from agg_view1;
+ aggfns
+-----------------------------------------------
+ {"(2,2,bar)","(3,1,baz)","(1,3,foo)","(0,,)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(v.a, v.b, v.c ORDER BY v.c USING ~<~ NULLS LAST) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
+(1 row)
+
+create or replace view agg_view1 as
+ select aggfns(distinct a,b,c order by a,c using ~<~,b)
+ from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
+ generate_series(1,2) i;
+select * from agg_view1;
+ aggfns
+-----------------------------------------------
+ {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
+(1 row)
+
+select pg_get_viewdef('agg_view1'::regclass);
+ pg_get_viewdef
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.a, v.c USING ~<~ NULLS LAST, v.b) AS aggfns FROM (VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c), generate_series(1, 2) i(i);
+(1 row)
+
+drop view agg_view1;
+-- incorrect DISTINCT usage errors
+select aggfns(distinct a,b,c order by i)
+ from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
+ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select aggfns(distinct a,b,c order by i)
+ ^
+select aggfns(distinct a,b,c order by a,b+1)
+ from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
+ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select aggfns(distinct a,b,c order by a,b+1)
+ ^
+select aggfns(distinct a,b,c order by a,b,i,c)
+ from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
+ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select aggfns(distinct a,b,c order by a,b,i,c)
+ ^
+select aggfns(distinct a,a,c order by a,b)
+ from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
+ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select aggfns(distinct a,a,c order by a,b)
+ ^
+-- string_agg tests
+select string_agg(a,',') from (values('aaaa'),('bbbb'),('cccc')) g(a);
+ string_agg
+----------------
+ aaaa,bbbb,cccc
+(1 row)
+
+select string_agg(a,',') from (values('aaaa'),(null),('bbbb'),('cccc')) g(a);
+ string_agg
+----------------
+ aaaa,bbbb,cccc
+(1 row)
+
+select string_agg(a,'AB') from (values(null),(null),('bbbb'),('cccc')) g(a);
+ string_agg
+------------
+ bbbbABcccc
+(1 row)
+
+select string_agg(a,',') from (values(null),(null)) g(a);
+ string_agg
+------------
+
+(1 row)
+
+-- check some implicit casting cases, as per bug #5564
+select string_agg(distinct f1, ',' order by f1) from varchar_tbl; -- ok
+ string_agg
+------------
+ a,ab,abcd
+(1 row)
+
+select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not ok
+ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select string_agg(distinct f1::text, ',' order by f1) from v...
+ ^
+select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok
+ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select string_agg(distinct f1, ',' order by f1::text) from v...
+ ^
+select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok
+ string_agg
+------------
+ a,ab,abcd
+(1 row)
+
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index 7e148f5471..bd8df68d0e 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -208,36 +208,38 @@ FROM bool_test;
--
-- Test cases that should be optimized into indexscans instead of
-- the generic aggregate implementation.
+-- In Postgres-XC, plans printed by explain are the ones created on the
+-- coordinator. Coordinator does not generate index scan plans.
--
analyze tenk1; -- ensure we get consistent plans here
-- Basic cases
-explain (costs off)
+explain (costs off, nodes off)
select min(unique1) from tenk1;
select min(unique1) from tenk1;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1;
select max(unique1) from tenk1;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1 where unique1 < 42;
select max(unique1) from tenk1 where unique1 < 42;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1 where unique1 > 42;
select max(unique1) from tenk1 where unique1 > 42;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique1) from tenk1 where unique1 > 42000;
select max(unique1) from tenk1 where unique1 > 42000;
-- multi-column index (uses tenk1_thous_tenthous)
-explain (costs off)
+explain (costs off, nodes off)
select max(tenthous) from tenk1 where thousand = 33;
select max(tenthous) from tenk1 where thousand = 33;
-explain (costs off)
+explain (costs off, nodes off)
select min(tenthous) from tenk1 where thousand = 33;
select min(tenthous) from tenk1 where thousand = 33;
-- check parameter propagation into an indexscan subquery
-explain (costs off)
+explain (costs off, nodes off)
select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
from int4_tbl;
select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
@@ -245,19 +247,19 @@ from int4_tbl
order by f1;
-- check some cases that were handled incorrectly in 8.3.0
-explain (costs off)
+explain (costs off, nodes off)
select distinct max(unique2) from tenk1;
select distinct max(unique2) from tenk1;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2) from tenk1 order by 1;
select max(unique2) from tenk1 order by 1;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2) from tenk1 order by max(unique2);
select max(unique2) from tenk1 order by max(unique2);
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2) from tenk1 order by max(unique2)+1;
select max(unique2) from tenk1 order by max(unique2)+1;
-explain (costs off)
+explain (costs off, nodes off)
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
@@ -276,7 +278,7 @@ insert into minmaxtest1 values(13), (14);
insert into minmaxtest2 values(15), (16);
insert into minmaxtest3 values(17), (18);
-explain (costs off)
+explain (costs off, nodes off)
select min(f1), max(f1) from minmaxtest;
select min(f1), max(f1) from minmaxtest;