CREATE SCHEMA query_single_shard_table; SET search_path TO query_single_shard_table; SET citus.next_shard_id TO 1620000; SET citus.shard_count TO 32; SET citus.shard_replication_factor TO 1; SET client_min_messages TO NOTICE; CREATE TABLE nullkey_c1_t1(a int, b int); CREATE TABLE nullkey_c1_t2(a int, b int); SELECT create_distributed_table('nullkey_c1_t1', null, colocate_with=>'none'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT create_distributed_table('nullkey_c1_t2', null, colocate_with=>'nullkey_c1_t1'); create_distributed_table --------------------------------------------------------------------- (1 row) INSERT INTO nullkey_c1_t1 SELECT i, i FROM generate_series(1, 8) i; INSERT INTO nullkey_c1_t2 SELECT i, i FROM generate_series(2, 7) i; CREATE TABLE nullkey_c2_t1(a int, b int); CREATE TABLE nullkey_c2_t2(a int, b int); SELECT create_distributed_table('nullkey_c2_t1', null, colocate_with=>'none'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT create_distributed_table('nullkey_c2_t2', null, colocate_with=>'nullkey_c2_t1', distribution_type=>null); create_distributed_table --------------------------------------------------------------------- (1 row) INSERT INTO nullkey_c2_t1 SELECT i, i FROM generate_series(2, 7) i; INSERT INTO nullkey_c2_t2 SELECT i, i FROM generate_series(1, 8) i; CREATE TABLE nullkey_c3_t1(a int, b int); SELECT create_distributed_table('nullkey_c3_t1', null, colocate_with=>'none'); create_distributed_table --------------------------------------------------------------------- (1 row) INSERT INTO nullkey_c3_t1 SELECT i, i FROM generate_series(1, 8) i; RESET citus.shard_replication_factor; CREATE TABLE reference_table(a int, b int); SELECT create_reference_table('reference_table'); create_reference_table --------------------------------------------------------------------- (1 row) INSERT INTO reference_table SELECT i, i FROM generate_series(0, 5) i; CREATE TABLE distributed_table(a int, b int); SELECT create_distributed_table('distributed_table', 'a'); create_distributed_table --------------------------------------------------------------------- (1 row) INSERT INTO distributed_table SELECT i, i FROM generate_series(3, 8) i; CREATE TABLE citus_local_table(a int, b int); SELECT citus_add_local_table_to_metadata('citus_local_table'); citus_add_local_table_to_metadata --------------------------------------------------------------------- (1 row) INSERT INTO citus_local_table SELECT i, i FROM generate_series(0, 10) i; CREATE TABLE postgres_local_table(a int, b int); INSERT INTO postgres_local_table SELECT i, i FROM generate_series(5, 10) i; CREATE TABLE articles_hash ( id bigint NOT NULL, author_id bigint NOT NULL, title varchar(20) NOT NULL, word_count integer ); INSERT INTO articles_hash VALUES ( 4, 4, 'altdorfer', 14551),( 5, 5, 'aruru', 11389), (13, 3, 'aseyev', 2255),(15, 5, 'adversa', 3164), (18, 8, 'assembly', 911),(19, 9, 'aubergiste', 4981), (28, 8, 'aerophyte', 5454),(29, 9, 'amateur', 9524), (42, 2, 'ausable', 15885),(43, 3, 'affixal', 12723), (49, 9, 'anyone', 2681),(50, 10, 'anjanette', 19519); SET citus.shard_replication_factor TO 1; SELECT create_distributed_table('articles_hash', null, colocate_with=>'none'); NOTICE: Copying data from local table... NOTICE: copying the data has completed DETAIL: The local data in the table is no longer visible, but is still on disk. HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$query_single_shard_table.articles_hash$$) create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE raw_events_first (user_id int, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint, UNIQUE(user_id, value_1)); SELECT create_distributed_table('raw_events_first', null, colocate_with=>'none', distribution_type=>null); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE raw_events_second (user_id int, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint, UNIQUE(user_id, value_1)); SELECT create_distributed_table('raw_events_second', null, colocate_with=>'raw_events_first', distribution_type=>null); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE agg_events (user_id int, value_1_agg int, value_2_agg int, value_3_agg float, value_4_agg bigint, agg_time timestamp, UNIQUE(user_id, value_1_agg)); SELECT create_distributed_table('agg_events', null, colocate_with=>'raw_events_first', distribution_type=>null); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE users_ref_table (user_id int); SELECT create_reference_table('users_ref_table'); create_reference_table --------------------------------------------------------------------- (1 row) INSERT INTO raw_events_first VALUES (1, '1970-01-01', 10, 100, 1000.1, 10000), (3, '1971-01-01', 30, 300, 3000.1, 30000), (5, '1972-01-01', 50, 500, 5000.1, 50000), (2, '1973-01-01', 20, 200, 2000.1, 20000), (4, '1974-01-01', 40, 400, 4000.1, 40000), (6, '1975-01-01', 60, 600, 6000.1, 60000); CREATE TABLE modify_fast_path(key int, value_1 int, value_2 text); SELECT create_distributed_table('modify_fast_path', null); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE modify_fast_path_reference(key int, value_1 int, value_2 text); SELECT create_reference_table('modify_fast_path_reference'); create_reference_table --------------------------------------------------------------------- (1 row) CREATE TABLE bigserial_test (x int, y int, z bigserial); SELECT create_distributed_table('bigserial_test', null); create_distributed_table --------------------------------------------------------------------- (1 row) RESET citus.shard_replication_factor; CREATE TABLE append_table (text_col text, a int); SELECT create_distributed_table('append_table', 'a', 'append'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT master_create_empty_shard('append_table') AS shardid1 \gset SELECT master_create_empty_shard('append_table') AS shardid2 \gset SELECT master_create_empty_shard('append_table') AS shardid3 \gset COPY append_table (text_col, a) FROM STDIN WITH (format 'csv', append_to_shard :shardid1); COPY append_table (text_col, a) FROM STDIN WITH (format 'csv', append_to_shard :shardid2); CREATE TABLE range_table(a int, b int); SELECT create_distributed_table('range_table', 'a', 'range'); create_distributed_table --------------------------------------------------------------------- (1 row) CALL public.create_range_partitioned_shards('range_table', '{"0","25"}','{"24","49"}'); INSERT INTO range_table VALUES (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 50); \set users_table_data_file :abs_srcdir '/data/users_table.data' \set events_table_data_file :abs_srcdir '/data/events_table.data' SET citus.shard_replication_factor TO 1; CREATE TABLE users_table (user_id int, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint); SELECT create_distributed_table('users_table', null, colocate_with=>'none'); create_distributed_table --------------------------------------------------------------------- (1 row) \set client_side_copy_command '\\copy users_table FROM ' :'users_table_data_file' ' WITH CSV;' :client_side_copy_command CREATE TABLE non_colocated_users_table (id int, value int); SELECT create_distributed_table('non_colocated_users_table', null, colocate_with => 'none'); create_distributed_table --------------------------------------------------------------------- (1 row) INSERT INTO non_colocated_users_table (id, value) VALUES(1, 2),(2, 3),(3,4); CREATE TABLE colocated_events_table (user_id int, time timestamp, event_type int, value_2 int, value_3 float, value_4 bigint); SELECT create_distributed_table('colocated_events_table', null, colocate_with=>'users_table'); create_distributed_table --------------------------------------------------------------------- (1 row) \set client_side_copy_command '\\copy colocated_events_table FROM ' :'events_table_data_file' ' WITH CSV;' :client_side_copy_command CREATE TABLE non_colocated_events_table (user_id int, time timestamp, event_type int, value_2 int, value_3 float, value_4 bigint); SELECT create_distributed_table('non_colocated_events_table', null, colocate_with=>'non_colocated_users_table'); create_distributed_table --------------------------------------------------------------------- (1 row) \set client_side_copy_command '\\copy non_colocated_events_table FROM ' :'events_table_data_file' ' WITH CSV;' :client_side_copy_command CREATE TABLE users_table_local AS SELECT * FROM users_table; CREATE TABLE colocated_users_table (id int, value int); SELECT create_distributed_table('colocated_users_table', null, colocate_with => 'users_table'); create_distributed_table --------------------------------------------------------------------- (1 row) INSERT INTO colocated_users_table (id, value) VALUES(1, 2),(2, 3),(3,4); CREATE TABLE users_reference_table (like users_table including all); SELECT create_reference_table('users_reference_table'); create_reference_table --------------------------------------------------------------------- (1 row) CREATE TABLE events_reference_table (like colocated_events_table including all); SELECT create_reference_table('events_reference_table'); create_reference_table --------------------------------------------------------------------- (1 row) CREATE FUNCTION func() RETURNS TABLE (id int, value int) AS $$ SELECT 1, 2 $$ LANGUAGE SQL; SET client_min_messages to DEBUG2; -- simple insert INSERT INTO nullkey_c1_t1 VALUES (1,2), (2,2), (3,4); DEBUG: Creating router plan INSERT INTO nullkey_c1_t2 VALUES (1,3), (3,4), (5,1), (6,2); DEBUG: Creating router plan INSERT INTO nullkey_c2_t1 VALUES (1,0), (2,5), (4,3), (5,2); DEBUG: Creating router plan INSERT INTO nullkey_c2_t2 VALUES (2,4), (3,2), (5,2), (7,4); DEBUG: Creating router plan -- simple select SELECT * FROM nullkey_c1_t1 ORDER BY 1,2; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan a | b --------------------------------------------------------------------- 1 | 1 1 | 2 2 | 2 2 | 2 3 | 3 3 | 4 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 (11 rows) -- for update / share SELECT * FROM modify_fast_path WHERE key = 1 FOR UPDATE; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) SELECT * FROM modify_fast_path WHERE key = 1 FOR SHARE; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) SELECT * FROM modify_fast_path FOR UPDATE; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) SELECT * FROM modify_fast_path FOR SHARE; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) -- cartesian product with different table types -- with other table types SELECT COUNT(*) FROM distributed_table d1, nullkey_c1_t1; DEBUG: Router planner cannot handle multi-shard select queries ERROR: cannot perform distributed planning on this query DETAIL: Cartesian products are currently unsupported SELECT COUNT(*) FROM reference_table d1, nullkey_c1_t1; DEBUG: Creating router plan count --------------------------------------------------------------------- 66 (1 row) SELECT COUNT(*) FROM citus_local_table d1, nullkey_c1_t1; DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" "d1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT NULL::integer AS "dummy-1" FROM query_single_shard_table.citus_local_table d1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT NULL::integer AS a, NULL::integer AS b FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) d1_1) d1, query_single_shard_table.nullkey_c1_t1 DEBUG: Creating router plan count --------------------------------------------------------------------- 121 (1 row) SELECT COUNT(*) FROM postgres_local_table d1, nullkey_c1_t1; DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" "d1" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT NULL::integer AS "dummy-1" FROM query_single_shard_table.postgres_local_table d1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT NULL::integer AS a, NULL::integer AS b FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) d1_1) d1, query_single_shard_table.nullkey_c1_t1 DEBUG: Creating router plan count --------------------------------------------------------------------- 66 (1 row) -- with a colocated single-shard table SELECT COUNT(*) FROM nullkey_c1_t1 d1, nullkey_c1_t2; DEBUG: Creating router plan count --------------------------------------------------------------------- 110 (1 row) -- with a non-colocated single-shard table SELECT COUNT(*) FROM nullkey_c1_t1 d1, nullkey_c2_t1; DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot perform distributed planning on this query DETAIL: Cartesian products are currently unsupported -- First, show that nullkey_c1_t1 and nullkey_c3_t1 are not colocated. SELECT (SELECT colocationid FROM pg_dist_partition WHERE logicalrelid = 'query_single_shard_table.nullkey_c1_t1'::regclass) != (SELECT colocationid FROM pg_dist_partition WHERE logicalrelid = 'query_single_shard_table.nullkey_c3_t1'::regclass); ?column? --------------------------------------------------------------------- t (1 row) -- Now verify that we can join them via router planner because it doesn't care -- about whether two tables are colocated or not but physical location of shards -- when citus.enable_non_colocated_router_query_pushdown is set to on. SET citus.enable_non_colocated_router_query_pushdown TO ON; SELECT COUNT(*) FROM nullkey_c1_t1 JOIN nullkey_c3_t1 USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SET citus.enable_non_colocated_router_query_pushdown TO OFF; SET citus.enable_repartition_joins TO ON; SET client_min_messages TO DEBUG1; SELECT COUNT(*) FROM nullkey_c1_t1 JOIN nullkey_c3_t1 USING(a); count --------------------------------------------------------------------- 11 (1 row) SET client_min_messages TO DEBUG2; SET citus.enable_repartition_joins TO OFF; RESET citus.enable_non_colocated_router_query_pushdown; -- colocated join between single-shard tables SELECT COUNT(*) FROM nullkey_c1_t1 JOIN nullkey_c1_t2 USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 14 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 LEFT JOIN nullkey_c1_t2 USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 15 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 FULL JOIN nullkey_c1_t2 USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 15 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c1_t2 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT * FROM nullkey_c1_t2 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 4 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE EXISTS ( SELECT * FROM nullkey_c1_t2 t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 9 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b IN ( SELECT b+1 FROM nullkey_c1_t2 t2 WHERE t2.b = t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 2 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b NOT IN ( SELECT a FROM nullkey_c1_t2 t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 7 (1 row) -- non-colocated inner joins between single-shard tables SET client_min_messages to DEBUG1; SET citus.enable_repartition_joins TO ON; SELECT * FROM nullkey_c1_t1 JOIN nullkey_c2_t1 USING(a) ORDER BY 1,2,3; a | b | b --------------------------------------------------------------------- 1 | 1 | 0 1 | 2 | 0 2 | 2 | 2 2 | 2 | 2 2 | 2 | 5 2 | 2 | 5 3 | 3 | 3 3 | 4 | 3 4 | 4 | 3 4 | 4 | 4 5 | 5 | 2 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 (14 rows) SELECT * FROM (SELECT * FROM nullkey_c1_t1) nullkey_c1_t1 JOIN nullkey_c2_t1 USING(a) ORDER BY 1,2,3; a | b | b --------------------------------------------------------------------- 1 | 1 | 0 1 | 2 | 0 2 | 2 | 2 2 | 2 | 2 2 | 2 | 5 2 | 2 | 5 3 | 3 | 3 3 | 4 | 3 4 | 4 | 3 4 | 4 | 4 5 | 5 | 2 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 (14 rows) SELECT * FROM nullkey_c2_t1 JOIN (SELECT * FROM nullkey_c1_t1) nullkey_c1_t1 USING(a) ORDER BY 1,2,3; a | b | b --------------------------------------------------------------------- 1 | 0 | 1 1 | 0 | 2 2 | 2 | 2 2 | 2 | 2 2 | 5 | 2 2 | 5 | 2 3 | 3 | 3 3 | 3 | 4 4 | 3 | 4 4 | 4 | 4 5 | 2 | 5 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 (14 rows) SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT * FROM nullkey_c2_t2 t2 WHERE t2.b > t1.a ) q USING(a); count --------------------------------------------------------------------- 2 (1 row) SET citus.enable_repartition_joins TO OFF; SET client_min_messages to DEBUG2; -- non-colocated outer joins between single-shard tables SELECT * FROM nullkey_c1_t1 LEFT JOIN nullkey_c2_t2 USING(a) ORDER BY 1,2,3 LIMIT 4; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 4 ERROR: cannot push down this subquery DETAIL: nullkey_c1_t1 and nullkey_c2_t2 are not colocated SELECT * FROM nullkey_c1_t1 FULL JOIN nullkey_c2_t2 USING(a) ORDER BY 1,2,3 LIMIT 4; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 4 ERROR: cannot push down this subquery DETAIL: nullkey_c1_t1 and nullkey_c2_t2 are not colocated SELECT * FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c2_t2 t2 WHERE t2.b > t1.a ) q USING(a) ORDER BY 1,2,3 OFFSET 3 LIMIT 4; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 7 ERROR: cannot push down this subquery DETAIL: nullkey_c1_t1 and nullkey_c2_t2 are not colocated SELECT COUNT(*) FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c2_t2 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot push down this subquery DETAIL: nullkey_c1_t1 and nullkey_c2_t2 are not colocated SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE EXISTS ( SELECT * FROM nullkey_c2_t2 t2 WHERE t2.b > t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot push down this subquery DETAIL: nullkey_c2_t2 and nullkey_c1_t1 are not colocated SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b IN ( SELECT b+1 FROM nullkey_c2_t2 t2 WHERE t2.b = t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot push down this subquery DETAIL: nullkey_c2_t2 and nullkey_c1_t1 are not colocated SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b NOT IN ( SELECT a FROM nullkey_c2_t2 t2 WHERE t2.b > t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot push down this subquery DETAIL: nullkey_c2_t2 and nullkey_c1_t1 are not colocated -- join with a reference table SELECT COUNT(*) FROM nullkey_c1_t1, reference_table WHERE nullkey_c1_t1.a = reference_table.a; DEBUG: Creating router plan count --------------------------------------------------------------------- 8 (1 row) WITH cte_1 AS (SELECT * FROM nullkey_c1_t1, reference_table WHERE nullkey_c1_t1.a = reference_table.a ORDER BY 1,2,3,4 FOR UPDATE) SELECT COUNT(*) FROM cte_1; DEBUG: Creating router plan count --------------------------------------------------------------------- 8 (1 row) -- join with postgres / citus local tables SELECT * FROM nullkey_c1_t1 JOIN postgres_local_table USING(a) ORDER BY 1,2,3; DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.postgres_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT nullkey_c1_t1.a, nullkey_c1_t1.b, postgres_local_table.b FROM (query_single_shard_table.nullkey_c1_t1 JOIN (SELECT postgres_local_table_1.a, postgres_local_table_1.b FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) postgres_local_table_1) postgres_local_table USING (a)) ORDER BY nullkey_c1_t1.a, nullkey_c1_t1.b, postgres_local_table.b DEBUG: Creating router plan a | b | b --------------------------------------------------------------------- 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (4 rows) SELECT * FROM nullkey_c1_t1 JOIN citus_local_table USING(a) ORDER BY 1,2,3; DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.citus_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT nullkey_c1_t1.a, nullkey_c1_t1.b, citus_local_table.b FROM (query_single_shard_table.nullkey_c1_t1 JOIN (SELECT citus_local_table_1.a, citus_local_table_1.b FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) citus_local_table_1) citus_local_table USING (a)) ORDER BY nullkey_c1_t1.a, nullkey_c1_t1.b, citus_local_table.b DEBUG: Creating router plan a | b | b --------------------------------------------------------------------- 1 | 1 | 1 1 | 2 | 1 2 | 2 | 2 2 | 2 | 2 3 | 3 | 3 3 | 4 | 3 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (11 rows) SET citus.local_table_join_policy TO 'prefer-distributed'; SELECT * FROM nullkey_c1_t1 JOIN citus_local_table USING(a) ORDER BY 1,2,3; DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT nullkey_c1_t1.a, nullkey_c1_t1.b, citus_local_table.b FROM ((SELECT nullkey_c1_t1_1.a, nullkey_c1_t1_1.b FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) nullkey_c1_t1_1) nullkey_c1_t1 JOIN query_single_shard_table.citus_local_table USING (a)) ORDER BY nullkey_c1_t1.a, nullkey_c1_t1.b, citus_local_table.b DEBUG: Creating router plan a | b | b --------------------------------------------------------------------- 1 | 1 | 1 1 | 2 | 1 2 | 2 | 2 2 | 2 | 2 3 | 3 | 3 3 | 4 | 3 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (11 rows) RESET citus.local_table_join_policy; -- join with a distributed table SET citus.enable_repartition_joins TO ON; SET client_min_messages TO DEBUG1; SELECT * FROM distributed_table d1 JOIN nullkey_c1_t1 USING(a) ORDER BY 1,2,3; a | b | b --------------------------------------------------------------------- 3 | 3 | 3 3 | 3 | 4 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (7 rows) SELECT * FROM (SELECT * FROM distributed_table) d1 JOIN nullkey_c1_t1 USING(a) ORDER BY 1,2,3; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT d1.a, d1.b, nullkey_c1_t1.b FROM ((SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) d1 JOIN query_single_shard_table.nullkey_c1_t1 USING (a)) ORDER BY d1.a, d1.b, nullkey_c1_t1.b a | b | b --------------------------------------------------------------------- 3 | 3 | 3 3 | 3 | 4 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (7 rows) SELECT * FROM nullkey_c1_t1 JOIN (SELECT * FROM distributed_table) d1 USING(a) ORDER BY 1,2,3; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT nullkey_c1_t1.a, nullkey_c1_t1.b, d1.b FROM (query_single_shard_table.nullkey_c1_t1 JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) d1 USING (a)) ORDER BY nullkey_c1_t1.a, nullkey_c1_t1.b, d1.b a | b | b --------------------------------------------------------------------- 3 | 3 | 3 3 | 4 | 3 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (7 rows) SELECT * FROM distributed_table d1 JOIN (SELECT * FROM nullkey_c1_t1) nullkey_c1_t1 USING(a) ORDER BY 1,2,3; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT d1.a, d1.b, nullkey_c1_t1.b FROM (query_single_shard_table.distributed_table d1 JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) nullkey_c1_t1 USING (a)) ORDER BY d1.a, d1.b, nullkey_c1_t1.b a | b | b --------------------------------------------------------------------- 3 | 3 | 3 3 | 3 | 4 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (7 rows) SELECT * FROM (SELECT * FROM nullkey_c1_t1) nullkey_c1_t1 JOIN distributed_table d1 USING(a) ORDER BY 1,2,3; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT nullkey_c1_t1.a, nullkey_c1_t1.b, d1.b FROM ((SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) nullkey_c1_t1 JOIN query_single_shard_table.distributed_table d1 USING (a)) ORDER BY nullkey_c1_t1.a, nullkey_c1_t1.b, d1.b a | b | b --------------------------------------------------------------------- 3 | 3 | 3 3 | 4 | 3 4 | 4 | 4 5 | 5 | 5 6 | 6 | 6 7 | 7 | 7 8 | 8 | 8 (7 rows) -- test joins with non-colocated distributed tables, by using subqueries SELECT * FROM nullkey_c1_t1 t1 JOIN (SELECT * FROM distributed_table) t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t2) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT t1.a, t1.b, t2.b, t3.b FROM ((query_single_shard_table.nullkey_c1_t1 t1 JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) t2 USING (a)) JOIN (SELECT nullkey_c1_t2.a, nullkey_c1_t2.b FROM query_single_shard_table.nullkey_c1_t2) t3 USING (a)) ORDER BY t1.a, t1.b, t2.b, t3.b LIMIT 1 a | b | b | b --------------------------------------------------------------------- 3 | 3 | 3 | 3 (1 row) SELECT * FROM (SELECT * FROM nullkey_c1_t1) t1 JOIN nullkey_c2_t1 t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t2) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 1 | 1 | 0 | 3 (1 row) SELECT * FROM distributed_table t1 JOIN (SELECT * FROM nullkey_c1_t1) t2 USING (a) JOIN (SELECT b as a FROM distributed_table) t3 USING (a) ORDER BY 1,2,3 LIMIT 1; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 DEBUG: generating subplan XXX_2 for subquery SELECT b AS a FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT t1.a, t1.b, t2.b FROM ((query_single_shard_table.distributed_table t1 JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) t2 USING (a)) JOIN (SELECT intermediate_result.a FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) t3 USING (a)) ORDER BY t1.a, t1.b, t2.b LIMIT 1 DEBUG: push down of limit count: 1 a | b | b --------------------------------------------------------------------- 3 | 3 | 3 (1 row) SELECT * FROM (SELECT * FROM nullkey_c2_t1) t1 JOIN nullkey_c1_t1 t2 USING (a) JOIN (SELECT * FROM nullkey_c2_t1) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 1 | 0 | 1 | 0 (1 row) SELECT * FROM nullkey_c1_t1 t1 JOIN (SELECT * FROM distributed_table) t2 USING (a) JOIN (SELECT * FROM distributed_table) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 3 | 3 | 3 | 3 (1 row) SELECT * FROM (SELECT * FROM nullkey_c1_t1) t1 JOIN nullkey_c2_t1 t2 USING (a) JOIN (SELECT * FROM nullkey_c2_t1) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 1 | 1 | 0 | 0 (1 row) SELECT * FROM distributed_table t1 JOIN (SELECT * FROM nullkey_c1_t1) t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t1) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 DEBUG: generating subplan XXX_2 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT t1.a, t1.b, t2.b, t3.b FROM ((query_single_shard_table.distributed_table t1 JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) t2 USING (a)) JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) t3 USING (a)) ORDER BY t1.a, t1.b, t2.b, t3.b LIMIT 1 DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 3 | 3 | 3 | 3 (1 row) SELECT * FROM (SELECT * FROM nullkey_c2_t1) t1 JOIN nullkey_c1_t1 t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t1) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 1 | 0 | 1 | 1 (1 row) SELECT * FROM nullkey_c1_t1 t1 JOIN (SELECT * FROM nullkey_c1_t1) t2 USING (a) JOIN distributed_table t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 3 | 3 | 3 | 3 (1 row) SELECT * FROM nullkey_c1_t1 t1 JOIN nullkey_c1_t1 t2 USING (a) JOIN nullkey_c2_t1 t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 1 | 1 | 1 | 0 (1 row) SELECT * FROM (SELECT * FROM distributed_table) t1 JOIN distributed_table t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t1) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 3 | 3 | 3 | 3 (1 row) SELECT * FROM (SELECT * FROM nullkey_c2_t1) t1 JOIN nullkey_c2_t1 t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t1) t3 USING (a) ORDER BY 1,2,3,4 LIMIT 1; DEBUG: push down of limit count: 1 a | b | b | b --------------------------------------------------------------------- 1 | 0 | 0 | 1 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT * FROM distributed_table t2 WHERE t2.b > t1.a ) q USING(a); count --------------------------------------------------------------------- 0 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT *, random() FROM distributed_table t2 WHERE t2.b > t1.a ) q USING(a); ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM distributed_table t1 JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); count --------------------------------------------------------------------- 1 (1 row) SET client_min_messages TO DEBUG2; SET citus.enable_repartition_joins TO OFF; -- outer joins with different table types SELECT COUNT(*) FROM nullkey_c1_t1 LEFT JOIN reference_table USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SELECT COUNT(*) FROM reference_table LEFT JOIN nullkey_c1_t1 USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 9 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 LEFT JOIN citus_local_table USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.citus_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (query_single_shard_table.nullkey_c1_t1 LEFT JOIN (SELECT citus_local_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) citus_local_table_1) citus_local_table USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SELECT COUNT(*) FROM citus_local_table LEFT JOIN nullkey_c1_t1 USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.citus_local_table WHERE true DEBUG: recursively planning right side of the left join since the outer side is a recurring rel DEBUG: recursively planning distributed relation "nullkey_c1_t1" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT a FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT citus_local_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) citus_local_table_1) citus_local_table LEFT JOIN (SELECT nullkey_c1_t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) nullkey_c1_t1_1) nullkey_c1_t1 USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 14 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 LEFT JOIN postgres_local_table USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.postgres_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (query_single_shard_table.nullkey_c1_t1 LEFT JOIN (SELECT postgres_local_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) postgres_local_table_1) postgres_local_table USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SELECT COUNT(*) FROM postgres_local_table LEFT JOIN nullkey_c1_t1 USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.postgres_local_table WHERE true DEBUG: recursively planning right side of the left join since the outer side is a recurring rel DEBUG: recursively planning distributed relation "nullkey_c1_t1" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT a FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT postgres_local_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) postgres_local_table_1) postgres_local_table LEFT JOIN (SELECT nullkey_c1_t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) nullkey_c1_t1_1) nullkey_c1_t1 USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 6 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 FULL JOIN citus_local_table USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.citus_local_table WHERE true DEBUG: recursively planning left side of the full join since the other side is a recurring rel DEBUG: recursively planning distributed relation "nullkey_c1_t1" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT a FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT nullkey_c1_t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) nullkey_c1_t1_1) nullkey_c1_t1 FULL JOIN (SELECT citus_local_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) citus_local_table_1) citus_local_table USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 14 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 FULL JOIN postgres_local_table USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.postgres_local_table WHERE true DEBUG: recursively planning left side of the full join since the other side is a recurring rel DEBUG: recursively planning distributed relation "nullkey_c1_t1" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT a FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT nullkey_c1_t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) nullkey_c1_t1_1) nullkey_c1_t1 FULL JOIN (SELECT postgres_local_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) postgres_local_table_1) postgres_local_table USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 13 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 FULL JOIN reference_table USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 12 (1 row) SET citus.enable_repartition_joins TO ON; SET client_min_messages TO DEBUG1; SELECT COUNT(*) FROM nullkey_c1_t1 JOIN append_table USING(a); count --------------------------------------------------------------------- 2 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 JOIN range_table USING(a); count --------------------------------------------------------------------- 9 (1 row) SET client_min_messages TO DEBUG2; SET citus.enable_repartition_joins TO OFF; SET citus.enable_non_colocated_router_query_pushdown TO ON; SELECT COUNT(*) FROM nullkey_c1_t1 JOIN range_table USING(a) WHERE range_table.a = 20; DEBUG: Creating router plan count --------------------------------------------------------------------- 0 (1 row) SET citus.enable_non_colocated_router_query_pushdown TO OFF; SET citus.enable_repartition_joins TO ON; SET client_min_messages TO DEBUG1; SELECT COUNT(*) FROM nullkey_c1_t1 JOIN range_table USING(a) WHERE range_table.a = 20; count --------------------------------------------------------------------- 0 (1 row) SET client_min_messages TO DEBUG2; SET citus.enable_repartition_joins TO OFF; RESET citus.enable_non_colocated_router_query_pushdown; -- lateral / semi / anti joins with different table types -- with a reference table SELECT COUNT(*) FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM reference_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE EXISTS ( SELECT * FROM reference_table t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 7 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE NOT EXISTS ( SELECT * FROM reference_table t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 4 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b IN ( SELECT b+1 FROM reference_table t2 WHERE t2.b = t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 2 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b NOT IN ( SELECT a FROM reference_table t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 9 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT * FROM reference_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 0 (1 row) SELECT COUNT(*) FROM reference_table t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 6 (1 row) SELECT COUNT(*) FROM reference_table t1 WHERE EXISTS ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 6 (1 row) SELECT COUNT(*) FROM reference_table t1 WHERE t1.b IN ( SELECT b+1 FROM nullkey_c1_t1 t2 WHERE t2.b = t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 0 (1 row) SELECT COUNT(*) FROM reference_table t1 WHERE t1.b NOT IN ( SELECT a FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: Creating router plan count --------------------------------------------------------------------- 4 (1 row) SELECT COUNT(*) FROM reference_table t1 JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Creating router plan count --------------------------------------------------------------------- 2 (1 row) -- with a distributed table SELECT COUNT(*) FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM distributed_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE EXISTS ( SELECT * FROM distributed_table t2 WHERE t2.b > t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE NOT EXISTS ( SELECT * FROM distributed_table t2 WHERE t2.b > t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b IN ( SELECT b+1 FROM distributed_table t2 WHERE t2.b = t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b NOT IN ( SELECT a FROM distributed_table t2 WHERE t2.b > t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM distributed_table t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM distributed_table t1 WHERE EXISTS ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM distributed_table t1 WHERE t1.b IN ( SELECT b+1 FROM nullkey_c1_t1 t2 WHERE t2.b = t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns SELECT COUNT(*) FROM distributed_table t1 WHERE t1.b NOT IN ( SELECT a FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns -- with postgres / citus local tables SELECT COUNT(*) FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM citus_local_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE EXISTS ( SELECT * FROM citus_local_table t2 WHERE t2.b > t1.a ); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE NOT EXISTS ( SELECT * FROM citus_local_table t2 WHERE t2.b > t1.a ); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b + random() IN ( SELECT b+1 FROM citus_local_table t2 WHERE t2.b = t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b NOT IN ( SELECT a FROM citus_local_table t2 WHERE t2.b > t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT * FROM citus_local_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported -- The following and a few other tests in this file unnecessarily go through -- recursive planning. This is because we recursive plan distributed tables -- when they are referred in the inner side of an outer join, if the outer -- side is a recurring rel. In future, we can optimize that such that we -- can skip recursively planning the single-shard table because such a join -- wouldn't result in returning recurring tuples. -- -- And specifically for the tests that contains a sublink (as below), things -- get even more interesting. We try to recursively plan the single-shard -- table but we cannot do so due to the sublink. However, the final query -- can go through router planner and hence is supported. SELECT COUNT(*) FROM citus_local_table t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" "t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.citus_local_table t1 WHERE true DEBUG: recursively planning right side of the left join since the outer side is a recurring rel DEBUG: recursively planning the distributed subquery since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: skipping recursive planning for the subquery since it contains references to outer queries DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) t1_1) t1 LEFT JOIN LATERAL (SELECT t2.a, t2.b FROM query_single_shard_table.nullkey_c1_t1 t2 WHERE (t2.b OPERATOR(pg_catalog.>) t1.a)) q USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 11 (1 row) SELECT COUNT(*) FROM postgres_local_table t1 LEFT JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" "t1" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.postgres_local_table t1 WHERE true DEBUG: recursively planning right side of the left join since the outer side is a recurring rel DEBUG: recursively planning the distributed subquery since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: skipping recursive planning for the subquery since it contains references to outer queries DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) t1_1) t1 LEFT JOIN LATERAL (SELECT t2.a, t2.b FROM query_single_shard_table.nullkey_c1_t1 t2 WHERE (t2.b OPERATOR(pg_catalog.>) t1.a)) q USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 6 (1 row) SELECT COUNT(*) FROM citus_local_table t1 WHERE EXISTS ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM citus_local_table t1 WHERE t1.b + random() IN ( SELECT b+1 FROM nullkey_c1_t1 t2 WHERE t2.b = t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM citus_local_table t1 WHERE t1.b NOT IN ( SELECT a FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported SELECT COUNT(*) FROM citus_local_table t1 JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "citus_local_table" "t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.citus_local_table t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) t1_1) t1 JOIN LATERAL (SELECT t2.a, t2.b FROM query_single_shard_table.nullkey_c1_t1 t2 WHERE (t2.b OPERATOR(pg_catalog.>) t1.a)) q USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 2 (1 row) SELECT COUNT(*) FROM nullkey_c1_t1 t1 LEFT JOIN LATERAL ( SELECT * FROM postgres_local_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE EXISTS ( SELECT * FROM postgres_local_table t2 WHERE t2.b > t1.a ); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE NOT EXISTS ( SELECT * FROM postgres_local_table t2 WHERE t2.b > t1.a ); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b + random() IN ( SELECT b+1 FROM postgres_local_table t2 WHERE t2.b = t1.a ); DEBUG: found no worker with all shard placements DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM nullkey_c1_t1 t1 WHERE t1.b NOT IN ( SELECT a FROM postgres_local_table t2 WHERE t2.b > t1.a ); DEBUG: found no worker with all shard placements DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN LATERAL ( SELECT * FROM postgres_local_table t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM postgres_local_table t1 WHERE EXISTS ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: Local tables cannot be used in distributed queries. DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM postgres_local_table t1 WHERE t1.b + random() IN ( SELECT b+1 FROM nullkey_c1_t1 t2 WHERE t2.b = t1.a ); DEBUG: found no worker with all shard placements DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM postgres_local_table t1 WHERE t1.b NOT IN ( SELECT a FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ); DEBUG: found no worker with all shard placements DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: direct joins between distributed and local tables are not supported HINT: Use CTE's or subqueries to select from local tables and use them in joins SELECT COUNT(*) FROM postgres_local_table t1 JOIN LATERAL ( SELECT * FROM nullkey_c1_t1 t2 WHERE t2.b > t1.a ) q USING(a); DEBUG: Local tables cannot be used in distributed queries. DEBUG: Wrapping relation "postgres_local_table" "t1" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.postgres_local_table t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT t1_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) t1_1) t1 JOIN LATERAL (SELECT t2.a, t2.b FROM query_single_shard_table.nullkey_c1_t1 t2 WHERE (t2.b OPERATOR(pg_catalog.>) t1.a)) q USING (a)) DEBUG: Creating router plan count --------------------------------------------------------------------- 0 (1 row) -- insert .. select -- between two colocated single-shard tables -- The target list of "distributed statement"s that we send to workers -- differ(*) in Postgres versions < 15. For this reason, we temporarily -- disable debug messages here and run the EXPLAIN'ed version of the -- command. -- -- (*): < SELECT a, b > vs < SELECT table_name.a, table_name.b > SET client_min_messages TO WARNING; EXPLAIN (ANALYZE TRUE, TIMING FALSE, COSTS FALSE, SUMMARY FALSE, VERBOSE FALSE) INSERT INTO nullkey_c1_t1 SELECT * FROM nullkey_c1_t2; QUERY PLAN --------------------------------------------------------------------- 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 nullkey_c1_t1_1620000 citus_table_alias (actual rows=0 loops=1) -> Seq Scan on nullkey_c1_t2_1620001 nullkey_c1_t2 (actual rows=10 loops=1) (7 rows) SET client_min_messages TO DEBUG2; -- between two non-colocated single-shard tables INSERT INTO nullkey_c1_t1 SELECT * FROM nullkey_c2_t1; DEBUG: Creating router plan DEBUG: INSERT target relation and all source relations of the SELECT must be colocated in distributed INSERT ... SELECT DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Collecting INSERT ... SELECT results on coordinator -- between a single-shard table and a table of different type SET client_min_messages TO WARNING; EXPLAIN (ANALYZE TRUE, TIMING FALSE, COSTS FALSE, SUMMARY FALSE, VERBOSE FALSE) INSERT INTO nullkey_c1_t1 SELECT * FROM reference_table; QUERY PLAN --------------------------------------------------------------------- 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 nullkey_c1_t1_1620000 citus_table_alias (actual rows=0 loops=1) -> Seq Scan on reference_table_1620005 reference_table (actual rows=6 loops=1) (7 rows) SET client_min_messages TO DEBUG2; INSERT INTO nullkey_c1_t1 SELECT * FROM distributed_table; DEBUG: INSERT target relation and all source relations of the SELECT must be colocated in distributed INSERT ... SELECT DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO nullkey_c1_t1 SELECT * FROM citus_local_table; DEBUG: Creating router plan DEBUG: distributed INSERT ... SELECT cannot select from a local relation when inserting into a distributed table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO nullkey_c1_t1 SELECT * FROM postgres_local_table; DEBUG: Creating router plan DEBUG: distributed INSERT ... SELECT can only select from distributed tables DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO reference_table SELECT * FROM nullkey_c1_t1; DEBUG: Creating router plan DEBUG: only reference tables may be queried when targeting a reference table with distributed INSERT ... SELECT DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO distributed_table SELECT * FROM nullkey_c1_t1; DEBUG: Creating router plan DEBUG: cannot perform distributed INSERT INTO ... SELECT because the partition columns in the source table and subquery do not match DETAIL: The target table's partition column should correspond to a partition column in the subquery. DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO citus_local_table SELECT * FROM nullkey_c1_t1; DEBUG: Creating router plan DEBUG: distributed INSERT ... SELECT cannot insert into a local table that is added to metadata DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO postgres_local_table SELECT * FROM nullkey_c1_t1; DEBUG: Creating router plan -- test subquery SELECT count(*) FROM ( SELECT * FROM (SELECT * FROM nullkey_c1_t2) as subquery_inner ) AS subquery_top; DEBUG: Creating router plan count --------------------------------------------------------------------- 10 (1 row) -- test cte inlining WITH cte_nullkey_c1_t1 AS (SELECT * FROM nullkey_c1_t1), cte_postgres_local_table AS (SELECT * FROM postgres_local_table), cte_distributed_table AS (SELECT * FROM distributed_table) SELECT COUNT(*) FROM cte_distributed_table, cte_nullkey_c1_t1, cte_postgres_local_table WHERE cte_nullkey_c1_t1.a > 3 AND cte_distributed_table.a < 5; DEBUG: CTE cte_nullkey_c1_t1 is going to be inlined via distributed planning DEBUG: CTE cte_postgres_local_table is going to be inlined via distributed planning DEBUG: CTE cte_distributed_table is going to be inlined via distributed planning DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.postgres_local_table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT distributed_table.a, distributed_table.b FROM query_single_shard_table.distributed_table) cte_distributed_table, (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte_nullkey_c1_t1, (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte_postgres_local_table WHERE ((cte_nullkey_c1_t1.a OPERATOR(pg_catalog.>) 3) AND (cte_distributed_table.a OPERATOR(pg_catalog.<) 5)) DEBUG: Router planner cannot handle multi-shard select queries count --------------------------------------------------------------------- 78144 (1 row) -- test recursive ctes WITH level_0 AS ( WITH level_1 AS ( WITH RECURSIVE level_2_recursive(x) AS ( VALUES (1) UNION ALL SELECT a + 1 FROM nullkey_c1_t1 JOIN level_2_recursive ON (a = x) WHERE a < 2 ) SELECT * FROM level_2_recursive RIGHT JOIN reference_table ON (level_2_recursive.x = reference_table.a) ) SELECT * FROM level_1 ) SELECT COUNT(*) FROM level_0; DEBUG: CTE level_0 is going to be inlined via distributed planning DEBUG: CTE level_1 is going to be inlined via distributed planning DEBUG: Creating router plan count --------------------------------------------------------------------- 106 (1 row) WITH level_0 AS ( WITH level_1 AS ( WITH RECURSIVE level_2_recursive(x) AS ( VALUES (1) UNION ALL SELECT a + 1 FROM nullkey_c1_t1 JOIN level_2_recursive ON (a = x) WHERE a < 100 ) SELECT * FROM level_2_recursive JOIN distributed_table ON (level_2_recursive.x = distributed_table.a) ) SELECT * FROM level_1 ) SELECT COUNT(*) FROM level_0; DEBUG: CTE level_0 is going to be inlined via distributed planning DEBUG: CTE level_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for CTE level_0: WITH level_1 AS (WITH RECURSIVE level_2_recursive(x) AS (VALUES (1) UNION ALL SELECT (nullkey_c1_t1.a OPERATOR(pg_catalog.+) 1) FROM (query_single_shard_table.nullkey_c1_t1 JOIN level_2_recursive level_2_recursive_1 ON ((nullkey_c1_t1.a OPERATOR(pg_catalog.=) level_2_recursive_1.x))) WHERE (nullkey_c1_t1.a OPERATOR(pg_catalog.<) 100)) SELECT level_2_recursive.x, distributed_table.a, distributed_table.b FROM (level_2_recursive JOIN query_single_shard_table.distributed_table ON ((level_2_recursive.x OPERATOR(pg_catalog.=) distributed_table.a)))) SELECT x, a, b FROM level_1 DEBUG: CTE level_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for CTE level_1: WITH RECURSIVE level_2_recursive(x) AS (VALUES (1) UNION ALL SELECT (nullkey_c1_t1.a OPERATOR(pg_catalog.+) 1) FROM (query_single_shard_table.nullkey_c1_t1 JOIN level_2_recursive level_2_recursive_1 ON ((nullkey_c1_t1.a OPERATOR(pg_catalog.=) level_2_recursive_1.x))) WHERE (nullkey_c1_t1.a OPERATOR(pg_catalog.<) 100)) SELECT level_2_recursive.x, distributed_table.a, distributed_table.b FROM (level_2_recursive JOIN query_single_shard_table.distributed_table ON ((level_2_recursive.x OPERATOR(pg_catalog.=) distributed_table.a))) DEBUG: Router planner cannot handle multi-shard select queries ERROR: recursive CTEs are only supported when they contain a filter on the distribution column -- grouping set SELECT id, substring(title, 2, 1) AS subtitle, count(*) FROM articles_hash WHERE author_id = 1 or author_id = 2 GROUP BY GROUPING SETS ((id),(subtitle)) ORDER BY id, subtitle; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | subtitle | count --------------------------------------------------------------------- 42 | | 1 | u | 1 (2 rows) -- subquery in SELECT clause SELECT a.title AS name, (SELECT a2.id FROM articles_hash a2 WHERE a.id = a2.id LIMIT 1) AS special_price FROM articles_hash a ORDER BY 1,2; DEBUG: Creating router plan name | special_price --------------------------------------------------------------------- adversa | 15 aerophyte | 28 affixal | 43 altdorfer | 4 amateur | 29 anjanette | 50 anyone | 49 aruru | 5 aseyev | 13 assembly | 18 aubergiste | 19 ausable | 42 (12 rows) -- test having clause SELECT COUNT(*), b FROM nullkey_c1_t1 GROUP BY 2 HAVING (SELECT COUNT(*) FROM nullkey_c1_t2) > 0 ORDER BY 1,2; DEBUG: Creating router plan count | b --------------------------------------------------------------------- 2 | 9 2 | 10 3 | 0 4 | 1 4 | 8 6 | 6 6 | 7 8 | 3 8 | 4 8 | 5 9 | 2 (11 rows) SELECT COUNT(*), b FROM nullkey_c1_t1 GROUP BY 2 HAVING (SELECT COUNT(*) FROM nullkey_c2_t1) > 0 ORDER BY 1,2; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT count(*) AS count FROM query_single_shard_table.nullkey_c2_t1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count, b FROM query_single_shard_table.nullkey_c1_t1 GROUP BY b HAVING ((SELECT intermediate_result.count FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) OPERATOR(pg_catalog.>) 0) ORDER BY (count(*)), b DEBUG: Creating router plan count | b --------------------------------------------------------------------- 2 | 9 2 | 10 3 | 0 4 | 1 4 | 8 6 | 6 6 | 7 8 | 3 8 | 4 8 | 5 9 | 2 (11 rows) SELECT COUNT(*), b FROM nullkey_c1_t1 GROUP BY 2 HAVING (SELECT COUNT(*) FROM distributed_table) > 0 ORDER BY 1,2; DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for subquery SELECT count(*) AS count FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count, b FROM query_single_shard_table.nullkey_c1_t1 GROUP BY b HAVING ((SELECT intermediate_result.count FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) OPERATOR(pg_catalog.>) 0) ORDER BY (count(*)), b DEBUG: Creating router plan count | b --------------------------------------------------------------------- 2 | 9 2 | 10 3 | 0 4 | 1 4 | 8 6 | 6 6 | 7 8 | 3 8 | 4 8 | 5 9 | 2 (11 rows) SELECT COUNT(*), b FROM nullkey_c1_t1 t4 GROUP BY 2 HAVING ( SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN (SELECT * FROM nullkey_c1_t2) t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t2) t3 USING (a) WHERE t2.b > t4.b ) > 5 ORDER BY 1,2; DEBUG: Creating router plan count | b --------------------------------------------------------------------- 3 | 0 4 | 1 6 | 6 8 | 3 8 | 4 8 | 5 9 | 2 (7 rows) SELECT COUNT(*), b FROM distributed_table t4 GROUP BY 2 HAVING ( SELECT COUNT(*) FROM nullkey_c1_t1 t1 JOIN (SELECT * FROM distributed_table) t2 USING (a) JOIN (SELECT * FROM nullkey_c1_t2) t3 USING (a) WHERE t2.b > t4.b ) > 5 ORDER BY 1,2; DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for subquery SELECT a, b FROM query_single_shard_table.distributed_table ERROR: Subqueries in HAVING cannot refer to outer query -- test prepared statements -- prepare queries can be router plannable PREPARE author_1_articles as SELECT * FROM articles_hash WHERE author_id = 1; EXECUTE author_1_articles; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_1_articles; id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_1_articles; id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_1_articles; id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_1_articles; id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_1_articles; id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) -- parametric prepare queries can be router plannable PREPARE author_articles(int) as SELECT * FROM articles_hash WHERE author_id = $1; EXECUTE author_articles(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) EXECUTE author_articles(NULL); id | author_id | title | word_count --------------------------------------------------------------------- (0 rows) PREPARE author_articles_update(int) AS UPDATE articles_hash SET title = 'test' WHERE author_id = $1; EXECUTE author_articles_update(NULL); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE author_articles_update(NULL); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE author_articles_update(NULL); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE author_articles_update(NULL); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE author_articles_update(NULL); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE author_articles_update(NULL); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE author_articles_update(NULL); -- More tests with insert .. select. -- -- The target list of "distributed statement"s that we send to workers -- might differ(*) in Postgres versions < 15 and they are reported when -- "log level >= DEBUG2". For this reason, we set log level to DEBUG1 to -- avoid reporting them. -- -- DEBUG1 still allows reporting the reason why given INSERT .. SELECT -- query is not distributed / requires pull-to-coordinator. SET client_min_messages TO DEBUG1; INSERT INTO bigserial_test (x, y) SELECT x, y FROM bigserial_test; DEBUG: volatile functions are not allowed in distributed INSERT ... SELECT queries DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO bigserial_test (x, y) SELECT a, a FROM reference_table; DEBUG: volatile functions are not allowed in distributed INSERT ... SELECT queries DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO agg_events (user_id) SELECT f2.id FROM (SELECT id FROM (SELECT users_ref_table.user_id AS id FROM raw_events_first, users_ref_table WHERE raw_events_first.user_id = users_ref_table.user_id ) AS foo) as f INNER JOIN (SELECT v4, v1, id FROM (SELECT SUM(raw_events_second.value_4) AS v4, SUM(raw_events_first.value_1) AS v1, raw_events_second.user_id AS id FROM raw_events_first, raw_events_second WHERE raw_events_first.user_id = raw_events_second.user_id GROUP BY raw_events_second.user_id HAVING SUM(raw_events_second.value_4) > 1000) AS foo2 ) as f2 ON (f.id = f2.id) WHERE f.id IN (SELECT user_id FROM raw_events_second); -- upsert with returning INSERT INTO agg_events AS ae ( user_id, value_1_agg, agg_time ) SELECT user_id, value_1, time FROM raw_events_first ON conflict (user_id, value_1_agg) DO UPDATE SET agg_time = EXCLUDED.agg_time WHERE ae.agg_time < EXCLUDED.agg_time RETURNING user_id, value_1_agg; user_id | value_1_agg --------------------------------------------------------------------- 1 | 10 2 | 20 3 | 30 4 | 40 5 | 50 6 | 60 (6 rows) -- using a left join INSERT INTO agg_events (user_id) SELECT raw_events_first.user_id FROM raw_events_first LEFT JOIN raw_events_second ON raw_events_first.user_id = raw_events_second.user_id WHERE raw_events_second.user_id = 10 OR raw_events_second.user_id = 11; INSERT INTO agg_events (user_id) SELECT users_ref_table.user_id FROM users_ref_table LEFT JOIN raw_events_second ON users_ref_table.user_id = raw_events_second.user_id WHERE raw_events_second.user_id = 10 OR raw_events_second.user_id = 11; INSERT INTO agg_events (user_id) SELECT COALESCE(raw_events_first.user_id, users_ref_table.user_id) FROM raw_events_first RIGHT JOIN (users_ref_table LEFT JOIN raw_events_second ON users_ref_table.user_id = raw_events_second.user_id) ON raw_events_first.user_id = users_ref_table.user_id; -- using a full join INSERT INTO agg_events (user_id, value_1_agg) SELECT t1.user_id AS col1, t2.user_id AS col2 FROM raw_events_first t1 FULL JOIN raw_events_second t2 ON t1.user_id = t2.user_id; -- using semi join INSERT INTO raw_events_second (user_id) SELECT user_id FROM raw_events_first WHERE user_id IN (SELECT raw_events_second.user_id FROM raw_events_second, raw_events_first WHERE raw_events_second.user_id = raw_events_first.user_id AND raw_events_first.user_id = 200); -- using lateral join INSERT INTO raw_events_second (user_id) SELECT user_id FROM raw_events_first WHERE NOT EXISTS (SELECT 1 FROM raw_events_second WHERE raw_events_second.user_id =raw_events_first.user_id); INSERT INTO raw_events_second (user_id) SELECT user_id FROM users_ref_table WHERE NOT EXISTS (SELECT 1 FROM raw_events_second WHERE raw_events_second.user_id = users_ref_table.user_id); -- using inner join INSERT INTO agg_events (user_id) SELECT raw_events_first.user_id FROM raw_events_first INNER JOIN raw_events_second ON raw_events_first.user_id = raw_events_second.value_1 WHERE raw_events_first.value_1 IN (10, 11,12) OR raw_events_second.user_id IN (1,2,3,4); INSERT INTO agg_events (user_id) SELECT raw_events_first.user_id FROM raw_events_first INNER JOIN users_ref_table ON raw_events_first.user_id = users_ref_table.user_id WHERE raw_events_first.value_1 IN (10, 11,12) OR users_ref_table.user_id IN (1,2,3,4); -- limit / offset clause INSERT INTO agg_events (user_id) SELECT raw_events_first.user_id FROM raw_events_first LIMIT 1; INSERT INTO agg_events (user_id) SELECT raw_events_first.user_id FROM raw_events_first OFFSET 1; INSERT INTO agg_events (user_id) SELECT users_ref_table.user_id FROM users_ref_table LIMIT 1; -- using a materialized cte WITH cte AS MATERIALIZED (SELECT max(value_1)+1 as v1_agg, user_id FROM raw_events_first GROUP BY user_id) INSERT INTO agg_events (value_1_agg, user_id) SELECT v1_agg, user_id FROM cte; DEBUG: distributed INSERT ... SELECT can only select from distributed tables DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO raw_events_second WITH cte AS MATERIALIZED (SELECT * FROM raw_events_first) SELECT user_id * 1000, time, value_1, value_2, value_3, value_4 FROM cte; INSERT INTO raw_events_second (user_id) WITH cte AS MATERIALIZED (SELECT * FROM users_ref_table) SELECT user_id FROM cte; -- using a regular cte WITH cte AS (SELECT * FROM raw_events_first) INSERT INTO raw_events_second SELECT user_id * 7000, time, value_1, value_2, value_3, value_4 FROM cte; DEBUG: distributed INSERT ... SELECT can only select from distributed tables DEBUG: CTE cte is going to be inlined via distributed planning DEBUG: Collecting INSERT ... SELECT results on coordinator INSERT INTO raw_events_second WITH cte AS (SELECT * FROM raw_events_first) SELECT * FROM cte; DEBUG: CTE cte is going to be inlined via distributed planning INSERT INTO agg_events WITH sub_cte AS (SELECT 1) SELECT raw_events_first.user_id, (SELECT * FROM sub_cte) FROM raw_events_first; DEBUG: CTE sub_cte is going to be inlined via distributed planning -- we still support complex joins via INSERT's cte list .. WITH cte AS ( SELECT DISTINCT(reference_table.a) AS a, 1 AS b FROM distributed_table RIGHT JOIN reference_table USING (a) ) INSERT INTO raw_events_second (user_id, value_1) SELECT (a+5)*-1, b FROM cte; DEBUG: distributed INSERT ... SELECT can only select from distributed tables DEBUG: CTE cte is going to be inlined via distributed planning DEBUG: recursively planning left side of the right join since the outer side is a recurring rel DEBUG: recursively planning distributed relation "distributed_table" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "distributed_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.distributed_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT "?column?" AS user_id, b AS value_1 FROM (SELECT ((cte.a OPERATOR(pg_catalog.+) 5) OPERATOR(pg_catalog.*) '-1'::integer), cte.b FROM (SELECT DISTINCT reference_table.a, 1 AS b FROM ((SELECT distributed_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) distributed_table_1) distributed_table RIGHT JOIN query_single_shard_table.reference_table USING (a))) cte) citus_insert_select_subquery("?column?", b) DEBUG: Collecting INSERT ... SELECT results on coordinator -- .. and via SELECT's cte list too INSERT INTO raw_events_second (user_id, value_1) WITH cte AS ( SELECT DISTINCT(reference_table.a) AS a, 1 AS b FROM distributed_table RIGHT JOIN reference_table USING (a) ) SELECT (a+5)*2, b FROM cte; DEBUG: CTE cte is going to be inlined via distributed planning DEBUG: cannot perform a lateral outer join when a distributed subquery references a reference table DEBUG: recursively planning left side of the right join since the outer side is a recurring rel DEBUG: recursively planning distributed relation "distributed_table" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "distributed_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.distributed_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((a OPERATOR(pg_catalog.+) 5) OPERATOR(pg_catalog.*) 2) AS user_id, b AS value_1 FROM (SELECT DISTINCT reference_table.a, 1 AS b FROM ((SELECT distributed_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) distributed_table_1) distributed_table RIGHT JOIN query_single_shard_table.reference_table USING (a))) cte DEBUG: Collecting INSERT ... SELECT results on coordinator -- using set operations INSERT INTO raw_events_first(user_id) (SELECT user_id FROM raw_events_first) INTERSECT (SELECT user_id FROM raw_events_first); INSERT INTO raw_events_first(user_id) (SELECT user_id FROM users_ref_table) INTERSECT (SELECT user_id FROM raw_events_first); -- group by clause inside subquery INSERT INTO agg_events (user_id) SELECT f2.id FROM (SELECT id FROM (SELECT raw_events_second.user_id AS id FROM raw_events_first, raw_events_second WHERE raw_events_first.user_id = raw_events_second.user_id ) AS foo) as f INNER JOIN (SELECT v4, v1, id FROM (SELECT SUM(raw_events_second.value_4) AS v4, SUM(raw_events_first.value_1) AS v1, raw_events_second.user_id AS id FROM raw_events_first, raw_events_second WHERE raw_events_first.user_id = raw_events_second.user_id GROUP BY raw_events_second.user_id HAVING SUM(raw_events_second.value_4) > 1000) AS foo2 ) as f2 ON (f.id = f2.id) WHERE f.id IN (SELECT user_id FROM raw_events_second); -- group by clause inside lateral subquery INSERT INTO agg_events (user_id, value_4_agg) SELECT averages.user_id, avg(averages.value_4) FROM (SELECT t1.user_id FROM raw_events_second t1 JOIN raw_events_second t2 on (t1.user_id = t2.user_id) ) reference_ids JOIN LATERAL (SELECT user_id, value_4 FROM raw_events_first) as averages ON averages.value_4 = reference_ids.user_id GROUP BY averages.user_id; -- using aggregates INSERT INTO agg_events (value_3_agg, value_4_agg, value_1_agg, value_2_agg, user_id) SELECT SUM(value_3), Count(value_4), user_id, SUM(value_1), Avg(value_2) FROM raw_events_first GROUP BY user_id; INSERT INTO agg_events (value_3_agg, value_1_agg) SELECT AVG(user_id), SUM(user_id) FROM users_ref_table GROUP BY user_id; -- using generate_series INSERT INTO raw_events_first (user_id, value_1, value_2) SELECT s, s, s FROM generate_series(1, 5) s; DEBUG: distributed INSERT ... SELECT can only select from distributed tables DEBUG: Collecting INSERT ... SELECT results on coordinator CREATE SEQUENCE insert_select_test_seq; -- nextval() expression in select's targetlist INSERT INTO raw_events_first (user_id, value_1, value_2) SELECT s, nextval('insert_select_test_seq'), (random()*10)::int FROM generate_series(100, 105) s; DEBUG: distributed INSERT ... SELECT can only select from distributed tables DEBUG: Collecting INSERT ... SELECT results on coordinator -- non-immutable function INSERT INTO modify_fast_path (key, value_1) VALUES (2,1) RETURNING value_1, random() * key; ERROR: non-IMMUTABLE functions are not allowed in the RETURNING clause SET client_min_messages TO DEBUG2; -- update / delete UPDATE nullkey_c1_t1 SET a = 1 WHERE b = 5; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan UPDATE nullkey_c1_t1 SET a = 1 WHERE a = 5; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan UPDATE nullkey_c1_t1 SET a = random(); DEBUG: functions used in UPDATE queries on distributed tables must not be VOLATILE ERROR: functions used in UPDATE queries on distributed tables must not be VOLATILE UPDATE nullkey_c1_t1 SET a = 1 WHERE a = random(); DEBUG: functions used in the WHERE/ON/WHEN clause of modification queries on distributed tables must not be VOLATILE ERROR: functions used in the WHERE/ON/WHEN clause of modification queries on distributed tables must not be VOLATILE DELETE FROM nullkey_c1_t1 WHERE b = 5; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DELETE FROM nullkey_c1_t1 WHERE a = random(); DEBUG: functions used in the WHERE/ON/WHEN clause of modification queries on distributed tables must not be VOLATILE ERROR: functions used in the WHERE/ON/WHEN clause of modification queries on distributed tables must not be VOLATILE -- simple update queries between different table types / colocated tables UPDATE nullkey_c1_t1 SET b = 5 FROM nullkey_c1_t2 WHERE nullkey_c1_t1.b = nullkey_c1_t2.b; DEBUG: Creating router plan UPDATE nullkey_c1_t1 SET b = 5 FROM nullkey_c2_t1 WHERE nullkey_c1_t1.b = nullkey_c2_t1.b; DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: router planner does not support queries that reference non-colocated distributed tables UPDATE nullkey_c1_t1 SET b = 5 FROM reference_table WHERE nullkey_c1_t1.b = reference_table.b; DEBUG: Creating router plan UPDATE nullkey_c1_t1 SET b = 5 FROM distributed_table WHERE nullkey_c1_t1.b = distributed_table.b; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns UPDATE nullkey_c1_t1 SET b = 5 FROM distributed_table WHERE nullkey_c1_t1.b = distributed_table.a; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns UPDATE nullkey_c1_t1 SET b = 5 FROM citus_local_table WHERE nullkey_c1_t1.b = citus_local_table.b; DEBUG: local table citus_local_table cannot be joined with these distributed tables DEBUG: Wrapping relation "citus_local_table" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.citus_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.nullkey_c1_t1 SET b = 5 FROM (SELECT NULL::integer AS a, citus_local_table_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) citus_local_table_1) citus_local_table WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) citus_local_table.b) DEBUG: Creating router plan UPDATE nullkey_c1_t1 SET b = 5 FROM postgres_local_table WHERE nullkey_c1_t1.b = postgres_local_table.b; DEBUG: relation postgres_local_table is not distributed DEBUG: Wrapping relation "postgres_local_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.postgres_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.nullkey_c1_t1 SET b = 5 FROM (SELECT NULL::integer AS a, postgres_local_table_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) postgres_local_table_1) postgres_local_table WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) postgres_local_table.b) DEBUG: Creating router plan UPDATE reference_table SET b = 5 FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b = reference_table.b; ERROR: cannot perform select on a distributed table and modify a reference table UPDATE distributed_table SET b = 5 FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b = distributed_table.b; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns UPDATE distributed_table SET b = 5 FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b = distributed_table.a; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns UPDATE citus_local_table SET b = 5 FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b = citus_local_table.b; DEBUG: local table citus_local_table cannot be joined with these distributed tables DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.citus_local_table SET b = 5 FROM (SELECT NULL::integer AS a, nullkey_c1_t1_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) nullkey_c1_t1_1) nullkey_c1_t1 WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) citus_local_table.b) DEBUG: Creating router plan UPDATE postgres_local_table SET b = 5 FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b = postgres_local_table.b; DEBUG: relation postgres_local_table is not distributed DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.postgres_local_table SET b = 5 FROM (SELECT NULL::integer AS a, nullkey_c1_t1_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) nullkey_c1_t1_1) nullkey_c1_t1 WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) postgres_local_table.b) DEBUG: Creating router plan -- simple delete queries between different table types / colocated tables DELETE FROM nullkey_c1_t1 USING nullkey_c1_t2 WHERE nullkey_c1_t1.b = nullkey_c1_t2.b; DEBUG: Creating router plan DELETE FROM nullkey_c1_t1 USING nullkey_c2_t1 WHERE nullkey_c1_t1.b = nullkey_c2_t1.b; DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: router planner does not support queries that reference non-colocated distributed tables DELETE FROM nullkey_c1_t1 USING reference_table WHERE nullkey_c1_t1.b = reference_table.b; DEBUG: Creating router plan DELETE FROM nullkey_c1_t1 USING distributed_table WHERE nullkey_c1_t1.b = distributed_table.b; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DELETE FROM nullkey_c1_t1 USING distributed_table WHERE nullkey_c1_t1.b = distributed_table.a; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DELETE FROM nullkey_c1_t1 USING citus_local_table WHERE nullkey_c1_t1.b = citus_local_table.b; DEBUG: local table citus_local_table cannot be joined with these distributed tables DEBUG: Wrapping relation "citus_local_table" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.citus_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.nullkey_c1_t1 USING (SELECT NULL::integer AS a, citus_local_table_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) citus_local_table_1) citus_local_table WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) citus_local_table.b) DEBUG: Creating router plan DELETE FROM nullkey_c1_t1 USING postgres_local_table WHERE nullkey_c1_t1.b = postgres_local_table.b; DEBUG: relation postgres_local_table is not distributed DEBUG: Wrapping relation "postgres_local_table" to a subquery DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.postgres_local_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.nullkey_c1_t1 USING (SELECT NULL::integer AS a, postgres_local_table_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) postgres_local_table_1) postgres_local_table WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) postgres_local_table.b) DEBUG: Creating router plan DELETE FROM reference_table USING nullkey_c1_t1 WHERE nullkey_c1_t1.b = reference_table.b; ERROR: cannot perform select on a distributed table and modify a reference table DELETE FROM distributed_table USING nullkey_c1_t1 WHERE nullkey_c1_t1.b = distributed_table.b; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DELETE FROM distributed_table USING nullkey_c1_t1 WHERE nullkey_c1_t1.b = distributed_table.a; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DELETE FROM citus_local_table USING nullkey_c1_t1 WHERE nullkey_c1_t1.b = citus_local_table.b; DEBUG: local table citus_local_table cannot be joined with these distributed tables DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.citus_local_table USING (SELECT NULL::integer AS a, nullkey_c1_t1_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) nullkey_c1_t1_1) nullkey_c1_t1 WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) citus_local_table.b) DEBUG: Creating router plan DELETE FROM postgres_local_table USING nullkey_c1_t1 WHERE nullkey_c1_t1.b = postgres_local_table.b; DEBUG: relation postgres_local_table is not distributed DEBUG: Wrapping relation "nullkey_c1_t1" to a subquery DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.nullkey_c1_t1 WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.postgres_local_table USING (SELECT NULL::integer AS a, nullkey_c1_t1_1.b FROM (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer)) nullkey_c1_t1_1) nullkey_c1_t1 WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) postgres_local_table.b) DEBUG: Creating router plan -- slightly more complex update queries UPDATE nullkey_c1_t1 SET b = 5 WHERE nullkey_c1_t1.b IN (SELECT b FROM distributed_table); DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.nullkey_c1_t1 SET b = 5 WHERE (b OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer))) DEBUG: Creating router plan WITH cte AS materialized( SELECT * FROM distributed_table ) UPDATE nullkey_c1_t1 SET b = 5 FROM cte WHERE nullkey_c1_t1.b = cte.a; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DEBUG: generating subplan XXX_1 for CTE cte: SELECT a, b FROM query_single_shard_table.distributed_table DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.nullkey_c1_t1 SET b = 5 FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) cte.a) DEBUG: Creating router plan WITH cte AS ( SELECT reference_table.a AS a, 1 AS b FROM distributed_table RIGHT JOIN reference_table USING (a) ) UPDATE nullkey_c1_t1 SET b = 5 WHERE nullkey_c1_t1.b IN (SELECT b FROM cte); DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DEBUG: generating subplan XXX_1 for CTE cte: SELECT reference_table.a, 1 AS b FROM (query_single_shard_table.distributed_table RIGHT JOIN query_single_shard_table.reference_table USING (a)) DEBUG: Router planner cannot handle multi-shard select queries DEBUG: recursively planning left side of the right join since the outer side is a recurring rel DEBUG: recursively planning distributed relation "distributed_table" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "distributed_table" to a subquery DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.distributed_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT reference_table.a, 1 AS b FROM ((SELECT distributed_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) distributed_table_1) distributed_table RIGHT JOIN query_single_shard_table.reference_table USING (a)) DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.nullkey_c1_t1 SET b = 5 WHERE (b OPERATOR(pg_catalog.=) ANY (SELECT cte.b FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Creating router plan UPDATE nullkey_c1_t1 SET b = 5 FROM reference_table WHERE EXISTS ( SELECT 1 FROM reference_table LEFT JOIN nullkey_c1_t1 USING (a) WHERE nullkey_c1_t1.b IS NULL ); DEBUG: Creating router plan UPDATE nullkey_c1_t1 tx SET b = ( SELECT nullkey_c1_t2.b FROM nullkey_c1_t2 JOIN nullkey_c1_t1 ON (nullkey_c1_t1.a != nullkey_c1_t2.a) WHERE nullkey_c1_t1.a = tx.a ORDER BY 1 LIMIT 1 ); DEBUG: Creating router plan UPDATE nullkey_c1_t1 tx SET b = t2.b FROM nullkey_c1_t1 t1 JOIN nullkey_c1_t2 t2 ON (t1.a = t2.a); DEBUG: Creating router plan WITH cte AS ( SELECT * FROM nullkey_c1_t2 ORDER BY 1,2 LIMIT 10 ) UPDATE nullkey_c1_t1 SET b = 5 WHERE nullkey_c1_t1.a IN (SELECT b FROM cte); DEBUG: Creating router plan UPDATE modify_fast_path SET value_1 = value_1 + 12 * value_1 WHERE key = 1; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan UPDATE modify_fast_path SET value_1 = NULL WHERE value_1 = 15 AND (key = 1 OR value_2 = 'citus'); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan UPDATE modify_fast_path SET value_1 = 5 WHERE key = 2 RETURNING value_1 * 15, value_1::numeric * 16; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan ?column? | ?column? --------------------------------------------------------------------- (0 rows) UPDATE modify_fast_path SET value_1 = 1 FROM modify_fast_path_reference WHERE modify_fast_path.key = modify_fast_path_reference.key AND modify_fast_path.key = 1 AND modify_fast_path_reference.key = 1; DEBUG: Creating router plan PREPARE p1 (int, int, int) AS UPDATE modify_fast_path SET value_1 = value_1 + $1 WHERE key = $2 AND value_1 = $3; EXECUTE p1(1,1,1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p1(2,2,2); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p1(3,3,3); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p1(4,4,4); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p1(5,5,5); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p1(6,6,6); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p1(7,7,7); PREPARE prepared_zero_shard_update(int) AS UPDATE modify_fast_path SET value_1 = 1 WHERE key = $1 AND false; EXECUTE prepared_zero_shard_update(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_update(2); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_update(3); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_update(4); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_update(5); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_update(6); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_update(7); -- slightly more complex delete queries DELETE FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b IN (SELECT b FROM distributed_table); DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for subquery SELECT b FROM query_single_shard_table.distributed_table DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.nullkey_c1_t1 WHERE (b OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(b integer))) DEBUG: Creating router plan WITH cte AS materialized( SELECT * FROM distributed_table ) DELETE FROM nullkey_c1_t1 USING cte WHERE nullkey_c1_t1.b = cte.a; DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DEBUG: generating subplan XXX_1 for CTE cte: SELECT a, b FROM query_single_shard_table.distributed_table DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.nullkey_c1_t1 USING (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte WHERE (nullkey_c1_t1.b OPERATOR(pg_catalog.=) cte.a) DEBUG: Creating router plan WITH cte AS ( SELECT reference_table.a AS a, 1 AS b FROM distributed_table RIGHT JOIN reference_table USING (a) ) DELETE FROM nullkey_c1_t1 WHERE nullkey_c1_t1.b IN (SELECT b FROM cte); DEBUG: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DEBUG: generating subplan XXX_1 for CTE cte: SELECT reference_table.a, 1 AS b FROM (query_single_shard_table.distributed_table RIGHT JOIN query_single_shard_table.reference_table USING (a)) DEBUG: Router planner cannot handle multi-shard select queries DEBUG: recursively planning left side of the right join since the outer side is a recurring rel DEBUG: recursively planning distributed relation "distributed_table" since it is part of a distributed join node that is outer joined with a recurring rel DEBUG: Wrapping relation "distributed_table" to a subquery DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.distributed_table WHERE true DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT reference_table.a, 1 AS b FROM ((SELECT distributed_table_1.a, NULL::integer AS b FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) distributed_table_1) distributed_table RIGHT JOIN query_single_shard_table.reference_table USING (a)) DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: DELETE FROM query_single_shard_table.nullkey_c1_t1 WHERE (b OPERATOR(pg_catalog.=) ANY (SELECT cte.b FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Creating router plan DELETE FROM nullkey_c1_t1 USING reference_table WHERE EXISTS ( SELECT 1 FROM reference_table LEFT JOIN nullkey_c1_t1 USING (a) WHERE nullkey_c1_t1.b IS NULL ); DEBUG: Creating router plan DELETE FROM nullkey_c1_t1 tx USING nullkey_c1_t1 t1 JOIN nullkey_c1_t2 t2 ON (t1.a = t2.a); DEBUG: Creating router plan WITH cte AS ( SELECT * FROM nullkey_c1_t2 ORDER BY 1,2 LIMIT 10 ) DELETE FROM nullkey_c1_t1 WHERE nullkey_c1_t1.a IN (SELECT b FROM cte); DEBUG: Creating router plan DELETE FROM modify_fast_path WHERE value_1 = 15 AND (key = 1 OR value_2 = 'citus'); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DELETE FROM modify_fast_path WHERE key = 2 RETURNING value_1 * 15, value_1::numeric * 16; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan ?column? | ?column? --------------------------------------------------------------------- (0 rows) DELETE FROM modify_fast_path USING modify_fast_path_reference WHERE modify_fast_path.key = modify_fast_path_reference.key AND modify_fast_path.key = 1 AND modify_fast_path_reference.key = 1; DEBUG: Creating router plan PREPARE p2 (int, int, int) AS DELETE FROM modify_fast_path WHERE key = ($2)*$1 AND value_1 = $3; EXECUTE p2(1,1,1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p2(2,2,2); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p2(3,3,3); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p2(4,4,4); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p2(5,5,5); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p2(6,6,6); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE p2(7,7,7); PREPARE prepared_zero_shard_delete(int) AS DELETE FROM modify_fast_path WHERE key = $1 AND false; EXECUTE prepared_zero_shard_delete(1); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_delete(2); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_delete(3); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_delete(4); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_delete(5); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_delete(6); DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan EXECUTE prepared_zero_shard_delete(7); -- test modifying ctes WITH cte AS ( UPDATE modify_fast_path SET value_1 = value_1 + 1 WHERE key = 1 RETURNING * ) SELECT * FROM cte; DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM modify_fast_path WHERE key = 1 RETURNING * ) SELECT * FROM modify_fast_path; DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM modify_fast_path WHERE key = 1 RETURNING * ) SELECT * FROM modify_fast_path_reference WHERE key IN (SELECT key FROM cte); DEBUG: Creating router plan key | value_1 | value_2 --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM reference_table WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c1_t1 WHERE a IN (SELECT a FROM cte); DEBUG: cannot router plan modification of a non-distributed table DEBUG: generating subplan XXX_1 for CTE cte: DELETE FROM query_single_shard_table.reference_table WHERE (a OPERATOR(pg_catalog.=) 1) RETURNING a, b DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT cte.a FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Creating router plan a | b --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM nullkey_c1_t1 WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c1_t2 WHERE a IN (SELECT a FROM cte); DEBUG: Creating router plan a | b --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM nullkey_c1_t1 WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c2_t1 WHERE a IN (SELECT a FROM cte); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte: DELETE FROM query_single_shard_table.nullkey_c1_t1 WHERE (a OPERATOR(pg_catalog.=) 1) RETURNING a, b DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, b FROM query_single_shard_table.nullkey_c2_t1 WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT cte.a FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Creating router plan a | b --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM nullkey_c1_t1 WHERE a = 1 RETURNING * ) SELECT * FROM distributed_table WHERE a IN (SELECT a FROM cte); DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_1 for CTE cte: DELETE FROM query_single_shard_table.nullkey_c1_t1 WHERE (a OPERATOR(pg_catalog.=) 1) RETURNING a, b DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, b FROM query_single_shard_table.distributed_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT cte.a FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Router planner cannot handle multi-shard select queries a | b --------------------------------------------------------------------- (0 rows) -- Below two queries fail very late when -- citus.enable_non_colocated_router_query_pushdown is set to on. SET citus.enable_non_colocated_router_query_pushdown TO ON; WITH cte AS ( DELETE FROM distributed_table WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c1_t1 WHERE a IN (SELECT a FROM cte); DEBUG: Creating router plan DEBUG: query has a single distribution column value: 1 ERROR: relation "query_single_shard_table.nullkey_c1_t1_1620000" does not exist CONTEXT: while executing command on localhost:xxxxx WITH cte AS ( DELETE FROM distributed_table WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c1_t1 WHERE b IN (SELECT b FROM cte); DEBUG: Creating router plan DEBUG: query has a single distribution column value: 1 ERROR: relation "query_single_shard_table.nullkey_c1_t1_1620000" does not exist CONTEXT: while executing command on localhost:xxxxx SET citus.enable_non_colocated_router_query_pushdown TO OFF; WITH cte AS ( DELETE FROM distributed_table WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c1_t1 WHERE a IN (SELECT a FROM cte); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte: DELETE FROM query_single_shard_table.distributed_table WHERE (a OPERATOR(pg_catalog.=) 1) RETURNING a, b DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: query has a single distribution column value: 1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT cte.a FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Creating router plan a | b --------------------------------------------------------------------- (0 rows) WITH cte AS ( DELETE FROM distributed_table WHERE a = 1 RETURNING * ) SELECT * FROM nullkey_c1_t1 WHERE b IN (SELECT b FROM cte); DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte: DELETE FROM query_single_shard_table.distributed_table WHERE (a OPERATOR(pg_catalog.=) 1) RETURNING a, b DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: query has a single distribution column value: 1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, b FROM query_single_shard_table.nullkey_c1_t1 WHERE (b OPERATOR(pg_catalog.=) ANY (SELECT cte.b FROM (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) cte)) DEBUG: Creating router plan a | b --------------------------------------------------------------------- (0 rows) RESET citus.enable_non_colocated_router_query_pushdown; WITH cte AS ( UPDATE modify_fast_path SET value_1 = value_1 + 1 WHERE key = 1 RETURNING * ) UPDATE modify_fast_path SET value_1 = value_1 + 1 WHERE key = 1; DEBUG: Creating router plan WITH cte AS ( DELETE FROM modify_fast_path WHERE key = 1 RETURNING * ) DELETE FROM modify_fast_path WHERE key = 1; DEBUG: Creating router plan -- test window functions SELECT user_id, avg(avg(value_3)) OVER (PARTITION BY user_id, MIN(value_2)) FROM raw_events_first GROUP BY 1 ORDER BY 2 DESC NULLS LAST, 1 DESC; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan user_id | avg --------------------------------------------------------------------- 6 | 6000.1 5 | 5000.1 4 | 4000.1 3 | 3000.1 2 | 2000.1 1 | 1000.1 105 | 104 | 103 | 102 | 101 | 100 | (12 rows) SELECT user_id, max(value_1) OVER (PARTITION BY user_id, MIN(value_2)) FROM ( SELECT DISTINCT us.user_id, us.value_2, us.value_1, random() as r1 FROM raw_events_first as us, raw_events_second WHERE us.user_id = raw_events_second.user_id ORDER BY user_id, value_2 ) s GROUP BY 1, value_1 ORDER BY 2 DESC, 1; DEBUG: Creating router plan user_id | max --------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 6 | 60 5 | 50 4 | 40 3 | 30 2 | 20 1 | 10 5 | 5 4 | 4 3 | 3 2 | 2 1 | 1 (17 rows) SELECT DISTINCT ON (raw_events_second.user_id, rnk) raw_events_second.user_id, rank() OVER my_win AS rnk FROM raw_events_second, raw_events_first WHERE raw_events_first.user_id = raw_events_second.user_id WINDOW my_win AS (PARTITION BY raw_events_second.user_id, raw_events_first.value_1 ORDER BY raw_events_second.time DESC) ORDER BY rnk DESC, 1 DESC LIMIT 10; DEBUG: Creating router plan user_id | rnk --------------------------------------------------------------------- 6 | 2 5 | 2 4 | 2 3 | 2 2 | 2 1 | 2 6 | 1 5 | 1 4 | 1 3 | 1 (10 rows) -- more tests with ctes and subqueries -- CTEs are recursively planned, and subquery foo is also recursively planned. -- Then the final plan becomes a router plan. WITH cte AS MATERIALIZED ( WITH local_cte AS MATERIALIZED ( SELECT * FROM users_table_local ), dist_cte AS MATERIALIZED ( SELECT user_id FROM colocated_events_table ) SELECT dist_cte.user_id FROM local_cte JOIN dist_cte ON dist_cte.user_id=local_cte.user_id ) SELECT count(*) FROM cte, ( SELECT DISTINCT users_table.user_id FROM users_table, colocated_events_table WHERE users_table.user_id = colocated_events_table.user_id AND event_type IN (1,2,3,4) ORDER BY 1 DESC LIMIT 5 ) AS foo WHERE foo.user_id = cte.user_id; DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE cte: WITH local_cte AS MATERIALIZED (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM query_single_shard_table.users_table_local), dist_cte AS MATERIALIZED (SELECT colocated_events_table.user_id FROM query_single_shard_table.colocated_events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table_local DEBUG: generating subplan XXX_2 for CTE dist_cte: SELECT user_id FROM query_single_shard_table.colocated_events_table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT dist_cte.user_id FROM ((SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Creating router plan DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT DISTINCT users_table.user_id FROM query_single_shard_table.users_table, query_single_shard_table.colocated_events_table WHERE ((users_table.user_id OPERATOR(pg_catalog.=) colocated_events_table.user_id) AND (colocated_events_table.event_type OPERATOR(pg_catalog.=) ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id OPERATOR(pg_catalog.=) cte.user_id) DEBUG: Creating router plan count --------------------------------------------------------------------- 1644 (1 row) -- CTEs are colocated, route entire query. WITH cte1 AS ( SELECT * FROM users_table WHERE user_id = 1 ), cte2 AS ( SELECT * FROM colocated_events_table WHERE user_id = 1 ) SELECT cte1.user_id, cte1.value_1, cte2.user_id, cte2.event_type FROM cte1, cte2 ORDER BY cte1.user_id, cte1.value_1, cte2.user_id, cte2.event_type LIMIT 5; DEBUG: CTE cte1 is going to be inlined via distributed planning DEBUG: CTE cte2 is going to be inlined via distributed planning DEBUG: Creating router plan user_id | value_1 | user_id | event_type --------------------------------------------------------------------- 1 | 1 | 1 | 0 1 | 1 | 1 | 0 1 | 1 | 1 | 1 1 | 1 | 1 | 1 1 | 1 | 1 | 2 (5 rows) -- CTEs aren't colocated, CTEs become intermediate results. WITH cte1 AS MATERIALIZED ( SELECT * FROM users_table WHERE user_id = 1 ), cte2 AS MATERIALIZED ( SELECT * FROM non_colocated_events_table WHERE user_id = 6 ) SELECT cte1.user_id, cte1.value_1, cte2.user_id, cte2.user_id FROM cte1, cte2 ORDER BY cte1.user_id, cte1.value_1, cte2.user_id, cte2.event_type LIMIT 5; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte1: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table WHERE (user_id OPERATOR(pg_catalog.=) 1) DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for CTE cte2: SELECT user_id, "time", event_type, value_2, value_3, value_4 FROM query_single_shard_table.non_colocated_events_table WHERE (user_id OPERATOR(pg_catalog.=) 6) DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT cte1.user_id, cte1.value_1, cte2.user_id, cte2.user_id FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) cte1, (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) cte2 ORDER BY cte1.user_id, cte1.value_1, cte2.user_id, cte2.event_type LIMIT 5 DEBUG: Creating router plan user_id | value_1 | user_id | user_id --------------------------------------------------------------------- 1 | 1 | 6 | 6 1 | 1 | 6 | 6 1 | 1 | 6 | 6 1 | 1 | 6 | 6 1 | 1 | 6 | 6 (5 rows) -- users_table & colocated_users_table are colocated, route entire query. WITH cte1 AS ( SELECT * FROM users_table WHERE user_id = 1 ) UPDATE colocated_users_table dt SET value = cte1.value_1 FROM cte1 WHERE cte1.user_id = dt.id AND dt.id = 1; DEBUG: Creating router plan -- users_table & non_colocated_users_table are not colocated, cte is recursive planned. WITH cte1 AS ( SELECT * FROM users_table WHERE user_id = 1 ) UPDATE non_colocated_users_table dt SET value = cte1.value_1 FROM cte1 WHERE cte1.user_id = dt.id AND dt.id = 1; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte1: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table WHERE (user_id OPERATOR(pg_catalog.=) 1) DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.non_colocated_users_table dt SET value = cte1.value_1 FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) cte1 WHERE ((cte1.user_id OPERATOR(pg_catalog.=) dt.id) AND (dt.id OPERATOR(pg_catalog.=) 1)) DEBUG: Creating router plan -- All relations are not colocated, CTEs become intermediate results. WITH cte1 AS MATERIALIZED ( SELECT * FROM users_table WHERE user_id = 1 ), cte2 AS MATERIALIZED ( SELECT * FROM non_colocated_events_table WHERE user_id = 6 ) UPDATE non_colocated_users_table dt SET value = cte1.value_1 + cte2.event_type FROM cte1, cte2 WHERE cte1.user_id = dt.id AND dt.id = 1; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte1: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table WHERE (user_id OPERATOR(pg_catalog.=) 1) DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for CTE cte2: SELECT user_id, "time", event_type, value_2, value_3, value_4 FROM query_single_shard_table.non_colocated_events_table WHERE (user_id OPERATOR(pg_catalog.=) 6) DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.non_colocated_users_table dt SET value = (cte1.value_1 OPERATOR(pg_catalog.+) cte2.event_type) FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) cte1, (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) cte2 WHERE ((cte1.user_id OPERATOR(pg_catalog.=) dt.id) AND (dt.id OPERATOR(pg_catalog.=) 1)) DEBUG: Creating router plan -- Volatile function calls should not be routed. WITH cte1 AS MATERIALIZED (SELECT id, value FROM func()) UPDATE colocated_users_table dt SET value = cte1.value FROM cte1 WHERE dt.id = 1; DEBUG: Router planner doesn't support VOLATILE functions in common table expressions. DEBUG: generating subplan XXX_1 for CTE cte1: SELECT id, value FROM query_single_shard_table.func() func(id, value) DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE query_single_shard_table.colocated_users_table dt SET value = cte1.value FROM (SELECT intermediate_result.id, intermediate_result.value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer, value integer)) cte1 WHERE (dt.id OPERATOR(pg_catalog.=) 1) DEBUG: Creating router plan -- CTEs are recursively planned, and subquery foo is also recursively planned. WITH cte AS MATERIALIZED ( WITH local_cte AS MATERIALIZED ( SELECT * FROM users_table_local ), dist_cte AS MATERIALIZED ( SELECT user_id FROM colocated_events_table ) SELECT dist_cte.user_id FROM local_cte JOIN dist_cte ON dist_cte.user_id=local_cte.user_id ) SELECT count(*) FROM cte, ( SELECT DISTINCT users_table.user_id FROM users_table, colocated_events_table WHERE users_table.user_id = colocated_events_table.user_id AND event_type IN (1,2,3,4) ORDER BY 1 DESC LIMIT 5 ) AS foo, colocated_events_table WHERE foo.user_id = cte.user_id AND colocated_events_table.user_id = cte.user_id; DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE cte: WITH local_cte AS MATERIALIZED (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM query_single_shard_table.users_table_local), dist_cte AS MATERIALIZED (SELECT colocated_events_table.user_id FROM query_single_shard_table.colocated_events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table_local DEBUG: generating subplan XXX_2 for CTE dist_cte: SELECT user_id FROM query_single_shard_table.colocated_events_table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT dist_cte.user_id FROM ((SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Creating router plan DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT DISTINCT users_table.user_id FROM query_single_shard_table.users_table, query_single_shard_table.colocated_events_table WHERE ((users_table.user_id OPERATOR(pg_catalog.=) colocated_events_table.user_id) AND (colocated_events_table.event_type OPERATOR(pg_catalog.=) ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo, query_single_shard_table.colocated_events_table WHERE ((foo.user_id OPERATOR(pg_catalog.=) cte.user_id) AND (colocated_events_table.user_id OPERATOR(pg_catalog.=) cte.user_id)) DEBUG: Creating router plan count --------------------------------------------------------------------- 30608 (1 row) -- CTEs are replaced and subquery in WHERE is also replaced. WITH cte AS MATERIALIZED ( WITH local_cte AS MATERIALIZED ( SELECT * FROM users_table_local ), dist_cte AS MATERIALIZED ( SELECT user_id FROM colocated_events_table ) SELECT dist_cte.user_id FROM local_cte JOIN dist_cte ON dist_cte.user_id=local_cte.user_id ) SELECT DISTINCT cte.user_id FROM users_table, cte WHERE users_table.user_id = cte.user_id AND users_table.user_id IN ( SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5 ) ORDER BY 1 DESC; DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE cte: WITH local_cte AS MATERIALIZED (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM query_single_shard_table.users_table_local), dist_cte AS MATERIALIZED (SELECT colocated_events_table.user_id FROM query_single_shard_table.colocated_events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table_local DEBUG: generating subplan XXX_2 for CTE dist_cte: SELECT user_id FROM query_single_shard_table.colocated_events_table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT dist_cte.user_id FROM ((SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Creating router plan DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT DISTINCT value_2 FROM query_single_shard_table.users_table WHERE ((value_1 OPERATOR(pg_catalog.>=) 1) AND (value_1 OPERATOR(pg_catalog.<=) 20)) ORDER BY value_2 LIMIT 5 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT DISTINCT cte.user_id FROM query_single_shard_table.users_table, (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE ((users_table.user_id OPERATOR(pg_catalog.=) cte.user_id) AND (users_table.user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_2 FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) ORDER BY cte.user_id DESC DEBUG: Creating router plan user_id --------------------------------------------------------------------- 4 3 2 1 (4 rows) -- Subquery in WHERE clause is planned recursively due to the recurring table -- in FROM clause. WITH cte AS MATERIALIZED ( WITH local_cte AS MATERIALIZED ( SELECT * FROM users_table_local ), dist_cte AS MATERIALIZED ( SELECT user_id FROM colocated_events_table ) SELECT dist_cte.user_id FROM local_cte JOIN dist_cte ON dist_cte.user_id=local_cte.user_id ) SELECT DISTINCT cte.user_id FROM cte WHERE cte.user_id IN (SELECT DISTINCT user_id FROM users_table WHERE value_1 >= 1 AND value_1 <= 20) ORDER BY 1 DESC; DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE cte: WITH local_cte AS MATERIALIZED (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM query_single_shard_table.users_table_local), dist_cte AS MATERIALIZED (SELECT colocated_events_table.user_id FROM query_single_shard_table.colocated_events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table_local DEBUG: generating subplan XXX_2 for CTE dist_cte: SELECT user_id FROM query_single_shard_table.colocated_events_table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT dist_cte.user_id FROM ((SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Creating router plan DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT DISTINCT user_id FROM query_single_shard_table.users_table WHERE ((value_1 OPERATOR(pg_catalog.>=) 1) AND (value_1 OPERATOR(pg_catalog.<=) 20)) DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT DISTINCT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) ORDER BY user_id DESC DEBUG: Creating router plan user_id --------------------------------------------------------------------- 6 5 4 3 2 1 (6 rows) -- CTEs inside a subquery and the final query becomes a router -- query. SELECT user_id FROM ( WITH cte AS MATERIALIZED ( SELECT DISTINCT users_table.user_id FROM users_table, colocated_events_table WHERE users_table.user_id = colocated_events_table.user_id AND event_type IN (1,2,3,4) ) SELECT * FROM cte ORDER BY 1 DESC ) AS foo ORDER BY 1 DESC; DEBUG: Creating router plan user_id --------------------------------------------------------------------- 6 5 4 3 2 1 (6 rows) -- CTEs inside a deeper subquery and also the subquery that contains the CTE are -- recursively planned. SELECT DISTINCT bar.user_id FROM ( WITH cte AS MATERIALIZED ( SELECT DISTINCT users_table.user_id FROM users_table, colocated_events_table WHERE users_table.user_id = colocated_events_table.user_id AND event_type IN (1,2,3,4) ) SELECT * FROM cte ORDER BY 1 DESC ) AS foo, ( SELECT users_table.user_id, some_events.event_type FROM users_table, ( WITH cte AS MATERIALIZED ( SELECT event_type, users_table.user_id FROM users_table, colocated_events_table WHERE users_table.user_id = colocated_events_table.user_id AND value_1 IN (1,2) ) SELECT * FROM cte ORDER BY 1 DESC ) AS some_events WHERE users_table.user_id = some_events.user_id AND event_type IN (1,2,3,4) ORDER BY 2,1 LIMIT 2 ) AS bar WHERE foo.user_id = bar.user_id ORDER BY 1 DESC LIMIT 5; DEBUG: Creating router plan user_id --------------------------------------------------------------------- 1 (1 row) -- Recursively plan subqueries inside the CTEs that contains LIMIT and OFFSET. WITH cte AS MATERIALIZED ( WITH local_cte AS MATERIALIZED ( SELECT * FROM users_table_local ), dist_cte AS MATERIALIZED ( SELECT user_id FROM colocated_events_table, (SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo WHERE colocated_events_table.user_id = foo.value_2 AND colocated_events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3) ) SELECT dist_cte.user_id FROM local_cte JOIN dist_cte ON dist_cte.user_id=local_cte.user_id ) SELECT count(*) FROM cte, ( SELECT DISTINCT users_table.user_id FROM users_table, colocated_events_table WHERE users_table.user_id = colocated_events_table.user_id AND event_type IN (1,2,3,4) ORDER BY 1 DESC LIMIT 5 ) AS foo WHERE foo.user_id = cte.user_id; DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE cte: WITH local_cte AS MATERIALIZED (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM query_single_shard_table.users_table_local), dist_cte AS MATERIALIZED (SELECT colocated_events_table.user_id FROM query_single_shard_table.colocated_events_table, (SELECT DISTINCT users_table.value_2 FROM query_single_shard_table.users_table OFFSET 0) foo WHERE ((colocated_events_table.user_id OPERATOR(pg_catalog.=) foo.value_2) AND (colocated_events_table.user_id OPERATOR(pg_catalog.=) ANY (SELECT DISTINCT users_table.value_1 FROM query_single_shard_table.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Local tables cannot be used in distributed queries. DEBUG: generating subplan XXX_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM query_single_shard_table.users_table_local DEBUG: generating subplan XXX_2 for CTE dist_cte: SELECT colocated_events_table.user_id FROM query_single_shard_table.colocated_events_table, (SELECT DISTINCT users_table.value_2 FROM query_single_shard_table.users_table OFFSET 0) foo WHERE ((colocated_events_table.user_id OPERATOR(pg_catalog.=) foo.value_2) AND (colocated_events_table.user_id OPERATOR(pg_catalog.=) ANY (SELECT DISTINCT users_table.value_1 FROM query_single_shard_table.users_table ORDER BY users_table.value_1 LIMIT 3))) DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT dist_cte.user_id FROM ((SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id OPERATOR(pg_catalog.=) local_cte.user_id))) DEBUG: Creating router plan DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT DISTINCT users_table.user_id FROM query_single_shard_table.users_table, query_single_shard_table.colocated_events_table WHERE ((users_table.user_id OPERATOR(pg_catalog.=) colocated_events_table.user_id) AND (colocated_events_table.event_type OPERATOR(pg_catalog.=) ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id OPERATOR(pg_catalog.=) cte.user_id) DEBUG: Creating router plan count --------------------------------------------------------------------- 432 (1 row) -- more tests with sublinks and subqueries in targetlist SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1), (SELECT e.value_2) FROM non_colocated_events_table e ORDER BY 1,2 LIMIT 1; DEBUG: Creating router plan event_type | value_2 | value_2 --------------------------------------------------------------------- 0 | | 0 (1 row) SELECT event_type, (SELECT time FROM users_table WHERE user_id = e.user_id ORDER BY time LIMIT 1) FROM non_colocated_events_table e ORDER BY 1,2 LIMIT 1; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 1 ERROR: cannot push down this subquery DETAIL: users_table and non_colocated_events_table are not colocated SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.value_2) FROM non_colocated_events_table e ORDER BY 1,2 LIMIT 1; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 1 ERROR: cannot push down this subquery DETAIL: users_table and non_colocated_events_table are not colocated SELECT event_type, (SELECT max(time) FROM users_table) FROM non_colocated_events_table e ORDER BY 1,2 LIMIT 1; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT max("time") AS max FROM query_single_shard_table.users_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT event_type, (SELECT intermediate_result.max FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) AS max FROM query_single_shard_table.non_colocated_events_table e ORDER BY event_type, (SELECT intermediate_result.max FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) LIMIT 1 DEBUG: Creating router plan event_type | max --------------------------------------------------------------------- 0 | Thu Nov 23 17:30:34.635085 2017 (1 row) WITH cte_1 AS (SELECT max(time) FROM users_table) SELECT event_type, (SELECT * FROM cte_1) FROM non_colocated_events_table e ORDER BY 1,2 LIMIT 1; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT max("time") AS max FROM query_single_shard_table.users_table DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT event_type, (SELECT cte_1.max FROM (SELECT intermediate_result.max FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) cte_1) AS max FROM query_single_shard_table.non_colocated_events_table e ORDER BY event_type, (SELECT cte_1.max FROM (SELECT intermediate_result.max FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) cte_1) LIMIT 1 DEBUG: Creating router plan event_type | max --------------------------------------------------------------------- 0 | Thu Nov 23 17:30:34.635085 2017 (1 row) WITH cte_1 AS (SELECT max(time) FROM users_table) SELECT event_type, (SELECT * FROM cte_1 LIMIT 1) FROM non_colocated_events_table e ORDER BY 1,2 LIMIT 1; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT max("time") AS max FROM query_single_shard_table.users_table DEBUG: Creating router plan DEBUG: generating subplan XXX_2 for subquery SELECT max FROM (SELECT intermediate_result.max FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) cte_1 LIMIT 1 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT event_type, (SELECT intermediate_result.max FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) AS max FROM query_single_shard_table.non_colocated_events_table e ORDER BY event_type, (SELECT intermediate_result.max FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(max timestamp without time zone)) LIMIT 1 DEBUG: Creating router plan event_type | max --------------------------------------------------------------------- 0 | Thu Nov 23 17:30:34.635085 2017 (1 row) WITH cte_1 AS (SELECT max(time) m FROM users_table) SELECT count(*), (SELECT * FROM cte_1 c1 join cte_1 c2 using (m)) FROM non_colocated_events_table e GROUP BY 2 ORDER BY 1,2 LIMIT 1; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT max("time") AS m FROM query_single_shard_table.users_table DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count, (SELECT c1.m FROM ((SELECT intermediate_result.m FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(m timestamp without time zone)) c1 JOIN (SELECT intermediate_result.m FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(m timestamp without time zone)) c2 USING (m))) AS m FROM query_single_shard_table.non_colocated_events_table e GROUP BY (SELECT c1.m FROM ((SELECT intermediate_result.m FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(m timestamp without time zone)) c1 JOIN (SELECT intermediate_result.m FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(m timestamp without time zone)) c2 USING (m))) ORDER BY (count(*)), (SELECT c1.m FROM ((SELECT intermediate_result.m FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(m timestamp without time zone)) c1 JOIN (SELECT intermediate_result.m FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(m timestamp without time zone)) c2 USING (m))) LIMIT 1 DEBUG: Creating router plan count | m --------------------------------------------------------------------- 101 | Thu Nov 23 17:30:34.635085 2017 (1 row) WITH cte_1 AS (SELECT min(user_id) u, max(time) m FROM users_table) SELECT count(*), (SELECT max(time) FROM users_table WHERE user_id = cte_1.u GROUP BY user_id) FROM cte_1 GROUP BY 2 ORDER BY 1,2 LIMIT 1; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Creating router plan count | max --------------------------------------------------------------------- 1 | Thu Nov 23 17:30:34.635085 2017 (1 row) SELECT sum(e.user_id) + (SELECT max(value_3) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) FROM non_colocated_events_table e GROUP BY e.user_id ORDER BY 1 LIMIT 3; DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot push down subquery on the target list DETAIL: Subqueries in the SELECT part of the query can only be pushed down if they happen before aggregates and window functions SELECT e.user_id, sum((SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id)) OVER (PARTITION BY e.user_id) FROM non_colocated_events_table e ORDER BY 1, 2 LIMIT 3; DEBUG: Creating router plan user_id | sum --------------------------------------------------------------------- 1 | 1 | 1 | (3 rows) SELECT (SELECT (SELECT e.user_id + user_id) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) FROM non_colocated_events_table e GROUP BY 1 ORDER BY 1 LIMIT 3; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 3 ERROR: cannot push down this subquery DETAIL: users_table and non_colocated_events_table are not colocated SELECT (SELECT (SELECT e.user_id + user_id) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id) FROM non_colocated_events_table e GROUP BY 1 ORDER BY 1 LIMIT 3; DEBUG: Creating router plan ?column? --------------------------------------------------------------------- (1 row) WITH cte_1 AS (SELECT user_id FROM users_table ORDER BY 1 LIMIT 1) SELECT (SELECT (SELECT e.user_id + user_id) FROM cte_1 WHERE user_id = e.user_id GROUP BY user_id) FROM non_colocated_events_table e GROUP BY 1 ORDER BY 1 LIMIT 3; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT user_id FROM query_single_shard_table.users_table ORDER BY user_id LIMIT 1 DEBUG: skipping recursive planning for the subquery since it contains references to outer queries DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (SELECT (SELECT (e.user_id OPERATOR(pg_catalog.+) cte_1.user_id)) FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte_1 WHERE (cte_1.user_id OPERATOR(pg_catalog.=) e.user_id) GROUP BY cte_1.user_id) FROM query_single_shard_table.non_colocated_events_table e GROUP BY (SELECT (SELECT (e.user_id OPERATOR(pg_catalog.+) cte_1.user_id)) FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte_1 WHERE (cte_1.user_id OPERATOR(pg_catalog.=) e.user_id) GROUP BY cte_1.user_id) ORDER BY (SELECT (SELECT (e.user_id OPERATOR(pg_catalog.+) cte_1.user_id)) FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte_1 WHERE (cte_1.user_id OPERATOR(pg_catalog.=) e.user_id) GROUP BY cte_1.user_id) LIMIT 3 DEBUG: Creating router plan ?column? --------------------------------------------------------------------- 2 (2 rows) SELECT (SELECT (SELECT e.user_id + user_id) FROM (SELECT 1 AS user_id) s WHERE user_id = e.user_id GROUP BY user_id) FROM non_colocated_events_table e GROUP BY 1 ORDER BY 1 LIMIT 3; DEBUG: Creating router plan ?column? --------------------------------------------------------------------- 2 (2 rows) CREATE TEMP VIEW view_1 AS (SELECT user_id, value_2 FROM users_table WHERE user_id = 1 AND value_1 = 1 ORDER BY 1,2); WARNING: "view view_1" has dependency on unsupported object "schema pg_temp_xxx" DETAIL: "view view_1" will be created only locally SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY value_2) FROM non_colocated_events_table e GROUP BY 1 ORDER BY 1 LIMIT 3; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: push down of limit count: 3 ERROR: cannot push down this subquery DETAIL: users_table and non_colocated_events_table are not colocated SELECT user_id, count(*) FROM non_colocated_events_table e1 GROUP BY user_id HAVING count(*) > (SELECT count(*) FROM (SELECT (SELECT sum(user_id) FROM users_table WHERE user_id = u1.user_id GROUP BY user_id) FROM users_table u1 GROUP BY user_id) as foo) ORDER BY 1 DESC; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT count(*) AS count FROM (SELECT (SELECT sum(users_table.user_id) AS sum FROM query_single_shard_table.users_table WHERE (users_table.user_id OPERATOR(pg_catalog.=) u1.user_id) GROUP BY users_table.user_id) AS sum FROM query_single_shard_table.users_table u1 GROUP BY u1.user_id) foo DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT user_id, count(*) AS count FROM query_single_shard_table.non_colocated_events_table e1 GROUP BY user_id HAVING (count(*) OPERATOR(pg_catalog.>) (SELECT intermediate_result.count FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(count bigint))) ORDER BY user_id DESC DEBUG: Creating router plan user_id | count --------------------------------------------------------------------- 6 | 10 5 | 14 4 | 17 3 | 21 2 | 24 1 | 15 (6 rows) SELECT count(*) FROM (SELECT (SELECT user_id FROM users_table WHERE user_id = u1.user_id FOR UPDATE) FROM users_table u1 GROUP BY user_id) as foo; DEBUG: Creating router plan count --------------------------------------------------------------------- 6 (1 row) -- test single hash repartition join SET citus.log_multi_join_order TO ON; SET client_min_messages TO DEBUG1; SET citus.enable_repartition_joins TO ON; SET citus.enable_single_hash_repartition_joins TO ON; SELECT count(*) FROM nullkey_c1_t1 JOIN distributed_table USING(a); LOG: join order: [ "nullkey_c1_t1" ][ single hash partition join "distributed_table" ] count --------------------------------------------------------------------- 0 (1 row) select count(*) from nullkey_c1_t1 JOIN nullkey_c2_t2 USING(a); LOG: join order: [ "nullkey_c1_t1" ][ dual partition join "nullkey_c2_t2" ] count --------------------------------------------------------------------- 0 (1 row) RESET citus.log_multi_join_order; SET client_min_messages TO DEBUG2; RESET citus.enable_repartition_joins; RESET citus.enable_single_hash_repartition_joins; SET client_min_messages TO DEBUG1; SET citus.enable_repartition_joins TO ON; SET citus.log_multi_join_order TO ON; SELECT count(*), avg(avgsub.a) FROM ( SELECT table_0.a FROM reference_table AS table_0 INNER JOIN nullkey_c1_t1 AS table_1 USING (a) INNER JOIN reference_table AS table_2 USING (a) INNER JOIN nullkey_c2_t1 AS table_3 USING (a) ORDER BY a LIMIT 7 ) AS avgsub; LOG: join order: [ "nullkey_c1_t1" ][ reference join "reference_table" ][ reference join "reference_table" ][ dual partition join "nullkey_c2_t1" ] DEBUG: push down of limit count: 7 DEBUG: generating subplan XXX_1 for subquery SELECT table_0.a FROM (((query_single_shard_table.reference_table table_0 JOIN query_single_shard_table.nullkey_c1_t1 table_1 USING (a)) JOIN query_single_shard_table.reference_table table_2 USING (a)) JOIN query_single_shard_table.nullkey_c2_t1 table_3 USING (a)) ORDER BY table_0.a LIMIT 7 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count, avg(a) AS avg FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) avgsub count | avg --------------------------------------------------------------------- 0 | (1 row) SET citus.enable_single_hash_repartition_joins TO ON; -- We prefer dual-hash repartition join over single-hash repartition join -- even if citus.enable_single_hash_repartition_joins is set to ON. This -- happens because single shard tables don't have a shard key. SELECT count(*), avg(avgsub.a) FROM ( SELECT table_0.a FROM reference_table AS table_0 INNER JOIN nullkey_c1_t1 AS table_1 USING (a) INNER JOIN reference_table AS table_2 USING (a) INNER JOIN nullkey_c2_t1 AS table_3 USING (a) ORDER BY a LIMIT 7 ) AS avgsub; LOG: join order: [ "nullkey_c1_t1" ][ reference join "reference_table" ][ reference join "reference_table" ][ dual partition join "nullkey_c2_t1" ] DEBUG: push down of limit count: 7 DEBUG: generating subplan XXX_1 for subquery SELECT table_0.a FROM (((query_single_shard_table.reference_table table_0 JOIN query_single_shard_table.nullkey_c1_t1 table_1 USING (a)) JOIN query_single_shard_table.reference_table table_2 USING (a)) JOIN query_single_shard_table.nullkey_c2_t1 table_3 USING (a)) ORDER BY table_0.a LIMIT 7 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count, avg(a) AS avg FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) avgsub count | avg --------------------------------------------------------------------- 0 | (1 row) RESET citus.enable_single_hash_repartition_joins; SET client_min_messages TO DEBUG2; RESET citus.enable_repartition_joins; RESET citus.log_multi_join_order; SELECT count(*), avg(avgsub.a) FROM ( SELECT table_0.a FROM nullkey_c1_t1 AS table_0 RIGHT JOIN ( SELECT table_2.a FROM ( SELECT table_3.a FROM nullkey_c2_t1 AS table_3 ORDER BY a LIMIT 0 ) AS table_2 INNER JOIN nullkey_c2_t1 AS table_4 USING (a) WHERE table_4.a < 8 ) AS table_1 USING (a) ) AS avgsub; DEBUG: router planner does not support queries that reference non-colocated distributed tables DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan DEBUG: generating subplan XXX_1 for subquery SELECT a FROM query_single_shard_table.nullkey_c2_t1 table_3 ORDER BY a LIMIT 0 DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count, avg(a) AS avg FROM (SELECT table_0.a FROM (query_single_shard_table.nullkey_c1_t1 table_0 RIGHT JOIN (SELECT table_2.a FROM ((SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) table_2 JOIN query_single_shard_table.nullkey_c2_t1 table_4 USING (a)) WHERE (table_4.a OPERATOR(pg_catalog.<) 8)) table_1 USING (a))) avgsub DEBUG: router planner does not support queries that reference non-colocated distributed tables ERROR: cannot perform a lateral outer join when a distributed subquery references complex subqueries, CTEs or local tables -- test nested exec CREATE FUNCTION dist_query_single_shard(p_key int) RETURNS bigint LANGUAGE plpgsql AS $$ DECLARE result bigint; BEGIN SELECT count(*) INTO result FROM query_single_shard_table.nullkey_c1_t1 WHERE a = p_key; RETURN result; END; $$; DEBUG: switching to sequential query execution mode DETAIL: A command for a distributed function is run. To make sure subsequent commands see the function correctly we need to make sure to use only one connection for all future commands CREATE FUNCTION ref_query() RETURNS bigint LANGUAGE plpgsql AS $$ DECLARE result bigint; BEGIN SELECT count(*) INTO result FROM query_single_shard_table.reference_table; RETURN result; END; $$; DEBUG: switching to sequential query execution mode DETAIL: A command for a distributed function is run. To make sure subsequent commands see the function correctly we need to make sure to use only one connection for all future commands SELECT dist_query_single_shard(count(*)::int) FROM nullkey_c1_t1; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan ERROR: cannot execute a distributed query from a query on a shard DETAIL: Executing a distributed query in a function call that may be pushed to a remote node can lead to incorrect results. HINT: Avoid nesting of distributed queries or use alter user current_user set citus.allow_nested_distributed_execution to on to allow it with possible incorrectness. CONTEXT: SQL statement "SELECT count(*) FROM query_single_shard_table.nullkey_c1_t1 WHERE a = p_key" PL/pgSQL function query_single_shard_table.dist_query_single_shard(integer) line XX at SQL statement while executing command on localhost:xxxxx SELECT ref_query()+count(*) FROM nullkey_c1_t1; DEBUG: Distributed planning for a fast-path router query DEBUG: Creating router plan ERROR: cannot execute a distributed query from a query on a shard DETAIL: Executing a distributed query in a function call that may be pushed to a remote node can lead to incorrect results. HINT: Avoid nesting of distributed queries or use alter user current_user set citus.allow_nested_distributed_execution to on to allow it with possible incorrectness. CONTEXT: SQL statement "SELECT count(*) FROM query_single_shard_table.reference_table" PL/pgSQL function query_single_shard_table.ref_query() line XX at SQL statement while executing command on localhost:xxxxx SET client_min_messages TO ERROR; DROP SCHEMA query_single_shard_table CASCADE;