diff --git a/src/test/regress/expected/alter_table_set_access_method.out b/src/test/regress/expected/alter_table_set_access_method.out index fe8b8622a..26047c897 100644 --- a/src/test/regress/expected/alter_table_set_access_method.out +++ b/src/test/regress/expected/alter_table_set_access_method.out @@ -776,15 +776,8 @@ RESET client_min_messages; create table events (event_id bigserial, event_time timestamptz default now(), payload text); create index on events (event_id); insert into events (payload) select 'hello-'||s from generate_series(1,10) s; -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset BEGIN; - \if :server_version_ge_16 SET LOCAL debug_parallel_query = regress; - \else - SET LOCAL force_parallel_mode = regress; - \endif SET LOCAL min_parallel_table_scan_size = 1; SET LOCAL parallel_tuple_cost = 0; SET LOCAL max_parallel_workers = 4; diff --git a/src/test/regress/expected/columnar_fallback_scan.out b/src/test/regress/expected/columnar_fallback_scan.out index b65e4118c..d4f3ee504 100644 --- a/src/test/regress/expected/columnar_fallback_scan.out +++ b/src/test/regress/expected/columnar_fallback_scan.out @@ -21,14 +21,7 @@ select count(*), min(i), max(i), avg(i) from fallback_scan; -- Negative test: try to force a parallel plan with at least two -- workers, but columnar should reject it and use a non-parallel scan. -- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset -\if :server_version_ge_16 set debug_parallel_query = regress; -\else -set force_parallel_mode = regress; -\endif set min_parallel_table_scan_size = 1; set parallel_tuple_cost = 0; set max_parallel_workers = 4; @@ -46,11 +39,7 @@ select count(*), min(i), max(i), avg(i) from fallback_scan; 150000 | 1 | 150000 | 75000.500000000000 (1 row) -\if :server_version_ge_16 set debug_parallel_query = default; -\else -set force_parallel_mode = default; -\endif set min_parallel_table_scan_size to default; set parallel_tuple_cost to default; set max_parallel_workers to default; diff --git a/src/test/regress/expected/columnar_indexes.out b/src/test/regress/expected/columnar_indexes.out index 341dc6b63..7d292dbca 100644 --- a/src/test/regress/expected/columnar_indexes.out +++ b/src/test/regress/expected/columnar_indexes.out @@ -556,9 +556,6 @@ create table events (event_id bigserial, event_time timestamptz default now(), p BEGIN; -- this wouldn't flush any data insert into events (payload) select 'hello-'||s from generate_series(1, 10) s; - SHOW server_version \gset - SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 - \gset -- Since table is large enough, normally postgres would prefer using -- parallel workers when building the index. -- @@ -570,11 +567,7 @@ BEGIN; -- by postgres and throws an error. For this reason, here we don't expect -- following commnad to fail since we prevent using parallel workers for -- columnar tables. - \if :server_version_ge_16 SET LOCAL debug_parallel_query = regress; - \else - SET LOCAL force_parallel_mode = regress; - \endif SET LOCAL min_parallel_table_scan_size = 1; SET LOCAL parallel_tuple_cost = 0; SET LOCAL max_parallel_workers = 4; diff --git a/src/test/regress/expected/columnar_partitioning.out b/src/test/regress/expected/columnar_partitioning.out index bd7bbdc25..ca2b35dd8 100644 --- a/src/test/regress/expected/columnar_partitioning.out +++ b/src/test/regress/expected/columnar_partitioning.out @@ -20,15 +20,8 @@ INSERT INTO parent SELECT '2020-03-15', 30, 300, 'three thousand' FROM generate_series(1,100000); INSERT INTO parent SELECT '2020-04-15', 30, 300, 'three thousand' FROM generate_series(1,100000); -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset -- run parallel plans -\if :server_version_ge_16 SET debug_parallel_query = regress; -\else -SET force_parallel_mode = regress; -\endif SET min_parallel_table_scan_size = 1; SET parallel_tuple_cost = 0; SET max_parallel_workers = 4; @@ -104,11 +97,7 @@ SELECT count(*), sum(i), min(i), max(i) FROM parent; (1 row) SET columnar.enable_custom_scan TO DEFAULT; -\if :server_version_ge_16 SET debug_parallel_query TO DEFAULT; -\else -SET force_parallel_mode TO DEFAULT; -\endif SET min_parallel_table_scan_size TO DEFAULT; SET parallel_tuple_cost TO DEFAULT; SET max_parallel_workers TO DEFAULT; diff --git a/src/test/regress/expected/create_drop_database_propagation_pg16.out b/src/test/regress/expected/create_drop_database_propagation_pg16.out index 75cd99e61..0245ac9e6 100644 --- a/src/test/regress/expected/create_drop_database_propagation_pg16.out +++ b/src/test/regress/expected/create_drop_database_propagation_pg16.out @@ -1,13 +1,3 @@ --- --- PG16 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset -\if :server_version_ge_16 -\else -\q -\endif -- create/drop database for pg >= 16 set citus.enable_create_database_propagation=on; -- test icu_rules diff --git a/src/test/regress/expected/create_drop_database_propagation_pg16_0.out b/src/test/regress/expected/create_drop_database_propagation_pg16_0.out deleted file mode 100644 index 730c916ca..000000000 --- a/src/test/regress/expected/create_drop_database_propagation_pg16_0.out +++ /dev/null @@ -1,9 +0,0 @@ --- --- PG16 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset -\if :server_version_ge_16 -\else -\q diff --git a/src/test/regress/expected/metadata_sync_helpers.out b/src/test/regress/expected/metadata_sync_helpers.out index 6345e15ac..1e2ab9601 100644 --- a/src/test/regress/expected/metadata_sync_helpers.out +++ b/src/test/regress/expected/metadata_sync_helpers.out @@ -1287,21 +1287,14 @@ BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; SET application_name to 'citus_internal gpid=10000000001'; -- with an ugly trick, update the vartype of table from int to bigint -- so that making two tables colocated fails - -- include varnullingrels for PG16+ - SHOW server_version \gset - SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 - \gset -- include varreturningtype for PG18+ SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18 \gset \if :server_version_ge_18 UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 1 :varreturningtype 0 :varnoold 1 :varoattno 1 :location -1}' WHERE logicalrelid = 'test_2'::regclass; - \elif :server_version_ge_16 - UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 1 :varnoold 1 :varoattno 1 :location -1}' - WHERE logicalrelid = 'test_2'::regclass; \else - UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varlevelsup 1 :varnoold 1 :varoattno 1 :location -1}' + UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 1 :varnoold 1 :varoattno 1 :location -1}' WHERE logicalrelid = 'test_2'::regclass; \endif SELECT citus_internal.update_relation_colocation('test_2'::regclass, 251); diff --git a/src/test/regress/expected/multi_complex_count_distinct.out b/src/test/regress/expected/multi_complex_count_distinct.out index baa9c829a..85be7fde8 100644 --- a/src/test/regress/expected/multi_complex_count_distinct.out +++ b/src/test/regress/expected/multi_complex_count_distinct.out @@ -1,18 +1,6 @@ -- -- COMPLEX_COUNT_DISTINCT -- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; - server_version_ge_16 ---------------------------------------------------------------------- - t -(1 row) - SET citus.next_shard_id TO 240000; SET citus.shard_count TO 8; SET citus.shard_replication_factor TO 1; diff --git a/src/test/regress/expected/multi_complex_count_distinct_0.out b/src/test/regress/expected/multi_complex_count_distinct_0.out deleted file mode 100644 index 36af62e96..000000000 --- a/src/test/regress/expected/multi_complex_count_distinct_0.out +++ /dev/null @@ -1,1139 +0,0 @@ --- --- COMPLEX_COUNT_DISTINCT --- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; - server_version_ge_16 ---------------------------------------------------------------------- - f -(1 row) - -SET citus.next_shard_id TO 240000; -SET citus.shard_count TO 8; -SET citus.shard_replication_factor TO 1; -SET citus.coordinator_aggregation_strategy TO 'disabled'; -CREATE TABLE lineitem_hash ( - l_orderkey bigint not null, - l_partkey integer not null, - l_suppkey integer not null, - l_linenumber integer not null, - l_quantity decimal(15, 2) not null, - l_extendedprice decimal(15, 2) not null, - l_discount decimal(15, 2) not null, - l_tax decimal(15, 2) not null, - l_returnflag char(1) not null, - l_linestatus char(1) not null, - l_shipdate date not null, - l_commitdate date not null, - l_receiptdate date not null, - l_shipinstruct char(25) not null, - l_shipmode char(10) not null, - l_comment varchar(44) not null, - PRIMARY KEY(l_orderkey, l_linenumber) ); -SELECT create_distributed_table('lineitem_hash', 'l_orderkey', 'hash'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - -\set lineitem_1_data_file :abs_srcdir '/data/lineitem.1.data' -\set lineitem_2_data_file :abs_srcdir '/data/lineitem.2.data' -\set client_side_copy_command '\\copy lineitem_hash FROM ' :'lineitem_1_data_file' ' with delimiter '''|''';' -:client_side_copy_command -\set client_side_copy_command '\\copy lineitem_hash FROM ' :'lineitem_2_data_file' ' with delimiter '''|''';' -:client_side_copy_command -ANALYZE lineitem_hash; --- count(distinct) is supported on top level query if there --- is a grouping on the partition key -SELECT - l_orderkey, count(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_orderkey - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_orderkey | count ---------------------------------------------------------------------- - 14885 | 7 - 14884 | 7 - 14821 | 7 - 14790 | 7 - 14785 | 7 - 14755 | 7 - 14725 | 7 - 14694 | 7 - 14627 | 7 - 14624 | 7 -(10 rows) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT - l_orderkey, count(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_orderkey - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: remote_scan.l_orderkey, remote_scan.count - -> Sort - Output: remote_scan.l_orderkey, remote_scan.count - Sort Key: remote_scan.count DESC, remote_scan.l_orderkey DESC - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_orderkey, remote_scan.count - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_orderkey, count(DISTINCT l_partkey) AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_orderkey ORDER BY (count(DISTINCT l_partkey)) DESC, l_orderkey DESC LIMIT '10'::bigint - Node: host=localhost port=xxxxx dbname=regression - -> Limit - Output: l_orderkey, (count(DISTINCT l_partkey)) - -> Sort - Output: l_orderkey, (count(DISTINCT l_partkey)) - Sort Key: (count(DISTINCT lineitem_hash.l_partkey)) DESC, lineitem_hash.l_orderkey DESC - -> GroupAggregate - Output: l_orderkey, count(DISTINCT l_partkey) - Group Key: lineitem_hash.l_orderkey - -> Index Scan Backward using lineitem_hash_pkey_240000 on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(22 rows) - --- it is also supported if there is no grouping or grouping is on non-partition field -SELECT - count(DISTINCT l_partkey) - FROM lineitem_hash - ORDER BY 1 DESC - LIMIT 10; - count ---------------------------------------------------------------------- - 11661 -(1 row) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT - count(DISTINCT l_partkey) - FROM lineitem_hash - ORDER BY 1 DESC - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: (count(DISTINCT remote_scan.count)) - -> Sort - Output: (count(DISTINCT remote_scan.count)) - Sort Key: (count(DISTINCT remote_scan.count)) DESC - -> Aggregate - Output: count(DISTINCT remote_scan.count) - -> Custom Scan (Citus Adaptive) - Output: remote_scan.count - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_partkey AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_partkey - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_partkey - Group Key: lineitem_hash.l_partkey - -> Seq Scan on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(19 rows) - -SELECT - l_shipmode, count(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_shipmode - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_shipmode | count ---------------------------------------------------------------------- - TRUCK | 1757 - MAIL | 1730 - AIR | 1702 - FOB | 1700 - RAIL | 1696 - SHIP | 1684 - REG AIR | 1676 -(7 rows) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT - l_shipmode, count(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_shipmode - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: remote_scan.l_shipmode, (count(DISTINCT remote_scan.count)) - -> Sort - Output: remote_scan.l_shipmode, (count(DISTINCT remote_scan.count)) - Sort Key: (count(DISTINCT remote_scan.count)) DESC, remote_scan.l_shipmode DESC - -> GroupAggregate - Output: remote_scan.l_shipmode, count(DISTINCT remote_scan.count) - Group Key: remote_scan.l_shipmode - -> Sort - Output: remote_scan.l_shipmode, remote_scan.count - Sort Key: remote_scan.l_shipmode DESC - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_shipmode, remote_scan.count - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_shipmode, l_partkey AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_shipmode, l_partkey - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_shipmode, l_partkey - Group Key: lineitem_hash.l_shipmode, lineitem_hash.l_partkey - -> Seq Scan on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(23 rows) - --- mixed mode count distinct, grouped by partition column -SELECT - l_orderkey, count(distinct l_partkey), count(distinct l_shipmode) - FROM lineitem_hash - GROUP BY l_orderkey - ORDER BY 3 DESC, 2 DESC, 1 - LIMIT 10; - l_orderkey | count | count ---------------------------------------------------------------------- - 226 | 7 | 7 - 1316 | 7 | 7 - 1477 | 7 | 7 - 3555 | 7 | 7 - 12258 | 7 | 7 - 12835 | 7 | 7 - 768 | 7 | 6 - 1121 | 7 | 6 - 1153 | 7 | 6 - 1281 | 7 | 6 -(10 rows) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT - l_orderkey, count(distinct l_partkey), count(distinct l_shipmode) - FROM lineitem_hash - GROUP BY l_orderkey - ORDER BY 3 DESC, 2 DESC, 1 - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: remote_scan.l_orderkey, remote_scan.count, remote_scan.count_1 - -> Sort - Output: remote_scan.l_orderkey, remote_scan.count, remote_scan.count_1 - Sort Key: remote_scan.count_1 DESC, remote_scan.count DESC, remote_scan.l_orderkey - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_orderkey, remote_scan.count, remote_scan.count_1 - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_orderkey, count(DISTINCT l_partkey) AS count, count(DISTINCT l_shipmode) AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_orderkey ORDER BY (count(DISTINCT l_shipmode)) DESC, (count(DISTINCT l_partkey)) DESC, l_orderkey LIMIT '10'::bigint - Node: host=localhost port=xxxxx dbname=regression - -> Limit - Output: l_orderkey, (count(DISTINCT l_partkey)), (count(DISTINCT l_shipmode)) - -> Sort - Output: l_orderkey, (count(DISTINCT l_partkey)), (count(DISTINCT l_shipmode)) - Sort Key: (count(DISTINCT lineitem_hash.l_shipmode)) DESC, (count(DISTINCT lineitem_hash.l_partkey)) DESC, lineitem_hash.l_orderkey - -> GroupAggregate - Output: l_orderkey, count(DISTINCT l_partkey), count(DISTINCT l_shipmode) - Group Key: lineitem_hash.l_orderkey - -> Index Scan using lineitem_hash_pkey_240000 on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(22 rows) - --- partition/non-partition column count distinct no grouping -SELECT - count(distinct l_orderkey), count(distinct l_partkey), count(distinct l_shipmode) - FROM lineitem_hash; - count | count | count ---------------------------------------------------------------------- - 2985 | 11661 | 7 -(1 row) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT - count(distinct l_orderkey), count(distinct l_partkey), count(distinct l_shipmode) - FROM lineitem_hash; - QUERY PLAN ---------------------------------------------------------------------- - Aggregate - Output: count(DISTINCT remote_scan.count), count(DISTINCT remote_scan.count_1), count(DISTINCT remote_scan.count_2) - -> Custom Scan (Citus Adaptive) - Output: remote_scan.count, remote_scan.count_1, remote_scan.count_2 - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_orderkey AS count, l_partkey AS count, l_shipmode AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_orderkey, l_partkey, l_shipmode - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_orderkey, l_partkey, l_shipmode - Group Key: lineitem_hash.l_orderkey, lineitem_hash.l_partkey, lineitem_hash.l_shipmode - -> Seq Scan on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(14 rows) - --- distinct/non-distinct on partition and non-partition columns -SELECT - count(distinct l_orderkey), count(l_orderkey), - count(distinct l_partkey), count(l_partkey), - count(distinct l_shipmode), count(l_shipmode) - FROM lineitem_hash; - count | count | count | count | count | count ---------------------------------------------------------------------- - 2985 | 12000 | 11661 | 12000 | 7 | 12000 -(1 row) - --- mixed mode count distinct, grouped by non-partition column -SELECT - l_shipmode, count(distinct l_partkey), count(distinct l_orderkey) - FROM lineitem_hash - GROUP BY l_shipmode - ORDER BY 1, 2 DESC, 3 DESC; - l_shipmode | count | count ---------------------------------------------------------------------- - AIR | 1702 | 1327 - FOB | 1700 | 1276 - MAIL | 1730 | 1299 - RAIL | 1696 | 1265 - REG AIR | 1676 | 1275 - SHIP | 1684 | 1289 - TRUCK | 1757 | 1333 -(7 rows) - --- mixed mode count distinct, grouped by non-partition column --- having on partition column -SELECT - l_shipmode, count(distinct l_partkey), count(distinct l_orderkey) - FROM lineitem_hash - GROUP BY l_shipmode - HAVING count(distinct l_orderkey) > 1300 - ORDER BY 1, 2 DESC; - l_shipmode | count | count ---------------------------------------------------------------------- - AIR | 1702 | 1327 - TRUCK | 1757 | 1333 -(2 rows) - --- same but having clause is not on target list -SELECT - l_shipmode, count(distinct l_partkey) - FROM lineitem_hash - GROUP BY l_shipmode - HAVING count(distinct l_orderkey) > 1300 - ORDER BY 1, 2 DESC; - l_shipmode | count ---------------------------------------------------------------------- - AIR | 1702 - TRUCK | 1757 -(2 rows) - --- mixed mode count distinct, grouped by non-partition column --- having on non-partition column -SELECT - l_shipmode, count(distinct l_partkey), count(distinct l_suppkey) - FROM lineitem_hash - GROUP BY l_shipmode - HAVING count(distinct l_suppkey) > 1550 - ORDER BY 1, 2 DESC; - l_shipmode | count | count ---------------------------------------------------------------------- - AIR | 1702 | 1564 - FOB | 1700 | 1571 - MAIL | 1730 | 1573 - RAIL | 1696 | 1581 - REG AIR | 1676 | 1557 - SHIP | 1684 | 1554 - TRUCK | 1757 | 1602 -(7 rows) - --- same but having clause is not on target list -SELECT - l_shipmode, count(distinct l_partkey) - FROM lineitem_hash - GROUP BY l_shipmode - HAVING count(distinct l_suppkey) > 1550 - ORDER BY 1, 2 DESC; - l_shipmode | count ---------------------------------------------------------------------- - AIR | 1702 - FOB | 1700 - MAIL | 1730 - RAIL | 1696 - REG AIR | 1676 - SHIP | 1684 - TRUCK | 1757 -(7 rows) - --- count distinct is supported on single table subqueries -SELECT * - FROM ( - SELECT - l_orderkey, count(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_orderkey) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_orderkey | count ---------------------------------------------------------------------- - 14885 | 7 - 14884 | 7 - 14821 | 7 - 14790 | 7 - 14785 | 7 - 14755 | 7 - 14725 | 7 - 14694 | 7 - 14627 | 7 - 14624 | 7 -(10 rows) - -SELECT * - FROM ( - SELECT - l_partkey, count(DISTINCT l_orderkey) - FROM lineitem_hash - GROUP BY l_partkey) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_partkey | count ---------------------------------------------------------------------- - 199146 | 3 - 188804 | 3 - 177771 | 3 - 160895 | 3 - 149926 | 3 - 136884 | 3 - 87761 | 3 - 15283 | 3 - 6983 | 3 - 1927 | 3 -(10 rows) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT * - FROM ( - SELECT - l_partkey, count(DISTINCT l_orderkey) - FROM lineitem_hash - GROUP BY l_partkey) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Custom Scan (Citus Adaptive) - Output: remote_scan.l_partkey, remote_scan.count - -> Distributed Subplan XXX_1 - -> HashAggregate - Output: remote_scan.l_partkey, COALESCE((pg_catalog.sum(remote_scan.count))::bigint, '0'::bigint) - Group Key: remote_scan.l_partkey - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_partkey, remote_scan.count - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_partkey, count(DISTINCT l_orderkey) AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_partkey - Node: host=localhost port=xxxxx dbname=regression - -> GroupAggregate - Output: l_partkey, count(DISTINCT l_orderkey) - Group Key: lineitem_hash.l_partkey - -> Sort - Output: l_partkey, l_orderkey - Sort Key: lineitem_hash.l_partkey - -> Seq Scan on public.lineitem_hash_240000 lineitem_hash - Output: l_partkey, l_orderkey - Task Count: 1 - Tasks Shown: All - -> Task - Query: SELECT l_partkey, count FROM (SELECT intermediate_result.l_partkey, intermediate_result.count FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(l_partkey integer, count bigint)) sub ORDER BY count DESC, l_partkey DESC LIMIT 10 - Node: host=localhost port=xxxxx dbname=regression - -> Limit - Output: intermediate_result.l_partkey, intermediate_result.count - -> Sort - Output: intermediate_result.l_partkey, intermediate_result.count - Sort Key: intermediate_result.count DESC, intermediate_result.l_partkey DESC - -> Function Scan on pg_catalog.read_intermediate_result intermediate_result - Output: intermediate_result.l_partkey, intermediate_result.count - Function Call: read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) -(34 rows) - --- count distinct with filters -SELECT - l_orderkey, - count(DISTINCT l_suppkey) FILTER (WHERE l_shipmode = 'AIR'), - count(DISTINCT l_suppkey) - FROM lineitem_hash - GROUP BY l_orderkey - ORDER BY 2 DESC, 3 DESC, 1 - LIMIT 10; - l_orderkey | count | count ---------------------------------------------------------------------- - 4964 | 4 | 7 - 12005 | 4 | 7 - 5409 | 4 | 6 - 164 | 3 | 7 - 322 | 3 | 7 - 871 | 3 | 7 - 1156 | 3 | 7 - 1574 | 3 | 7 - 2054 | 3 | 7 - 2309 | 3 | 7 -(10 rows) - -EXPLAIN (COSTS false, VERBOSE true) -SELECT - l_orderkey, - count(DISTINCT l_suppkey) FILTER (WHERE l_shipmode = 'AIR'), - count(DISTINCT l_suppkey) - FROM lineitem_hash - GROUP BY l_orderkey - ORDER BY 2 DESC, 3 DESC, 1 - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: remote_scan.l_orderkey, remote_scan.count, remote_scan.count_1 - -> Sort - Output: remote_scan.l_orderkey, remote_scan.count, remote_scan.count_1 - Sort Key: remote_scan.count DESC, remote_scan.count_1 DESC, remote_scan.l_orderkey - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_orderkey, remote_scan.count, remote_scan.count_1 - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_orderkey, count(DISTINCT l_suppkey) FILTER (WHERE (l_shipmode OPERATOR(pg_catalog.=) 'AIR'::bpchar)) AS count, count(DISTINCT l_suppkey) AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_orderkey ORDER BY (count(DISTINCT l_suppkey) FILTER (WHERE (l_shipmode OPERATOR(pg_catalog.=) 'AIR'::bpchar))) DESC, (count(DISTINCT l_suppkey)) DESC, l_orderkey LIMIT '10'::bigint - Node: host=localhost port=xxxxx dbname=regression - -> Limit - Output: l_orderkey, (count(DISTINCT l_suppkey) FILTER (WHERE (l_shipmode = 'AIR'::bpchar))), (count(DISTINCT l_suppkey)) - -> Sort - Output: l_orderkey, (count(DISTINCT l_suppkey) FILTER (WHERE (l_shipmode = 'AIR'::bpchar))), (count(DISTINCT l_suppkey)) - Sort Key: (count(DISTINCT lineitem_hash.l_suppkey) FILTER (WHERE (lineitem_hash.l_shipmode = 'AIR'::bpchar))) DESC, (count(DISTINCT lineitem_hash.l_suppkey)) DESC, lineitem_hash.l_orderkey - -> GroupAggregate - Output: l_orderkey, count(DISTINCT l_suppkey) FILTER (WHERE (l_shipmode = 'AIR'::bpchar)), count(DISTINCT l_suppkey) - Group Key: lineitem_hash.l_orderkey - -> Index Scan using lineitem_hash_pkey_240000 on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(22 rows) - --- group by on non-partition column -SELECT - l_suppkey, count(DISTINCT l_partkey) FILTER (WHERE l_shipmode = 'AIR') - FROM lineitem_hash - GROUP BY l_suppkey - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_suppkey | count ---------------------------------------------------------------------- - 7680 | 4 - 7703 | 3 - 7542 | 3 - 7072 | 3 - 6335 | 3 - 5873 | 3 - 1318 | 3 - 1042 | 3 - 160 | 3 - 9872 | 2 -(10 rows) - --- explaining the same query fails -EXPLAIN (COSTS false, VERBOSE true) -SELECT - l_suppkey, count(DISTINCT l_partkey) FILTER (WHERE l_shipmode = 'AIR') - FROM lineitem_hash - GROUP BY l_suppkey - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - QUERY PLAN ---------------------------------------------------------------------- - Limit - Output: remote_scan.l_suppkey, (count(DISTINCT remote_scan.count) FILTER (WHERE (remote_scan.count_1 = 'AIR'::bpchar))) - -> Sort - Output: remote_scan.l_suppkey, (count(DISTINCT remote_scan.count) FILTER (WHERE (remote_scan.count_1 = 'AIR'::bpchar))) - Sort Key: (count(DISTINCT remote_scan.count) FILTER (WHERE (remote_scan.count_1 = 'AIR'::bpchar))) DESC, remote_scan.l_suppkey DESC - -> GroupAggregate - Output: remote_scan.l_suppkey, count(DISTINCT remote_scan.count) FILTER (WHERE (remote_scan.count_1 = 'AIR'::bpchar)) - Group Key: remote_scan.l_suppkey - -> Sort - Output: remote_scan.l_suppkey, remote_scan.count, remote_scan.count_1 - Sort Key: remote_scan.l_suppkey DESC - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_suppkey, remote_scan.count, remote_scan.count_1 - Task Count: 8 - Tasks Shown: One of 8 - -> Task - Query: SELECT l_suppkey, l_partkey AS count, l_shipmode AS count FROM public.lineitem_hash_240000 lineitem_hash WHERE true GROUP BY l_suppkey, l_partkey, l_shipmode - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_suppkey, l_partkey, l_shipmode - Group Key: lineitem_hash.l_suppkey, lineitem_hash.l_partkey, lineitem_hash.l_shipmode - -> Seq Scan on public.lineitem_hash_240000 lineitem_hash - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment -(23 rows) - --- without group by, on partition column -SELECT - count(DISTINCT l_orderkey) FILTER (WHERE l_shipmode = 'AIR') - FROM lineitem_hash; - count ---------------------------------------------------------------------- - 1327 -(1 row) - --- without group by, on non-partition column -SELECT - count(DISTINCT l_partkey) FILTER (WHERE l_shipmode = 'AIR') - FROM lineitem_hash; - count ---------------------------------------------------------------------- - 1702 -(1 row) - -SELECT - count(DISTINCT l_partkey) FILTER (WHERE l_shipmode = 'AIR'), - count(DISTINCT l_partkey), - count(DISTINCT l_shipdate) - FROM lineitem_hash; - count | count | count ---------------------------------------------------------------------- - 1702 | 11661 | 2470 -(1 row) - --- filter column already exists in target list -SELECT * - FROM ( - SELECT - l_orderkey, count(DISTINCT l_partkey) FILTER (WHERE l_orderkey > 100) - FROM lineitem_hash - GROUP BY l_orderkey) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_orderkey | count ---------------------------------------------------------------------- - 14885 | 7 - 14884 | 7 - 14821 | 7 - 14790 | 7 - 14785 | 7 - 14755 | 7 - 14725 | 7 - 14694 | 7 - 14627 | 7 - 14624 | 7 -(10 rows) - --- filter column does not exist in target list -SELECT * - FROM ( - SELECT - l_orderkey, count(DISTINCT l_partkey) FILTER (WHERE l_shipmode = 'AIR') - FROM lineitem_hash - GROUP BY l_orderkey) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_orderkey | count ---------------------------------------------------------------------- - 12005 | 4 - 5409 | 4 - 4964 | 4 - 14848 | 3 - 14496 | 3 - 13473 | 3 - 13122 | 3 - 12929 | 3 - 12645 | 3 - 12417 | 3 -(10 rows) - --- case expr in count distinct is supported. --- count orders partkeys if l_shipmode is air -SELECT * - FROM ( - SELECT - l_orderkey, count(DISTINCT CASE WHEN l_shipmode = 'AIR' THEN l_partkey ELSE NULL END) as count - FROM lineitem_hash - GROUP BY l_orderkey) sub - WHERE count > 0 - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_orderkey | count ---------------------------------------------------------------------- - 12005 | 4 - 5409 | 4 - 4964 | 4 - 14848 | 3 - 14496 | 3 - 13473 | 3 - 13122 | 3 - 12929 | 3 - 12645 | 3 - 12417 | 3 -(10 rows) - --- text like operator is also supported -SELECT * - FROM ( - SELECT - l_orderkey, count(DISTINCT CASE WHEN l_shipmode like '%A%' THEN l_partkey ELSE NULL END) as count - FROM lineitem_hash - GROUP BY l_orderkey) sub - WHERE count > 0 - ORDER BY 2 DESC, 1 DESC - LIMIT 10; - l_orderkey | count ---------------------------------------------------------------------- - 14275 | 7 - 14181 | 7 - 13605 | 7 - 12707 | 7 - 12384 | 7 - 11746 | 7 - 10727 | 7 - 10467 | 7 - 5636 | 7 - 4614 | 7 -(10 rows) - --- count distinct is rejected if it does not reference any columns -SELECT * - FROM ( - SELECT - l_linenumber, count(DISTINCT 1) - FROM lineitem_hash - GROUP BY l_linenumber) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; -ERROR: cannot compute aggregate (distinct) -DETAIL: aggregate (distinct) with no columns is unsupported -HINT: You can load the hll extension from contrib packages and enable distinct approximations. --- count distinct is rejected if it does not reference any columns -SELECT * - FROM ( - SELECT - l_linenumber, count(DISTINCT (random() * 5)::int) - FROM lineitem_hash - GROUP BY l_linenumber) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; -ERROR: cannot compute aggregate (distinct) -DETAIL: aggregate (distinct) with no columns is unsupported -HINT: You can load the hll extension from contrib packages and enable distinct approximations. --- even non-const function calls are supported within count distinct -SELECT * - FROM ( - SELECT - l_orderkey, count(DISTINCT (random() * 5)::int = l_linenumber) - FROM lineitem_hash - GROUP BY l_orderkey) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 0; - l_orderkey | count ---------------------------------------------------------------------- -(0 rows) - --- multiple nested subquery -SELECT - total, - avg(avg_count) as total_avg_count - FROM ( - SELECT - number_sum, - count(DISTINCT l_suppkey) as total, - avg(total_count) avg_count - FROM ( - SELECT - l_suppkey, - sum(l_linenumber) as number_sum, - count(DISTINCT l_shipmode) as total_count - FROM - lineitem_hash - WHERE - l_partkey > 100 and - l_quantity > 2 and - l_orderkey < 10000 - GROUP BY - l_suppkey) as distributed_table - WHERE - number_sum >= 10 - GROUP BY - number_sum) as distributed_table_2 - GROUP BY - total - ORDER BY - total_avg_count DESC; - total | total_avg_count ---------------------------------------------------------------------- - 1 | 3.6000000000000000 - 6 | 2.8333333333333333 - 10 | 2.6000000000000000 - 27 | 2.5555555555555556 - 32 | 2.4687500000000000 - 77 | 2.1948051948051948 - 57 | 2.1754385964912281 -(7 rows) - --- multiple cases query -SELECT * - FROM ( - SELECT - count(DISTINCT - CASE - WHEN l_shipmode = 'TRUCK' THEN l_partkey - WHEN l_shipmode = 'AIR' THEN l_quantity - WHEN l_shipmode = 'SHIP' THEN l_discount - ELSE l_suppkey - END) as count, - l_shipdate - FROM - lineitem_hash - GROUP BY - l_shipdate) sub - WHERE - count > 0 - ORDER BY - 1 DESC, 2 DESC - LIMIT 10; - count | l_shipdate ---------------------------------------------------------------------- - 14 | 07-30-1997 - 13 | 05-26-1998 - 13 | 08-08-1997 - 13 | 11-17-1995 - 13 | 01-09-1993 - 12 | 01-15-1998 - 12 | 10-15-1997 - 12 | 09-07-1997 - 12 | 06-02-1997 - 12 | 03-14-1997 -(10 rows) - --- count DISTINCT expression -SELECT * - FROM ( - SELECT - l_quantity, count(DISTINCT ((l_orderkey / 1000) * 1000 )) as count - FROM - lineitem_hash - GROUP BY - l_quantity) sub - WHERE - count > 0 - ORDER BY - 2 DESC, 1 DESC - LIMIT 10; - l_quantity | count ---------------------------------------------------------------------- - 48.00 | 13 - 47.00 | 13 - 37.00 | 13 - 33.00 | 13 - 26.00 | 13 - 25.00 | 13 - 23.00 | 13 - 21.00 | 13 - 15.00 | 13 - 12.00 | 13 -(10 rows) - --- count DISTINCT is part of an expression which includes another aggregate -SELECT * - FROM ( - SELECT - sum(((l_partkey * l_tax) / 100)) / - count(DISTINCT - CASE - WHEN l_shipmode = 'TRUCK' THEN l_partkey - ELSE l_suppkey - END) as avg, - l_shipmode - FROM - lineitem_hash - GROUP BY - l_shipmode) sub - ORDER BY - 1 DESC, 2 DESC - LIMIT 10; - avg | l_shipmode ---------------------------------------------------------------------- - 44.82904609027336300064 | MAIL - 44.80704536679536679537 | SHIP - 44.68891732736572890026 | AIR - 44.34106724470134874759 | REG AIR - 43.12739987269255251432 | FOB - 43.07299253636938646426 | RAIL - 40.50298377916903813318 | TRUCK -(7 rows) - --- count DISTINCT CASE WHEN expression -SELECT * - FROM ( - SELECT - count(DISTINCT - CASE - WHEN l_shipmode = 'TRUCK' THEN l_linenumber - WHEN l_shipmode = 'AIR' THEN l_linenumber + 10 - ELSE 2 - END) as avg - FROM - lineitem_hash - GROUP BY l_shipdate) sub - ORDER BY 1 DESC - LIMIT 10; - avg ---------------------------------------------------------------------- - 7 - 6 - 6 - 6 - 6 - 6 - 6 - 6 - 5 - 5 -(10 rows) - --- COUNT DISTINCT (c1, c2) -SELECT * - FROM - (SELECT - l_shipmode, - count(DISTINCT (l_shipdate, l_tax)) - FROM - lineitem_hash - GROUP BY - l_shipmode) t - ORDER BY - 2 DESC,1 DESC - LIMIT 10; - l_shipmode | count ---------------------------------------------------------------------- - TRUCK | 1689 - MAIL | 1683 - FOB | 1655 - AIR | 1650 - SHIP | 1644 - RAIL | 1636 - REG AIR | 1607 -(7 rows) - --- distinct on non-var (type cast/field select) columns are also --- supported if grouped on distribution column --- random is added to prevent flattening by postgresql -SELECT - l_orderkey, count(a::int), count(distinct a::int) - FROM ( - SELECT l_orderkey, l_orderkey * 1.5 a, random() b - FROM lineitem_hash) sub - GROUP BY 1 - ORDER BY 1 DESC - LIMIT 5; - l_orderkey | count | count ---------------------------------------------------------------------- - 14947 | 2 | 1 - 14946 | 2 | 1 - 14945 | 6 | 1 - 14944 | 2 | 1 - 14919 | 1 | 1 -(5 rows) - -SELECT user_id, - count(sub.a::int), - count(DISTINCT sub.a::int), - count(DISTINCT (sub).a) -FROM - (SELECT user_id, - unnest(ARRAY[user_id * 1.5])a, - random() b - FROM users_table - ) sub -GROUP BY 1 -ORDER BY 1 DESC -LIMIT 5; - user_id | count | count | count ---------------------------------------------------------------------- - 6 | 11 | 1 | 1 - 5 | 27 | 1 | 1 - 4 | 24 | 1 | 1 - 3 | 18 | 1 | 1 - 2 | 19 | 1 | 1 -(5 rows) - -CREATE TYPE test_item AS -( - id INTEGER, - duration INTEGER -); -CREATE TABLE test_count_distinct_array (key int, value int , value_arr test_item[]); -SELECT create_distributed_table('test_count_distinct_array', 'key'); - create_distributed_table ---------------------------------------------------------------------- - -(1 row) - -INSERT INTO test_count_distinct_array SELECT i, i, ARRAY[(i,i)::test_item] FROM generate_Series(0, 1000) i; -SELECT - key, - count(DISTINCT value), - count(DISTINCT (item)."id"), - count(DISTINCT (item)."id" * 3) -FROM - ( - SELECT key, unnest(value_arr) as item, value FROM test_count_distinct_array - ) as sub -GROUP BY 1 -ORDER BY 1 DESC -LIMIT 5; - key | count | count | count ---------------------------------------------------------------------- - 1000 | 1 | 1 | 1 - 999 | 1 | 1 | 1 - 998 | 1 | 1 | 1 - 997 | 1 | 1 | 1 - 996 | 1 | 1 | 1 -(5 rows) - -DROP TABLE test_count_distinct_array; -DROP TYPE test_item; --- other distinct aggregate are not supported -SELECT * - FROM ( - SELECT - l_linenumber, sum(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_linenumber) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; -ERROR: cannot compute aggregate (distinct) -DETAIL: table partitioning is unsuitable for aggregate (distinct) -SELECT * - FROM ( - SELECT - l_linenumber, avg(DISTINCT l_partkey) - FROM lineitem_hash - GROUP BY l_linenumber) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; -ERROR: cannot compute aggregate (distinct) -DETAIL: table partitioning is unsuitable for aggregate (distinct) --- whole row references, oid, and ctid are not supported in count distinct --- test table does not have oid or ctid enabled, so tests for them are skipped -SELECT * - FROM ( - SELECT - l_linenumber, count(DISTINCT lineitem_hash) - FROM lineitem_hash - GROUP BY l_linenumber) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; -ERROR: cannot compute count (distinct) -DETAIL: Non-column references are not supported yet -SELECT * - FROM ( - SELECT - l_linenumber, count(DISTINCT lineitem_hash.*) - FROM lineitem_hash - GROUP BY l_linenumber) sub - ORDER BY 2 DESC, 1 DESC - LIMIT 10; -ERROR: cannot compute count (distinct) -DETAIL: Non-column references are not supported yet --- count distinct pushdown is enabled -SELECT * - FROM ( - SELECT - l_shipdate, - count(DISTINCT - CASE - WHEN l_shipmode = 'TRUCK' THEN l_partkey - ELSE NULL - END) as distinct_part, - extract(year from l_shipdate) as year - FROM - lineitem_hash - GROUP BY l_shipdate, year) sub - WHERE year = 1995 - ORDER BY 2 DESC, 1 - LIMIT 10; - l_shipdate | distinct_part | year ---------------------------------------------------------------------- - 11-29-1995 | 5 | 1995 - 03-24-1995 | 4 | 1995 - 09-18-1995 | 4 | 1995 - 01-17-1995 | 3 | 1995 - 04-02-1995 | 3 | 1995 - 05-23-1995 | 3 | 1995 - 08-11-1995 | 3 | 1995 - 09-27-1995 | 3 | 1995 - 10-27-1995 | 3 | 1995 - 10-30-1995 | 3 | 1995 -(10 rows) - --- count distinct pushdown is enabled -SELECT * - FROM ( - SELECT - l_shipdate, - count(DISTINCT - CASE - WHEN l_shipmode = 'TRUCK' THEN l_partkey - ELSE NULL - END) as distinct_part, - extract(year from l_shipdate) as year - FROM - lineitem_hash - GROUP BY l_shipdate, year) sub - WHERE year = 1995 - ORDER BY 2 DESC, 1 - LIMIT 10; - l_shipdate | distinct_part | year ---------------------------------------------------------------------- - 11-29-1995 | 5 | 1995 - 03-24-1995 | 4 | 1995 - 09-18-1995 | 4 | 1995 - 01-17-1995 | 3 | 1995 - 04-02-1995 | 3 | 1995 - 05-23-1995 | 3 | 1995 - 08-11-1995 | 3 | 1995 - 09-27-1995 | 3 | 1995 - 10-27-1995 | 3 | 1995 - 10-30-1995 | 3 | 1995 -(10 rows) - -SELECT * - FROM ( - SELECT - l_shipdate, - count(DISTINCT - CASE - WHEN l_shipmode = 'TRUCK' THEN l_partkey - ELSE NULL - END) as distinct_part, - extract(year from l_shipdate) as year - FROM - lineitem_hash - GROUP BY l_shipdate) sub - WHERE year = 1995 - ORDER BY 2 DESC, 1 - LIMIT 10; - l_shipdate | distinct_part | year ---------------------------------------------------------------------- - 11-29-1995 | 5 | 1995 - 03-24-1995 | 4 | 1995 - 09-18-1995 | 4 | 1995 - 01-17-1995 | 3 | 1995 - 04-02-1995 | 3 | 1995 - 05-23-1995 | 3 | 1995 - 08-11-1995 | 3 | 1995 - 09-27-1995 | 3 | 1995 - 10-27-1995 | 3 | 1995 - 10-30-1995 | 3 | 1995 -(10 rows) - -DROP TABLE lineitem_hash; diff --git a/src/test/regress/expected/multi_explain.out b/src/test/regress/expected/multi_explain.out index ca97fc0c1..b7a911564 100644 --- a/src/test/regress/expected/multi_explain.out +++ b/src/test/regress/expected/multi_explain.out @@ -1,22 +1,11 @@ -- -- MULTI_EXPLAIN -- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- -- This test file has an alternative output because of the following in PG18: -- https://github.com/postgres/postgres/commit/161320b4b960ee4fe918959be6529ae9b106ea5a -- The alternative output can be deleted when we drop support for PG17 -- SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; - server_version_ge_16 ---------------------------------------------------------------------- - t -(1 row) - SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18; server_version_ge_18 --------------------------------------------------------------------- diff --git a/src/test/regress/expected/multi_explain_0.out b/src/test/regress/expected/multi_explain_0.out index 667f932dc..68245bfc3 100644 --- a/src/test/regress/expected/multi_explain_0.out +++ b/src/test/regress/expected/multi_explain_0.out @@ -1,22 +1,11 @@ -- -- MULTI_EXPLAIN -- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- -- This test file has an alternative output because of the following in PG18: -- https://github.com/postgres/postgres/commit/161320b4b960ee4fe918959be6529ae9b106ea5a -- The alternative output can be deleted when we drop support for PG17 -- SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; - server_version_ge_16 ---------------------------------------------------------------------- - t -(1 row) - SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18; server_version_ge_18 --------------------------------------------------------------------- diff --git a/src/test/regress/expected/multi_explain_1.out b/src/test/regress/expected/multi_explain_1.out deleted file mode 100644 index 13434c256..000000000 --- a/src/test/regress/expected/multi_explain_1.out +++ /dev/null @@ -1,3363 +0,0 @@ --- --- MULTI_EXPLAIN --- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- --- This test file has an alternative output because of the following in PG18: --- https://github.com/postgres/postgres/commit/161320b4b960ee4fe918959be6529ae9b106ea5a --- The alternative output can be deleted when we drop support for PG17 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; - server_version_ge_16 ---------------------------------------------------------------------- - f -(1 row) - -SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18; - server_version_ge_18 ---------------------------------------------------------------------- - f -(1 row) - -SET citus.next_shard_id TO 570000; -\a\t -SET citus.explain_distributed_queries TO on; -SET citus.enable_repartition_joins to ON; --- Ensure tuple data in explain analyze output is the same on all PG versions -SET citus.enable_binary_protocol = TRUE; --- Function that parses explain output as JSON -CREATE OR REPLACE FUNCTION explain_json(query text) -RETURNS jsonb -AS $BODY$ -DECLARE - result jsonb; -BEGIN - EXECUTE format('EXPLAIN (FORMAT JSON) %s', query) INTO result; - RETURN result; -END; -$BODY$ LANGUAGE plpgsql; -CREATE OR REPLACE FUNCTION explain_analyze_json(query text) -RETURNS jsonb -AS $BODY$ -DECLARE - result jsonb; -BEGIN - EXECUTE format('EXPLAIN (ANALYZE TRUE, FORMAT JSON) %s', query) INTO result; - RETURN result; -END; -$BODY$ LANGUAGE plpgsql; --- Function that parses explain output as XML -CREATE OR REPLACE FUNCTION explain_xml(query text) -RETURNS xml -AS $BODY$ -DECLARE - result xml; -BEGIN - EXECUTE format('EXPLAIN (FORMAT XML) %s', query) INTO result; - RETURN result; -END; -$BODY$ LANGUAGE plpgsql; --- Function that parses explain output as XML -CREATE OR REPLACE FUNCTION explain_analyze_xml(query text) -RETURNS xml -AS $BODY$ -DECLARE - result xml; -BEGIN - EXECUTE format('EXPLAIN (ANALYZE true, FORMAT XML) %s', query) INTO result; - RETURN result; -END; -$BODY$ LANGUAGE plpgsql; --- VACUMM related tables to ensure test outputs are stable -VACUUM ANALYZE lineitem; -VACUUM ANALYZE orders; --- Test Text format -EXPLAIN (COSTS FALSE, FORMAT TEXT) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -Sort - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - -> HashAggregate - Group Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Group Key: l_quantity - -> Seq Scan on lineitem_360000 lineitem --- Test disable hash aggregate -SET enable_hashagg TO off; -EXPLAIN (COSTS FALSE, FORMAT TEXT) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -Sort - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - -> GroupAggregate - Group Key: remote_scan.l_quantity - -> Sort - Sort Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Group Key: l_quantity - -> Seq Scan on lineitem_360000 lineitem -SET enable_hashagg TO on; --- Test JSON format -EXPLAIN (COSTS FALSE, FORMAT JSON) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -[ - { - "Plan": { - "Node Type": "Sort", - "Parallel Aware": false, - "Async Capable": false, - "Sort Key": ["(COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))", "remote_scan.l_quantity"], - "Plans": [ - { - "Node Type": "Aggregate", - "Strategy": "Hashed", - "Partial Mode": "Simple", - "Parent Relationship": "Outer", - "Parallel Aware": false, - "Async Capable": false, - "Group Key": ["remote_scan.l_quantity"], - "Plans": [ - { - "Node Type": "Custom Scan", - "Parent Relationship": "Outer", - "Custom Plan Provider": "Citus Adaptive", - "Parallel Aware": false, - "Async Capable": false, - "Distributed Query": { - "Job": { - "Task Count": 2, - "Tasks Shown": "One of 2", - "Tasks": [ - { - "Node": "host=localhost port=xxxxx dbname=regression", - "Remote Plan": [ - [ - { - "Plan": { - "Node Type": "Aggregate", - "Strategy": "Hashed", - "Partial Mode": "Simple", - "Parallel Aware": false, - "Async Capable": false, - "Group Key": ["l_quantity"], - "Plans": [ - { - "Node Type": "Seq Scan", - "Parent Relationship": "Outer", - "Parallel Aware": false, - "Async Capable": false, - "Relation Name": "lineitem_360000", - "Alias": "lineitem" - } - ] - } - } - ] - - ] - } - ] - } - } - } - ] - } - ] - } - } -] --- Validate JSON format -SELECT true AS valid FROM explain_json($$ - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity$$); -t -SELECT true AS valid FROM explain_analyze_json($$ - WITH a AS ( - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity LIMIT 10) - SELECT count(*) FROM a -$$); -t --- Test XML format -EXPLAIN (COSTS FALSE, FORMAT XML) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; - - - - Sort - false - false - - (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)) - remote_scan.l_quantity - - - - Aggregate - Hashed - Simple - Outer - false - false - - remote_scan.l_quantity - - - - Custom Scan - Outer - Citus Adaptive - false - false - - - 2 - One of 2 - - - host=localhost port=xxxxx dbname=regression - - - - - Aggregate - Hashed - Simple - false - false - - l_quantity - - - - Seq Scan - Outer - false - false - lineitem_360000 - lineitem - - - - - - - - - - - - - - - - - --- Validate XML format -SELECT true AS valid FROM explain_xml($$ - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity$$); -t -SELECT true AS valid FROM explain_analyze_xml($$ - WITH a AS ( - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity LIMIT 10) - SELECT count(*) FROM a -$$); -t --- Test YAML format -EXPLAIN (COSTS FALSE, FORMAT YAML) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -- Plan: - Node Type: "Sort" - Parallel Aware: false - Async Capable: false - Sort Key: - - "(COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint))" - - "remote_scan.l_quantity" - Plans: - - Node Type: "Aggregate" - Strategy: "Hashed" - Partial Mode: "Simple" - Parent Relationship: "Outer" - Parallel Aware: false - Async Capable: false - Group Key: - - "remote_scan.l_quantity" - Plans: - - Node Type: "Custom Scan" - Parent Relationship: "Outer" - Custom Plan Provider: "Citus Adaptive" - Parallel Aware: false - Async Capable: false - Distributed Query: - Job: - Task Count: 2 - Tasks Shown: "One of 2" - Tasks: - - Node: "host=localhost port=xxxxx dbname=regression" - Remote Plan: - - Plan: - Node Type: "Aggregate" - Strategy: "Hashed" - Partial Mode: "Simple" - Parallel Aware: false - Async Capable: false - Group Key: - - "l_quantity" - Plans: - - Node Type: "Seq Scan" - Parent Relationship: "Outer" - Parallel Aware: false - Async Capable: false - Relation Name: "lineitem_360000" - Alias: "lineitem" - --- Test Text format -EXPLAIN (COSTS FALSE, FORMAT TEXT) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -Sort - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - -> HashAggregate - Group Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Group Key: l_quantity - -> Seq Scan on lineitem_360000 lineitem --- Test analyze (with TIMING FALSE and SUMMARY FALSE for consistent output) -SELECT public.plan_normalize_memory($Q$ -EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE, BUFFERS OFF) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -$Q$); -Sort (actual rows=50 loops=1) - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - Sort Method: quicksort Memory: xxx - -> HashAggregate (actual rows=50 loops=1) - Group Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) (actual rows=100 loops=1) - Task Count: 2 - Tuple data received from nodes: 1800 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 900 bytes - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate (actual rows=50 loops=1) - Group Key: l_quantity - -> Seq Scan on lineitem_360000 lineitem (actual rows=5894 loops=1) --- EXPLAIN ANALYZE doesn't show worker tasks for repartition joins yet -SET citus.shard_count TO 3; -CREATE TABLE t1(a int, b int); -CREATE TABLE t2(a int, b int); -SELECT create_distributed_table('t1', 'a'), create_distributed_table('t2', 'a'); -| -BEGIN; -SET LOCAL citus.enable_repartition_joins TO true; -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, BUFFERS OFF) SELECT count(*) FROM t1, t2 WHERE t1.a=t2.b; -Aggregate (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 6 - Tuple data received from nodes: 48 bytes - Tasks Shown: None, not supported for re-partition queries - -> MapMergeJob - Map Task Count: 3 - Merge Task Count: 6 - -> MapMergeJob - Map Task Count: 3 - Merge Task Count: 6 --- Confirm repartiton join in distributed subplan works -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, BUFFERS OFF) -WITH repartition AS (SELECT count(*) FROM t1, t2 WHERE t1.a=t2.b) -SELECT count(*) from repartition; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 14 bytes - Result destination: Write locally - -> Aggregate (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 6 - Tuple data received from nodes: 48 bytes - Tasks Shown: None, not supported for re-partition queries - -> MapMergeJob - Map Task Count: 3 - Merge Task Count: 6 - -> MapMergeJob - Map Task Count: 3 - Merge Task Count: 6 - Task Count: 1 - Tuple data received from nodes: 8 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate (actual rows=1 loops=1) - -> Function Scan on read_intermediate_result intermediate_result (actual rows=1 loops=1) -END; -DROP TABLE t1, t2; --- Test query text output, with ANALYZE ON -SELECT public.plan_normalize_memory($Q$ -EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE, VERBOSE TRUE, BUFFERS OFF) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -$Q$); -Sort (actual rows=50 loops=1) - Output: remote_scan.l_quantity, (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)) - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - Sort Method: quicksort Memory: xxx - -> HashAggregate (actual rows=50 loops=1) - Output: remote_scan.l_quantity, COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint) - Group Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) (actual rows=100 loops=1) - Output: remote_scan.l_quantity, remote_scan.count_quantity - Task Count: 2 - Tuple data received from nodes: 1800 bytes - Tasks Shown: One of 2 - -> Task - Query: SELECT l_quantity, count(*) AS count_quantity FROM public.lineitem_360000 lineitem WHERE true GROUP BY l_quantity - Tuple data received from node: 900 bytes - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate (actual rows=50 loops=1) - Output: l_quantity, count(*) - Group Key: lineitem.l_quantity - -> Seq Scan on public.lineitem_360000 lineitem (actual rows=5894 loops=1) - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment --- Test query text output, with ANALYZE OFF -EXPLAIN (COSTS FALSE, ANALYZE FALSE, TIMING FALSE, SUMMARY FALSE, VERBOSE TRUE) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -Sort - Output: remote_scan.l_quantity, (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)) - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - -> HashAggregate - Output: remote_scan.l_quantity, COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint) - Group Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_quantity, remote_scan.count_quantity - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Query: SELECT l_quantity, count(*) AS count_quantity FROM public.lineitem_360000 lineitem WHERE true GROUP BY l_quantity - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_quantity, count(*) - Group Key: lineitem.l_quantity - -> Seq Scan on public.lineitem_360000 lineitem - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment --- Test verbose -EXPLAIN (COSTS FALSE, VERBOSE TRUE) - SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem; -Aggregate - Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / pg_catalog.sum(remote_scan."?column?_2"))) - -> Custom Scan (Citus Adaptive) - Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2" - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Query: SELECT sum(l_quantity), sum(l_quantity), count(l_quantity) FROM public.lineitem_360000 lineitem WHERE true - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - Output: sum(l_quantity), sum(l_quantity), count(l_quantity) - -> Seq Scan on public.lineitem_360000 lineitem - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment --- Test join -EXPLAIN (COSTS FALSE) - SELECT * FROM lineitem - JOIN orders ON l_orderkey = o_orderkey AND l_quantity < 5.0 - ORDER BY l_quantity LIMIT 10; -Limit - -> Sort - Sort Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Limit - -> Sort - Sort Key: lineitem.l_quantity - -> Hash Join - Hash Cond: (lineitem.l_orderkey = orders.o_orderkey) - -> Seq Scan on lineitem_360000 lineitem - Filter: (l_quantity < 5.0) - -> Hash - -> Seq Scan on orders_360002 orders --- Test insert -EXPLAIN (COSTS FALSE) - INSERT INTO lineitem VALUES (1,0), (2, 0), (3, 0), (4, 0); -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on lineitem_360000 citus_table_alias - -> Values Scan on "*VALUES*" --- Test update -EXPLAIN (COSTS FALSE) - UPDATE lineitem - SET l_suppkey = 12 - WHERE l_orderkey = 1 AND l_partkey = 0; -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_360000 lineitem - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey = 1) - Filter: (l_partkey = 0) --- Test analyze (with TIMING FALSE and SUMMARY FALSE for consistent output) -BEGIN; -select public.explain_filter(' -EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE, BUFFERS OFF) - UPDATE lineitem - SET l_suppkey = 12 - WHERE l_orderkey = 1 AND l_partkey = 0 - '); -Custom Scan (Citus Adaptive) (actual rows=N loops=N) - Task Count: N - Tasks Shown: All - -> Task - Node: host=localhost port=N dbname=regression - -> Update on lineitem_360000 lineitem (actual rows=N loops=N) - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem (actual rows=N loops=N) - Index Cond: (l_orderkey = N) - Filter: (l_partkey = N) - Rows Removed by Filter: N -ROLLBACk; --- Test delete -EXPLAIN (COSTS FALSE) - DELETE FROM lineitem - WHERE l_orderkey = 1 AND l_partkey = 0; -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_360000 lineitem - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey = 1) - Filter: (l_partkey = 0) --- Test zero-shard update -EXPLAIN (COSTS FALSE) - UPDATE lineitem - SET l_suppkey = 12 - WHERE l_orderkey = 1 AND l_orderkey = 0; -Custom Scan (Citus Adaptive) - Task Count: 0 - Tasks Shown: All --- Test zero-shard delete -EXPLAIN (COSTS FALSE) - DELETE FROM lineitem - WHERE l_orderkey = 1 AND l_orderkey = 0; -Custom Scan (Citus Adaptive) - Task Count: 0 - Tasks Shown: All --- Test single-shard SELECT -EXPLAIN (COSTS FALSE) - SELECT l_quantity FROM lineitem WHERE l_orderkey = 5; -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey = 5) -SELECT true AS valid FROM explain_xml($$ - SELECT l_quantity FROM lineitem WHERE l_orderkey = 5$$); -t -SELECT true AS valid FROM explain_json($$ - SELECT l_quantity FROM lineitem WHERE l_orderkey = 5$$); -t --- Test CREATE TABLE ... AS -EXPLAIN (COSTS FALSE) - CREATE TABLE explain_result AS - SELECT * FROM lineitem; -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on lineitem_360000 lineitem --- Test having -EXPLAIN (COSTS FALSE, VERBOSE TRUE) - SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem - HAVING sum(l_quantity) > 100; -Aggregate - Output: (sum(remote_scan."?column?") / (sum(remote_scan."?column?_1") / pg_catalog.sum(remote_scan."?column?_2"))) - Filter: (sum(remote_scan.worker_column_4) > '100'::numeric) - -> Custom Scan (Citus Adaptive) - Output: remote_scan."?column?", remote_scan."?column?_1", remote_scan."?column?_2", remote_scan.worker_column_4 - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Query: SELECT sum(l_quantity), sum(l_quantity), count(l_quantity), sum(l_quantity) AS worker_column_4 FROM public.lineitem_360000 lineitem WHERE true - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - Output: sum(l_quantity), sum(l_quantity), count(l_quantity), sum(l_quantity) - -> Seq Scan on public.lineitem_360000 lineitem - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment --- Test having without aggregate -EXPLAIN (COSTS FALSE, VERBOSE TRUE) - SELECT l_quantity FROM lineitem - GROUP BY l_quantity - HAVING l_quantity > (100 * random()); -HashAggregate - Output: remote_scan.l_quantity - Group Key: remote_scan.l_quantity - Filter: ((remote_scan.worker_column_2)::double precision > ('100'::double precision * random())) - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_quantity, remote_scan.worker_column_2 - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Query: SELECT l_quantity, l_quantity AS worker_column_2 FROM public.lineitem_360000 lineitem WHERE true GROUP BY l_quantity - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_quantity, l_quantity - Group Key: lineitem.l_quantity - -> Seq Scan on public.lineitem_360000 lineitem - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment --- Subquery pushdown tests with explain -EXPLAIN (COSTS OFF) -SELECT - avg(array_length(events, 1)) AS event_average -FROM - (SELECT - tenant_id, - user_id, - array_agg(event_type ORDER BY event_time) AS events - FROM - (SELECT - (users.composite_id).tenant_id, - (users.composite_id).user_id, - event_type, - events.event_time - FROM - users, - events - WHERE - (users.composite_id) = (events.composite_id) AND - users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type IN ('click', 'submit', 'pay')) AS subquery - GROUP BY - tenant_id, - user_id) AS subquery; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> GroupAggregate - Group Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id) - -> Sort - Sort Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id) - -> Hash Join - Hash Cond: (users.composite_id = events.composite_id) - -> Seq Scan on users_1400289 users - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type)) - -> Hash - -> Seq Scan on events_1400285 events - Filter: ((event_type)::text = ANY ('{click,submit,pay}'::text[])) -SELECT success FROM run_command_on_workers('alter system set enable_nestloop to off'); -t -t -SELECT success FROM run_command_on_workers('alter system set enable_sort to off'); -t -t -SELECT success FROM run_command_on_workers('select pg_reload_conf()'); -t -t --- Union and left join subquery pushdown -EXPLAIN (COSTS OFF) -SELECT - avg(array_length(events, 1)) AS event_average, - hasdone -FROM - (SELECT - subquery_1.tenant_id, - subquery_1.user_id, - array_agg(event ORDER BY event_time) AS events, - COALESCE(hasdone, 'Has not done paying') AS hasdone - FROM - ( - (SELECT - (users.composite_id).tenant_id, - (users.composite_id).user_id, - (users.composite_id) as composite_id, - 'action=>1'AS event, - events.event_time - FROM - users, - events - WHERE - (users.composite_id) = (events.composite_id) AND - users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type = 'click') - UNION - (SELECT - (users.composite_id).tenant_id, - (users.composite_id).user_id, - (users.composite_id) as composite_id, - 'action=>2'AS event, - events.event_time - FROM - users, - events - WHERE - (users.composite_id) = (events.composite_id) AND - users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type = 'submit') - ) AS subquery_1 - LEFT JOIN - (SELECT - DISTINCT ON ((composite_id).tenant_id, (composite_id).user_id) composite_id, - (composite_id).tenant_id, - (composite_id).user_id, - 'Has done paying'::TEXT AS hasdone - FROM - events - WHERE - events.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - events.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type = 'pay') AS subquery_2 - ON - subquery_1.composite_id = subquery_2.composite_id - GROUP BY - subquery_1.tenant_id, - subquery_1.user_id, - hasdone) AS subquery_top -GROUP BY - hasdone; -HashAggregate - Group Key: remote_scan.hasdone - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Group Key: COALESCE(subquery_2.hasdone, 'Has not done paying'::text) - -> GroupAggregate - Group Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id), subquery_2.hasdone - -> Sort - Sort Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id), subquery_2.hasdone - -> Hash Left Join - Hash Cond: (users.composite_id = subquery_2.composite_id) - -> HashAggregate - Group Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id), users.composite_id, ('action=>1'::text), events.event_time - -> Append - -> Hash Join - Hash Cond: (users.composite_id = events.composite_id) - -> Seq Scan on users_1400289 users - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type)) - -> Hash - -> Seq Scan on events_1400285 events - Filter: ((event_type)::text = 'click'::text) - -> Hash Join - Hash Cond: (users_1.composite_id = events_1.composite_id) - -> Seq Scan on users_1400289 users_1 - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type)) - -> Hash - -> Seq Scan on events_1400285 events_1 - Filter: ((event_type)::text = 'submit'::text) - -> Hash - -> Subquery Scan on subquery_2 - -> Unique - -> Sort - Sort Key: ((events_2.composite_id).tenant_id), ((events_2.composite_id).user_id) - -> Seq Scan on events_1400285 events_2 - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type) AND ((event_type)::text = 'pay'::text)) --- Union, left join and having subquery pushdown -EXPLAIN (COSTS OFF) - SELECT - avg(array_length(events, 1)) AS event_average, - count_pay - FROM ( - SELECT - subquery_1.tenant_id, - subquery_1.user_id, - array_agg(event ORDER BY event_time) AS events, - COALESCE(count_pay, 0) AS count_pay - FROM - ( - (SELECT - (users.composite_id).tenant_id, - (users.composite_id).user_id, - (users.composite_id), - 'action=>1'AS event, - events.event_time - FROM - users, - events - WHERE - (users.composite_id) = (events.composite_id) AND - users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type = 'click') - UNION - (SELECT - (users.composite_id).tenant_id, - (users.composite_id).user_id, - (users.composite_id), - 'action=>2'AS event, - events.event_time - FROM - users, - events - WHERE - (users.composite_id) = (events.composite_id) AND - users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type = 'submit') - ) AS subquery_1 - LEFT JOIN - (SELECT - (composite_id).tenant_id, - (composite_id).user_id, - composite_id, - COUNT(*) AS count_pay - FROM - events - WHERE - events.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - events.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND - event_type = 'pay' - GROUP BY - composite_id - HAVING - COUNT(*) > 2) AS subquery_2 - ON - subquery_1.composite_id = subquery_2.composite_id - GROUP BY - subquery_1.tenant_id, - subquery_1.user_id, - count_pay) AS subquery_top -WHERE - array_ndims(events) > 0 -GROUP BY - count_pay -ORDER BY - count_pay; -Sort - Sort Key: remote_scan.count_pay - -> HashAggregate - Group Key: remote_scan.count_pay - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Group Key: COALESCE(subquery_2.count_pay, '0'::bigint) - -> GroupAggregate - Group Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id), subquery_2.count_pay - Filter: (array_ndims(array_agg(('action=>1'::text) ORDER BY events.event_time)) > 0) - -> Sort - Sort Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id), subquery_2.count_pay - -> Hash Left Join - Hash Cond: (users.composite_id = subquery_2.composite_id) - -> HashAggregate - Group Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id), users.composite_id, ('action=>1'::text), events.event_time - -> Append - -> Hash Join - Hash Cond: (users.composite_id = events.composite_id) - -> Seq Scan on users_1400289 users - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type)) - -> Hash - -> Seq Scan on events_1400285 events - Filter: ((event_type)::text = 'click'::text) - -> Hash Join - Hash Cond: (users_1.composite_id = events_1.composite_id) - -> Seq Scan on users_1400289 users_1 - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type)) - -> Hash - -> Seq Scan on events_1400285 events_1 - Filter: ((event_type)::text = 'submit'::text) - -> Hash - -> Subquery Scan on subquery_2 - -> HashAggregate - Group Key: events_2.composite_id - Filter: (count(*) > 2) - -> Seq Scan on events_1400285 events_2 - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type) AND ((event_type)::text = 'pay'::text)) -SELECT success FROM run_command_on_workers('alter system reset enable_nestloop'); -t -t -SELECT success FROM run_command_on_workers('alter system reset enable_sort'); -t -t -SELECT success FROM run_command_on_workers('select pg_reload_conf()'); -t -t --- Lateral join subquery pushdown --- set subquery_pushdown due to limit in the query -SET citus.subquery_pushdown to ON; -NOTICE: Setting citus.subquery_pushdown flag is discouraged becuase it forces the planner to pushdown certain queries, skipping relevant correctness checks. -DETAIL: When enabled, the planner skips many correctness checks for subqueries and pushes down the queries to shards as-is. It means that the queries are likely to return wrong results unless the user is absolutely sure that pushing down the subquery is safe. This GUC is maintained only for backward compatibility, no new users are supposed to use it. The planner is capable of pushing down as much computation as possible to the shards depending on the query. -EXPLAIN (COSTS OFF) -SELECT - tenant_id, - user_id, - user_lastseen, - event_array -FROM - (SELECT - tenant_id, - user_id, - max(lastseen) as user_lastseen, - array_agg(event_type ORDER BY event_time) AS event_array - FROM - (SELECT - (composite_id).tenant_id, - (composite_id).user_id, - composite_id, - lastseen - FROM - users - WHERE - composite_id >= '(1, -9223372036854775808)'::user_composite_type AND - composite_id <= '(1, 9223372036854775807)'::user_composite_type - ORDER BY - lastseen DESC - LIMIT - 10 - ) AS subquery_top - LEFT JOIN LATERAL - (SELECT - event_type, - event_time - FROM - events - WHERE - (composite_id) = subquery_top.composite_id - ORDER BY - event_time DESC - LIMIT - 99) AS subquery_lateral - ON - true - GROUP BY - tenant_id, - user_id - ) AS shard_union -ORDER BY - user_lastseen DESC -LIMIT - 10; -Limit - -> Sort - Sort Key: remote_scan.user_lastseen DESC - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Limit - -> Sort - Sort Key: (max(users.lastseen)) DESC - -> GroupAggregate - Group Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id) - -> Sort - Sort Key: ((users.composite_id).tenant_id), ((users.composite_id).user_id) - -> Nested Loop Left Join - -> Limit - -> Sort - Sort Key: users.lastseen DESC - -> Seq Scan on users_1400289 users - Filter: ((composite_id >= '(1,-9223372036854775808)'::user_composite_type) AND (composite_id <= '(1,9223372036854775807)'::user_composite_type)) - -> Limit - -> Sort - Sort Key: events.event_time DESC - -> Seq Scan on events_1400285 events - Filter: (composite_id = users.composite_id) -RESET citus.subquery_pushdown; --- Test all tasks output -SET citus.explain_all_tasks TO on; -EXPLAIN (COSTS FALSE) - SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> Index Only Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey > 9030) - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> Index Only Scan using lineitem_pkey_360001 on lineitem_360001 lineitem - Index Cond: (l_orderkey > 9030) -SELECT true AS valid FROM explain_xml($$ - SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030$$); -t -SELECT true AS valid FROM explain_json($$ - SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030$$); -t --- Test multi shard update -EXPLAIN (COSTS FALSE) - UPDATE lineitem_hash_part - SET l_suppkey = 12; -Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360041 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360042 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360042 lineitem_hash_part - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360043 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360043 lineitem_hash_part - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360044 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360044 lineitem_hash_part -EXPLAIN (COSTS FALSE) - UPDATE lineitem_hash_part - SET l_suppkey = 12 - WHERE l_orderkey = 1 OR l_orderkey = 3; -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360041 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part - Filter: ((l_orderkey = 1) OR (l_orderkey = 3)) - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360042 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360042 lineitem_hash_part - Filter: ((l_orderkey = 1) OR (l_orderkey = 3)) --- Test multi shard delete -EXPLAIN (COSTS FALSE) - DELETE FROM lineitem_hash_part; -Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360041 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360042 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360042 lineitem_hash_part - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360043 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360043 lineitem_hash_part - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360044 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360044 lineitem_hash_part --- Test analyze (with TIMING FALSE and SUMMARY FALSE for consistent output) -SELECT public.plan_normalize_memory($Q$ -EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE, BUFFERS OFF) - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity; -$Q$); -Sort (actual rows=50 loops=1) - Sort Key: (COALESCE((pg_catalog.sum(remote_scan.count_quantity))::bigint, '0'::bigint)), remote_scan.l_quantity - Sort Method: quicksort Memory: xxx - -> HashAggregate (actual rows=50 loops=1) - Group Key: remote_scan.l_quantity - -> Custom Scan (Citus Adaptive) (actual rows=100 loops=1) - Task Count: 2 - Tuple data received from nodes: 1800 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 900 bytes - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate (actual rows=50 loops=1) - Group Key: l_quantity - -> Seq Scan on lineitem_360000 lineitem (actual rows=5894 loops=1) - -> Task - Tuple data received from node: 900 bytes - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate (actual rows=50 loops=1) - Group Key: l_quantity - -> Seq Scan on lineitem_360001 lineitem (actual rows=6106 loops=1) -SET citus.explain_all_tasks TO off; --- Test update with subquery -EXPLAIN (COSTS FALSE) - UPDATE lineitem_hash_part - SET l_suppkey = 12 - FROM orders_hash_part - WHERE orders_hash_part.o_orderkey = lineitem_hash_part.l_orderkey; -Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_hash_part_360041 lineitem_hash_part - -> Hash Join - Hash Cond: (lineitem_hash_part.l_orderkey = orders_hash_part.o_orderkey) - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part - -> Hash - -> Seq Scan on orders_hash_part_360045 orders_hash_part --- Test delete with subquery -EXPLAIN (COSTS FALSE) - DELETE FROM lineitem_hash_part - USING orders_hash_part - WHERE orders_hash_part.o_orderkey = lineitem_hash_part.l_orderkey; -Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360041 lineitem_hash_part - -> Hash Join - Hash Cond: (lineitem_hash_part.l_orderkey = orders_hash_part.o_orderkey) - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part - -> Hash - -> Seq Scan on orders_hash_part_360045 orders_hash_part --- Test track tracker -EXPLAIN (COSTS FALSE) - SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> Index Only Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey > 9030) --- Test re-partition join -EXPLAIN (COSTS FALSE) - SELECT count(*) - FROM lineitem, orders, customer_append, supplier_single_shard - WHERE l_orderkey = o_orderkey - AND o_custkey = c_custkey - AND l_suppkey = s_suppkey; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 6 - Tasks Shown: None, not supported for re-partition queries - -> MapMergeJob - Map Task Count: 6 - Merge Task Count: 6 - -> MapMergeJob - Map Task Count: 2 - Merge Task Count: 6 - -> MapMergeJob - Map Task Count: 1 - Merge Task Count: 6 - -> MapMergeJob - Map Task Count: 1 - Merge Task Count: 6 -EXPLAIN (COSTS FALSE, FORMAT JSON) - SELECT count(*) - FROM lineitem, orders, customer_append, supplier_single_shard - WHERE l_orderkey = o_orderkey - AND o_custkey = c_custkey - AND l_suppkey = s_suppkey; -[ - { - "Plan": { - "Node Type": "Aggregate", - "Strategy": "Plain", - "Partial Mode": "Simple", - "Parallel Aware": false, - "Async Capable": false, - "Plans": [ - { - "Node Type": "Custom Scan", - "Parent Relationship": "Outer", - "Custom Plan Provider": "Citus Adaptive", - "Parallel Aware": false, - "Async Capable": false, - "Distributed Query": { - "Job": { - "Task Count": 6, - "Tasks Shown": "None, not supported for re-partition queries", - "Dependent Jobs": [ - { - "Map Task Count": 6, - "Merge Task Count": 6, - "Dependent Jobs": [ - { - "Map Task Count": 2, - "Merge Task Count": 6 - }, - { - "Map Task Count": 1, - "Merge Task Count": 6 - } - ] - }, - { - "Map Task Count": 1, - "Merge Task Count": 6 - } - ] - } - } - } - ] - } - } -] -SELECT true AS valid FROM explain_json($$ - SELECT count(*) - FROM lineitem, orders, customer_append, supplier_single_shard - WHERE l_orderkey = o_orderkey - AND o_custkey = c_custkey - AND l_suppkey = s_suppkey$$); -t -EXPLAIN (COSTS FALSE, FORMAT XML) - SELECT count(*) - FROM lineitem, orders, customer_append, supplier_single_shard - WHERE l_orderkey = o_orderkey - AND o_custkey = c_custkey - AND l_suppkey = s_suppkey; - - - - Aggregate - Plain - Simple - false - false - - - Custom Scan - Outer - Citus Adaptive - false - false - - - 6 - None, not supported for re-partition queries - - - 6 - 6 - - - 2 - 6 - - - 1 - 6 - - - - - 1 - 6 - - - - - - - - - -SELECT true AS valid FROM explain_xml($$ - SELECT count(*) - FROM lineitem, orders, customer_append, supplier - WHERE l_orderkey = o_orderkey - AND o_custkey = c_custkey - AND l_suppkey = s_suppkey$$); -t --- make sure that EXPLAIN works without --- problems for queries that inlvolves only --- reference tables -SELECT true AS valid FROM explain_xml($$ - SELECT count(*) - FROM nation - WHERE n_name = 'CHINA'$$); -t -SELECT true AS valid FROM explain_xml($$ - SELECT count(*) - FROM nation, supplier - WHERE nation.n_nationkey = supplier.s_nationkey$$); -t -EXPLAIN (COSTS FALSE, FORMAT YAML) - SELECT count(*) - FROM lineitem, orders, customer, supplier_single_shard - WHERE l_orderkey = o_orderkey - AND o_custkey = c_custkey - AND l_suppkey = s_suppkey; -- Plan: - Node Type: "Aggregate" - Strategy: "Plain" - Partial Mode: "Simple" - Parallel Aware: false - Async Capable: false - Plans: - - Node Type: "Custom Scan" - Parent Relationship: "Outer" - Custom Plan Provider: "Citus Adaptive" - Parallel Aware: false - Async Capable: false - Distributed Query: - Job: - Task Count: 6 - Tasks Shown: "None, not supported for re-partition queries" - Dependent Jobs: - - Map Task Count: 2 - Merge Task Count: 6 - - Map Task Count: 1 - Merge Task Count: 6 --- ensure local plans display correctly -CREATE TABLE lineitem_clone (LIKE lineitem); -EXPLAIN (COSTS FALSE) SELECT avg(l_linenumber) FROM lineitem_clone; -Aggregate - -> Seq Scan on lineitem_clone -DROP TABLE lineitem_clone; --- ensure distributed plans don't break -EXPLAIN (COSTS FALSE) SELECT avg(l_linenumber) FROM lineitem; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> Seq Scan on lineitem_360000 lineitem --- ensure EXPLAIN EXECUTE doesn't crash -PREPARE task_tracker_query AS - SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030; -EXPLAIN (COSTS FALSE) EXECUTE task_tracker_query; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> Index Only Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey > 9030) -PREPARE router_executor_query AS SELECT l_quantity FROM lineitem WHERE l_orderkey = 5; -EXPLAIN EXECUTE router_executor_query; -Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem (cost=0.28..13.60 rows=4 width=5) - Index Cond: (l_orderkey = 5) -PREPARE real_time_executor_query AS - SELECT avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030; -EXPLAIN (COSTS FALSE) EXECUTE real_time_executor_query; -Aggregate - -> Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate - -> Index Only Scan using lineitem_pkey_360000 on lineitem_360000 lineitem - Index Cond: (l_orderkey > 9030) --- EXPLAIN EXECUTE of parametrized prepared statements is broken, but --- at least make sure to fail without crashing -PREPARE router_executor_query_param(int) AS SELECT l_quantity FROM lineitem WHERE l_orderkey = $1; -EXPLAIN EXECUTE router_executor_query_param(5); -Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem (cost=0.28..13.60 rows=4 width=5) - Index Cond: (l_orderkey = 5) -select public.explain_filter('EXPLAIN (ANALYZE ON, COSTS OFF, TIMING OFF, SUMMARY OFF, BUFFERS OFF) EXECUTE router_executor_query_param(5)'); -Custom Scan (Citus Adaptive) (actual rows=N loops=N) - Task Count: N - Tuple data received from nodes: N bytes - Tasks Shown: All - -> Task - Tuple data received from node: N bytes - Node: host=localhost port=N dbname=regression - -> Index Scan using lineitem_pkey_360000 on lineitem_360000 lineitem (actual rows=N loops=N) - Index Cond: (l_orderkey = N) -\set VERBOSITY TERSE -PREPARE multi_shard_query_param(int) AS UPDATE lineitem SET l_quantity = $1; -BEGIN; -EXPLAIN (COSTS OFF) EXECUTE multi_shard_query_param(5); -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_360000 lineitem - -> Seq Scan on lineitem_360000 lineitem -ROLLBACK; -BEGIN; -EXPLAIN (ANALYZE ON, COSTS OFF, TIMING OFF, SUMMARY OFF, BUFFERS OFF) EXECUTE multi_shard_query_param(5); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on lineitem_360000 lineitem (actual rows=0 loops=1) - -> Seq Scan on lineitem_360000 lineitem (actual rows=5894 loops=1) -ROLLBACK; -\set VERBOSITY DEFAULT --- test explain in a transaction with alter table to test we use right connections -BEGIN; -CREATE TABLE explain_table(id int); -SELECT create_distributed_table('explain_table', 'id'); - -ALTER TABLE explain_table ADD COLUMN value int; -ROLLBACK; --- test explain with local INSERT ... SELECT -EXPLAIN (COSTS OFF) -INSERT INTO lineitem_hash_part -SELECT o_orderkey FROM orders_hash_part LIMIT 3; -Custom Scan (Citus INSERT ... SELECT) - INSERT/SELECT method: pull to coordinator - -> Limit - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Limit - -> Seq Scan on orders_hash_part_360045 orders_hash_part -SELECT true AS valid FROM explain_json($$ - INSERT INTO lineitem_hash_part (l_orderkey) - SELECT o_orderkey FROM orders_hash_part LIMIT 3; -$$); -t -EXPLAIN (COSTS OFF) -INSERT INTO lineitem_hash_part (l_orderkey, l_quantity) -SELECT o_orderkey, 5 FROM orders_hash_part LIMIT 3; -Custom Scan (Citus INSERT ... SELECT) - INSERT/SELECT method: pull to coordinator - -> Limit - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Limit - -> Seq Scan on orders_hash_part_360045 orders_hash_part -EXPLAIN (COSTS OFF) -INSERT INTO lineitem_hash_part (l_orderkey) -SELECT s FROM generate_series(1,5) s; -Custom Scan (Citus INSERT ... SELECT) - INSERT/SELECT method: pull to coordinator - -> Function Scan on generate_series s --- WHERE EXISTS forces pg12 to materialize cte -SELECT public.explain_with_pg17_initplan_format($Q$ -EXPLAIN (COSTS OFF) -WITH cte1 AS (SELECT s FROM generate_series(1,10) s) -INSERT INTO lineitem_hash_part -WITH cte1 AS (SELECT * FROM cte1 WHERE EXISTS (SELECT * FROM cte1) LIMIT 5) -SELECT s FROM cte1 WHERE EXISTS (SELECT * FROM cte1); -$Q$); -Custom Scan (Citus INSERT ... SELECT) - INSERT/SELECT method: pull to coordinator - -> Result - One-Time Filter: (InitPlan 4).col1 - CTE cte1 - -> Function Scan on generate_series s - CTE cte1 - -> Limit - InitPlan 2 - -> CTE Scan on cte1 cte1_1 - -> Result - One-Time Filter: (InitPlan 2).col1 - -> CTE Scan on cte1 cte1_2 - InitPlan 4 - -> CTE Scan on cte1 cte1_3 - -> CTE Scan on cte1 -EXPLAIN (COSTS OFF) -INSERT INTO lineitem_hash_part -( SELECT s FROM generate_series(1,5) s) UNION -( SELECT s FROM generate_series(5,10) s); -Custom Scan (Citus INSERT ... SELECT) - INSERT/SELECT method: pull to coordinator - -> Subquery Scan on citus_insert_select_subquery - -> HashAggregate - Group Key: s.s - -> Append - -> Function Scan on generate_series s - -> Function Scan on generate_series s_1 --- explain with recursive planning -EXPLAIN (COSTS OFF, VERBOSE true) -WITH keys AS MATERIALIZED ( - SELECT DISTINCT l_orderkey FROM lineitem_hash_part -), -series AS MATERIALIZED ( - SELECT s FROM generate_series(1,10) s -) -SELECT l_orderkey FROM series JOIN keys ON (s = l_orderkey) -ORDER BY s; -Custom Scan (Citus Adaptive) - Output: remote_scan.l_orderkey - -> Distributed Subplan XXX_1 - -> HashAggregate - Output: remote_scan.l_orderkey - Group Key: remote_scan.l_orderkey - -> Custom Scan (Citus Adaptive) - Output: remote_scan.l_orderkey - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Query: SELECT DISTINCT l_orderkey FROM public.lineitem_hash_part_360041 lineitem_hash_part WHERE true - Node: host=localhost port=xxxxx dbname=regression - -> HashAggregate - Output: l_orderkey - Group Key: lineitem_hash_part.l_orderkey - -> Seq Scan on public.lineitem_hash_part_360041 lineitem_hash_part - Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment - -> Distributed Subplan XXX_2 - -> Function Scan on pg_catalog.generate_series s - Output: s - Function Call: generate_series(1, 10) - Task Count: 1 - Tasks Shown: All - -> Task - Query: SELECT keys.l_orderkey FROM ((SELECT intermediate_result.s FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(s integer)) series JOIN (SELECT intermediate_result.l_orderkey FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(l_orderkey bigint)) keys ON ((series.s OPERATOR(pg_catalog.=) keys.l_orderkey))) ORDER BY series.s - Node: host=localhost port=xxxxx dbname=regression - -> Merge Join - Output: intermediate_result_1.l_orderkey, intermediate_result.s - Merge Cond: (intermediate_result.s = intermediate_result_1.l_orderkey) - -> Sort - Output: intermediate_result.s - Sort Key: intermediate_result.s - -> Function Scan on pg_catalog.read_intermediate_result intermediate_result - Output: intermediate_result.s - Function Call: read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) - -> Sort - Output: intermediate_result_1.l_orderkey - Sort Key: intermediate_result_1.l_orderkey - -> Function Scan on pg_catalog.read_intermediate_result intermediate_result_1 - Output: intermediate_result_1.l_orderkey - Function Call: read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) -SELECT true AS valid FROM explain_json($$ - WITH result AS ( - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity - ), - series AS ( - SELECT s FROM generate_series(1,10) s - ) - SELECT * FROM result JOIN series ON (s = count_quantity) JOIN orders_hash_part ON (s = o_orderkey) -$$); -t -SELECT true AS valid FROM explain_xml($$ - WITH result AS ( - SELECT l_quantity, count(*) count_quantity FROM lineitem - GROUP BY l_quantity ORDER BY count_quantity, l_quantity - ), - series AS ( - SELECT s FROM generate_series(1,10) s - ) - SELECT * FROM result JOIN series ON (s = l_quantity) JOIN orders_hash_part ON (s = o_orderkey) -$$); -t --- --- Test EXPLAIN ANALYZE udfs --- -\a\t -\set default_opts '''{"costs": false, "timing": false, "summary": false}'''::jsonb -CREATE TABLE explain_analyze_test(a int, b text); -INSERT INTO explain_analyze_test VALUES (1, 'value 1'), (2, 'value 2'), (3, 'value 3'), (4, 'value 4'); --- simple select -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', :default_opts) as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Result (actual rows=1 loops=1)+ - -(1 row) - -END; --- insert into select -BEGIN; -SELECT * FROM worker_save_query_explain_analyze($Q$ - INSERT INTO explain_analyze_test SELECT i, i::text FROM generate_series(1, 5) i $Q$, - :default_opts) as (a int); - a ---------------------------------------------------------------------- -(0 rows) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Insert on explain_analyze_test (actual rows=0 loops=1) + - -> Function Scan on generate_series i (actual rows=5 loops=1)+ - -(1 row) - -ROLLBACK; --- select from table -BEGIN; -SELECT * FROM worker_save_query_explain_analyze($Q$SELECT * FROM explain_analyze_test$Q$, - :default_opts) as (a int, b text); - a | b ---------------------------------------------------------------------- - 1 | value 1 - 2 | value 2 - 3 | value 3 - 4 | value 4 -(4 rows) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Seq Scan on explain_analyze_test (actual rows=4 loops=1)+ - -(1 row) - -ROLLBACK; --- insert into with returning -BEGIN; -SELECT * FROM worker_save_query_explain_analyze($Q$ - INSERT INTO explain_analyze_test SELECT i, i::text FROM generate_series(1, 5) i - RETURNING a, b$Q$, - :default_opts) as (a int, b text); - a | b ---------------------------------------------------------------------- - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 -(5 rows) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Insert on explain_analyze_test (actual rows=5 loops=1) + - -> Function Scan on generate_series i (actual rows=5 loops=1)+ - -(1 row) - -ROLLBACK; --- delete with returning -BEGIN; -SELECT * FROM worker_save_query_explain_analyze($Q$ - DELETE FROM explain_analyze_test WHERE a % 2 = 0 - RETURNING a, b$Q$, - :default_opts) as (a int, b text); - a | b ---------------------------------------------------------------------- - 2 | value 2 - 4 | value 4 -(2 rows) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Delete on explain_analyze_test (actual rows=2 loops=1) + - -> Seq Scan on explain_analyze_test (actual rows=2 loops=1)+ - Filter: ((a % 2) = 0) + - Rows Removed by Filter: 2 + - -(1 row) - -ROLLBACK; --- delete without returning -BEGIN; -SELECT * FROM worker_save_query_explain_analyze($Q$ - DELETE FROM explain_analyze_test WHERE a % 2 = 0$Q$, - :default_opts) as (a int); - a ---------------------------------------------------------------------- -(0 rows) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Delete on explain_analyze_test (actual rows=0 loops=1) + - -> Seq Scan on explain_analyze_test (actual rows=2 loops=1)+ - Filter: ((a % 2) = 0) + - Rows Removed by Filter: 2 + - -(1 row) - -ROLLBACK; --- multiple queries (should ERROR) -SELECT * FROM worker_save_query_explain_analyze('SELECT 1; SELECT 2', :default_opts) as (a int); -ERROR: cannot EXPLAIN ANALYZE multiple queries --- error in query -SELECT * FROM worker_save_query_explain_analyze('SELECT x', :default_opts) as (a int); -ERROR: column "x" does not exist --- error in format string -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{"format": "invlaid_format"}') as (a int); -ERROR: Invalid explain analyze format: "invlaid_format" --- test formats -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{"format": "text", "costs": false}') as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - Result (actual rows=1 loops=1)+ - -(1 row) - -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{"format": "json", "costs": false}') as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - [ + - { + - "Plan": { + - "Node Type": "Result", + - "Parallel Aware": false,+ - "Async Capable": false, + - "Actual Rows": 1, + - "Actual Loops": 1 + - }, + - "Triggers": [ + - ] + - } + - ] -(1 row) - -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{"format": "xml", "costs": false}') as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - + - + - + - Result + - false + - false + - 1 + - 1 + - + - + - + - + - -(1 row) - -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{"format": "yaml", "costs": false}') as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT explain_analyze_output FROM worker_last_saved_explain_analyze(); - explain_analyze_output ---------------------------------------------------------------------- - - Plan: + - Node Type: "Result" + - Parallel Aware: false+ - Async Capable: false + - Actual Rows: 1 + - Actual Loops: 1 + - Triggers: -(1 row) - -END; --- costs on, timing off -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT * FROM explain_analyze_test', '{"timing": false, "costs": true}') as (a int); - a ---------------------------------------------------------------------- - 1 - 2 - 3 - 4 -(4 rows) - -SELECT explain_analyze_output ~ 'Seq Scan.*\(cost=0.00.*\) \(actual rows.*\)' FROM worker_last_saved_explain_analyze(); - ?column? ---------------------------------------------------------------------- - t -(1 row) - -END; --- costs off, timing on -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT * FROM explain_analyze_test', '{"timing": true, "costs": false}') as (a int); - a ---------------------------------------------------------------------- - 1 - 2 - 3 - 4 -(4 rows) - -SELECT explain_analyze_output ~ 'Seq Scan on explain_analyze_test \(actual time=.* rows=.* loops=1\)' FROM worker_last_saved_explain_analyze(); - ?column? ---------------------------------------------------------------------- - t -(1 row) - -END; --- summary on -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{"timing": false, "costs": false, "summary": true}') as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT explain_analyze_output ~ 'Planning Time:.*Execution Time:.*' FROM worker_last_saved_explain_analyze(); - ?column? ---------------------------------------------------------------------- - t -(1 row) - -END; --- buffers on -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT * FROM explain_analyze_test', '{"timing": false, "costs": false, "buffers": true}') as (a int); - a ---------------------------------------------------------------------- - 1 - 2 - 3 - 4 -(4 rows) - -SELECT explain_analyze_output ~ 'Buffers:' FROM worker_last_saved_explain_analyze(); - ?column? ---------------------------------------------------------------------- - t -(1 row) - -END; --- verbose on -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('SELECT * FROM explain_analyze_test', '{"timing": false, "costs": false, "verbose": true}') as (a int); - a ---------------------------------------------------------------------- - 1 - 2 - 3 - 4 -(4 rows) - -SELECT explain_analyze_output ~ 'Output: a, b' FROM worker_last_saved_explain_analyze(); - ?column? ---------------------------------------------------------------------- - t -(1 row) - -END; --- make sure deleted at transaction end -SELECT * FROM worker_save_query_explain_analyze('SELECT 1', '{}') as (a int); - a ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT count(*) FROM worker_last_saved_explain_analyze(); - count ---------------------------------------------------------------------- - 0 -(1 row) - --- should be deleted at the end of prepare commit -BEGIN; -SELECT * FROM worker_save_query_explain_analyze('UPDATE explain_analyze_test SET a=6 WHERE a=4', '{}') as (a int); - a ---------------------------------------------------------------------- -(0 rows) - -SELECT count(*) FROM worker_last_saved_explain_analyze(); - count ---------------------------------------------------------------------- - 1 -(1 row) - -PREPARE TRANSACTION 'citus_0_1496350_7_0'; -SELECT count(*) FROM worker_last_saved_explain_analyze(); - count ---------------------------------------------------------------------- - 0 -(1 row) - -COMMIT PREPARED 'citus_0_1496350_7_0'; --- verify execution time makes sense -BEGIN; -SELECT count(*) FROM worker_save_query_explain_analyze('SELECT pg_sleep(0.05)', :default_opts) as (a int); - count ---------------------------------------------------------------------- - 1 -(1 row) - -SELECT execution_duration BETWEEN 30 AND 200 FROM worker_last_saved_explain_analyze(); - ?column? ---------------------------------------------------------------------- - t -(1 row) - -END; --- --- verify we handle parametrized queries properly --- -CREATE TABLE t(a int); -INSERT INTO t VALUES (1), (2), (3); --- simple case -PREPARE save_explain AS -SELECT $1, * FROM worker_save_query_explain_analyze('SELECT $1::int', :default_opts) as (a int); -EXECUTE save_explain(1); - ?column? | a ---------------------------------------------------------------------- - 1 | 1 -(1 row) - -deallocate save_explain; --- Call a UDF first to make sure that we handle stacks of executorBoundParams properly. --- --- The prepared statement will first call f() which will force new executor run with new --- set of parameters. Then it will call worker_save_query_explain_analyze with a --- parametrized query. If we don't have the correct set of parameters here, it will fail. -CREATE FUNCTION f() RETURNS INT -AS $$ -PREPARE pp1 AS SELECT $1 WHERE $2 = $3; -EXECUTE pp1(4, 5, 5); -deallocate pp1; -SELECT 1$$ LANGUAGE sql volatile; -PREPARE save_explain AS - SELECT $1, CASE WHEN i < 2 THEN - f() = 1 - ELSE - EXISTS(SELECT * FROM worker_save_query_explain_analyze('SELECT $1::int', :default_opts) as (a int) - WHERE a = 1) - END - FROM generate_series(1, 4) i; -EXECUTE save_explain(1); - ?column? | exists ---------------------------------------------------------------------- - 1 | t - 1 | t - 1 | t - 1 | t -(4 rows) - -deallocate save_explain; -DROP FUNCTION f(); -DROP TABLE t; -SELECT * FROM explain_analyze_test ORDER BY a; - a | b ---------------------------------------------------------------------- - 1 | value 1 - 2 | value 2 - 3 | value 3 - 6 | value 4 -(4 rows) - -\a\t --- --- Test different cases of EXPLAIN ANALYZE --- -SET citus.shard_count TO 4; -SET client_min_messages TO WARNING; -SELECT create_distributed_table('explain_analyze_test', 'a'); - -\set default_analyze_flags '(ANALYZE on, COSTS off, TIMING off, SUMMARY off, BUFFERS off)' -\set default_explain_flags '(ANALYZE off, COSTS off, TIMING off, SUMMARY off)' --- router SELECT -EXPLAIN :default_analyze_flags SELECT * FROM explain_analyze_test WHERE a = 1; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 11 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 11 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=1 loops=1) - Filter: (a = 1) --- multi-shard SELECT -EXPLAIN :default_analyze_flags SELECT count(*) FROM explain_analyze_test; -Aggregate (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=4 loops=1) - Task Count: 4 - Tuple data received from nodes: 32 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate (actual rows=1 loops=1) - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=1 loops=1) --- empty router SELECT -EXPLAIN :default_analyze_flags SELECT * FROM explain_analyze_test WHERE a = 10000; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on explain_analyze_test_570012 explain_analyze_test (actual rows=0 loops=1) - Filter: (a = 10000) - Rows Removed by Filter: 1 --- empty multi-shard SELECT -EXPLAIN :default_analyze_flags SELECT * FROM explain_analyze_test WHERE b = 'does not exist'; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 4 - Tuple data received from nodes: 0 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=0 loops=1) - Filter: (b = 'does not exist'::text) - Rows Removed by Filter: 1 --- router DML -BEGIN; -EXPLAIN :default_analyze_flags DELETE FROM explain_analyze_test WHERE a = 1; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on explain_analyze_test_570009 explain_analyze_test (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=1 loops=1) - Filter: (a = 1) -EXPLAIN :default_analyze_flags UPDATE explain_analyze_test SET b = 'b' WHERE a = 2; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on explain_analyze_test_570012 explain_analyze_test (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570012 explain_analyze_test (actual rows=1 loops=1) - Filter: (a = 2) -SELECT * FROM explain_analyze_test ORDER BY a; -2|b -3|value 3 -6|value 4 -ROLLBACK; --- multi-shard DML -BEGIN; -EXPLAIN :default_analyze_flags UPDATE explain_analyze_test SET b = 'b' WHERE a IN (1, 2); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on explain_analyze_test_570009 explain_analyze_test (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=1 loops=1) - Filter: (a = ANY ('{1,2}'::integer[])) -EXPLAIN :default_analyze_flags DELETE FROM explain_analyze_test; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on explain_analyze_test_570009 explain_analyze_test (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=1 loops=1) -SELECT * FROM explain_analyze_test ORDER BY a; -ROLLBACK; --- router DML with RETURNING with empty result -EXPLAIN :default_analyze_flags UPDATE explain_analyze_test SET b = 'something' WHERE a = 10000 RETURNING *; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Update on explain_analyze_test_570012 explain_analyze_test (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570012 explain_analyze_test (actual rows=0 loops=1) - Filter: (a = 10000) - Rows Removed by Filter: 1 --- multi-shard DML with RETURNING with empty result -EXPLAIN :default_analyze_flags UPDATE explain_analyze_test SET b = 'something' WHERE b = 'does not exist' RETURNING *; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 4 - Tuple data received from nodes: 0 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Update on explain_analyze_test_570009 explain_analyze_test (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=0 loops=1) - Filter: (b = 'does not exist'::text) - Rows Removed by Filter: 1 --- single-row insert -BEGIN; -EXPLAIN :default_analyze_flags INSERT INTO explain_analyze_test VALUES (5, 'value 5'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on explain_analyze_test_570009 (actual rows=0 loops=1) - -> Result (actual rows=1 loops=1) -ROLLBACK; --- multi-row insert -BEGIN; -EXPLAIN :default_analyze_flags INSERT INTO explain_analyze_test VALUES (5, 'value 5'), (6, 'value 6'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on explain_analyze_test_570009 citus_table_alias (actual rows=0 loops=1) - -> Result (actual rows=1 loops=1) -ROLLBACK; --- distributed insert/select -BEGIN; -EXPLAIN :default_analyze_flags INSERT INTO explain_analyze_test SELECT * FROM explain_analyze_test; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on explain_analyze_test_570009 citus_table_alias (actual rows=0 loops=1) - -> Seq Scan on explain_analyze_test_570009 explain_analyze_test (actual rows=1 loops=1) - Filter: (a IS NOT NULL) -ROLLBACK; -DROP TABLE explain_analyze_test; --- test EXPLAIN ANALYZE works fine with primary keys -CREATE TABLE explain_pk(a int primary key, b int); -SELECT create_distributed_table('explain_pk', 'a'); - -BEGIN; -EXPLAIN :default_analyze_flags INSERT INTO explain_pk VALUES (1, 2), (2, 3); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on explain_pk_570013 citus_table_alias (actual rows=0 loops=1) - -> Result (actual rows=1 loops=1) -SELECT * FROM explain_pk ORDER BY 1; -1|2 -2|3 -ROLLBACK; --- test EXPLAIN ANALYZE with non-text output formats -BEGIN; -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, FORMAT YAML, BUFFERS OFF) INSERT INTO explain_pk VALUES (1, 2), (2, 3); -- Plan: - Node Type: "Custom Scan" - Custom Plan Provider: "Citus Adaptive" - Parallel Aware: false - Async Capable: false - Actual Rows: 0 - Actual Loops: 1 - Distributed Query: - Job: - Task Count: 2 - Tasks Shown: "One of 2" - Tasks: - - Node: "host=localhost port=xxxxx dbname=regression" - Remote Plan: - - Plan: - Node Type: "ModifyTable" - Operation: "Insert" - Parallel Aware: false - Async Capable: false - Relation Name: "explain_pk_570013" - Alias: "citus_table_alias" - Actual Rows: 0 - Actual Loops: 1 - Plans: - - Node Type: "Result" - Parent Relationship: "Outer" - Parallel Aware: false - Async Capable: false - Actual Rows: 1 - Actual Loops: 1 - Triggers: - - Triggers: -ROLLBACK; -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, FORMAT YAML, BUFFERS OFF) SELECT * FROM explain_pk; -- Plan: - Node Type: "Custom Scan" - Custom Plan Provider: "Citus Adaptive" - Parallel Aware: false - Async Capable: false - Actual Rows: 0 - Actual Loops: 1 - Distributed Query: - Job: - Task Count: 4 - Tuple data received from nodes: "0 bytes" - Tasks Shown: "One of 4" - Tasks: - - Tuple data received from node: "0 bytes" - Node: "host=localhost port=xxxxx dbname=regression" - Remote Plan: - - Plan: - Node Type: "Seq Scan" - Parallel Aware: false - Async Capable: false - Relation Name: "explain_pk_570013" - Alias: "explain_pk" - Actual Rows: 0 - Actual Loops: 1 - Triggers: - - Triggers: -BEGIN; -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, FORMAT XML, BUFFERS OFF) INSERT INTO explain_pk VALUES (1, 2), (2, 3); - - - - Custom Scan - Citus Adaptive - false - false - 0 - 1 - - - 2 - One of 2 - - - host=localhost port=xxxxx dbname=regression - - - - - ModifyTable - Insert - false - false - explain_pk_570013 - citus_table_alias - 0 - 1 - - - Result - Outer - false - false - 1 - 1 - - - - - - - - - - - - - - - - - -ROLLBACK; -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, FORMAT XML, BUFFERS OFF) SELECT * FROM explain_pk; - - - - Custom Scan - Citus Adaptive - false - false - 0 - 1 - - - 4 - 0 bytes - One of 4 - - - 0 bytes - host=localhost port=xxxxx dbname=regression - - - - - Seq Scan - false - false - explain_pk_570013 - explain_pk - 0 - 1 - - - - - - - - - - - - - - - -DROP TABLE explain_pk; --- test EXPLAIN ANALYZE with CTEs and subqueries -CREATE TABLE dist_table(a int, b int); -SELECT create_distributed_table('dist_table', 'a'); - -CREATE TABLE ref_table(a int); -SELECT create_reference_table('ref_table'); - -INSERT INTO dist_table SELECT i, i*i FROM generate_series(1, 10) i; -INSERT INTO ref_table SELECT i FROM generate_series(1, 10) i; -EXPLAIN :default_analyze_flags -WITH r AS ( - SELECT GREATEST(random(), 2) r, a FROM dist_table -) -SELECT count(distinct a) from r NATURAL JOIN ref_table; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 220 bytes - Result destination: Send to 3 nodes - -> Custom Scan (Citus Adaptive) (actual rows=10 loops=1) - Task Count: 4 - Tuple data received from nodes: 120 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 48 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_570017 dist_table (actual rows=4 loops=1) - Task Count: 1 - Tuple data received from nodes: 8 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate (actual rows=1 loops=1) - -> Hash Join (actual rows=10 loops=1) - Hash Cond: (ref_table.a = intermediate_result.a) - -> Seq Scan on ref_table_570021 ref_table (actual rows=10 loops=1) - -> Hash (actual rows=10 loops=1) - -> Function Scan on read_intermediate_result intermediate_result (actual rows=10 loops=1) -EXPLAIN :default_analyze_flags -SELECT count(distinct a) FROM (SELECT GREATEST(random(), 2) r, a FROM dist_table) t NATURAL JOIN ref_table; -Aggregate (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=4 loops=1) - Task Count: 4 - Tuple data received from nodes: 32 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate (actual rows=1 loops=1) - -> Merge Join (actual rows=4 loops=1) - Merge Cond: (t.a = ref_table.a) - -> Sort (actual rows=4 loops=1) - Sort Key: t.a - Sort Method: quicksort Memory: 25kB - -> Subquery Scan on t (actual rows=4 loops=1) - -> Seq Scan on dist_table_570017 dist_table (actual rows=4 loops=1) - -> Sort (actual rows=10 loops=1) - Sort Key: ref_table.a - Sort Method: quicksort Memory: 25kB - -> Seq Scan on ref_table_570021 ref_table (actual rows=10 loops=1) -SELECT public.explain_with_pg17_initplan_format($Q$ -EXPLAIN (ANALYZE on, COSTS off, TIMING off, SUMMARY off, BUFFERS OFF) -SELECT count(distinct a) FROM dist_table -WHERE EXISTS(SELECT random() < 2 FROM dist_table NATURAL JOIN ref_table); -$Q$); -Aggregate (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=4 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 70 bytes - Result destination: Send to 2 nodes - -> Custom Scan (Citus Adaptive) (actual rows=10 loops=1) - Task Count: 4 - Tuple data received from nodes: 10 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Merge Join (actual rows=4 loops=1) - Merge Cond: (dist_table.a = ref_table.a) - -> Sort (actual rows=4 loops=1) - Sort Key: dist_table.a - Sort Method: quicksort Memory: 25kB - -> Seq Scan on dist_table_570017 dist_table (actual rows=4 loops=1) - -> Sort (actual rows=10 loops=1) - Sort Key: ref_table.a - Sort Method: quicksort Memory: 25kB - -> Seq Scan on ref_table_570021 ref_table (actual rows=10 loops=1) - Task Count: 4 - Tuple data received from nodes: 32 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate (actual rows=1 loops=1) - InitPlan 1 - -> Function Scan on read_intermediate_result intermediate_result (actual rows=1 loops=1) - -> Result (actual rows=4 loops=1) - One-Time Filter: (InitPlan 1).col1 - -> Seq Scan on dist_table_570017 dist_table (actual rows=4 loops=1) -BEGIN; -EXPLAIN :default_analyze_flags -WITH r AS ( - INSERT INTO dist_table SELECT a, a * a FROM dist_table - RETURNING a -), s AS ( - SELECT random() < 2, a * a a2 FROM r -) -SELECT count(distinct a2) FROM s; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 100 bytes - Result destination: Write locally - -> Custom Scan (Citus Adaptive) (actual rows=10 loops=1) - Task Count: 4 - Tuple data received from nodes: 80 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 32 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Insert on dist_table_570017 citus_table_alias (actual rows=4 loops=1) - -> Seq Scan on dist_table_570017 dist_table (actual rows=4 loops=1) - Filter: (a IS NOT NULL) - -> Distributed Subplan XXX_2 - Intermediate Data Size: 150 bytes - Result destination: Write locally - -> Custom Scan (Citus Adaptive) (actual rows=10 loops=1) - Task Count: 1 - Tuple data received from nodes: 50 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 50 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Function Scan on read_intermediate_result intermediate_result (actual rows=10 loops=1) - Task Count: 1 - Tuple data received from nodes: 8 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Aggregate (actual rows=1 loops=1) - -> Function Scan on read_intermediate_result intermediate_result (actual rows=10 loops=1) -ROLLBACK; --- https://github.com/citusdata/citus/issues/4074 -prepare ref_select(int) AS select * from ref_table where 1 = $1; -explain :default_analyze_flags execute ref_select(1); -Custom Scan (Citus Adaptive) (actual rows=10 loops=1) - Task Count: 1 - Tuple data received from nodes: 40 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 40 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Result (actual rows=10 loops=1) - One-Time Filter: (1 = $1) - -> Seq Scan on ref_table_570021 ref_table (actual rows=10 loops=1) -deallocate ref_select; -DROP TABLE ref_table, dist_table; --- test EXPLAIN ANALYZE with different replication factors -SET citus.shard_count = 2; -SET citus.shard_replication_factor = 1; -CREATE TABLE dist_table_rep1(a int); -SELECT create_distributed_table('dist_table_rep1', 'a'); - -SET citus.shard_replication_factor = 2; -CREATE TABLE dist_table_rep2(a int); -SELECT create_distributed_table('dist_table_rep2', 'a'); - -EXPLAIN :default_analyze_flags INSERT INTO dist_table_rep1 VALUES(1), (2), (3), (4), (10), (100) RETURNING *; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Insert on dist_table_rep1_570022 citus_table_alias (actual rows=4 loops=1) - -> Values Scan on "*VALUES*" (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags SELECT * from dist_table_rep1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags INSERT INTO dist_table_rep2 VALUES(1), (2), (3), (4), (10), (100) RETURNING *; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 48 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 32 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Insert on dist_table_rep2_570024 citus_table_alias (actual rows=4 loops=1) - -> Values Scan on "*VALUES*" (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags SELECT * from dist_table_rep2; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep2_570024 dist_table_rep2 (actual rows=4 loops=1) -prepare p1 as SELECT * FROM dist_table_rep1; -EXPLAIN :default_analyze_flags EXECUTE p1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags EXECUTE p1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags EXECUTE p1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags EXECUTE p1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags EXECUTE p1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -EXPLAIN :default_analyze_flags EXECUTE p1; -Custom Scan (Citus Adaptive) (actual rows=6 loops=1) - Task Count: 2 - Tuple data received from nodes: 24 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=4 loops=1) -prepare p2 AS SELECT * FROM dist_table_rep1 WHERE a = $1; -EXPLAIN :default_analyze_flags EXECUTE p2(1); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(1); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(1); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(1); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(1); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(1); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(10); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 10) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p2(100); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570023 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 100) - Rows Removed by Filter: 1 -prepare p3 AS SELECT * FROM dist_table_rep1 WHERE a = 1; -EXPLAIN :default_analyze_flags EXECUTE p3; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p3; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p3; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p3; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p3; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -EXPLAIN :default_analyze_flags EXECUTE p3; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 4 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on dist_table_rep1_570022 dist_table_rep1 (actual rows=1 loops=1) - Filter: (a = 1) - Rows Removed by Filter: 3 -DROP TABLE dist_table_rep1, dist_table_rep2; --- https://github.com/citusdata/citus/issues/2009 -CREATE TABLE simple (id integer, name text); -SELECT create_distributed_table('simple', 'id'); - -PREPARE simple_router AS SELECT *, $1 FROM simple WHERE id = 1; -EXPLAIN :default_explain_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -EXPLAIN :default_analyze_flags EXECUTE simple_router(1); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (id = 1) -deallocate simple_router; --- prepared multi-row insert -PREPARE insert_query AS INSERT INTO simple VALUES ($1, 2), (2, $2); -EXPLAIN :default_explain_flags EXECUTE insert_query(3, 4); -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on simple_570026 citus_table_alias - -> Result -EXPLAIN :default_analyze_flags EXECUTE insert_query(3, 4); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on simple_570026 citus_table_alias (actual rows=0 loops=1) - -> Result (actual rows=1 loops=1) -deallocate insert_query; --- prepared updates -PREPARE update_query AS UPDATE simple SET name=$1 WHERE name=$2; -EXPLAIN :default_explain_flags EXECUTE update_query('x', 'y'); -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on simple_570026 simple - -> Seq Scan on simple_570026 simple - Filter: (name = 'y'::text) -EXPLAIN :default_analyze_flags EXECUTE update_query('x', 'y'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Update on simple_570026 simple (actual rows=0 loops=1) - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: (name = $2) - Rows Removed by Filter: 1 -deallocate update_query; --- prepared deletes -PREPARE delete_query AS DELETE FROM simple WHERE name=$1 OR name=$2; -EXPLAIN (COSTS OFF) EXECUTE delete_query('x', 'y'); -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on simple_570026 simple - -> Seq Scan on simple_570026 simple - Filter: ((name = 'x'::text) OR (name = 'y'::text)) -EXPLAIN :default_analyze_flags EXECUTE delete_query('x', 'y'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on simple_570026 simple (actual rows=0 loops=1) - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: ((name = $1) OR (name = $2)) - Rows Removed by Filter: 1 -deallocate delete_query; --- prepared distributed insert/select --- we don't support EXPLAIN for prepared insert/selects of other types. -PREPARE distributed_insert_select AS INSERT INTO simple SELECT * FROM simple WHERE name IN ($1, $2); -EXPLAIN :default_explain_flags EXECUTE distributed_insert_select('x', 'y'); -Custom Scan (Citus Adaptive) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on simple_570026 citus_table_alias - -> Seq Scan on simple_570026 simple - Filter: ((id IS NOT NULL) AND (name = ANY ('{x,y}'::text[]))) -EXPLAIN :default_analyze_flags EXECUTE distributed_insert_select('x', 'y'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on simple_570026 citus_table_alias (actual rows=0 loops=1) - -> Seq Scan on simple_570026 simple (actual rows=0 loops=1) - Filter: ((id IS NOT NULL) AND (name = ANY (ARRAY[$1, $2]))) - Rows Removed by Filter: 1 -deallocate distributed_insert_select; -DROP TABLE simple; --- prepared cte -BEGIN; -PREPARE cte_query AS -WITH keys AS ( - SELECT count(*) FROM - (SELECT DISTINCT l_orderkey, GREATEST(random(), 2) FROM lineitem_hash_part WHERE l_quantity > $1) t -), -series AS ( - SELECT s FROM generate_series(1, $2) s -), -delete_result AS ( - DELETE FROM lineitem_hash_part WHERE l_quantity < $3 RETURNING * -) -SELECT s FROM series; -EXPLAIN :default_explain_flags EXECUTE cte_query(2, 10, -1); -Custom Scan (Citus Adaptive) - -> Distributed Subplan XXX_1 - -> Custom Scan (Citus Adaptive) - Task Count: 4 - Tasks Shown: One of 4 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360041 lineitem_hash_part - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part - Filter: (l_quantity < '-1'::numeric) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Function Scan on generate_series s -EXPLAIN :default_analyze_flags EXECUTE cte_query(2, 10, -1); -Custom Scan (Citus Adaptive) (actual rows=10 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 0 bytes - Result destination: Send to 0 nodes - -> Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 4 - Tuple data received from nodes: 0 bytes - Tasks Shown: One of 4 - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Delete on lineitem_hash_part_360041 lineitem_hash_part (actual rows=0 loops=1) - -> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part (actual rows=0 loops=1) - Filter: (l_quantity < '-1'::numeric) - Rows Removed by Filter: 2885 - Task Count: 1 - Tuple data received from nodes: 40 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 40 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Function Scan on generate_series s (actual rows=10 loops=1) -ROLLBACK; --- https://github.com/citusdata/citus/issues/2009#issuecomment-653036502 -CREATE TABLE users_table_2 (user_id int primary key, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint); -SELECT create_reference_table('users_table_2'); - -PREPARE p4 (int, int) AS insert into users_table_2 ( value_1, user_id) select value_1, user_id + $2 FROM users_table_2 ON CONFLICT (user_id) DO UPDATE SET value_2 = EXCLUDED.value_1 + $1; -EXPLAIN :default_explain_flags execute p4(20,20); -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on users_table_2_570028 citus_table_alias - Conflict Resolution: UPDATE - Conflict Arbiter Indexes: users_table_2_pkey_570028 - -> Seq Scan on users_table_2_570028 users_table_2 -EXPLAIN :default_analyze_flags execute p4(20,20); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Insert on users_table_2_570028 citus_table_alias (actual rows=0 loops=1) - Conflict Resolution: UPDATE - Conflict Arbiter Indexes: users_table_2_pkey_570028 - Tuples Inserted: 0 - Conflicting Tuples: 0 - -> Seq Scan on users_table_2_570028 users_table_2 (actual rows=0 loops=1) --- simple test to confirm we can fetch long (>4KB) plans -EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF, BUFFERS OFF) SELECT * FROM users_table_2 WHERE value_1::text = '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000X'; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on users_table_2_570028 users_table_2 (actual rows=0 loops=1) - Filter: ((value_1)::text = '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000X'::text) -DROP TABLE users_table_2; --- sorted explain analyze output -CREATE TABLE explain_analyze_execution_time (a int); -INSERT INTO explain_analyze_execution_time VALUES (2); -SELECT create_distributed_table('explain_analyze_execution_time', 'a'); - --- show that we can sort the output wrt execution time --- we do the following hack to make the test outputs --- be consistent. First, ingest a single row then add --- pg_sleep() call on the query. Postgres will only --- sleep for the shard that has the single row, so that --- will definitely be slower -set citus.explain_analyze_sort_method to "taskId"; -EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE, BUFFERS OFF) select a, CASE WHEN pg_sleep(0.4) IS NULL THEN 'x' END from explain_analyze_execution_time; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 2 - Tuple data received from nodes: 4 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on explain_analyze_execution_time_570029 explain_analyze_execution_time (actual rows=0 loops=1) -set citus.explain_analyze_sort_method to "execution-time"; -EXPLAIN (COSTS FALSE, ANALYZE TRUE, TIMING FALSE, SUMMARY FALSE, BUFFERS OFF) select a, CASE WHEN pg_sleep(0.4) IS NULL THEN 'x' END from explain_analyze_execution_time; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 2 - Tuple data received from nodes: 4 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 4 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on explain_analyze_execution_time_570030 explain_analyze_execution_time (actual rows=1 loops=1) --- reset back -reset citus.explain_analyze_sort_method; -DROP TABLE explain_analyze_execution_time; -CREATE SCHEMA multi_explain; -SET search_path TO multi_explain; --- test EXPLAIN ANALYZE when original query returns no columns -CREATE TABLE reference_table(a int); -SELECT create_reference_table('reference_table'); - -INSERT INTO reference_table VALUES (1); -EXPLAIN :default_analyze_flags SELECT FROM reference_table; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on reference_table_570031 reference_table (actual rows=1 loops=1) -CREATE TABLE distributed_table_1(a int, b int); -SELECT create_distributed_table('distributed_table_1','a'); - -INSERT INTO distributed_table_1 values (1,1); -select public.explain_filter(' -EXPLAIN (ANALYZE on, COSTS off, TIMING off, SUMMARY off, BUFFERS off) SELECT row_number() OVER() AS r FROM distributed_table_1 -', true); -WindowAgg (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on distributed_table_1_570032 distributed_table_1 (actual rows=1 loops=1) -CREATE TABLE distributed_table_2(a int, b int); -SELECT create_distributed_table('distributed_table_2','a'); - -INSERT INTO distributed_table_2 VALUES (1,1); -select public.explain_filter(' -EXPLAIN (ANALYZE on, COSTS off, TIMING off, SUMMARY off, BUFFERS off) -WITH r AS (SELECT row_number() OVER () AS r FROM distributed_table_1) -SELECT * FROM distributed_table_2 -JOIN r ON (r = distributed_table_2.b) -LIMIT 3 -', true); -Limit (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 14 bytes - Result destination: Send to 2 nodes - -> WindowAgg (actual rows=1 loops=1) - -> Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on distributed_table_1_570032 distributed_table_1 (actual rows=1 loops=1) - Task Count: 2 - Tuple data received from nodes: 16 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Limit (actual rows=1 loops=1) - -> Nested Loop (actual rows=1 loops=1) - Join Filter: (distributed_table_2.b = intermediate_result.r) - -> Function Scan on read_intermediate_result intermediate_result (actual rows=1 loops=1) - -> Seq Scan on distributed_table_2_570034 distributed_table_2 (actual rows=1 loops=1) -EXPLAIN :default_analyze_flags SELECT FROM (SELECT * FROM reference_table) subquery; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on reference_table_570031 reference_table (actual rows=1 loops=1) -PREPARE dummy_prep_stmt(int) AS SELECT FROM distributed_table_1; -EXPLAIN :default_analyze_flags EXECUTE dummy_prep_stmt(50); -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 2 - Tasks Shown: One of 2 - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on distributed_table_1_570032 distributed_table_1 (actual rows=1 loops=1) -CREATE TYPE multi_explain.int_wrapper_type AS (int_field int); -CREATE TABLE tbl (a int, b multi_explain.int_wrapper_type); -SELECT create_distributed_table('tbl', 'a'); - -EXPLAIN :default_analyze_flags SELECT * FROM tbl; -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 2 - Tuple data received from nodes: 0 bytes - Tasks Shown: One of 2 - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on tbl_570036 tbl (actual rows=0 loops=1) -PREPARE q1(int_wrapper_type) AS WITH a AS (SELECT * FROM tbl WHERE b = $1 AND a = 1 OFFSET 0) SELECT * FROM a; -EXPLAIN (COSTS false) EXECUTE q1('(1)'); -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on tbl_570036 tbl - Filter: ((b = '(1)'::multi_explain.int_wrapper_type) AND (a = 1)) -EXPLAIN :default_analyze_flags EXECUTE q1('(1)'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Seq Scan on tbl_570036 tbl (actual rows=0 loops=1) - Filter: ((b = $1) AND (a = 1)) -PREPARE q2(int_wrapper_type) AS WITH a AS (UPDATE tbl SET b = $1 WHERE a = 1 RETURNING *) SELECT * FROM a; -EXPLAIN (COSTS false) EXECUTE q2('(1)'); -Custom Scan (Citus Adaptive) - Task Count: 1 - Tasks Shown: All - -> Task - Node: host=localhost port=xxxxx dbname=regression - -> CTE Scan on a - CTE a - -> Update on tbl_570036 tbl - -> Seq Scan on tbl_570036 tbl - Filter: (a = 1) -EXPLAIN :default_analyze_flags EXECUTE q2('(1)'); -Custom Scan (Citus Adaptive) (actual rows=0 loops=1) - Task Count: 1 - Tuple data received from nodes: 0 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 0 bytes - Node: host=localhost port=xxxxx dbname=regression - -> CTE Scan on a (actual rows=0 loops=1) - CTE a - -> Update on tbl_570036 tbl (actual rows=0 loops=1) - -> Seq Scan on tbl_570036 tbl (actual rows=0 loops=1) - Filter: (a = 1) --- EXPLAIN ANALYZE shouldn't execute SubPlans twice (bug #4212) -SET search_path TO multi_explain; -CREATE TABLE test_subplans (x int primary key, y int); -SELECT create_distributed_table('test_subplans','x'); - -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, BUFFERS OFF) -WITH a AS (INSERT INTO test_subplans VALUES (1,2) RETURNING *) -SELECT * FROM a; -Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - -> Distributed Subplan XXX_1 - Intermediate Data Size: 18 bytes - Result destination: Write locally - -> Custom Scan (Citus Adaptive) (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 16 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 16 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Insert on test_subplans_570038 (actual rows=1 loops=1) - -> Result (actual rows=1 loops=1) - Task Count: 1 - Tuple data received from nodes: 8 bytes - Tasks Shown: All - -> Task - Tuple data received from node: 8 bytes - Node: host=localhost port=xxxxx dbname=regression - -> Function Scan on read_intermediate_result intermediate_result (actual rows=1 loops=1) --- Only one row must exist -SELECT * FROM test_subplans; -1|2 --- Will fail with duplicate pk -EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, BUFFERS OFF) -WITH a AS (INSERT INTO test_subplans VALUES (1,2) RETURNING *) -SELECT * FROM a; -ERROR: duplicate key value violates unique constraint "test_subplans_pkey_570038" -DETAIL: Key (x)=(1) already exists. -CONTEXT: while executing command on localhost:xxxxx --- Test JSON format -TRUNCATE test_subplans; -EXPLAIN (FORMAT JSON, COSTS off, ANALYZE on, TIMING off, SUMMARY off, BUFFERS OFF) -WITH a AS (INSERT INTO test_subplans VALUES (1,2) RETURNING *) -SELECT * FROM a; -[ - { - "Plan": { - "Node Type": "Custom Scan", - "Custom Plan Provider": "Citus Adaptive", - "Parallel Aware": false, - "Async Capable": false, - "Actual Rows": 1, - "Actual Loops": 1, - "Distributed Query": { - "Subplans": [ - { - "Intermediate Data Size": "18 bytes", - "Result destination": "Write locally", - "PlannedStmt": [ - { - "Plan": { - "Node Type": "Custom Scan", - "Custom Plan Provider": "Citus Adaptive", - "Parallel Aware": false, - "Async Capable": false, - "Actual Rows": 1, - "Actual Loops": 1, - "Distributed Query": { - "Job": { - "Task Count": 1, - "Tuple data received from nodes": "16 bytes", - "Tasks Shown": "All", - "Tasks": [ - { - "Tuple data received from node": "16 bytes", - "Node": "host=localhost port=xxxxx dbname=regression", - "Remote Plan": [ - [ - { - "Plan": { - "Node Type": "ModifyTable", - "Operation": "Insert", - "Parallel Aware": false, - "Async Capable": false, - "Relation Name": "test_subplans_570038", - "Alias": "test_subplans_570038", - "Actual Rows": 1, - "Actual Loops": 1, - "Plans": [ - { - "Node Type": "Result", - "Parent Relationship": "Outer", - "Parallel Aware": false, - "Async Capable": false, - "Actual Rows": 1, - "Actual Loops": 1 - } - ] - }, - "Triggers": [ - ] - } - ] - - ] - } - ] - } - } - }, - "Triggers": [ - ] - } - ] - } - ], - "Job": { - "Task Count": 1, - "Tuple data received from nodes": "8 bytes", - "Tasks Shown": "All", - "Tasks": [ - { - "Tuple data received from node": "8 bytes", - "Node": "host=localhost port=xxxxx dbname=regression", - "Remote Plan": [ - [ - { - "Plan": { - "Node Type": "Function Scan", - "Parallel Aware": false, - "Async Capable": false, - "Function Name": "read_intermediate_result", - "Alias": "intermediate_result", - "Actual Rows": 1, - "Actual Loops": 1 - }, - "Triggers": [ - ] - } - ] - - ] - } - ] - } - } - }, - "Triggers": [ - ] - } -] --- Only one row must exist -SELECT * FROM test_subplans; -1|2 --- check when auto explain + analyze is enabled, we do not allow local execution. -CREATE SCHEMA test_auto_explain; -SET search_path TO 'test_auto_explain'; -CREATE TABLE test_ref_table (key int PRIMARY KEY); -SELECT create_reference_table('test_ref_table'); - -LOAD 'auto_explain'; -SET auto_explain.log_min_duration = 0; -set auto_explain.log_analyze to true; --- the following should not be locally executed since explain analyze is on -select * from test_ref_table; -DROP SCHEMA test_auto_explain CASCADE; -SET client_min_messages TO ERROR; -DROP SCHEMA multi_explain CASCADE; diff --git a/src/test/regress/expected/multi_mx_create_table.out b/src/test/regress/expected/multi_mx_create_table.out index f5882e5e7..bf09ae02c 100644 --- a/src/test/regress/expected/multi_mx_create_table.out +++ b/src/test/regress/expected/multi_mx_create_table.out @@ -58,8 +58,6 @@ CREATE OPERATOR citus_mx_test_schema.=== ( ); SET search_path TO public; SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset SELECT substring(:'server_version', '\d+')::int >= 17 AS server_version_ge_17 \gset \if :server_version_ge_17 @@ -67,12 +65,10 @@ SELECT substring(:'server_version', '\d+')::int >= 17 AS server_version_ge_17 -- Relevant PG commit: -- https://github.com/postgres/postgres/commit/f696c0cd5f299f1b51e214efc55a22a782cc175d SELECT quote_ident((SELECT CASE WHEN datlocprovider='i' THEN datlocale ELSE datcollate END FROM pg_database WHERE datname = current_database())) as current_locale \gset -\elif :server_version_ge_16 +\else -- In PG16, read-only server settings lc_collate and lc_ctype are removed -- Relevant PG commit: b0f6c437160db640d4ea3e49398ebc3ba39d1982 SELECT quote_ident((SELECT CASE WHEN datlocprovider='i' THEN daticulocale ELSE datcollate END FROM pg_database WHERE datname = current_database())) as current_locale \gset -\else -SELECT quote_ident(current_setting('lc_collate')) as current_locale \gset \endif CREATE COLLATION citus_mx_test_schema.english (LOCALE=:current_locale); CREATE TYPE citus_mx_test_schema.new_composite_type as (key1 text, key2 text); diff --git a/src/test/regress/sql/alter_table_set_access_method.sql b/src/test/regress/sql/alter_table_set_access_method.sql index b9e214dab..0109f4d24 100644 --- a/src/test/regress/sql/alter_table_set_access_method.sql +++ b/src/test/regress/sql/alter_table_set_access_method.sql @@ -266,16 +266,8 @@ create table events (event_id bigserial, event_time timestamptz default now(), p create index on events (event_id); insert into events (payload) select 'hello-'||s from generate_series(1,10) s; -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset - BEGIN; - \if :server_version_ge_16 SET LOCAL debug_parallel_query = regress; - \else - SET LOCAL force_parallel_mode = regress; - \endif SET LOCAL min_parallel_table_scan_size = 1; SET LOCAL parallel_tuple_cost = 0; SET LOCAL max_parallel_workers = 4; diff --git a/src/test/regress/sql/columnar_fallback_scan.sql b/src/test/regress/sql/columnar_fallback_scan.sql index 93a701062..f79af130e 100644 --- a/src/test/regress/sql/columnar_fallback_scan.sql +++ b/src/test/regress/sql/columnar_fallback_scan.sql @@ -20,16 +20,7 @@ select count(*), min(i), max(i), avg(i) from fallback_scan; -- Negative test: try to force a parallel plan with at least two -- workers, but columnar should reject it and use a non-parallel scan. -- - -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset - -\if :server_version_ge_16 set debug_parallel_query = regress; -\else -set force_parallel_mode = regress; -\endif set min_parallel_table_scan_size = 1; set parallel_tuple_cost = 0; set max_parallel_workers = 4; @@ -37,11 +28,7 @@ set max_parallel_workers_per_gather = 4; explain (costs off) select count(*), min(i), max(i), avg(i) from fallback_scan; select count(*), min(i), max(i), avg(i) from fallback_scan; -\if :server_version_ge_16 set debug_parallel_query = default; -\else -set force_parallel_mode = default; -\endif set min_parallel_table_scan_size to default; set parallel_tuple_cost to default; set max_parallel_workers to default; diff --git a/src/test/regress/sql/columnar_indexes.sql b/src/test/regress/sql/columnar_indexes.sql index 6e54b8591..dd9b70d1d 100644 --- a/src/test/regress/sql/columnar_indexes.sql +++ b/src/test/regress/sql/columnar_indexes.sql @@ -414,10 +414,6 @@ BEGIN; -- this wouldn't flush any data insert into events (payload) select 'hello-'||s from generate_series(1, 10) s; - SHOW server_version \gset - SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 - \gset - -- Since table is large enough, normally postgres would prefer using -- parallel workers when building the index. -- @@ -430,11 +426,7 @@ BEGIN; -- following commnad to fail since we prevent using parallel workers for -- columnar tables. - \if :server_version_ge_16 SET LOCAL debug_parallel_query = regress; - \else - SET LOCAL force_parallel_mode = regress; - \endif SET LOCAL min_parallel_table_scan_size = 1; SET LOCAL parallel_tuple_cost = 0; SET LOCAL max_parallel_workers = 4; diff --git a/src/test/regress/sql/columnar_partitioning.sql b/src/test/regress/sql/columnar_partitioning.sql index 8e91b8919..f8a49f438 100644 --- a/src/test/regress/sql/columnar_partitioning.sql +++ b/src/test/regress/sql/columnar_partitioning.sql @@ -24,16 +24,9 @@ INSERT INTO parent SELECT '2020-03-15', 30, 300, 'three thousand' INSERT INTO parent SELECT '2020-04-15', 30, 300, 'three thousand' FROM generate_series(1,100000); -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset - -- run parallel plans -\if :server_version_ge_16 SET debug_parallel_query = regress; -\else -SET force_parallel_mode = regress; -\endif + SET min_parallel_table_scan_size = 1; SET parallel_tuple_cost = 0; SET max_parallel_workers = 4; @@ -57,11 +50,8 @@ EXPLAIN (costs off) SELECT count(*), sum(i), min(i), max(i) FROM parent; SELECT count(*), sum(i), min(i), max(i) FROM parent; SET columnar.enable_custom_scan TO DEFAULT; -\if :server_version_ge_16 SET debug_parallel_query TO DEFAULT; -\else -SET force_parallel_mode TO DEFAULT; -\endif + SET min_parallel_table_scan_size TO DEFAULT; SET parallel_tuple_cost TO DEFAULT; SET max_parallel_workers TO DEFAULT; diff --git a/src/test/regress/sql/create_drop_database_propagation_pg16.sql b/src/test/regress/sql/create_drop_database_propagation_pg16.sql index cec553813..bfe0862b8 100644 --- a/src/test/regress/sql/create_drop_database_propagation_pg16.sql +++ b/src/test/regress/sql/create_drop_database_propagation_pg16.sql @@ -1,14 +1,3 @@ --- --- PG16 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset -\if :server_version_ge_16 -\else -\q -\endif - -- create/drop database for pg >= 16 set citus.enable_create_database_propagation=on; diff --git a/src/test/regress/sql/metadata_sync_helpers.sql b/src/test/regress/sql/metadata_sync_helpers.sql index 9e67fa337..6482cdfb3 100644 --- a/src/test/regress/sql/metadata_sync_helpers.sql +++ b/src/test/regress/sql/metadata_sync_helpers.sql @@ -798,21 +798,14 @@ BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED; -- with an ugly trick, update the vartype of table from int to bigint -- so that making two tables colocated fails - -- include varnullingrels for PG16+ - SHOW server_version \gset - SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 - \gset -- include varreturningtype for PG18+ SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18 \gset \if :server_version_ge_18 UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 1 :varreturningtype 0 :varnoold 1 :varoattno 1 :location -1}' WHERE logicalrelid = 'test_2'::regclass; - \elif :server_version_ge_16 - UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 1 :varnoold 1 :varoattno 1 :location -1}' - WHERE logicalrelid = 'test_2'::regclass; \else - UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varlevelsup 1 :varnoold 1 :varoattno 1 :location -1}' + UPDATE pg_dist_partition SET partkey = '{VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 1 :varnoold 1 :varoattno 1 :location -1}' WHERE logicalrelid = 'test_2'::regclass; \endif diff --git a/src/test/regress/sql/multi_complex_count_distinct.sql b/src/test/regress/sql/multi_complex_count_distinct.sql index 0e06fc0c8..d2024607a 100644 --- a/src/test/regress/sql/multi_complex_count_distinct.sql +++ b/src/test/regress/sql/multi_complex_count_distinct.sql @@ -1,14 +1,6 @@ -- -- COMPLEX_COUNT_DISTINCT -- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- -SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; - SET citus.next_shard_id TO 240000; SET citus.shard_count TO 8; SET citus.shard_replication_factor TO 1; diff --git a/src/test/regress/sql/multi_explain.sql b/src/test/regress/sql/multi_explain.sql index 1c4841c6f..b22c5c200 100644 --- a/src/test/regress/sql/multi_explain.sql +++ b/src/test/regress/sql/multi_explain.sql @@ -1,17 +1,11 @@ -- -- MULTI_EXPLAIN -- --- This test file has an alternative output because of the following in PG16: --- https://github.com/postgres/postgres/commit/1349d2790bf48a4de072931c722f39337e72055e --- https://github.com/postgres/postgres/commit/f4c7c410ee4a7baa06f51ebb8d5333c169691dd3 --- The alternative output can be deleted when we drop support for PG15 --- -- This test file has an alternative output because of the following in PG18: -- https://github.com/postgres/postgres/commit/161320b4b960ee4fe918959be6529ae9b106ea5a -- The alternative output can be deleted when we drop support for PG17 -- SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16; SELECT substring(:'server_version', '\d+')::int >= 18 AS server_version_ge_18; SET citus.next_shard_id TO 570000; diff --git a/src/test/regress/sql/multi_mx_create_table.sql b/src/test/regress/sql/multi_mx_create_table.sql index 1a267b301..a6ad30997 100644 --- a/src/test/regress/sql/multi_mx_create_table.sql +++ b/src/test/regress/sql/multi_mx_create_table.sql @@ -59,8 +59,6 @@ CREATE OPERATOR citus_mx_test_schema.=== ( SET search_path TO public; SHOW server_version \gset -SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16 -\gset SELECT substring(:'server_version', '\d+')::int >= 17 AS server_version_ge_17 \gset @@ -69,12 +67,10 @@ SELECT substring(:'server_version', '\d+')::int >= 17 AS server_version_ge_17 -- Relevant PG commit: -- https://github.com/postgres/postgres/commit/f696c0cd5f299f1b51e214efc55a22a782cc175d SELECT quote_ident((SELECT CASE WHEN datlocprovider='i' THEN datlocale ELSE datcollate END FROM pg_database WHERE datname = current_database())) as current_locale \gset -\elif :server_version_ge_16 +\else -- In PG16, read-only server settings lc_collate and lc_ctype are removed -- Relevant PG commit: b0f6c437160db640d4ea3e49398ebc3ba39d1982 SELECT quote_ident((SELECT CASE WHEN datlocprovider='i' THEN daticulocale ELSE datcollate END FROM pg_database WHERE datname = current_database())) as current_locale \gset -\else -SELECT quote_ident(current_setting('lc_collate')) as current_locale \gset \endif CREATE COLLATION citus_mx_test_schema.english (LOCALE=:current_locale);