--
-- CITUS_LOCAL_TABLES_QUERIES
--
\set VERBOSITY terse
SET citus.next_shard_id TO 1509000;
SET citus.shard_replication_factor TO 1;
SET citus.enable_local_execution TO ON;
SET citus.log_local_commands TO ON;
CREATE SCHEMA citus_local_table_queries;
SET search_path TO citus_local_table_queries;
-- ensure that coordinator is added to pg_dist_node
SET client_min_messages to ERROR;
SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0);
 ?column?
---------------------------------------------------------------------
        1
(1 row)

RESET client_min_messages;
CREATE TABLE dummy_reference_table(a int unique, b int);
SELECT create_reference_table('dummy_reference_table');
 create_reference_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE citus_local_table(a int, b int);
ALTER TABLE citus_local_table ADD CONSTRAINT fkey_to_dummy_1 FOREIGN KEY (a) REFERENCES dummy_reference_table(a);
NOTICE:  executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1509001, 'citus_local_table_queries', 1509000, 'citus_local_table_queries', 'ALTER TABLE citus_local_table ADD CONSTRAINT fkey_to_dummy_1 FOREIGN KEY (a) REFERENCES dummy_reference_table(a);')
CREATE TABLE citus_local_table_2(a int, b int);
ALTER TABLE citus_local_table_2 ADD CONSTRAINT fkey_to_dummy_2 FOREIGN KEY (a) REFERENCES dummy_reference_table(a);
NOTICE:  executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1509002, 'citus_local_table_queries', 1509000, 'citus_local_table_queries', 'ALTER TABLE citus_local_table_2 ADD CONSTRAINT fkey_to_dummy_2 FOREIGN KEY (a) REFERENCES dummy_reference_table(a);')
CREATE TABLE reference_table(a int, b int);
SELECT create_reference_table('reference_table');
 create_reference_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE distributed_table(a int, b int);
SELECT create_distributed_table('distributed_table', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE postgres_local_table(a int, b int);
-- Define a helper function to truncate & insert some data into our test tables
-- We should call this function at some places in this test file to prevent
-- test to take a long time.
-- We shouldn't use LIMIT in INSERT SELECT queries to make the test faster as
-- LIMIT would force planner to wrap SELECT query in an intermediate result and
-- this might reduce the coverage of the test cases.
CREATE FUNCTION clear_and_init_test_tables() RETURNS void AS $$
    BEGIN
		SET client_min_messages to ERROR;

		TRUNCATE postgres_local_table, citus_local_table, reference_table, distributed_table, dummy_reference_table, citus_local_table_2;

		INSERT INTO dummy_reference_table SELECT i, i FROM generate_series(0, 5) i;
		INSERT INTO citus_local_table SELECT i, i FROM generate_series(0, 5) i;
		INSERT INTO citus_local_table_2 SELECT i, i FROM generate_series(0, 5) i;
		INSERT INTO postgres_local_table SELECT i, i FROM generate_series(0, 5) i;
		INSERT INTO distributed_table SELECT i, i FROM generate_series(0, 5) i;
		INSERT INTO reference_table SELECT i, i FROM generate_series(0, 5) i;

		RESET client_min_messages;
    END;
$$ LANGUAGE plpgsql;
---------------------------------------------------------------------
---- SELECT ----
---------------------------------------------------------------------
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

-- join between citus local tables and reference tables would succeed
SELECT count(*) FROM citus_local_table, reference_table WHERE citus_local_table.a = reference_table.a;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table, citus_local_table_queries.reference_table_1509003 reference_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a)
 count
---------------------------------------------------------------------
     6
(1 row)

SELECT * FROM citus_local_table, reference_table WHERE citus_local_table.a = reference_table.a ORDER BY 1,2,3,4 FOR UPDATE;
NOTICE:  executing the command locally: SELECT citus_local_table.a, citus_local_table.b, reference_table.a, reference_table.b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table, citus_local_table_queries.reference_table_1509003 reference_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a) ORDER BY citus_local_table.a, citus_local_table.b, reference_table.a, reference_table.b FOR UPDATE OF citus_local_table FOR UPDATE OF reference_table
 a | b | a | b
---------------------------------------------------------------------
 0 | 0 | 0 | 0
 1 | 1 | 1 | 1
 2 | 2 | 2 | 2
 3 | 3 | 3 | 3
 4 | 4 | 4 | 4
 5 | 5 | 5 | 5
(6 rows)

-- should work
WITH cte_1 AS
	(SELECT * FROM citus_local_table, reference_table WHERE citus_local_table.a = reference_table.a ORDER BY 1,2,3,4 FOR UPDATE)
SELECT count(*) FROM cte_1;
NOTICE:  executing the command locally: WITH cte_1 AS (SELECT citus_local_table.a, citus_local_table.b, reference_table.a, reference_table.b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table, citus_local_table_queries.reference_table_1509003 reference_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a) ORDER BY citus_local_table.a, citus_local_table.b, reference_table.a, reference_table.b FOR UPDATE OF citus_local_table FOR UPDATE OF reference_table) SELECT count(*) AS count FROM cte_1 cte_1(a, b, a_1, b_1)
 count
---------------------------------------------------------------------
     6
(1 row)

-- should work as joins are between ctes
WITH cte_citus_local_table AS
	(SELECT * FROM citus_local_table),
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_citus_local_table, cte_postgres_local_table
WHERE  cte_citus_local_table.a = 1 AND cte_distributed_table.a = 1;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

-- should fail as we don't support direct joins between distributed/local tables
SELECT count(*) FROM distributed_table d1, distributed_table d2, citus_local_table;
ERROR:  complex joins are only supported when all distributed tables are co-located and joined on their distribution columns
-- local table inside subquery should just work
SELECT count(*) FROM
(
	SELECT * FROM (SELECT * FROM citus_local_table) as subquery_inner
) as subquery_top;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (SELECT subquery_inner.a, subquery_inner.b FROM (SELECT citus_local_table.a, citus_local_table.b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table) subquery_inner) subquery_top
 count
---------------------------------------------------------------------
     6
(1 row)

SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

-- join between citus/postgres local tables should just work
SELECT count(*) FROM
(
	SELECT * FROM (SELECT count(*) FROM citus_local_table, postgres_local_table) as subquery_inner
) as subquery_top;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (SELECT subquery_inner.count FROM (SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table, citus_local_table_queries.postgres_local_table) subquery_inner) subquery_top
 count
---------------------------------------------------------------------
     1
(1 row)

-- should fail as we don't support direct joins between distributed/local tables
SELECT count(*) FROM
(
	SELECT *, random() FROM (SELECT *, random() FROM citus_local_table, distributed_table) as subquery_inner
) as subquery_top;
NOTICE:  executing the command locally: SELECT NULL::integer AS "dummy-1" FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
 count
---------------------------------------------------------------------
    36
(1 row)

-- should fail as we don't support direct joins between distributed/local tables
SELECT count(*) FROM
(
	SELECT *, random()
		FROM (
				WITH cte_1 AS (SELECT *, random() FROM citus_local_table, distributed_table) SELECT * FROM cte_1) as subquery_inner
) as subquery_top;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (SELECT subquery_inner.a, subquery_inner.b, subquery_inner.a_1 AS a, subquery_inner.b_1 AS b, subquery_inner.random, random() AS random FROM (SELECT cte_1.a, cte_1.b, cte_1.a_1 AS a, cte_1.b_1 AS b, cte_1.random FROM (SELECT intermediate_result.a, intermediate_result.b, intermediate_result.a_1 AS a, intermediate_result.b_1 AS b, intermediate_result.random FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer, a_1 integer, b_1 integer, random double precision)) cte_1(a, b, a_1, b_1, random)) subquery_inner(a, b, a_1, b_1, random)) subquery_top(a, b, a_1, b_1, random, random_1)
 count
---------------------------------------------------------------------
    36
(1 row)

-- should be  fine
SELECT count(*) FROM
(
	SELECT *, random()
		FROM (
				WITH cte_1 AS (SELECT *, random() FROM citus_local_table), cte_2  AS (SELECT * FROM distributed_table) SELECT count(*) FROM cte_1, cte_2
				) as subquery_inner
) as subquery_top;
NOTICE:  executing the command locally: SELECT a, b, random() AS random FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (SELECT subquery_inner.count, random() AS random FROM (SELECT intermediate_result.count FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) subquery_inner) subquery_top
 count
---------------------------------------------------------------------
     1
(1 row)

SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

-- prepared statement
PREPARE citus_local_only AS SELECT count(*) FROM citus_local_table;
-- execute 6 times, local tables without params
EXECUTE citus_local_only;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

EXECUTE citus_local_only;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

EXECUTE citus_local_only;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

EXECUTE citus_local_only;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

EXECUTE citus_local_only;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

EXECUTE citus_local_only;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

-- execute 6 times, with param
PREPARE citus_local_only_p(int) AS SELECT count(*) FROM citus_local_table WHERE a = $1;
EXECUTE citus_local_only_p(1);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE citus_local_only_p(1);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE citus_local_only_p(1);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE citus_local_only_p(1);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE citus_local_only_p(1);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE citus_local_only_p(1);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

-- do not evalute the function
-- show the logs
EXECUTE citus_local_only_p(random());
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE citus_local_only_p(random());
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) $1)
 count
---------------------------------------------------------------------
     1
(1 row)

PREPARE mixed_query(int,  int, int) AS
	WITH cte_citus_local_table AS
		(SELECT * FROM citus_local_table WHERE a = $1),
	cte_postgres_local_table AS
		(SELECT * FROM postgres_local_table WHERE a = $2),
	cte_distributed_table AS
		(SELECT * FROM distributed_table WHERE a = $3),
	cte_mixes AS (SELECT * FROM cte_distributed_table, cte_citus_local_table, cte_postgres_local_table)
	SELECT count(*) FROM cte_mixes;
EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

EXECUTE mixed_query(1,2,3);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) 1)
 count
---------------------------------------------------------------------
     1
(1 row)

SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

-- anonymous columns
WITH a AS (SELECT a, '' FROM citus_local_table GROUP BY a) SELECT a.a FROM a ORDER BY 1 LIMIT 5;
NOTICE:  executing the command locally: SELECT a FROM (SELECT citus_local_table.a, ''::text FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table GROUP BY citus_local_table.a) a(a, "?column?") ORDER BY a LIMIT 5
 a
---------------------------------------------------------------------
 0
 1
 2
 3
 4
(5 rows)

WITH a AS (SELECT b, '' FROM citus_local_table WHERE a = 1) SELECT * FROM a, a b ORDER BY 1 LIMIT 5;
NOTICE:  executing the command locally: WITH a AS (SELECT citus_local_table.b, ''::text FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) 1)) SELECT a.b, a."?column?", b.b, b."?column?" FROM a a(b, "?column?"), a b(b, "?column?") ORDER BY a.b LIMIT 5
 b | ?column? | b | ?column?
---------------------------------------------------------------------
 1 |          | 1 |
(1 row)

-- weird expression on citus/pg table joins should be fine
SELECT * FROM citus_local_table,  postgres_local_table
WHERE citus_local_table.a - postgres_local_table.a = 0
ORDER BY 1,2,3,4
LIMIT 10;
NOTICE:  executing the command locally: SELECT citus_local_table.a, citus_local_table.b, postgres_local_table.a, postgres_local_table.b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table, citus_local_table_queries.postgres_local_table WHERE ((citus_local_table.a OPERATOR(pg_catalog.-) postgres_local_table.a) OPERATOR(pg_catalog.=) 0) ORDER BY citus_local_table.a, citus_local_table.b, postgres_local_table.a, postgres_local_table.b LIMIT 10
 a | b | a | b
---------------------------------------------------------------------
 0 | 0 | 0 | 0
 1 | 1 | 1 | 1
 2 | 2 | 2 | 2
 3 | 3 | 3 | 3
 4 | 4 | 4 | 4
 5 | 5 | 5 | 5
(6 rows)

-- set operations should just work
SELECT * FROM citus_local_table UNION SELECT * FROM postgres_local_table UNION SELECT * FROM distributed_table ORDER BY 1,2;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
NOTICE:  executing the command locally: SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer) UNION SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer) UNION SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer) ORDER BY 1, 2
 a | b
---------------------------------------------------------------------
 0 | 0
 1 | 1
 2 | 2
 3 | 3
 4 | 4
 5 | 5
(6 rows)

(SELECT * FROM citus_local_table ORDER BY 1,2 LIMIT 5) INTERSECT (SELECT i, i FROM generate_series(0, 100) i) ORDER BY 1, 2;
NOTICE:  executing the command locally: (SELECT citus_local_table.a, citus_local_table.b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table ORDER BY citus_local_table.a, citus_local_table.b LIMIT 5) INTERSECT SELECT i.i, i.i FROM generate_series(0, 100) i(i) ORDER BY 1, 2
 a | b
---------------------------------------------------------------------
 0 | 0
 1 | 1
 2 | 2
 3 | 3
 4 | 4
(5 rows)

-- should just work as recursive planner kicks in
SELECT count(*) FROM distributed_table WHERE a IN (SELECT a FROM citus_local_table);
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 count
---------------------------------------------------------------------
     6
(1 row)

SELECT count(*) FROM citus_local_table  WHERE a IN (SELECT a FROM distributed_table);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)))
 count
---------------------------------------------------------------------
     6
(1 row)

SELECT count(*) FROM reference_table WHERE a IN (SELECT a FROM citus_local_table);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.reference_table_1509003 reference_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT citus_local_table.a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table))
 count
---------------------------------------------------------------------
     6
(1 row)

SELECT count(*) FROM citus_local_table  WHERE a IN (SELECT a FROM reference_table);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT reference_table.a FROM citus_local_table_queries.reference_table_1509003 reference_table))
 count
---------------------------------------------------------------------
     6
(1 row)

--  nested recursive queries should just work
SELECT count(*)  FROM citus_local_table
	WHERE a IN
	(SELECT a FROM distributed_table WHERE a IN
	 (SELECT b FROM citus_local_table WHERE b IN (SELECT b FROM postgres_local_table)));
NOTICE:  executing the command locally: SELECT b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table 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)))
NOTICE:  executing the command locally: SELECT count(*) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.a FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(a integer)))
 count
---------------------------------------------------------------------
     6
(1 row)

-- local outer joins
SELECT count(*) FROM citus_local_table LEFT JOIN reference_table ON (true);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (citus_local_table_queries.citus_local_table_1509001 citus_local_table LEFT JOIN citus_local_table_queries.reference_table_1509003 reference_table ON (true))
 count
---------------------------------------------------------------------
    36
(1 row)

SELECT count(*) FROM reference_table
  LEFT JOIN citus_local_table ON (true)
  LEFT JOIN postgres_local_table ON (true)
  LEFT JOIN reference_table r2 ON (true);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (((citus_local_table_queries.reference_table_1509003 reference_table LEFT JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true)) LEFT JOIN citus_local_table_queries.postgres_local_table ON (true)) LEFT JOIN citus_local_table_queries.reference_table_1509003 r2 ON (true))
 count
---------------------------------------------------------------------
  1296
(1 row)

SELECT count(*) FROM citus_local_table LEFT JOIN distributed_table ON (true);
NOTICE:  executing the command locally: SELECT NULL::integer AS "dummy-1" FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
NOTICE:  executing the command locally: 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)) citus_local_table_1) citus_local_table LEFT JOIN (SELECT NULL::integer AS a, NULL::integer AS b FROM (SELECT intermediate_result."dummy-1" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result("dummy-1" integer)) distributed_table_1) distributed_table ON (true))
 count
---------------------------------------------------------------------
    36
(1 row)

-- distinct in subquery on CTE
WITH one_row AS (
	SELECT a from citus_local_table WHERE b = 1
)
SELECT
  *
FROM
  distributed_table
WHERE
  b IN (SELECT DISTINCT a FROM one_row)
ORDER BY
  1, 2
LIMIT
  1;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (b OPERATOR(pg_catalog.=) 1)
 a | b
---------------------------------------------------------------------
 1 | 1
(1 row)

WITH one_row_2 AS (
	SELECT a from distributed_table WHERE b = 1
)
SELECT
  *
FROM
  citus_local_table
WHERE
  b IN (SELECT DISTINCT a FROM one_row_2)
ORDER BY
  1 ,2
LIMIT
  1;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (b OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer))) ORDER BY a, b LIMIT 1
 a | b
---------------------------------------------------------------------
 1 | 1
(1 row)

-- join between citus local tables and distributed tables would fail
SELECT count(*) FROM citus_local_table, distributed_table;
NOTICE:  executing the command locally: SELECT NULL::integer AS "dummy-1" FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
 count
---------------------------------------------------------------------
    36
(1 row)

SELECT * FROM citus_local_table, distributed_table ORDER BY 1,2,3,4 FOR UPDATE;
ERROR:  could not run distributed query with FOR UPDATE/SHARE commands
-- join between citus local tables and postgres local tables are okey
SELECT count(citus_local_table.b), count(postgres_local_table.a)
FROM citus_local_table, postgres_local_table
WHERE citus_local_table.a = postgres_local_table.b;
NOTICE:  executing the command locally: SELECT count(citus_local_table.b) AS count, count(postgres_local_table.a) AS count FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table, citus_local_table_queries.postgres_local_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) postgres_local_table.b)
 count | count
---------------------------------------------------------------------
     6 |     6
(1 row)

-- select for update is just OK
SELECT * FROM citus_local_table  ORDER BY 1,2 FOR UPDATE;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table ORDER BY a, b FOR UPDATE OF citus_local_table
 a | b
---------------------------------------------------------------------
 0 | 0
 1 | 1
 2 | 2
 3 | 3
 4 | 4
 5 | 5
(6 rows)

---------------------------------------------------------------------
----- INSERT SELECT -----
---------------------------------------------------------------------
-- simple INSERT SELECT is OK
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

INSERT INTO citus_local_table
SELECT * from reference_table;
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a, b) SELECT reference_table.a, reference_table.b FROM citus_local_table_queries.reference_table_1509003 reference_table
INSERT INTO reference_table
SELECT * from citus_local_table;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
NOTICE:  executing the copy locally for shard xxxxx
INSERT INTO citus_local_table
SELECT * from distributed_table;
NOTICE:  executing the copy locally for shard xxxxx
INSERT INTO distributed_table
SELECT * from citus_local_table;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
INSERT INTO citus_local_table
SELECT * from citus_local_table_2;
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a, b) SELECT citus_local_table_2.a, citus_local_table_2.b FROM citus_local_table_queries.citus_local_table_2_1509002 citus_local_table_2
INSERT INTO citus_local_table
SELECT sum(a), b from citus_local_table_2
GROUP BY b;
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a, b) SELECT sum(citus_local_table_2.a) AS sum, citus_local_table_2.b FROM citus_local_table_queries.citus_local_table_2_1509002 citus_local_table_2 GROUP BY citus_local_table_2.b
INSERT INTO citus_local_table
SELECT * from postgres_local_table;
NOTICE:  executing the copy locally for shard xxxxx
INSERT INTO postgres_local_table
SELECT * from citus_local_table;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
-- INSERT SELECT with local joins are OK
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

INSERT INTO citus_local_table
SELECT reference_table.* FROM reference_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a, b) SELECT reference_table.a, reference_table.b FROM (citus_local_table_queries.reference_table_1509003 reference_table JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true))
INSERT INTO reference_table
SELECT reference_table.* FROM reference_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: SELECT reference_table.a, reference_table.b FROM (citus_local_table_queries.reference_table_1509003 reference_table JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true))
NOTICE:  executing the copy locally for shard xxxxx
INSERT INTO reference_table
SELECT reference_table.* FROM reference_table, postgres_local_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: SELECT reference_table.a, reference_table.b FROM citus_local_table_queries.reference_table_1509003 reference_table, (citus_local_table_queries.postgres_local_table JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true))
NOTICE:  executing the copy locally for shard xxxxx
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

INSERT INTO distributed_table
SELECT reference_table.* FROM reference_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: SELECT reference_table.a, reference_table.b FROM (citus_local_table_queries.reference_table_1509003 reference_table JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true))
INSERT INTO distributed_table
SELECT reference_table.* FROM reference_table, postgres_local_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: SELECT reference_table.a, reference_table.b FROM citus_local_table_queries.reference_table_1509003 reference_table, (citus_local_table_queries.postgres_local_table JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true))
INSERT INTO postgres_local_table
SELECT reference_table.* FROM reference_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: SELECT reference_table.a, reference_table.b FROM (citus_local_table_queries.reference_table_1509003 reference_table JOIN citus_local_table_queries.citus_local_table_1509001 citus_local_table ON (true))
-- INSERT SELECT that joins reference and distributed tables is also OK
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

INSERT INTO citus_local_table
SELECT reference_table.* FROM reference_table
JOIN distributed_table ON (true);
NOTICE:  executing the copy locally for shard xxxxx
INSERT INTO citus_local_table
SELECT reference_table.*
FROM reference_table, distributed_table;
NOTICE:  executing the copy locally for shard xxxxx
-- INSERT SELECT that joins citus local and distributed table directly will fail ..
INSERT INTO citus_local_table
SELECT distributed_table.* FROM distributed_table
JOIN citus_local_table ON (true);
NOTICE:  executing the command locally: SELECT NULL::integer AS "dummy-1" FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
NOTICE:  executing the copy locally for shard xxxxx
-- .. but when wrapped into a CTE, join works fine
INSERT INTO citus_local_table
SELECT distributed_table.* FROM distributed_table
JOIN (WITH cte AS (SELECT * FROM citus_local_table) SELECT * FROM cte) as foo ON (true);
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
NOTICE:  executing the copy locally for shard xxxxx
-- multi row insert is OK
INSERT INTO citus_local_table VALUES (1, 2), (3, 4);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a, b) VALUES (1,2), (3,4)
---------------------------------------------------------------------
----- DELETE / UPDATE -----
---------------------------------------------------------------------
-- modifications using citus local tables and postgres local tables
-- are not supported, see below four tests
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

DELETE FROM citus_local_table
USING postgres_local_table
WHERE citus_local_table.b = postgres_local_table.b;
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table USING citus_local_table_queries.postgres_local_table WHERE (citus_local_table.b OPERATOR(pg_catalog.=) postgres_local_table.b)
UPDATE citus_local_table
SET b = 5
FROM postgres_local_table
WHERE citus_local_table.a = 3 AND citus_local_table.b = postgres_local_table.b;
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.citus_local_table_1509001 citus_local_table SET b = 5 FROM citus_local_table_queries.postgres_local_table WHERE ((citus_local_table.a OPERATOR(pg_catalog.=) 3) AND (citus_local_table.b OPERATOR(pg_catalog.=) postgres_local_table.b))
DELETE FROM postgres_local_table
USING citus_local_table
WHERE citus_local_table.b = postgres_local_table.b;
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.postgres_local_table USING citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (citus_local_table.b OPERATOR(pg_catalog.=) postgres_local_table.b)
UPDATE postgres_local_table
SET b = 5
FROM citus_local_table
WHERE citus_local_table.a = 3 AND citus_local_table.b = postgres_local_table.b;
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.postgres_local_table SET b = 5 FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE ((citus_local_table.a OPERATOR(pg_catalog.=) 3) AND (citus_local_table.b OPERATOR(pg_catalog.=) postgres_local_table.b))
-- no direct joins supported
UPDATE distributed_table
SET b = 6
FROM citus_local_table
WHERE citus_local_table.a = distributed_table.a;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
UPDATE reference_table
SET b = 6
FROM citus_local_table
WHERE citus_local_table.a = reference_table.a;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.reference_table_1509003 reference_table SET b = 6 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 WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a)
-- should not work, add HINT use CTEs
UPDATE citus_local_table
SET b = 6
FROM distributed_table
WHERE citus_local_table.a = distributed_table.a;
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.citus_local_table_1509001 citus_local_table SET b = 6 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 WHERE (citus_local_table.a OPERATOR(pg_catalog.=) distributed_table.a)
-- should work, add HINT use CTEs
UPDATE citus_local_table
SET b = 6
FROM reference_table
WHERE citus_local_table.a = reference_table.a;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.reference_table_1509003 reference_table WHERE true
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.citus_local_table_1509001 citus_local_table SET b = 6 FROM (SELECT reference_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)) reference_table_1) reference_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a)
-- should not work, add HINT use CTEs
DELETE FROM distributed_table
USING citus_local_table
WHERE citus_local_table.a = distributed_table.a;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
-- should not work, add HINT use CTEs
DELETE FROM citus_local_table
USING distributed_table
WHERE citus_local_table.a = distributed_table.a;
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table USING (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 WHERE (citus_local_table.a OPERATOR(pg_catalog.=) distributed_table.a)
DELETE FROM reference_table
USING citus_local_table
WHERE citus_local_table.a = reference_table.a;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.reference_table_1509003 reference_table USING (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 WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a)
-- should work, add HINT use CTEs
DELETE FROM citus_local_table
USING reference_table
WHERE citus_local_table.a = reference_table.a;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.reference_table_1509003 reference_table WHERE true
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table USING (SELECT reference_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)) reference_table_1) reference_table WHERE (citus_local_table.a OPERATOR(pg_catalog.=) reference_table.a)
-- just works
DELETE FROM citus_local_table
WHERE citus_local_table.a IN (SELECT a FROM distributed_table);
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)))
-- just works
DELETE FROM citus_local_table
WHERE citus_local_table.a IN (SELECT a FROM reference_table);
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.reference_table_1509003 reference_table
NOTICE:  executing the command locally: DELETE FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE (a OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)))
-- just works
WITH distributed_table_cte AS (SELECT * FROM distributed_table)
UPDATE citus_local_table
SET b = 6
FROM distributed_table_cte
WHERE citus_local_table.a = distributed_table_cte.a;
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.citus_local_table_1509001 citus_local_table SET b = 6 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)) distributed_table_cte WHERE (citus_local_table.a OPERATOR(pg_catalog.=) distributed_table_cte.a)
SET citus.log_local_commands to off;
-- just works
WITH reference_table_cte AS (SELECT * FROM reference_table)
UPDATE citus_local_table
SET b = 6
FROM reference_table_cte
WHERE citus_local_table.a = reference_table_cte.a;
set citus.log_local_commands to on;
---------------------------------------------------------------------
----- VIEW QUERIES -----
---------------------------------------------------------------------
CREATE MATERIALIZED VIEW mat_view_4 AS
SELECT count(*)
FROM citus_local_table
JOIN reference_table
USING (a);
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (citus_local_table_queries.citus_local_table_1509001 citus_local_table(a, b) JOIN citus_local_table_queries.reference_table_1509003 reference_table(a, b) USING (a))
-- ok
SELECT count(*) FROM mat_view_4;
 count
---------------------------------------------------------------------
     1
(1 row)

-- should work
SELECT count(*) FROM distributed_table WHERE b in
(SELECT count FROM mat_view_4);
 count
---------------------------------------------------------------------
     1
(1 row)

CREATE VIEW view_2 AS
SELECT count(*)
FROM citus_local_table
JOIN citus_local_table_2 USING (a)
JOIN distributed_table USING (a);
-- should fail as view contains direct local dist join
SELECT count(*) FROM view_2;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table WHERE true
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_2_1509002 citus_local_table_2 WHERE true
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (SELECT intermediate_result.count FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) view_2
 count
---------------------------------------------------------------------
     1
(1 row)

CREATE VIEW view_3
AS SELECT count(*)
FROM citus_local_table_2
JOIN reference_table
USING (a);
-- ok
SELECT count(*) FROM view_3;
NOTICE:  executing the command locally: SELECT count(*) AS count FROM (SELECT count(*) AS count FROM (citus_local_table_queries.citus_local_table_2_1509002 citus_local_table_2(a, b) JOIN citus_local_table_queries.reference_table_1509003 reference_table(a, b) USING (a))) view_3
 count
---------------------------------------------------------------------
     1
(1 row)

-- view treated as subquery, so should work
SELECT count(*) FROM view_3, distributed_table;
NOTICE:  executing the command locally: SELECT a FROM citus_local_table_queries.citus_local_table_2_1509002 citus_local_table_2 WHERE true
NOTICE:  executing the command locally: SELECT count(*) AS count FROM ((SELECT citus_local_table_2_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_2_1) citus_local_table_2 JOIN citus_local_table_queries.reference_table_1509003 reference_table(a, b) USING (a))
 count
---------------------------------------------------------------------
     6
(1 row)

---------------------------------------------------------------------
-- Some other tests with subqueries & CTE's --
---------------------------------------------------------------------
SELECT clear_and_init_test_tables();
 clear_and_init_test_tables
---------------------------------------------------------------------

(1 row)

SELECT count(*) AS a, count(*) AS b
FROM reference_table
JOIN (SELECT count(*) as a, count(*) as b
      FROM citus_local_table_2
      JOIN (SELECT count(*) as a, count(*) as b
            FROM postgres_local_table
            JOIN (SELECT count(*) as a, count(*) as b
                  FROM reference_table as table_4677) subquery5108
            USING (a)) subquery7132
      USING (b)) subquery7294
USING (a);
NOTICE:  executing the command locally: SELECT count(*) AS a, count(*) AS b FROM (citus_local_table_queries.reference_table_1509003 reference_table(a, b) JOIN (SELECT count(*) AS a, count(*) AS b FROM (citus_local_table_queries.citus_local_table_2_1509002 citus_local_table_2(a, b) JOIN (SELECT count(*) AS a, count(*) AS b FROM (citus_local_table_queries.postgres_local_table JOIN (SELECT count(*) AS a, count(*) AS b FROM citus_local_table_queries.reference_table_1509003 table_4677) subquery5108 USING (a))) subquery7132 USING (b))) subquery7294 USING (a))
 a | b
---------------------------------------------------------------------
 1 | 1
(1 row)

-- direct join inside CTE not supported
WITH cte AS (
UPDATE citus_local_table lt SET a = mt.a
FROM distributed_table mt WHERE mt.b = lt.b
RETURNING lt.b, lt.a
) SELECT * FROM cte JOIN distributed_table mt ON mt.b = cte.b ORDER BY 1,2,3,4;
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.citus_local_table_1509001 lt SET a = mt.a FROM (SELECT mt_1.a, mt_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)) mt_1) mt WHERE (mt.b OPERATOR(pg_catalog.=) lt.b) RETURNING lt.b, lt.a
 b | a | a | b
---------------------------------------------------------------------
 0 | 0 | 0 | 0
 1 | 1 | 1 | 1
 2 | 2 | 2 | 2
 3 | 3 | 3 | 3
 4 | 4 | 4 | 4
 5 | 5 | 5 | 5
(6 rows)

-- join with CTE just works
UPDATE citus_local_table
SET a=5
FROM (SELECT avg(distributed_table.b) as avg_b
      FROM distributed_table) as foo
WHERE
foo.avg_b = citus_local_table.b;
NOTICE:  executing the command locally: UPDATE citus_local_table_queries.citus_local_table_1509001 citus_local_table SET a = 5 FROM (SELECT intermediate_result.avg_b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(avg_b numeric)) foo WHERE (foo.avg_b OPERATOR(pg_catalog.=) (citus_local_table.b)::numeric)
-- should work
UPDATE distributed_table
SET b = avg_a
FROM (SELECT avg(citus_local_table.a) as avg_a FROM citus_local_table) as foo
WHERE foo.avg_a = distributed_table.a
RETURNING distributed_table.*;
NOTICE:  executing the command locally: SELECT avg(a) AS avg_a FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
 a | b
---------------------------------------------------------------------
(0 rows)

-- it is unfortunate that recursive planner cannot detect this
-- but expected to not work
UPDATE citus_local_table
SET a=5
FROM (SELECT b FROM distributed_table) AS foo
WHERE foo.b = citus_local_table.b;
ERROR:  local table citus_local_table cannot be joined with these distributed tables
---------------------------------------------------------------------
-- test different execution paths --
---------------------------------------------------------------------
-- a bit different explain output than for postgres local tables
EXPLAIN (COSTS FALSE)
INSERT INTO citus_local_table
SELECT * FROM distributed_table
ORDER BY distributed_table.*
LIMIT 10;
                                            QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (Citus INSERT ... SELECT)
   INSERT/SELECT method: pull to coordinator
   ->  Limit
         ->  Sort
               Sort Key: remote_scan.worker_column_3
               ->  Custom Scan (Citus Adaptive)
                     Task Count: 4
                     Tasks Shown: One of 4
                     ->  Task
                           Node: host=localhost port=xxxxx dbname=regression
                           ->  Limit
                                 ->  Sort
                                       Sort Key: distributed_table.*
                                       ->  Seq Scan on distributed_table_1509004 distributed_table
(14 rows)

-- show that we do not pull to coordinator
EXPLAIN (COSTS FALSE)
INSERT INTO citus_local_table
SELECT * FROM citus_local_table;
                                QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (Citus Adaptive)
   Task Count: 1
   Tasks Shown: All
   ->  Task
         Node: host=localhost port=xxxxx dbname=regression
         ->  Insert on citus_local_table_1509001 citus_table_alias
               ->  Seq Scan on citus_local_table_1509001 citus_local_table
(7 rows)

EXPLAIN (COSTS FALSE)
INSERT INTO citus_local_table
SELECT reference_table.* FROM reference_table;
                              QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (Citus Adaptive)
   Task Count: 1
   Tasks Shown: All
   ->  Task
         Node: host=localhost port=xxxxx dbname=regression
         ->  Insert on citus_local_table_1509001 citus_table_alias
               ->  Seq Scan on reference_table_1509003 reference_table
(7 rows)

EXPLAIN (COSTS FALSE)
INSERT INTO citus_local_table
SELECT reference_table.* FROM reference_table, postgres_local_table;
                                 QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (Citus INSERT ... SELECT)
   INSERT/SELECT method: pull to coordinator
   ->  Custom Scan (Citus Adaptive)
         Task Count: 1
         Tasks Shown: All
         ->  Task
               Node: host=localhost port=xxxxx dbname=regression
               ->  Nested Loop
                     ->  Seq Scan on reference_table_1509003 reference_table
                     ->  Materialize
                           ->  Seq Scan on postgres_local_table
(11 rows)

-- show that we pull to coordinator when a distributed table is involved
EXPLAIN (COSTS FALSE)
INSERT INTO citus_local_table
SELECT reference_table.* FROM reference_table, distributed_table;
                                    QUERY PLAN
---------------------------------------------------------------------
 Custom Scan (Citus INSERT ... SELECT)
   INSERT/SELECT method: pull to coordinator
   ->  Custom Scan (Citus Adaptive)
         Task Count: 4
         Tasks Shown: One of 4
         ->  Task
               Node: host=localhost port=xxxxx dbname=regression
               ->  Nested Loop
                     ->  Seq Scan on distributed_table_1509004 distributed_table
                     ->  Materialize
                           ->  Seq Scan on reference_table_1509003 reference_table
(11 rows)

-- truncate tables & add unique constraints to be able to define foreign keys
TRUNCATE reference_table, citus_local_table, distributed_table;
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.reference_table_xxxxx CASCADE
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.citus_local_table_xxxxx CASCADE
ALTER TABLE reference_table ADD CONSTRAINT pkey_ref PRIMARY KEY (a);
NOTICE:  executing the command locally: SELECT worker_apply_shard_ddl_command (1509003, 'citus_local_table_queries', 'ALTER TABLE reference_table ADD CONSTRAINT pkey_ref PRIMARY KEY (a);')
ALTER TABLE citus_local_table ADD CONSTRAINT pkey_c PRIMARY KEY (a);
NOTICE:  executing the command locally: SELECT worker_apply_shard_ddl_command (1509001, 'citus_local_table_queries', 'ALTER TABLE citus_local_table ADD CONSTRAINT pkey_c PRIMARY KEY (a);')
-- define a foreign key chain distributed table -> reference table -> citus local table
-- to test sequential execution
ALTER TABLE distributed_table ADD CONSTRAINT fkey_dist_to_ref FOREIGN KEY(a) REFERENCES reference_table(a) ON DELETE RESTRICT;
ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(a) REFERENCES citus_local_table(a) ON DELETE RESTRICT;
NOTICE:  executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1509003, 'citus_local_table_queries', 1509001, 'citus_local_table_queries', 'ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(a) REFERENCES citus_local_table(a) ON DELETE RESTRICT;')
INSERT INTO citus_local_table VALUES (1);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 (a) VALUES (1)
INSERT INTO reference_table VALUES (1);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.reference_table_1509003 (a) VALUES (1)
BEGIN;
    INSERT INTO citus_local_table VALUES (1) ON CONFLICT (a) DO NOTHING;
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a) VALUES (1) ON CONFLICT(a) DO NOTHING
    INSERT INTO distributed_table VALUES (1);
    -- should show sequential as first inserting into citus local table
	-- would force the xact block to use sequential execution
    show citus.multi_shard_modify_mode;
 citus.multi_shard_modify_mode
---------------------------------------------------------------------
 sequential
(1 row)

ROLLBACK;
BEGIN;
	TRUNCATE distributed_table;
	-- should error out as we truncated distributed_table via parallel execution
	TRUNCATE citus_local_table  CASCADE;
NOTICE:  truncate cascades to table "reference_table"
NOTICE:  truncate cascades to table "distributed_table"
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.citus_local_table_xxxxx CASCADE
ERROR:  cannot execute DDL on table "citus_local_table" because there was a parallel DDL access to distributed table "distributed_table" in the same transaction
ROLLBACK;
BEGIN;
	SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
	TRUNCATE distributed_table;
	-- should work fine as we already switched to sequential execution
	-- before parallel truncate
	TRUNCATE citus_local_table  CASCADE;
NOTICE:  truncate cascades to table "reference_table"
NOTICE:  truncate cascades to table "distributed_table"
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.citus_local_table_xxxxx CASCADE
NOTICE:  truncate cascades to table "reference_table_xxxxx"
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.reference_table_xxxxx CASCADE
ROLLBACK;
ALTER TABLE distributed_table DROP CONSTRAINT fkey_dist_to_ref;
BEGIN;
    INSERT INTO citus_local_table VALUES (1) ON CONFLICT (a) DO NOTHING;
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a) VALUES (1) ON CONFLICT(a) DO NOTHING
    show citus.multi_shard_modify_mode;
 citus.multi_shard_modify_mode
---------------------------------------------------------------------
 sequential
(1 row)

ROLLBACK;
-- remove uniqueness constraint and dependent foreign key constraint for next tests
ALTER TABLE reference_table DROP CONSTRAINT fkey_ref_to_local;
NOTICE:  executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1509003, 'citus_local_table_queries', 1509001, 'citus_local_table_queries', 'ALTER TABLE reference_table DROP CONSTRAINT fkey_ref_to_local;')
ALTER TABLE citus_local_table DROP CONSTRAINT pkey_c;
NOTICE:  executing the command locally: SELECT worker_apply_shard_ddl_command (1509001, 'citus_local_table_queries', 'ALTER TABLE citus_local_table DROP CONSTRAINT pkey_c;')
COPY  citus_local_table(a) FROM  PROGRAM 'seq 1';
-- should use local execution
BEGIN;
	COPY  citus_local_table(a) FROM  PROGRAM 'seq 1';
NOTICE:  executing the copy locally for shard xxxxx
	COPY  citus_local_table(a) FROM  PROGRAM 'seq 1';
NOTICE:  executing the copy locally for shard xxxxx
COMMIT;
COPY citus_local_table TO STDOUT;
1	\N
1	\N
1	\N
1	\N
COPY (SELECT * FROM citus_local_table) TO STDOUT;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
1	\N
1	\N
1	\N
1	\N
BEGIN;
  COPY citus_local_table TO STDOUT;
1	\N
1	\N
1	\N
1	\N
COMMIT;
BEGIN;
  COPY (SELECT * FROM citus_local_table) TO STDOUT;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table
1	\N
1	\N
1	\N
1	\N
COMMIT;
-- truncate test tables for next test
TRUNCATE citus_local_table, reference_table, distributed_table;
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.citus_local_table_xxxxx CASCADE
NOTICE:  executing the command locally: TRUNCATE TABLE citus_local_table_queries.reference_table_xxxxx CASCADE
BEGIN;
	INSERT INTO citus_local_table VALUES (1), (2);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a) VALUES (1), (2)
	SAVEPOINT sp1;
	INSERT INTO citus_local_table VALUES (3), (4);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a) VALUES (3), (4)
	ROLLBACK TO SAVEPOINT sp1;
	SELECT * FROM citus_local_table ORDER BY 1,2;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table ORDER BY a, b
 a | b
---------------------------------------------------------------------
 1 |
 2 |
(2 rows)

	SAVEPOINT sp2;
	INSERT INTO citus_local_table VALUES (3), (4);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a) VALUES (3), (4)
	INSERT INTO distributed_table VALUES (3), (4);
	ROLLBACK TO SAVEPOINT sp2;
	SELECT * FROM citus_local_table ORDER BY 1,2;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table ORDER BY a, b
 a | b
---------------------------------------------------------------------
 1 |
 2 |
(2 rows)

	SELECT * FROM distributed_table ORDER BY 1,2;
 a | b
---------------------------------------------------------------------
(0 rows)

	SAVEPOINT sp3;
	INSERT INTO citus_local_table VALUES (3), (2);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.citus_local_table_1509001 AS citus_table_alias (a) VALUES (3), (2)
	INSERT INTO reference_table VALUES (3), (2);
NOTICE:  executing the command locally: INSERT INTO citus_local_table_queries.reference_table_1509003 AS citus_table_alias (a) VALUES (3), (2)
	ROLLBACK TO SAVEPOINT sp3;
	SELECT * FROM citus_local_table ORDER BY 1,2;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.citus_local_table_1509001 citus_local_table ORDER BY a, b
 a | b
---------------------------------------------------------------------
 1 |
 2 |
(2 rows)

	SELECT * FROM reference_table ORDER BY 1,2;
NOTICE:  executing the command locally: SELECT a, b FROM citus_local_table_queries.reference_table_1509003 reference_table ORDER BY a, b
 a | b
---------------------------------------------------------------------
(0 rows)

COMMIT;
-- cleanup at exit
DROP SCHEMA citus_local_table_queries CASCADE;
NOTICE:  drop cascades to 14 other objects
