diff --git a/src/test/regress/expected/foreign_key_to_reference_table.out b/src/test/regress/expected/foreign_key_to_reference_table.out index 72e593647..b9f9e3de7 100644 --- a/src/test/regress/expected/foreign_key_to_reference_table.out +++ b/src/test/regress/expected/foreign_key_to_reference_table.out @@ -6,6 +6,7 @@ SET search_path TO 'fkey_reference_table'; SET citus.shard_replication_factor TO 1; SET citus.shard_count TO 8; SET citus.next_shard_id TO 7000000; +SET citus.next_placement_id TO 7000000; CREATE TYPE foreign_details AS (name text, relid text, refd_relid text); SELECT run_command_on_workers($$CREATE TYPE foreign_details AS (name text, relid text, refd_relid text)$$); run_command_on_workers @@ -50,6 +51,11 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(ref_id) REFERE ERROR: cannot create foreign key constraint DETAIL: SET NULL or SET DEFAULT is not supported in ON DELETE operation when distribution key is included in the foreign key constraint DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET NULL); +SELECT create_distributed_table('referencing_table', 'ref_id'); +ERROR: cannot create foreign key constraint +DETAIL: SET NULL or SET DEFAULT is not supported in ON DELETE operation when distribution key is included in the foreign key constraint +DROP TABLE referencing_table; CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); create_distributed_table @@ -61,6 +67,11 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(ref_id) REFERE ERROR: cannot create foreign key constraint DETAIL: SET NULL or SET DEFAULT is not supported in ON DELETE operation when distribution key is included in the foreign key constraint DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT); +SELECT create_distributed_table('referencing_table', 'ref_id'); +ERROR: cannot create foreign key constraint +DETAIL: SET NULL or SET DEFAULT is not supported in ON DELETE operation when distribution key is included in the foreign key constraint +DROP TABLE referencing_table; CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); create_distributed_table @@ -72,6 +83,12 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(ref_id) REFERE ERROR: cannot create foreign key constraint DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint. DROP TABLE referencing_table; +BEGIN; + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON UPDATE SET NULL); + SELECT create_distributed_table('referencing_table', 'ref_id'); +ERROR: cannot create foreign key constraint +DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint. +ROLLBACK; -- try with multiple columns including the distribution column DROP TABLE referenced_table; CREATE TABLE referenced_table(id int, test_column int, PRIMARY KEY(id, test_column)); @@ -92,6 +109,11 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id, ref_id) RE ERROR: cannot create foreign key constraint DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint. DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id, ref_id) REFERENCES referenced_table(id, test_column) ON UPDATE SET DEFAULT); +SELECT create_distributed_table('referencing_table', 'ref_id'); +ERROR: cannot create foreign key constraint +DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint. +DROP TABLE referencing_table; CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); create_distributed_table @@ -103,6 +125,12 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id, ref_id) RE ERROR: cannot create foreign key constraint DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint. DROP TABLE referencing_table; +BEGIN; + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id, ref_id) REFERENCES referenced_table(id, test_column) ON UPDATE CASCADE); + SELECT create_distributed_table('referencing_table', 'ref_id'); +ERROR: cannot create foreign key constraint +DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint. +ROLLBACK; -- all of the above is supported if the foreign key does not include distribution column DROP TABLE referenced_table; CREATE TABLE referenced_table(id int, test_column int, PRIMARY KEY(id)); @@ -134,25 +162,24 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A (8 rows) DROP TABLE referencing_table; -CREATE TABLE referencing_table(id int, ref_id int); +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET NULL); SELECT create_distributed_table('referencing_table', 'ref_id'); create_distributed_table -------------------------- (1 row) -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; - name | relid | refd_relid -------------------+------------------------------------------------+----------------------------------------------- - fkey_ref_7000051 | fkey_reference_table.referencing_table_7000051 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000052 | fkey_reference_table.referencing_table_7000052 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000053 | fkey_reference_table.referencing_table_7000053 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000054 | fkey_reference_table.referencing_table_7000054 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000055 | fkey_reference_table.referencing_table_7000055 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000056 | fkey_reference_table.referencing_table_7000056 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000057 | fkey_reference_table.referencing_table_7000057 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000058 | fkey_reference_table.referencing_table_7000058 | fkey_reference_table.referenced_table_7000042 + name | relid | refd_relid +-----------------------------------+------------------------------------------------+----------------------------------------------- + referencing_table_id_fkey_7000051 | fkey_reference_table.referencing_table_7000051 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000052 | fkey_reference_table.referencing_table_7000052 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000053 | fkey_reference_table.referencing_table_7000053 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000054 | fkey_reference_table.referencing_table_7000054 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000055 | fkey_reference_table.referencing_table_7000055 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000056 | fkey_reference_table.referencing_table_7000056 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000057 | fkey_reference_table.referencing_table_7000057 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000058 | fkey_reference_table.referencing_table_7000058 | fkey_reference_table.referenced_table_7000042 (8 rows) DROP TABLE referencing_table; @@ -163,7 +190,7 @@ SELECT create_distributed_table('referencing_table', 'ref_id'); (1 row) -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES referenced_table(id) ON UPDATE SET NULL; +ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid ------------------+------------------------------------------------+----------------------------------------------- @@ -177,6 +204,51 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A fkey_ref_7000066 | fkey_reference_table.referencing_table_7000066 | fkey_reference_table.referenced_table_7000042 (8 rows) +DROP TABLE referencing_table; +BEGIN; + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT); + SELECT create_distributed_table('referencing_table', 'ref_id'); + create_distributed_table +-------------------------- + +(1 row) + +COMMIT; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; + name | relid | refd_relid +-----------------------------------+------------------------------------------------+----------------------------------------------- + referencing_table_id_fkey_7000067 | fkey_reference_table.referencing_table_7000067 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000068 | fkey_reference_table.referencing_table_7000068 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000069 | fkey_reference_table.referencing_table_7000069 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000070 | fkey_reference_table.referencing_table_7000070 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000071 | fkey_reference_table.referencing_table_7000071 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000072 | fkey_reference_table.referencing_table_7000072 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000073 | fkey_reference_table.referencing_table_7000073 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000074 | fkey_reference_table.referencing_table_7000074 | fkey_reference_table.referenced_table_7000042 +(8 rows) + +DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int); +SELECT create_distributed_table('referencing_table', 'ref_id'); + create_distributed_table +-------------------------- + +(1 row) + +ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES referenced_table(id) ON UPDATE SET NULL; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; + name | relid | refd_relid +------------------+------------------------------------------------+----------------------------------------------- + fkey_ref_7000075 | fkey_reference_table.referencing_table_7000075 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000076 | fkey_reference_table.referencing_table_7000076 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000077 | fkey_reference_table.referencing_table_7000077 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000078 | fkey_reference_table.referencing_table_7000078 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000079 | fkey_reference_table.referencing_table_7000079 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000080 | fkey_reference_table.referencing_table_7000080 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000081 | fkey_reference_table.referencing_table_7000081 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000082 | fkey_reference_table.referencing_table_7000082 | fkey_reference_table.referenced_table_7000042 +(8 rows) + DROP TABLE referencing_table; CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); @@ -189,14 +261,14 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid ------------------+------------------------------------------------+----------------------------------------------- - fkey_ref_7000067 | fkey_reference_table.referencing_table_7000067 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000068 | fkey_reference_table.referencing_table_7000068 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000069 | fkey_reference_table.referencing_table_7000069 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000070 | fkey_reference_table.referencing_table_7000070 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000071 | fkey_reference_table.referencing_table_7000071 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000072 | fkey_reference_table.referencing_table_7000072 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000073 | fkey_reference_table.referencing_table_7000073 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000074 | fkey_reference_table.referencing_table_7000074 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000083 | fkey_reference_table.referencing_table_7000083 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000084 | fkey_reference_table.referencing_table_7000084 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000085 | fkey_reference_table.referencing_table_7000085 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000086 | fkey_reference_table.referencing_table_7000086 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000087 | fkey_reference_table.referencing_table_7000087 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000088 | fkey_reference_table.referencing_table_7000088 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000089 | fkey_reference_table.referencing_table_7000089 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000090 | fkey_reference_table.referencing_table_7000090 | fkey_reference_table.referenced_table_7000042 (8 rows) DROP TABLE referencing_table; @@ -211,14 +283,14 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid ------------------+------------------------------------------------+----------------------------------------------- - fkey_ref_7000075 | fkey_reference_table.referencing_table_7000075 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000076 | fkey_reference_table.referencing_table_7000076 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000077 | fkey_reference_table.referencing_table_7000077 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000078 | fkey_reference_table.referencing_table_7000078 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000079 | fkey_reference_table.referencing_table_7000079 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000080 | fkey_reference_table.referencing_table_7000080 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000081 | fkey_reference_table.referencing_table_7000081 | fkey_reference_table.referenced_table_7000042 - fkey_ref_7000082 | fkey_reference_table.referencing_table_7000082 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000091 | fkey_reference_table.referencing_table_7000091 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000092 | fkey_reference_table.referencing_table_7000092 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000093 | fkey_reference_table.referencing_table_7000093 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000094 | fkey_reference_table.referencing_table_7000094 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000095 | fkey_reference_table.referencing_table_7000095 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000096 | fkey_reference_table.referencing_table_7000096 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000097 | fkey_reference_table.referencing_table_7000097 | fkey_reference_table.referenced_table_7000042 + fkey_ref_7000098 | fkey_reference_table.referencing_table_7000098 | fkey_reference_table.referenced_table_7000042 (8 rows) DROP TABLE referencing_table; @@ -242,6 +314,59 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A DROP TABLE referencing_table; SET citus.shard_replication_factor TO 1; +-- simple create_distributed_table should work in/out transactions on tables with foreign key to reference tables +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(id)); +SELECT create_distributed_table('referencing_table', 'ref_id'); + create_distributed_table +-------------------------- + +(1 row) + +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; + name | relid | refd_relid +-----------------------------------+------------------------------------------------+----------------------------------------------- + referencing_table_id_fkey_7000107 | fkey_reference_table.referencing_table_7000107 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000108 | fkey_reference_table.referencing_table_7000108 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000109 | fkey_reference_table.referencing_table_7000109 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000110 | fkey_reference_table.referencing_table_7000110 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000111 | fkey_reference_table.referencing_table_7000111 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000112 | fkey_reference_table.referencing_table_7000112 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000113 | fkey_reference_table.referencing_table_7000113 | fkey_reference_table.referenced_table_7000042 + referencing_table_id_fkey_7000114 | fkey_reference_table.referencing_table_7000114 | fkey_reference_table.referenced_table_7000042 +(8 rows) + +DROP TABLE referencing_table; +DROP TABLE referenced_table; +BEGIN; + CREATE TABLE referenced_table(id int, test_column int, PRIMARY KEY(id)); + SELECT create_reference_table('referenced_table'); + create_reference_table +------------------------ + +(1 row) + + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(id)); + SELECT create_distributed_table('referencing_table', 'ref_id'); + create_distributed_table +-------------------------- + +(1 row) + +COMMIT; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; + name | relid | refd_relid +-----------------------------------+------------------------------------------------+----------------------------------------------- + referencing_table_id_fkey_7000116 | fkey_reference_table.referencing_table_7000116 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000117 | fkey_reference_table.referencing_table_7000117 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000118 | fkey_reference_table.referencing_table_7000118 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000119 | fkey_reference_table.referencing_table_7000119 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000120 | fkey_reference_table.referencing_table_7000120 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000121 | fkey_reference_table.referencing_table_7000121 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000122 | fkey_reference_table.referencing_table_7000122 | fkey_reference_table.referenced_table_7000115 + referencing_table_id_fkey_7000123 | fkey_reference_table.referencing_table_7000123 | fkey_reference_table.referenced_table_7000115 +(8 rows) + +DROP TABLE referencing_table; -- foreign keys are supported either in between distributed tables including the -- distribution column or from distributed tables to reference tables. CREATE TABLE referencing_table(id int, ref_id int); @@ -296,8 +421,8 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFER -- test inserts -- test insert to referencing table while there is NO corresponding value in referenced table INSERT INTO referencing_table VALUES(1, 1); -ERROR: insert or update on table "referencing_table_7000092" violates foreign key constraint "fkey_ref_7000092" -DETAIL: Key (ref_id)=(1) is not present in table "referenced_table_7000091". +ERROR: insert or update on table "referencing_table_7000125" violates foreign key constraint "fkey_ref_7000125" +DETAIL: Key (ref_id)=(1) is not present in table "referenced_table_7000124". CONTEXT: while executing command on localhost:57637 -- test insert to referencing while there is corresponding value in referenced table INSERT INTO referenced_table SELECT x, x from generate_series(1,1000) as f(x); @@ -305,8 +430,8 @@ INSERT INTO referencing_table SELECT x, x from generate_series(1,500) as f(x); -- test deletes -- test delete from referenced table while there is corresponding value in referencing table DELETE FROM referenced_table WHERE id > 3; -ERROR: update or delete on table "referenced_table_7000091" violates foreign key constraint "fkey_ref_7000094" on table "referencing_table_7000094" -DETAIL: Key (id)=(4) is still referenced from table "referencing_table_7000094". +ERROR: update or delete on table "referenced_table_7000124" violates foreign key constraint "fkey_ref_7000127" on table "referencing_table_7000127" +DETAIL: Key (id)=(4) is still referenced from table "referencing_table_7000127". CONTEXT: while executing command on localhost:57637 -- test delete from referenced table while there is NO corresponding value in referencing table DELETE FROM referenced_table WHERE id = 501; @@ -503,8 +628,8 @@ INSERT INTO referenced_table SELECT x,x FROM generate_series(1,1000) AS f(x); INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x); -- Fails for non existing value inserts (serial is already incremented) INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x); -ERROR: insert or update on table "referencing_table_7000144" violates foreign key constraint "fkey_ref_7000144" -DETAIL: Key (ref_id)=(1006) is not present in table "referenced_table_7000138". +ERROR: insert or update on table "referencing_table_7000172" violates foreign key constraint "fkey_ref_7000172" +DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000171". DROP TABLE referenced_table CASCADE; NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; @@ -534,8 +659,8 @@ INSERT INTO referenced_table(test_column2) SELECT x FROM generate_series(1,1000) INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x); -- Fails for non existing value inserts (serial is already incremented) INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x); -ERROR: insert or update on table "referencing_table_7000151" violates foreign key constraint "fkey_ref_7000151" -DETAIL: Key (ref_id)=(1003) is not present in table "referenced_table_7000147". +ERROR: insert or update on table "referencing_table_7000181" violates foreign key constraint "fkey_ref_7000181" +DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000180". DROP TABLE referenced_table CASCADE; NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; @@ -586,8 +711,8 @@ INSERT INTO referenced_table SELECT x, x FROM generate_series(0,1000) AS f(x); INSERT INTO referencing_table SELECT x, x FROM generate_series(0,1000) AS f(x); -- we expect this to fail because of the foreign constraint. INSERT INTO referencing_table SELECT x, x FROM generate_series(1000,1001) AS f(x); -ERROR: insert or update on table "referencing_table_7000171" violates foreign key constraint "fkey_ref_7000171" -DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000165". +ERROR: insert or update on table "referencing_table_7000204" violates foreign key constraint "fkey_ref_7000204" +DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000198". -- currently not supported ALTER TABLE referencing_table VALIDATE CONSTRAINT fkey_ref; ERROR: alter table command is currently unsupported @@ -630,6 +755,29 @@ SELECT * FROM referencing_table WHERE ref_id < 0 ORDER BY 1; DROP TABLE referenced_table CASCADE; NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; +-- create_distributed_table should fail for tables with data if fkey exists to reference table +CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); +CREATE TABLE referencing_table(id int, ref_id int DEFAULT -1, FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column) ON UPDATE CASCADE); +INSERT INTO referenced_table VALUES (1,1), (2,2), (3,3); +INSERT INTO referencing_table VALUES (1,1), (2,2), (3,3); +SELECT create_reference_table('referenced_table'); +NOTICE: Copying data from local table... + create_reference_table +------------------------ + +(1 row) + +SELECT create_distributed_table('referencing_table', 'id'); +ERROR: cannot distribute "referencing_table" in sequential mode because it is not empty +HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty. +BEGIN; + SELECT create_distributed_table('referencing_table', 'id'); +ERROR: cannot distribute "referencing_table" in sequential mode because it is not empty +HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty. +COMMIT; +DROP TABLE referenced_table CASCADE; +NOTICE: drop cascades to constraint referencing_table_ref_id_fkey on table referencing_table +DROP TABLE referencing_table CASCADE; -- Chained references -- In the following test, we create foreign keys from one column in a distributed -- table to two reference tables. We expect to see that even if a data exist in @@ -663,38 +811,38 @@ ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (id) REFE SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------+------------------------------------------------+------------------------------------------------ - fkey_ref_7000185 | fkey_reference_table.referencing_table_7000185 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000186 | fkey_reference_table.referencing_table_7000186 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000187 | fkey_reference_table.referencing_table_7000187 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000188 | fkey_reference_table.referencing_table_7000188 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000189 | fkey_reference_table.referencing_table_7000189 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000190 | fkey_reference_table.referencing_table_7000190 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000191 | fkey_reference_table.referencing_table_7000191 | fkey_reference_table.referenced_table_7000183 - fkey_ref_7000192 | fkey_reference_table.referencing_table_7000192 | fkey_reference_table.referenced_table_7000183 - foreign_key_2_7000185 | fkey_reference_table.referencing_table_7000185 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000186 | fkey_reference_table.referencing_table_7000186 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000187 | fkey_reference_table.referencing_table_7000187 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000188 | fkey_reference_table.referencing_table_7000188 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000189 | fkey_reference_table.referencing_table_7000189 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000190 | fkey_reference_table.referencing_table_7000190 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000191 | fkey_reference_table.referencing_table_7000191 | fkey_reference_table.referenced_table2_7000184 - foreign_key_2_7000192 | fkey_reference_table.referencing_table_7000192 | fkey_reference_table.referenced_table2_7000184 + fkey_ref_7000219 | fkey_reference_table.referencing_table_7000219 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000220 | fkey_reference_table.referencing_table_7000220 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table_7000217 + fkey_ref_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table_7000217 + foreign_key_2_7000219 | fkey_reference_table.referencing_table_7000219 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000220 | fkey_reference_table.referencing_table_7000220 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table2_7000218 + foreign_key_2_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table2_7000218 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x); -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x); -ERROR: insert or update on table "referencing_table_7000192" violates foreign key constraint "foreign_key_2_7000192" -DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000184". +ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "foreign_key_2_7000220" +DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000218". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -ERROR: insert or update on table "referencing_table_7000192" violates foreign key constraint "foreign_key_2_7000192" -DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000184". +ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "foreign_key_2_7000220" +DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000218". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x); -ERROR: insert or update on table "referencing_table_7000192" violates foreign key constraint "fkey_ref_7000192" -DETAIL: Key (id)=(1023) is not present in table "referenced_table_7000183". +ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220" +DETAIL: Key (id)=(1005) is not present in table "referenced_table_7000217". -- should success INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x); SELECT count(*) FROM referencing_table; @@ -722,6 +870,39 @@ NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referenced_table2 CASCADE; NOTICE: drop cascades to constraint foreign_key_2 on table referencing_table DROP TABLE referencing_table CASCADE; +-- check if the above fkeys are created with create_distributed_table +CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); +CREATE TABLE referenced_table2(test_column int, test_column2 int, PRIMARY KEY(test_column2)); +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE, FOREIGN KEY (id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE); +SELECT create_reference_table('referenced_table'); + create_reference_table +------------------------ + +(1 row) + +SELECT create_reference_table('referenced_table2'); + create_reference_table +------------------------ + +(1 row) + +SELECT create_distributed_table('referencing_table', 'id'); + create_distributed_table +-------------------------- + +(1 row) + +SELECT count(*) FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%'; + count +------- + 16 +(1 row) + +DROP TABLE referenced_table CASCADE; +NOTICE: drop cascades to constraint referencing_table_id_fkey on table referencing_table +DROP TABLE referenced_table2 CASCADE; +NOTICE: drop cascades to constraint referencing_table_id_fkey1 on table referencing_table +DROP TABLE referencing_table CASCADE; -- In the following test, we create foreign keys from two columns in a distributed -- table to two reference tables separately. We expect to see that even if a data -- exist in one reference table for one column, it is not going to be inserted in @@ -751,44 +932,44 @@ SELECT create_distributed_table('referencing_table', 'id'); (1 row) BEGIN; -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE; -ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (ref_id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE; + ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE; + ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (ref_id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE; COMMIT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------+------------------------------------------------+------------------------------------------------ - fkey_ref_7000195 | fkey_reference_table.referencing_table_7000195 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000196 | fkey_reference_table.referencing_table_7000196 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000197 | fkey_reference_table.referencing_table_7000197 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000198 | fkey_reference_table.referencing_table_7000198 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000199 | fkey_reference_table.referencing_table_7000199 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000200 | fkey_reference_table.referencing_table_7000200 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000201 | fkey_reference_table.referencing_table_7000201 | fkey_reference_table.referenced_table_7000193 - fkey_ref_7000202 | fkey_reference_table.referencing_table_7000202 | fkey_reference_table.referenced_table_7000193 - foreign_key_2_7000195 | fkey_reference_table.referencing_table_7000195 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000196 | fkey_reference_table.referencing_table_7000196 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000197 | fkey_reference_table.referencing_table_7000197 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000198 | fkey_reference_table.referencing_table_7000198 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000199 | fkey_reference_table.referencing_table_7000199 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000200 | fkey_reference_table.referencing_table_7000200 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000201 | fkey_reference_table.referencing_table_7000201 | fkey_reference_table.referenced_table2_7000194 - foreign_key_2_7000202 | fkey_reference_table.referencing_table_7000202 | fkey_reference_table.referenced_table2_7000194 + fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000243 | fkey_reference_table.referencing_table_7000243 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000244 | fkey_reference_table.referencing_table_7000244 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000245 | fkey_reference_table.referencing_table_7000245 | fkey_reference_table.referenced_table_7000237 + fkey_ref_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table_7000237 + foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000243 | fkey_reference_table.referencing_table_7000243 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000244 | fkey_reference_table.referencing_table_7000244 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000245 | fkey_reference_table.referencing_table_7000245 | fkey_reference_table.referenced_table2_7000238 + foreign_key_2_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table2_7000238 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x); -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x); -ERROR: insert or update on table "referencing_table_7000197" violates foreign key constraint "foreign_key_2_7000197" -DETAIL: Key (ref_id)=(5) is not present in table "referenced_table2_7000194". +ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "foreign_key_2_7000245" +DETAIL: Key (ref_id)=(3) is not present in table "referenced_table2_7000238". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -ERROR: insert or update on table "referencing_table_7000197" violates foreign key constraint "foreign_key_2_7000197" -DETAIL: Key (ref_id)=(5) is not present in table "referenced_table2_7000194". +ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "foreign_key_2_7000245" +DETAIL: Key (ref_id)=(3) is not present in table "referenced_table2_7000238". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x); -ERROR: insert or update on table "referencing_table_7000197" violates foreign key constraint "fkey_ref_7000197" -DETAIL: Key (id)=(1015) is not present in table "referenced_table_7000193". +ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "fkey_ref_7000245" +DETAIL: Key (id)=(1002) is not present in table "referenced_table_7000237". -- should success INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x); SELECT count(*) FROM referencing_table; @@ -816,6 +997,42 @@ NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referenced_table2 CASCADE; NOTICE: drop cascades to constraint foreign_key_2 on table referencing_table DROP TABLE referencing_table CASCADE; +-- check if the above fkeys are created when create_distributed_table is used for 1 foreign key and alter table for the other +CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); +CREATE TABLE referenced_table2(test_column int, test_column2 int, PRIMARY KEY(test_column2)); +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE); +BEGIN; + SELECT create_reference_table('referenced_table'); + create_reference_table +------------------------ + +(1 row) + + SELECT create_reference_table('referenced_table2'); + create_reference_table +------------------------ + +(1 row) + + SELECT create_distributed_table('referencing_table', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (ref_id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE; +COMMIT; +SELECT count(*) FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%'; + count +------- + 16 +(1 row) + +DROP TABLE referenced_table CASCADE; +NOTICE: drop cascades to constraint referencing_table_id_fkey on table referencing_table +DROP TABLE referenced_table2 CASCADE; +NOTICE: drop cascades to constraint foreign_key_2 on table referencing_table +DROP TABLE referencing_table CASCADE; -- two distributed tables are referencing to one reference table and -- in the same time the distributed table 2 is referencing to -- distributed table 1. Thus, we have a triangular @@ -851,46 +1068,46 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (id) REFERENCE ALTER TABLE referencing_table2 ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column2) ON DELETE CASCADE; ALTER TABLE referencing_table2 ADD CONSTRAINT fkey_ref_to_dist FOREIGN KEY (id) REFERENCES referencing_table(id) ON DELETE CASCADE; COMMIT; -SELECT * FROM table_fkeys_in_workers WHERE name LIKE 'fkey_ref%' ORDER BY 1,2,3; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid --------------------------+-------------------------------------------------+------------------------------------------------ - fkey_ref_7000204 | fkey_reference_table.referencing_table_7000204 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000205 | fkey_reference_table.referencing_table_7000205 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000206 | fkey_reference_table.referencing_table_7000206 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000207 | fkey_reference_table.referencing_table_7000207 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000208 | fkey_reference_table.referencing_table_7000208 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000209 | fkey_reference_table.referencing_table_7000209 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000210 | fkey_reference_table.referencing_table_7000210 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000211 | fkey_reference_table.referencing_table_7000211 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000212 | fkey_reference_table.referencing_table2_7000212 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000213 | fkey_reference_table.referencing_table2_7000213 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000214 | fkey_reference_table.referencing_table2_7000214 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000215 | fkey_reference_table.referencing_table2_7000215 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000216 | fkey_reference_table.referencing_table2_7000216 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000217 | fkey_reference_table.referencing_table2_7000217 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000218 | fkey_reference_table.referencing_table2_7000218 | fkey_reference_table.referenced_table_7000203 - fkey_ref_7000219 | fkey_reference_table.referencing_table2_7000219 | fkey_reference_table.referenced_table_7000203 - fkey_ref_to_dist_7000212 | fkey_reference_table.referencing_table2_7000212 | fkey_reference_table.referencing_table_7000204 - fkey_ref_to_dist_7000213 | fkey_reference_table.referencing_table2_7000213 | fkey_reference_table.referencing_table_7000205 - fkey_ref_to_dist_7000214 | fkey_reference_table.referencing_table2_7000214 | fkey_reference_table.referencing_table_7000206 - fkey_ref_to_dist_7000215 | fkey_reference_table.referencing_table2_7000215 | fkey_reference_table.referencing_table_7000207 - fkey_ref_to_dist_7000216 | fkey_reference_table.referencing_table2_7000216 | fkey_reference_table.referencing_table_7000208 - fkey_ref_to_dist_7000217 | fkey_reference_table.referencing_table2_7000217 | fkey_reference_table.referencing_table_7000209 - fkey_ref_to_dist_7000218 | fkey_reference_table.referencing_table2_7000218 | fkey_reference_table.referencing_table_7000210 - fkey_ref_to_dist_7000219 | fkey_reference_table.referencing_table2_7000219 | fkey_reference_table.referencing_table_7000211 + fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000263 | fkey_reference_table.referencing_table_7000263 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000264 | fkey_reference_table.referencing_table_7000264 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000265 | fkey_reference_table.referencing_table_7000265 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000266 | fkey_reference_table.referencing_table2_7000266 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000267 | fkey_reference_table.referencing_table2_7000267 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000268 | fkey_reference_table.referencing_table2_7000268 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000269 | fkey_reference_table.referencing_table2_7000269 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000270 | fkey_reference_table.referencing_table2_7000270 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000271 | fkey_reference_table.referencing_table2_7000271 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000272 | fkey_reference_table.referencing_table2_7000272 | fkey_reference_table.referenced_table_7000257 + fkey_ref_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referenced_table_7000257 + fkey_ref_to_dist_7000266 | fkey_reference_table.referencing_table2_7000266 | fkey_reference_table.referencing_table_7000258 + fkey_ref_to_dist_7000267 | fkey_reference_table.referencing_table2_7000267 | fkey_reference_table.referencing_table_7000259 + fkey_ref_to_dist_7000268 | fkey_reference_table.referencing_table2_7000268 | fkey_reference_table.referencing_table_7000260 + fkey_ref_to_dist_7000269 | fkey_reference_table.referencing_table2_7000269 | fkey_reference_table.referencing_table_7000261 + fkey_ref_to_dist_7000270 | fkey_reference_table.referencing_table2_7000270 | fkey_reference_table.referencing_table_7000262 + fkey_ref_to_dist_7000271 | fkey_reference_table.referencing_table2_7000271 | fkey_reference_table.referencing_table_7000263 + fkey_ref_to_dist_7000272 | fkey_reference_table.referencing_table2_7000272 | fkey_reference_table.referencing_table_7000264 + fkey_ref_to_dist_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referencing_table_7000265 (24 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); -- should fail INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x); -ERROR: insert or update on table "referencing_table2_7000215" violates foreign key constraint "fkey_ref_to_dist_7000215" -DETAIL: Key (id)=(0) is not present in table "referencing_table_7000207". +ERROR: insert or update on table "referencing_table2_7000272" violates foreign key constraint "fkey_ref_to_dist_7000272" +DETAIL: Key (id)=(2) is not present in table "referencing_table_7000264". -- should success INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -- should fail INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x); -ERROR: insert or update on table "referencing_table2_7000215" violates foreign key constraint "fkey_ref_to_dist_7000215" -DETAIL: Key (id)=(407) is not present in table "referencing_table_7000207". +ERROR: insert or update on table "referencing_table2_7000272" violates foreign key constraint "fkey_ref_to_dist_7000272" +DETAIL: Key (id)=(404) is not present in table "referencing_table_7000264". -- should success INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x); DELETE FROM referenced_table WHERE test_column < 200; @@ -920,6 +1137,44 @@ drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; NOTICE: drop cascades to constraint fkey_ref_to_dist on table referencing_table2 DROP TABLE referencing_table2 CASCADE; +-- Check if the above fkeys are created with create_distributed_table +CREATE TABLE referenced_table(test_column int, test_column2 int UNIQUE, PRIMARY KEY(test_column)); +CREATE TABLE referencing_table(id int PRIMARY KEY, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE); +CREATE TABLE referencing_table2(id int, ref_id int, FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column2) ON DELETE CASCADE, FOREIGN KEY (id) REFERENCES referencing_table(id) ON DELETE CASCADE); +SELECT create_reference_table('referenced_table'); + create_reference_table +------------------------ + +(1 row) + +BEGIN; + SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; + SELECT create_distributed_table('referencing_table', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + SELECT create_distributed_table('referencing_table2', 'id'); + create_distributed_table +-------------------------- + +(1 row) + +COMMIT; +SELECT count(*) FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%'; + count +------- + 24 +(1 row) + +DROP TABLE referenced_table CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to constraint referencing_table2_ref_id_fkey on table referencing_table2 +drop cascades to constraint referencing_table_id_fkey on table referencing_table +DROP TABLE referencing_table CASCADE; +NOTICE: drop cascades to constraint referencing_table2_id_fkey on table referencing_table2 +DROP TABLE referencing_table2 CASCADE; -- In this test we have a chained relationship in form of -- distributed table (referencing_referencing_table) has a foreign key with two columns -- to another distributed table (referencing_table) @@ -950,22 +1205,22 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id, ref_i SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.referencing%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------------------------------+------------------------------------------------------------+------------------------------------------------ - fkey_ref_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000227 | fkey_reference_table.referencing_table_7000227 | fkey_reference_table.referenced_table_7000220 - fkey_ref_7000228 | fkey_reference_table.referencing_table_7000228 | fkey_reference_table.referenced_table_7000220 - referencing_referencing_table_id_fkey_7000229 | fkey_reference_table.referencing_referencing_table_7000229 | fkey_reference_table.referencing_table_7000221 - referencing_referencing_table_id_fkey_7000230 | fkey_reference_table.referencing_referencing_table_7000230 | fkey_reference_table.referencing_table_7000222 - referencing_referencing_table_id_fkey_7000231 | fkey_reference_table.referencing_referencing_table_7000231 | fkey_reference_table.referencing_table_7000223 - referencing_referencing_table_id_fkey_7000232 | fkey_reference_table.referencing_referencing_table_7000232 | fkey_reference_table.referencing_table_7000224 - referencing_referencing_table_id_fkey_7000233 | fkey_reference_table.referencing_referencing_table_7000233 | fkey_reference_table.referencing_table_7000225 - referencing_referencing_table_id_fkey_7000234 | fkey_reference_table.referencing_referencing_table_7000234 | fkey_reference_table.referencing_table_7000226 - referencing_referencing_table_id_fkey_7000235 | fkey_reference_table.referencing_referencing_table_7000235 | fkey_reference_table.referencing_table_7000227 - referencing_referencing_table_id_fkey_7000236 | fkey_reference_table.referencing_referencing_table_7000236 | fkey_reference_table.referencing_table_7000228 + fkey_ref_7000292 | fkey_reference_table.referencing_table_7000292 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000293 | fkey_reference_table.referencing_table_7000293 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000294 | fkey_reference_table.referencing_table_7000294 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000295 | fkey_reference_table.referencing_table_7000295 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000296 | fkey_reference_table.referencing_table_7000296 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000297 | fkey_reference_table.referencing_table_7000297 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000298 | fkey_reference_table.referencing_table_7000298 | fkey_reference_table.referenced_table_7000291 + fkey_ref_7000299 | fkey_reference_table.referencing_table_7000299 | fkey_reference_table.referenced_table_7000291 + referencing_referencing_table_id_fkey_7000300 | fkey_reference_table.referencing_referencing_table_7000300 | fkey_reference_table.referencing_table_7000292 + referencing_referencing_table_id_fkey_7000301 | fkey_reference_table.referencing_referencing_table_7000301 | fkey_reference_table.referencing_table_7000293 + referencing_referencing_table_id_fkey_7000302 | fkey_reference_table.referencing_referencing_table_7000302 | fkey_reference_table.referencing_table_7000294 + referencing_referencing_table_id_fkey_7000303 | fkey_reference_table.referencing_referencing_table_7000303 | fkey_reference_table.referencing_table_7000295 + referencing_referencing_table_id_fkey_7000304 | fkey_reference_table.referencing_referencing_table_7000304 | fkey_reference_table.referencing_table_7000296 + referencing_referencing_table_id_fkey_7000305 | fkey_reference_table.referencing_referencing_table_7000305 | fkey_reference_table.referencing_table_7000297 + referencing_referencing_table_id_fkey_7000306 | fkey_reference_table.referencing_referencing_table_7000306 | fkey_reference_table.referencing_table_7000298 + referencing_referencing_table_id_fkey_7000307 | fkey_reference_table.referencing_referencing_table_7000307 | fkey_reference_table.referencing_table_7000299 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(1,1000) AS f(x); @@ -983,6 +1238,125 @@ NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; NOTICE: drop cascades to constraint referencing_referencing_table_id_fkey on table referencing_referencing_table DROP TABLE referencing_referencing_table; +-- test if create_distributed_table works in transactions with some edge cases +-- the following checks if create_distributed_table works on foreign keys when +-- one of them is a self-referencing table of multiple distributed tables +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY); + SELECT create_reference_table('test_table_1'); + create_reference_table +------------------------ + +(1 row) + + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(id) REFERENCES test_table_1(id)); + SELECT create_distributed_table('test_table_2', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + CREATE TABLE test_table_3(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id), FOREIGN KEY(id) REFERENCES test_table_2(id)); + SELECT create_distributed_table('test_table_3', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + DROP TABLE test_table_1 CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to constraint test_table_2_id_fkey on table test_table_2 +drop cascades to constraint test_table_3_value_1_fkey on table test_table_3 +ROLLBACK; +-- create_reference_table, create_distributed_table and ALTER TABLE in the same transaction +-- FIXME: fails for now +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY); + SELECT create_reference_table('test_table_1'); + create_reference_table +------------------------ + +(1 row) + + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int); + SELECT create_distributed_table('test_table_2', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + ALTER TABLE test_table_2 ADD CONSTRAINT c_check FOREIGN KEY (value_1) REFERENCES test_table_1(id); +ERROR: relation "fkey_reference_table.test_table_1_7000325" does not exist +CONTEXT: while executing command on localhost:57637 + DROP TABLE test_table_1, test_table_2; +ERROR: current transaction is aborted, commands ignored until end of transaction block +COMMIT; +-- the order of create_reference_table and create_distributed_table is changed +-- FIXME: fails for now +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY, value_1 int); + SELECT create_distributed_table('test_table_1', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + CREATE TABLE test_table_2(id int PRIMARY KEY); + SELECT create_reference_table('test_table_2'); + create_reference_table +------------------------ + +(1 row) + + ALTER TABLE test_table_1 ADD CONSTRAINT c_check FOREIGN KEY (value_1) REFERENCES test_table_2(id); +ERROR: relation "fkey_reference_table.test_table_2_7000342" does not exist +CONTEXT: while executing command on localhost:57637 + DROP TABLE test_table_2 CASCADE; +ERROR: current transaction is aborted, commands ignored until end of transaction block +ROLLBACK; +-- make sure that we fail if we need parallel data load +BEGIN; + + CREATE TABLE test_table_1(id int PRIMARY KEY); + INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i; + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id)); + INSERT INTO test_table_2 SELECT i, i FROM generate_series(0,100) i; + SELECT create_reference_table('test_table_1'); +NOTICE: Copying data from local table... + create_reference_table +------------------------ + +(1 row) + + SELECT create_distributed_table('test_table_2', 'id'); +ERROR: cannot distribute "test_table_2" in sequential mode because it is not empty +HINT: If you have manually set citus.multi_shard_modify_mode to 'sequential', try with 'parallel' option. If that is not the case, try distributing local tables when they are empty. + DROP TABLE test_table_2, test_table_1; +ERROR: current transaction is aborted, commands ignored until end of transaction block +COMMIT; +-- make sure that other DDLs/DMLs also work fine +-- FIXME: fails for now +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY); + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id)); + SELECT create_reference_table('test_table_1'); + create_reference_table +------------------------ + +(1 row) + + SELECT create_distributed_table('test_table_2', 'id'); + create_distributed_table +-------------------------- + +(1 row) + + CREATE INDEX i1 ON test_table_1(id); + ALTER TABLE test_table_2 ADD CONSTRAINT check_val CHECK (id > 0); +ERROR: cannot establish a new connection for placement 7000388, since DDL has been executed on a connection that is in use + DROP TABLE test_table_2, test_table_1; +ERROR: current transaction is aborted, commands ignored until end of transaction block +COMMIT; DROP SCHEMA fkey_reference_table CASCADE; NOTICE: drop cascades to 3 other objects DETAIL: drop cascades to type foreign_details diff --git a/src/test/regress/sql/foreign_key_to_reference_table.sql b/src/test/regress/sql/foreign_key_to_reference_table.sql index 323be6889..723ba6fb1 100644 --- a/src/test/regress/sql/foreign_key_to_reference_table.sql +++ b/src/test/regress/sql/foreign_key_to_reference_table.sql @@ -7,6 +7,7 @@ SET search_path TO 'fkey_reference_table'; SET citus.shard_replication_factor TO 1; SET citus.shard_count TO 8; SET citus.next_shard_id TO 7000000; +SET citus.next_placement_id TO 7000000; CREATE TYPE foreign_details AS (name text, relid text, refd_relid text); SELECT run_command_on_workers($$CREATE TYPE foreign_details AS (name text, relid text, refd_relid text)$$); @@ -38,16 +39,29 @@ SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET NULL; DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET NULL); +SELECT create_distributed_table('referencing_table', 'ref_id'); +DROP TABLE referencing_table; + CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT; DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT); +SELECT create_distributed_table('referencing_table', 'ref_id'); +DROP TABLE referencing_table; + CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON UPDATE SET NULL; DROP TABLE referencing_table; +BEGIN; + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON UPDATE SET NULL); + SELECT create_distributed_table('referencing_table', 'ref_id'); +ROLLBACK; + -- try with multiple columns including the distribution column DROP TABLE referenced_table; CREATE TABLE referenced_table(id int, test_column int, PRIMARY KEY(id, test_column)); @@ -58,11 +72,20 @@ SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id, ref_id) REFERENCES referenced_table(id, test_column) ON UPDATE SET DEFAULT; DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id, ref_id) REFERENCES referenced_table(id, test_column) ON UPDATE SET DEFAULT); +SELECT create_distributed_table('referencing_table', 'ref_id'); +DROP TABLE referencing_table; + CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id, ref_id) REFERENCES referenced_table(id, test_column) ON UPDATE CASCADE; DROP TABLE referencing_table; +BEGIN; + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id, ref_id) REFERENCES referenced_table(id, test_column) ON UPDATE CASCADE); + SELECT create_distributed_table('referencing_table', 'ref_id'); +ROLLBACK; + -- all of the above is supported if the foreign key does not include distribution column DROP TABLE referenced_table; CREATE TABLE referenced_table(id int, test_column int, PRIMARY KEY(id)); @@ -74,12 +97,24 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; DROP TABLE referencing_table; +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET NULL); +SELECT create_distributed_table('referencing_table', 'ref_id'); +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; +DROP TABLE referencing_table; + CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; DROP TABLE referencing_table; +BEGIN; + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY(id) REFERENCES referenced_table(id) ON DELETE SET DEFAULT); + SELECT create_distributed_table('referencing_table', 'ref_id'); +COMMIT; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; +DROP TABLE referencing_table; + CREATE TABLE referencing_table(id int, ref_id int); SELECT create_distributed_table('referencing_table', 'ref_id'); ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES referenced_table(id) ON UPDATE SET NULL; @@ -107,6 +142,22 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A DROP TABLE referencing_table; SET citus.shard_replication_factor TO 1; +-- simple create_distributed_table should work in/out transactions on tables with foreign key to reference tables +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(id)); +SELECT create_distributed_table('referencing_table', 'ref_id'); +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; +DROP TABLE referencing_table; +DROP TABLE referenced_table; + +BEGIN; + CREATE TABLE referenced_table(id int, test_column int, PRIMARY KEY(id)); + SELECT create_reference_table('referenced_table'); + CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(id)); + SELECT create_distributed_table('referencing_table', 'ref_id'); +COMMIT; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; +DROP TABLE referencing_table; + -- foreign keys are supported either in between distributed tables including the -- distribution column or from distributed tables to reference tables. CREATE TABLE referencing_table(id int, ref_id int); @@ -340,6 +391,20 @@ SELECT * FROM referencing_table WHERE ref_id < 0 ORDER BY 1; DROP TABLE referenced_table CASCADE; DROP TABLE referencing_table CASCADE; +-- create_distributed_table should fail for tables with data if fkey exists to reference table +CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); +CREATE TABLE referencing_table(id int, ref_id int DEFAULT -1, FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column) ON UPDATE CASCADE); +INSERT INTO referenced_table VALUES (1,1), (2,2), (3,3); +INSERT INTO referencing_table VALUES (1,1), (2,2), (3,3); +SELECT create_reference_table('referenced_table'); +SELECT create_distributed_table('referencing_table', 'id'); + +BEGIN; + SELECT create_distributed_table('referencing_table', 'id'); +COMMIT; + +DROP TABLE referenced_table CASCADE; +DROP TABLE referencing_table CASCADE; -- Chained references -- In the following test, we create foreign keys from one column in a distributed @@ -380,6 +445,19 @@ DROP TABLE referenced_table CASCADE; DROP TABLE referenced_table2 CASCADE; DROP TABLE referencing_table CASCADE; +-- check if the above fkeys are created with create_distributed_table +CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); +CREATE TABLE referenced_table2(test_column int, test_column2 int, PRIMARY KEY(test_column2)); +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE, FOREIGN KEY (id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE); +SELECT create_reference_table('referenced_table'); +SELECT create_reference_table('referenced_table2'); +SELECT create_distributed_table('referencing_table', 'id'); + +SELECT count(*) FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%'; + +DROP TABLE referenced_table CASCADE; +DROP TABLE referenced_table2 CASCADE; +DROP TABLE referencing_table CASCADE; -- In the following test, we create foreign keys from two columns in a distributed -- table to two reference tables separately. We expect to see that even if a data @@ -396,8 +474,8 @@ SELECT create_reference_table('referenced_table2'); SELECT create_distributed_table('referencing_table', 'id'); BEGIN; -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE; -ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (ref_id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE; + ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE; + ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (ref_id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE; COMMIT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; @@ -423,6 +501,24 @@ DROP TABLE referenced_table CASCADE; DROP TABLE referenced_table2 CASCADE; DROP TABLE referencing_table CASCADE; +-- check if the above fkeys are created when create_distributed_table is used for 1 foreign key and alter table for the other +CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); +CREATE TABLE referenced_table2(test_column int, test_column2 int, PRIMARY KEY(test_column2)); +CREATE TABLE referencing_table(id int, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE); + +BEGIN; + SELECT create_reference_table('referenced_table'); + SELECT create_reference_table('referenced_table2'); + SELECT create_distributed_table('referencing_table', 'id'); + ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (ref_id) REFERENCES referenced_table2(test_column2) ON DELETE CASCADE; +COMMIT; + +SELECT count(*) FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%'; + +DROP TABLE referenced_table CASCADE; +DROP TABLE referenced_table2 CASCADE; +DROP TABLE referencing_table CASCADE; + -- two distributed tables are referencing to one reference table and -- in the same time the distributed table 2 is referencing to @@ -445,7 +541,7 @@ ALTER TABLE referencing_table2 ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFE ALTER TABLE referencing_table2 ADD CONSTRAINT fkey_ref_to_dist FOREIGN KEY (id) REFERENCES referencing_table(id) ON DELETE CASCADE; COMMIT; -SELECT * FROM table_fkeys_in_workers WHERE name LIKE 'fkey_ref%' ORDER BY 1,2,3; +SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); -- should fail @@ -467,6 +563,23 @@ DROP TABLE referenced_table CASCADE; DROP TABLE referencing_table CASCADE; DROP TABLE referencing_table2 CASCADE; +-- Check if the above fkeys are created with create_distributed_table +CREATE TABLE referenced_table(test_column int, test_column2 int UNIQUE, PRIMARY KEY(test_column)); +CREATE TABLE referencing_table(id int PRIMARY KEY, ref_id int, FOREIGN KEY (id) REFERENCES referenced_table(test_column) ON DELETE CASCADE); +CREATE TABLE referencing_table2(id int, ref_id int, FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column2) ON DELETE CASCADE, FOREIGN KEY (id) REFERENCES referencing_table(id) ON DELETE CASCADE); +SELECT create_reference_table('referenced_table'); +BEGIN; + SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; + SELECT create_distributed_table('referencing_table', 'id'); + SELECT create_distributed_table('referencing_table2', 'id'); +COMMIT; + +SELECT count(*) FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%'; + +DROP TABLE referenced_table CASCADE; +DROP TABLE referencing_table CASCADE; +DROP TABLE referencing_table2 CASCADE; + -- In this test we have a chained relationship in form of -- distributed table (referencing_referencing_table) has a foreign key with two columns @@ -494,5 +607,78 @@ DROP TABLE referenced_table CASCADE; DROP TABLE referencing_table CASCADE; DROP TABLE referencing_referencing_table; +-- test if create_distributed_table works in transactions with some edge cases +-- the following checks if create_distributed_table works on foreign keys when +-- one of them is a self-referencing table of multiple distributed tables +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY); + SELECT create_reference_table('test_table_1'); + + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(id) REFERENCES test_table_1(id)); + SELECT create_distributed_table('test_table_2', 'id'); + + CREATE TABLE test_table_3(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id), FOREIGN KEY(id) REFERENCES test_table_2(id)); + SELECT create_distributed_table('test_table_3', 'id'); + + DROP TABLE test_table_1 CASCADE; +ROLLBACK; + +-- create_reference_table, create_distributed_table and ALTER TABLE in the same transaction +-- FIXME: fails for now +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY); + SELECT create_reference_table('test_table_1'); + + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int); + SELECT create_distributed_table('test_table_2', 'id'); + + ALTER TABLE test_table_2 ADD CONSTRAINT c_check FOREIGN KEY (value_1) REFERENCES test_table_1(id); + + DROP TABLE test_table_1, test_table_2; +COMMIT; + +-- the order of create_reference_table and create_distributed_table is changed +-- FIXME: fails for now +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY, value_1 int); + SELECT create_distributed_table('test_table_1', 'id'); + + CREATE TABLE test_table_2(id int PRIMARY KEY); + SELECT create_reference_table('test_table_2'); + + ALTER TABLE test_table_1 ADD CONSTRAINT c_check FOREIGN KEY (value_1) REFERENCES test_table_2(id); + + DROP TABLE test_table_2 CASCADE; +ROLLBACK; + +-- make sure that we fail if we need parallel data load +BEGIN; + + CREATE TABLE test_table_1(id int PRIMARY KEY); + INSERT INTO test_table_1 SELECT i FROM generate_series(0,100) i; + + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id)); + INSERT INTO test_table_2 SELECT i, i FROM generate_series(0,100) i; + + SELECT create_reference_table('test_table_1'); + SELECT create_distributed_table('test_table_2', 'id'); + DROP TABLE test_table_2, test_table_1; +COMMIT; + +-- make sure that other DDLs/DMLs also work fine +-- FIXME: fails for now +BEGIN; + CREATE TABLE test_table_1(id int PRIMARY KEY); + CREATE TABLE test_table_2(id int PRIMARY KEY, value_1 int, FOREIGN KEY(value_1) REFERENCES test_table_1(id)); + + SELECT create_reference_table('test_table_1'); + SELECT create_distributed_table('test_table_2', 'id'); + + CREATE INDEX i1 ON test_table_1(id); + ALTER TABLE test_table_2 ADD CONSTRAINT check_val CHECK (id > 0); + + DROP TABLE test_table_2, test_table_1; +COMMIT; + DROP SCHEMA fkey_reference_table CASCADE; SET search_path TO DEFAULT;