summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;