\set VERBOSITY terse
SET citus.next_shard_id TO 1516000;
SET citus.next_placement_id TO 1516000;
SET citus.shard_replication_factor TO 1;
CREATE SCHEMA citus_add_local_table_to_metadata_cascade;
SET search_path TO citus_add_local_table_to_metadata_cascade;
SET client_min_messages to ERROR;
-- 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 local_table_1 (col_1 INT UNIQUE);
CREATE TABLE local_table_2 (col_1 INT UNIQUE);
CREATE TABLE local_table_3 (col_1 INT UNIQUE);
CREATE TABLE local_table_4 (col_1 INT UNIQUE);
--                                        _
--                                       | |
--                                       | v
-- local_table_2 -> local_table_1 -> local_table_4
--                      ^ |               |
--                      | v               |
--                  local_table_3 <--------
ALTER TABLE local_table_2 ADD CONSTRAINT fkey_1 FOREIGN KEY (col_1) REFERENCES local_table_1(col_1);
ALTER TABLE local_table_3 ADD CONSTRAINT fkey_2 FOREIGN KEY (col_1) REFERENCES local_table_1(col_1);
ALTER TABLE local_table_1 ADD CONSTRAINT fkey_3 FOREIGN KEY (col_1) REFERENCES local_table_3(col_1);
ALTER TABLE local_table_1 ADD CONSTRAINT fkey_4 FOREIGN KEY (col_1) REFERENCES local_table_4(col_1);
ALTER TABLE local_table_4 ADD CONSTRAINT fkey_5 FOREIGN KEY (col_1) REFERENCES local_table_3(col_1);
ALTER TABLE local_table_4 ADD CONSTRAINT fkey_6 FOREIGN KEY (col_1) REFERENCES local_table_4(col_1);
-- show that all of below fails as we didn't provide cascade_via_foreign_keys=true
SELECT citus_add_local_table_to_metadata('local_table_1');
ERROR:  relation citus_add_local_table_to_metadata_cascade.local_table_1 is involved in a foreign key relationship with another table
SELECT citus_add_local_table_to_metadata('local_table_4', cascade_via_foreign_keys=>false);
ERROR:  relation citus_add_local_table_to_metadata_cascade.local_table_4 is involved in a foreign key relationship with another table
-- In each of below two transaction blocks, show that we preserve foreign keys.
-- Also show that we converted all local_table_xxx tables in current schema
-- to citus local tables after citus_add_local_table_to_metadata (cascade).
-- So in each transaction, both selects should return true.
BEGIN;
  SELECT conname, conrelid::regclass::text, confrelid::regclass::text
  FROM pg_constraint
  WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname='citus_add_local_table_to_metadata_cascade') AND
        conname ~ '^fkey\_\d+$'
  ORDER BY 1,2,3;
 conname |   conrelid    |   confrelid
---------------------------------------------------------------------
 fkey_1  | local_table_2 | local_table_1
 fkey_2  | local_table_3 | local_table_1
 fkey_3  | local_table_1 | local_table_3
 fkey_4  | local_table_1 | local_table_4
 fkey_5  | local_table_4 | local_table_3
 fkey_6  | local_table_4 | local_table_4
(6 rows)

  SELECT citus_add_local_table_to_metadata('local_table_1', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

  -- show that we do sequential execution
  show citus.multi_shard_modify_mode;
 citus.multi_shard_modify_mode
---------------------------------------------------------------------
 sequential
(1 row)

  SELECT conname, conrelid::regclass::text, confrelid::regclass::text
  FROM pg_constraint
  WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname='citus_add_local_table_to_metadata_cascade') AND
        conname ~ '^fkey\_\d+$'
  ORDER BY 1,2,3;
 conname |   conrelid    |   confrelid
---------------------------------------------------------------------
 fkey_1  | local_table_2 | local_table_1
 fkey_2  | local_table_3 | local_table_1
 fkey_3  | local_table_1 | local_table_3
 fkey_4  | local_table_1 | local_table_4
 fkey_5  | local_table_4 | local_table_3
 fkey_6  | local_table_4 | local_table_4
(6 rows)

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

ROLLBACK;
BEGIN;
  SELECT citus_add_local_table_to_metadata('local_table_4', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

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

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

ROLLBACK;
BEGIN;
  CREATE TABLE partitioned_table (col_1 INT REFERENCES local_table_1 (col_1)) PARTITION BY RANGE (col_1);
  SELECT citus_add_local_table_to_metadata('local_table_2', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

ROLLBACK;
BEGIN;
  DROP TABLE local_table_2;
  -- show that citus_add_local_table_to_metadata(cascade_via_foreign_keys) works fine after
  -- dropping one of the relations from foreign key graph
  SELECT citus_add_local_table_to_metadata('local_table_1', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

ROLLBACK;
BEGIN;
  -- split local_table_2 from foreign key subgraph
  ALTER TABLE local_table_1 DROP CONSTRAINT local_table_1_col_1_key CASCADE;
  -- now that local_table_2 does not have any foreign keys, cascade_via_foreign_keys=true
  -- is not needed but show that it still works fine
  SELECT citus_add_local_table_to_metadata('local_table_2', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

  -- show citus tables in current schema
  SELECT tablename FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='citus_add_local_table_to_metadata_cascade'
  ORDER BY 1;
   tablename
---------------------------------------------------------------------
 local_table_2
(1 row)

ROLLBACK;
BEGIN;
  -- split local_table_2 from foreign key subgraph
  ALTER TABLE local_table_1 DROP CONSTRAINT local_table_1_col_1_key CASCADE;
  -- add a self reference on local_table_2
  ALTER TABLE local_table_2 ADD CONSTRAINT fkey_self FOREIGN KEY(col_1) REFERENCES local_table_2(col_1);
  -- now that local_table_2 does not have any
  -- foreign key relationships with other tables but a self
  -- referencing foreign key, cascade_via_foreign_keys=true
  -- is not needed but show that it still works fine
  SELECT citus_add_local_table_to_metadata('local_table_2', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

  -- show citus tables in current schema
  SELECT tablename FROM pg_dist_partition, pg_tables
  WHERE tablename=logicalrelid::regclass::text AND
        schemaname='citus_add_local_table_to_metadata_cascade'
  ORDER BY 1;
   tablename
---------------------------------------------------------------------
 local_table_2
(1 row)

ROLLBACK;
CREATE TABLE distributed_table(col INT);
SELECT create_distributed_Table('distributed_table', 'col');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

BEGIN;
  SELECT * FROM distributed_table;
 col
---------------------------------------------------------------------
(0 rows)

  -- fails as citus_add_local_table_to_metadata would require sequential execution
  -- execution like above select
  SELECT citus_add_local_table_to_metadata('local_table_4', cascade_via_foreign_keys=>true);
ERROR:  cannot modify table "local_table_3" because there was a parallel operation on a distributed table
ROLLBACK;
BEGIN;
  set citus.multi_shard_modify_mode to 'sequential';
  -- sequetial execution also works fine
  SELECT citus_add_local_table_to_metadata('local_table_4', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

ROLLBACK;
-- test behaviour when outside of transaction block
SELECT citus_add_local_table_to_metadata('local_table_4', cascade_via_foreign_keys=>true);
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

-- cleanup at exit
DROP SCHEMA citus_add_local_table_to_metadata_cascade CASCADE;
