\set VERBOSITY terse
SET citus.next_shard_id TO 1515000;
SET citus.shard_replication_factor TO 1;
CREATE SCHEMA undistribute_table_cascade;
SET search_path TO undistribute_table_cascade;
SET client_min_messages to ERROR;
-- remove coordinator if it is added to pg_dist_node
SELECT COUNT(master_remove_node(nodename, nodeport)) < 2
FROM pg_dist_node WHERE nodename='localhost' AND nodeport=:master_port;
 ?column?
---------------------------------------------------------------------
 t
(1 row)

BEGIN;
  CREATE TABLE reference_table(col_1 INT UNIQUE);
  CREATE TABLE distributed_table(col_1 INT UNIQUE);
  CREATE TABLE local_table (col_1 INT REFERENCES reference_table(col_1), FOREIGN KEY (col_1) REFERENCES distributed_table(col_1));
  SELECT create_reference_table('reference_table');
 create_reference_table
---------------------------------------------------------------------

(1 row)

  SELECT create_distributed_table('distributed_table', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

  -- show that we skip postgres tables when undistributing citus tables
  SELECT undistribute_table('reference_table', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

ROLLBACK;
-- ensure that coordinator is added to pg_dist_node
SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0);
 ?column?
---------------------------------------------------------------------
        1
(1 row)

CREATE TABLE reference_table_1 (col_1 INT UNIQUE, col_2 INT UNIQUE, UNIQUE (col_2, col_1));
CREATE TABLE reference_table_2 (col_1 INT UNIQUE, col_2 INT UNIQUE);
SELECT create_reference_table('reference_table_1');
 create_reference_table
---------------------------------------------------------------------

(1 row)

SELECT create_reference_table('reference_table_2');
 create_reference_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE distributed_table_1 (col_1 INT UNIQUE);
CREATE TABLE distributed_table_2 (col_1 INT UNIQUE);
CREATE TABLE distributed_table_3 (col_1 INT UNIQUE);
SELECT create_distributed_table('distributed_table_1', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('distributed_table_2', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('distributed_table_3', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE citus_local_table_1 (col_1 INT UNIQUE);
CREATE TABLE citus_local_table_2 (col_1 INT UNIQUE);
SELECT citus_add_local_table_to_metadata('citus_local_table_1');
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

SELECT citus_add_local_table_to_metadata('citus_local_table_2');
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

--        ---                                            ---
--        | |                                            | |
--        | v                                            | v
-- distributed_table_2 -> distributed_table_1 -> reference_table_1 <- reference_table_2
--         ^                        |                     ^                    |
--         v                        |                     |                    v
-- distributed_table_3  <------------            citus_local_table_1  citus_local_table_2
--
ALTER TABLE distributed_table_3 ADD CONSTRAINT fkey_1 FOREIGN KEY (col_1) REFERENCES distributed_table_2(col_1);
ALTER TABLE distributed_table_2 ADD CONSTRAINT fkey_2 FOREIGN KEY (col_1) REFERENCES distributed_table_3(col_1);
ALTER TABLE distributed_table_2 ADD CONSTRAINT fkey_3 FOREIGN KEY (col_1) REFERENCES distributed_table_1(col_1);
ALTER TABLE distributed_table_1 ADD CONSTRAINT fkey_4 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1);
ALTER TABLE reference_table_2 ADD CONSTRAINT fkey_5 FOREIGN KEY (col_1, col_2) REFERENCES reference_table_1(col_2, col_1);
ALTER TABLE citus_local_table_1 ADD CONSTRAINT fkey_6 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_2);
ALTER TABLE reference_table_2 ADD CONSTRAINT fkey_7 FOREIGN KEY (col_1) REFERENCES citus_local_table_2(col_1);
ALTER TABLE distributed_table_1 ADD CONSTRAINT fkey_8 FOREIGN KEY (col_1) REFERENCES distributed_table_3(col_1);
ALTER TABLE distributed_table_2 ADD CONSTRAINT fkey_11 FOREIGN KEY (col_1) REFERENCES distributed_table_2(col_1);
ALTER TABLE reference_table_1 ADD CONSTRAINT fkey_12 FOREIGN KEY (col_2) REFERENCES reference_table_1(col_1);
-- show that all of below fails as we didn't provide cascade=true
SELECT undistribute_table('distributed_table_1');
ERROR:  cannot complete operation because table distributed_table_1 has a foreign key
SELECT undistribute_table('citus_local_table_1', cascade_via_foreign_keys=>false);
ERROR:  cannot complete operation because table citus_local_table_1 has a foreign key
SELECT undistribute_table('reference_table_2');
ERROR:  cannot complete operation because table reference_table_2 has a foreign key
-- In each of below transation blocks, show that we preserve foreign keys.
-- Also show that we don't have any citus tables in current schema after
-- undistribute_table(cascade).
-- So in each transaction, both selects should return true.
BEGIN;
  SELECT undistribute_table('distributed_table_2', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  -- show that we switch to sequential execution as there are
  -- reference tables in our subgraph
  show citus.multi_shard_modify_mode;
 citus.multi_shard_modify_mode
---------------------------------------------------------------------
 sequential
(1 row)

  SELECT COUNT(*)=10 FROM pg_constraint
  WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname='undistribute_table_cascade') AND
        conname ~ '^fkey\_\d+$';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

  SELECT COUNT(*)=0 FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='undistribute_table_cascade';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

ROLLBACK;
BEGIN;
  SELECT undistribute_table('reference_table_1', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  SELECT COUNT(*)=10 FROM pg_constraint
  WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname='undistribute_table_cascade') AND
        conname ~ '^fkey\_\d+$';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

  SELECT COUNT(*)=0 FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='undistribute_table_cascade';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

ROLLBACK;
BEGIN;
  SELECT undistribute_table('citus_local_table_1', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  -- print foreign keys only in one of xact blocks not to make tests too verbose
  SELECT conname, conrelid::regclass, confrelid::regclass
  FROM pg_constraint
  WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname='undistribute_table_cascade') AND
        conname ~ '^fkey\_\d+$'
  ORDER BY conname;
 conname |      conrelid       |      confrelid
---------------------------------------------------------------------
 fkey_1  | distributed_table_3 | distributed_table_2
 fkey_11 | distributed_table_2 | distributed_table_2
 fkey_12 | reference_table_1   | reference_table_1
 fkey_2  | distributed_table_2 | distributed_table_3
 fkey_3  | distributed_table_2 | distributed_table_1
 fkey_4  | distributed_table_1 | reference_table_1
 fkey_5  | reference_table_2   | reference_table_1
 fkey_6  | citus_local_table_1 | reference_table_1
 fkey_7  | reference_table_2   | citus_local_table_2
 fkey_8  | distributed_table_1 | distributed_table_3
(10 rows)

  SELECT COUNT(*)=0 FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='undistribute_table_cascade';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

ROLLBACK;
BEGIN;
  SELECT COUNT(*) FROM distributed_table_1;
 count
---------------------------------------------------------------------
     0
(1 row)

  -- show that we error out as select is executed in parallel mode
  -- and there are reference tables in our subgraph
  SELECT undistribute_table('reference_table_1', cascade_via_foreign_keys=>true);
ERROR:  cannot execute command because there was a parallel operation on a distributed table in transaction
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  SELECT COUNT(*) FROM distributed_table_1;
 count
---------------------------------------------------------------------
     0
(1 row)

  -- even if there are reference tables in our subgraph, show that
  -- we don't error out as we already switched to sequential execution
  SELECT undistribute_table('reference_table_1', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

ROLLBACK;
ALTER TABLE distributed_table_1 DROP CONSTRAINT fkey_4;
BEGIN;
  SELECT undistribute_table('distributed_table_2', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  -- as we splitted distributed_table_1,2 & 3 into a seperate subgraph
  -- by dropping reference_table_1, we should not switch to sequential
  -- execution
  show citus.multi_shard_modify_mode;
 citus.multi_shard_modify_mode
---------------------------------------------------------------------
 parallel
(1 row)

ROLLBACK;
-- split distributed_table_2 & distributed_table_3 into a seperate foreign
-- key subgraph then undistribute them
ALTER TABLE distributed_table_2 DROP CONSTRAINT fkey_3;
ALTER TABLE distributed_table_1 DROP CONSTRAINT fkey_8;
SELECT undistribute_table('distributed_table_2', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

-- should return true as we undistributed those two tables
SELECT COUNT(*)=0 FROM pg_dist_partition, pg_tables
WHERE tablename=logicalrelid::regclass::text AND
      schemaname='undistribute_table_cascade' AND
      (tablename='distributed_table_2' OR tablename='distributed_table_3');
 ?column?
---------------------------------------------------------------------
 t
(1 row)

-- other tables should stay as is since we splited those two tables
SELECT COUNT(*)=5 FROM pg_dist_partition, pg_tables
WHERE tablename=logicalrelid::regclass::text AND
      schemaname='undistribute_table_cascade';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

-- test partitioned tables
CREATE TABLE partitioned_table_1 (col_1 INT UNIQUE, col_2 INT) PARTITION BY RANGE (col_1);
CREATE TABLE partitioned_table_1_100_200 PARTITION OF partitioned_table_1 FOR VALUES FROM (100) TO (200);
CREATE TABLE partitioned_table_1_200_300 PARTITION OF partitioned_table_1 FOR VALUES FROM (200) TO (300);
SELECT create_distributed_table('partitioned_table_1', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE partitioned_table_2 (col_1 INT UNIQUE, col_2 INT) PARTITION BY RANGE (col_1);
CREATE TABLE partitioned_table_2_100_200 PARTITION OF partitioned_table_2 FOR VALUES FROM (100) TO (200);
CREATE TABLE partitioned_table_2_200_300 PARTITION OF partitioned_table_2 FOR VALUES FROM (200) TO (300);
SELECT create_distributed_table('partitioned_table_2', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT fkey FOREIGN KEY(col_1) REFERENCES partitioned_table_1_100_200(col_1);
  SELECT undistribute_table('partitioned_table_1', true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
CREATE TABLE distributed_table_4 (col_1 INT UNIQUE, col_2 INT);
SELECT create_distributed_table('distributed_table_4', 'col_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE distributed_table_4 ADD CONSTRAINT fkey FOREIGN KEY(col_1) REFERENCES partitioned_table_1_100_200(col_1);
  SELECT undistribute_table('partitioned_table_1', true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
CREATE TABLE reference_table_3 (col_1 INT UNIQUE, col_2 INT UNIQUE);
SELECT create_reference_table('reference_table_3');
 create_reference_table
---------------------------------------------------------------------

(1 row)

ALTER TABLE partitioned_table_1 ADD CONSTRAINT fkey_9 FOREIGN KEY (col_1) REFERENCES reference_table_3(col_2);
ALTER TABLE partitioned_table_2 ADD CONSTRAINT fkey_10 FOREIGN KEY (col_1) REFERENCES reference_table_3(col_2);
-- show that we properly handle cases where undistribute_table is not supported
-- error out when table is a partition table
SELECT undistribute_table('partitioned_table_2_100_200', cascade_via_foreign_keys=>true);
ERROR:  cannot complete operation because table is a partition
-- error if table does not exist
SELECT undistribute_table('non_existent_table', cascade_via_foreign_keys=>true);
ERROR:  relation "non_existent_table" does not exist at character 27
-- error if table is a postgres table
CREATE TABLE local_table(a int);
SELECT undistribute_table('local_table', cascade_via_foreign_keys=>true);
ERROR:  cannot undistribute table because the table is not distributed
ALTER TABLE partitioned_table_1 ADD CONSTRAINT fkey_15 FOREIGN KEY (col_1) REFERENCES partitioned_table_1(col_1);
BEGIN;
  SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

ROLLBACK;
BEGIN;
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  -- show that we preserve foreign keys on partitions too
  SELECT conname, conrelid::regclass, confrelid::regclass
  FROM pg_constraint
  WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname='undistribute_table_cascade') AND
        conname = 'fkey_9' OR conname = 'fkey_10'
  ORDER BY 1,2,3;
 conname |          conrelid           |     confrelid
---------------------------------------------------------------------
 fkey_10 | partitioned_table_2         | reference_table_3
 fkey_10 | partitioned_table_2_100_200 | reference_table_3
 fkey_10 | partitioned_table_2_200_300 | reference_table_3
 fkey_9  | partitioned_table_1         | reference_table_3
 fkey_9  | partitioned_table_1_100_200 | reference_table_3
 fkey_9  | partitioned_table_1_200_300 | reference_table_3
(6 rows)

ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY(col_1) REFERENCES reference_table_3(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY(col_1) REFERENCES reference_table_3(col_1);
  SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY(col_1) REFERENCES reference_table_3(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY(col_1) REFERENCES partitioned_table_2_100_200(col_1);
  SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY(col_1) REFERENCES partitioned_table_2_100_200(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_2_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE distributed_table_4 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_2_100_200(col_1);
  SELECT undistribute_table('distributed_table_4', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_2_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE distributed_table_4 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_1_100_200(col_1);
  SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE distributed_table_4 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_1_100_200(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT fkey FOREIGN KEY(col_1) REFERENCES distributed_table_4(col_1);
  SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT fkey FOREIGN KEY(col_1) REFERENCES distributed_table_4(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_1_100_200 ADD CONSTRAINT fkey FOREIGN KEY(col_1) REFERENCES distributed_table_4(col_1);
  SELECT undistribute_table('distributed_table_4', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_2 ADD CONSTRAINT fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_1_100_200(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_1_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_2_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_2_100_200(col_1);
  SELECT undistribute_table('reference_table_3', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_2_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_2_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_2_100_200(col_1);
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_2_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  ALTER TABLE partitioned_table_2_100_200 ADD CONSTRAINT non_inherited_fkey FOREIGN KEY (col_1) REFERENCES partitioned_table_2_100_200(col_1);
  SELECT undistribute_table('partitioned_table_1', cascade_via_foreign_keys=>true);
ERROR:  cannot cascade operation via foreign keys as partition table undistribute_table_cascade.partitioned_table_2_100_200 involved in a foreign key relationship that is not inherited from its parent table
ROLLBACK;
ALTER TABLE partitioned_table_1 ADD CONSTRAINT fkey_13 FOREIGN KEY (col_1) REFERENCES partitioned_table_2(col_1);
BEGIN;
  -- For pg versions 11, 12 & 13, partitioned_table_1 references to reference_table_3
  -- and partitioned_table_2 references to reference_table_3.
  -- For pg versions > 11, partitioned_table_1 references to partitioned_table_2 as well.
  -- Anyway show that undistribute_table with cascade is fine.
  SELECT undistribute_table('partitioned_table_2', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

ROLLBACK;
-- now merge partitioned_table_1, 2 and reference_table_3 into right
-- hand-side of the graph
ALTER TABLE reference_table_3 ADD CONSTRAINT fkey_14 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1);
BEGIN;
  SELECT undistribute_table('citus_local_table_1', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  -- undistributing citus_local_table_1 cascades to partitioned tables too
  SELECT COUNT(*)=0 FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='undistribute_table_cascade' AND
        tablename LIKE 'partitioned_table_%';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

ROLLBACK;
BEGIN;
  ALTER TABLE reference_table_2 DROP CONSTRAINT fkey_5;
  ALTER TABLE reference_table_2 DROP CONSTRAINT fkey_7;
  -- since now reference_table_2 has no foreign keys, show that
  -- cascade_via_foreign_keys option still works fine
  SELECT undistribute_table('reference_table_2', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

  SELECT COUNT(*)=0 FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='undistribute_table_cascade' AND
        tablename='reference_table_2';
 ?column?
---------------------------------------------------------------------
 t
(1 row)

ROLLBACK;
CREATE SCHEMA "bad!schemaName";
CREATE TABLE "bad!schemaName"."LocalTabLE.1!?!"(col_1 INT UNIQUE);
CREATE TABLE "bad!schemaName"."LocalTabLE.2!?!"(col_1 INT UNIQUE);
SELECT citus_add_local_table_to_metadata('"bad!schemaName"."LocalTabLE.1!?!"');
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

SELECT citus_add_local_table_to_metadata('"bad!schemaName"."LocalTabLE.2!?!"');
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

ALTER TABLE "bad!schemaName"."LocalTabLE.1!?!" ADD CONSTRAINT "bad!constraintName" FOREIGN KEY (col_1) REFERENCES "bad!schemaName"."LocalTabLE.2!?!"(col_1);
-- test with weird schema, table & constraint names
SELECT undistribute_table('"bad!schemaName"."LocalTabLE.1!?!"', cascade_via_foreign_keys=>true);
 undistribute_table
---------------------------------------------------------------------

(1 row)

-- cleanup at exit
DROP SCHEMA undistribute_table_cascade, "bad!schemaName" CASCADE;
