\set VERBOSITY terse SET citus.next_shard_id TO 1506000; SET citus.shard_replication_factor TO 1; SET citus.enable_local_execution TO ON; SET citus.log_local_commands TO ON; CREATE SCHEMA ref_citus_local_fkeys; SET search_path TO ref_citus_local_fkeys; -- ensure that coordinator is added to pg_dist_node SET client_min_messages to ERROR; SELECT 1 FROM master_add_node('localhost', :master_port, groupId => 0); ?column? --------------------------------------------------------------------- 1 (1 row) RESET client_min_messages; -- create test tables CREATE TABLE citus_local_table(l1 int); SELECT create_citus_local_table('citus_local_table'); create_citus_local_table --------------------------------------------------------------------- (1 row) CREATE TABLE reference_table(r1 int primary key); SELECT create_reference_table('reference_table'); create_reference_table --------------------------------------------------------------------- (1 row) --------------------------------------------------------------------- -- foreign key from citus local table to reference table -- --------------------------------------------------------------------- -- we support ON DELETE CASCADE behaviour in "ALTER TABLE ADD fkey citus_local_table (to reference_table) commands ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1) ON DELETE CASCADE; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1) ON DELETE CASCADE;') -- show that on delete cascade works INSERT INTO reference_table VALUES (11); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.reference_table_1506001 (r1) VALUES (11) INSERT INTO citus_local_table VALUES (11); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.citus_local_table_1506000 (l1) VALUES (11) DELETE FROM reference_table WHERE r1=11; NOTICE: executing the command locally: DELETE FROM ref_citus_local_fkeys.reference_table_1506001 reference_table WHERE (r1 OPERATOR(pg_catalog.=) 11) -- should print 0 rows SELECT * FROM citus_local_table ORDER BY l1; NOTICE: executing the command locally: SELECT l1 FROM ref_citus_local_fkeys.citus_local_table_1506000 citus_local_table ORDER BY l1 l1 --------------------------------------------------------------------- (0 rows) -- show that we support drop constraint ALTER TABLE citus_local_table DROP CONSTRAINT fkey_local_to_ref; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table DROP CONSTRAINT fkey_local_to_ref;') -- we support ON UPDATE CASCADE behaviour in "ALTER TABLE ADD fkey citus_local_table (to reference table)" commands ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1) ON UPDATE CASCADE; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1) ON UPDATE CASCADE;') -- show that on update cascade works INSERT INTO reference_table VALUES (12); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.reference_table_1506001 (r1) VALUES (12) INSERT INTO citus_local_table VALUES (12); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.citus_local_table_1506000 (l1) VALUES (12) UPDATE reference_table SET r1=13 WHERE r1=12; NOTICE: executing the command locally: UPDATE ref_citus_local_fkeys.reference_table_1506001 reference_table SET r1 = 13 WHERE (r1 OPERATOR(pg_catalog.=) 12) -- should print a row with 13 SELECT * FROM citus_local_table ORDER BY l1; NOTICE: executing the command locally: SELECT l1 FROM ref_citus_local_fkeys.citus_local_table_1506000 citus_local_table ORDER BY l1 l1 --------------------------------------------------------------------- 13 (1 row) -- drop constraint for next commands ALTER TABLE citus_local_table DROP CONSTRAINT fkey_local_to_ref; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table DROP CONSTRAINT fkey_local_to_ref;') INSERT INTO citus_local_table VALUES (2); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.citus_local_table_1506000 (l1) VALUES (2) -- show that we are checking for foreign key constraint while defining, below should fail ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1); NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1);') ERROR: insert or update on table "citus_local_table_1506000" violates foreign key constraint "fkey_local_to_ref_1506000" INSERT INTO reference_table VALUES (2); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.reference_table_1506001 (r1) VALUES (2) -- this should work ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1); NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1);') -- show that we are checking for foreign key constraint after defining, this should fail INSERT INTO citus_local_table VALUES (1); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.citus_local_table_1506000 (l1) VALUES (1) ERROR: insert or update on table "citus_local_table_1506000" violates foreign key constraint "fkey_local_to_ref_1506000" INSERT INTO reference_table VALUES (1); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.reference_table_1506001 (r1) VALUES (1) -- this should work INSERT INTO citus_local_table VALUES (1); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.citus_local_table_1506000 (l1) VALUES (1) -- drop and add constraint for next commands ALTER TABLE citus_local_table DROP CONSTRAINT fkey_local_to_ref; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table DROP CONSTRAINT fkey_local_to_ref;') ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1); NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506000, 'ref_citus_local_fkeys', 1506001, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table ADD CONSTRAINT fkey_local_to_ref FOREIGN KEY(l1) REFERENCES reference_table(r1);') -- show that drop table without CASCADE errors out DROP TABLE reference_table; ERROR: cannot drop table reference_table because other objects depend on it -- this should work BEGIN; DROP TABLE reference_table CASCADE; NOTICE: drop cascades to constraint fkey_local_to_ref on table citus_local_table NOTICE: executing the command locally: DROP TABLE IF EXISTS ref_citus_local_fkeys.reference_table_xxxxx CASCADE NOTICE: drop cascades to constraint fkey_local_to_ref_1506000 on table ref_citus_local_fkeys.citus_local_table_1506000 ROLLBACK; -- drop tables finally DROP TABLE citus_local_table, reference_table; NOTICE: executing the command locally: DROP TABLE IF EXISTS ref_citus_local_fkeys.reference_table_xxxxx CASCADE NOTICE: drop cascades to constraint fkey_local_to_ref_1506000 on table ref_citus_local_fkeys.citus_local_table_1506000 NOTICE: executing the command locally: DROP TABLE IF EXISTS ref_citus_local_fkeys.citus_local_table_xxxxx CASCADE --------------------------------------------------------------------- -- foreign key from reference table to citus local table -- --------------------------------------------------------------------- -- first remove worker_2 to test the behavior when replicating a -- reference table that has a foreign key to a citus local table -- to a new node SELECT 1 FROM master_remove_node('localhost', :worker_2_port); ?column? --------------------------------------------------------------------- 1 (1 row) -- create test tables CREATE TABLE citus_local_table(l1 int primary key); SELECT create_citus_local_table('citus_local_table'); create_citus_local_table --------------------------------------------------------------------- (1 row) CREATE TABLE reference_table(r1 int); SELECT create_reference_table('reference_table'); create_reference_table --------------------------------------------------------------------- (1 row) INSERT INTO reference_table VALUES (3); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.reference_table_1506003 (r1) VALUES (3) -- show that we are checking for foreign key constraint while defining, this should fail ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1); NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506003, 'ref_citus_local_fkeys', 1506002, 'ref_citus_local_fkeys', 'ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1);') ERROR: insert or update on table "reference_table_1506003" violates foreign key constraint "fkey_ref_to_local_1506003" -- we do not support CASCADE / SET NULL / SET DEFAULT behavior in "ALTER TABLE ADD fkey reference_table (to citus_local_table)" commands ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE CASCADE; ERROR: cannot define foreign key constraint, foreign keys from reference tables to citus local tables can only be defined with NO ACTION or RESTRICT behaviors ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE SET NULL; ERROR: cannot define foreign key constraint, foreign keys from reference tables to citus local tables can only be defined with NO ACTION or RESTRICT behaviors ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE SET DEFAULT; ERROR: cannot define foreign key constraint, foreign keys from reference tables to citus local tables can only be defined with NO ACTION or RESTRICT behaviors ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON UPDATE CASCADE; ERROR: cannot define foreign key constraint, foreign keys from reference tables to citus local tables can only be defined with NO ACTION or RESTRICT behaviors ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON UPDATE SET NULL; ERROR: cannot define foreign key constraint, foreign keys from reference tables to citus local tables can only be defined with NO ACTION or RESTRICT behaviors ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON UPDATE SET DEFAULT; ERROR: cannot define foreign key constraint, foreign keys from reference tables to citus local tables can only be defined with NO ACTION or RESTRICT behaviors INSERT INTO citus_local_table VALUES (3); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.citus_local_table_1506002 (l1) VALUES (3) -- .. but we allow such foreign keys with RESTRICT behavior BEGIN; ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE RESTRICT; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506003, 'ref_citus_local_fkeys', 1506002, 'ref_citus_local_fkeys', 'ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE RESTRICT;') ROLLBACK; -- .. and we allow such foreign keys with NO ACTION behavior ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE NO ACTION; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506003, 'ref_citus_local_fkeys', 1506002, 'ref_citus_local_fkeys', 'ALTER TABLE reference_table ADD CONSTRAINT fkey_ref_to_local FOREIGN KEY(r1) REFERENCES citus_local_table(l1) ON DELETE NO ACTION;') -- show that we are checking for foreign key constraint after defining, this should fail INSERT INTO reference_table VALUES (4); NOTICE: executing the command locally: INSERT INTO ref_citus_local_fkeys.reference_table_1506003 (r1) VALUES (4) ERROR: insert or update on table "reference_table_1506003" violates foreign key constraint "fkey_ref_to_local_1506003" -- enable the worker_2 to show that we don't try to set up the foreign keys -- between reference tables and citus local tables in worker_2 placements of -- the reference tables SELECT 1 FROM master_add_node('localhost', :worker_2_port); NOTICE: Replicating reference table "reference_table" to the node localhost:xxxxx ?column? --------------------------------------------------------------------- 1 (1 row) -- show that we support drop constraint BEGIN; ALTER TABLE reference_table DROP CONSTRAINT fkey_ref_to_local; NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506003, 'ref_citus_local_fkeys', 1506002, 'ref_citus_local_fkeys', 'ALTER TABLE reference_table DROP CONSTRAINT fkey_ref_to_local;') ROLLBACK; -- show that drop table errors as expected DROP TABLE citus_local_table; ERROR: cannot drop table citus_local_table because other objects depend on it -- this should work DROP TABLE citus_local_table CASCADE; NOTICE: drop cascades to constraint fkey_ref_to_local on table reference_table NOTICE: executing the command locally: DROP TABLE IF EXISTS ref_citus_local_fkeys.citus_local_table_xxxxx CASCADE NOTICE: drop cascades to constraint fkey_ref_to_local_1506003 on table ref_citus_local_fkeys.reference_table_1506003 BEGIN; CREATE TABLE citus_local_table_1(a int, b int, unique (a,b)); CREATE TABLE citus_local_table_2(a int, b int, unique (a,b)); SELECT create_citus_local_table('citus_local_table_1'); create_citus_local_table --------------------------------------------------------------------- (1 row) SELECT create_citus_local_table('citus_local_table_2'); create_citus_local_table --------------------------------------------------------------------- (1 row) -- show that we properly handle multi column foreign keys ALTER TABLE citus_local_table_1 ADD CONSTRAINT multi_fkey FOREIGN KEY (a, b) REFERENCES citus_local_table_2(a, b); NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1506004, 'ref_citus_local_fkeys', 1506005, 'ref_citus_local_fkeys', 'ALTER TABLE citus_local_table_1 ADD CONSTRAINT multi_fkey FOREIGN KEY (a, b) REFERENCES citus_local_table_2(a, b);') COMMIT; -- cleanup at exit DROP SCHEMA ref_citus_local_fkeys CASCADE; NOTICE: drop cascades to 6 other objects