CREATE SCHEMA ignoring_orphaned_shards; SET search_path TO ignoring_orphaned_shards; -- Use a weird shard count that we don't use in any other tests SET citus.shard_count TO 13; SET citus.shard_replication_factor TO 1; SET citus.next_shard_id TO 92448000; CREATE TABLE ref(id int PRIMARY KEY); SELECT * FROM create_reference_table('ref'); create_reference_table --------------------------------------------------------------------- (1 row) SET citus.next_shard_id TO 92448100; ALTER SEQUENCE pg_catalog.pg_dist_colocationid_seq RESTART 92448100; CREATE TABLE dist1(id int); SELECT * FROM create_distributed_table('dist1', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448100 ORDER BY 1; logicalrelid --------------------------------------------------------------------- dist1 (1 row) -- Move first shard, so that the first shard now has 2 placements. One that's -- active and one that's orphaned. SELECT citus_move_shard_placement(92448100, 'localhost', :worker_1_port, 'localhost', :worker_2_port, 'block_writes'); citus_move_shard_placement --------------------------------------------------------------------- (1 row) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448100 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448100 | 4 | 57637 92448100 | 1 | 57638 (2 rows) -- Add a new table that should get colocated with dist1 automatically, but -- should not get a shard for the orphaned placement. SET citus.next_shard_id TO 92448200; CREATE TABLE dist2(id int); SELECT * FROM create_distributed_table('dist2', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448100 ORDER BY 1; logicalrelid --------------------------------------------------------------------- dist1 dist2 (2 rows) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448200 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448200 | 1 | 57638 (1 row) -- uncolocate it SELECT update_distributed_table_colocation('dist2', 'none'); update_distributed_table_colocation --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448100 ORDER BY 1; logicalrelid --------------------------------------------------------------------- dist1 (1 row) -- Make sure we can add it back to the colocation, even though it has a -- different number of shard placements for the first shard. SELECT update_distributed_table_colocation('dist2', 'dist1'); update_distributed_table_colocation --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448100 ORDER BY 1; logicalrelid --------------------------------------------------------------------- dist1 dist2 (2 rows) -- Make sure that replication count check in FOR UPDATE ignores orphaned -- shards. SELECT * FROM dist1 WHERE id = 1 FOR UPDATE; id --------------------------------------------------------------------- (0 rows) -- Make sure we don't send a query to the orphaned shard BEGIN; SET LOCAL citus.log_remote_commands TO ON; INSERT INTO dist1 VALUES (1); NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing INSERT INTO ignoring_orphaned_shards.dist1_92448100 (id) VALUES (1) DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx ROLLBACK; NOTICE: issuing ROLLBACK DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -- Make sure we can create a foreign key on community edition, because -- replication factor is 1 ALTER TABLE dist1 ADD CONSTRAINT dist1_ref_fk FOREIGN KEY (id) REFERENCES ref(id); SET citus.shard_replication_factor TO 2; SET citus.next_shard_id TO 92448300; ALTER SEQUENCE pg_catalog.pg_dist_colocationid_seq RESTART 92448300; CREATE TABLE rep1(id int); SELECT * FROM create_distributed_table('rep1', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) -- Add the coordinator, so we can have a replicated shard SELECT 1 FROM citus_add_node('localhost', :master_port, 0); NOTICE: Replicating reference table "ref" to the node localhost:xxxxx NOTICE: localhost:xxxxx is the coordinator and already contains metadata, skipping syncing the metadata ?column? --------------------------------------------------------------------- 1 (1 row) SELECT 1 FROM citus_set_node_property('localhost', :master_port, 'shouldhaveshards', true); ?column? --------------------------------------------------------------------- 1 (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448300 ORDER BY 1; logicalrelid --------------------------------------------------------------------- rep1 (1 row) SELECT citus_move_shard_placement(92448300, 'localhost', :worker_1_port, 'localhost', :master_port); citus_move_shard_placement --------------------------------------------------------------------- (1 row) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448300 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448300 | 4 | 57637 92448300 | 1 | 57638 92448300 | 1 | 57636 (3 rows) -- Add a new table that should get colocated with rep1 automatically, but -- should not get a shard for the orphaned placement. SET citus.next_shard_id TO 92448400; CREATE TABLE rep2(id int); SELECT * FROM create_distributed_table('rep2', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448300 ORDER BY 1; logicalrelid --------------------------------------------------------------------- rep1 rep2 (2 rows) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448400 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448400 | 1 | 57636 92448400 | 1 | 57638 (2 rows) -- uncolocate it SELECT update_distributed_table_colocation('rep2', 'none'); update_distributed_table_colocation --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448300 ORDER BY 1; logicalrelid --------------------------------------------------------------------- rep1 (1 row) -- Make sure we can add it back to the colocation, even though it has a -- different number of shard placements for the first shard. SELECT update_distributed_table_colocation('rep2', 'rep1'); update_distributed_table_colocation --------------------------------------------------------------------- (1 row) SELECT logicalrelid FROM pg_dist_partition WHERE colocationid = 92448300 ORDER BY 1; logicalrelid --------------------------------------------------------------------- rep1 rep2 (2 rows) UPDATE pg_dist_placement SET shardstate = 3 WHERE shardid = 92448300 AND groupid = 0; SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448300 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448300 | 4 | 57637 92448300 | 1 | 57638 92448300 | 3 | 57636 (3 rows) -- cannot copy from an orphaned shard SELECT * FROM citus_copy_shard_placement(92448300, 'localhost', :worker_1_port, 'localhost', :master_port); ERROR: source placement must be in active state -- cannot copy to an orphaned shard SELECT * FROM citus_copy_shard_placement(92448300, 'localhost', :worker_2_port, 'localhost', :worker_1_port); ERROR: target placement must be in inactive state -- can still copy to an inactive shard SELECT * FROM citus_copy_shard_placement(92448300, 'localhost', :worker_2_port, 'localhost', :master_port); citus_copy_shard_placement --------------------------------------------------------------------- (1 row) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448300 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448300 | 4 | 57637 92448300 | 1 | 57638 92448300 | 1 | 57636 (3 rows) -- Make sure we don't send a query to the orphaned shard BEGIN; SET LOCAL citus.log_remote_commands TO ON; SET LOCAL citus.log_local_commands TO ON; INSERT INTO rep1 VALUES (1); NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing SELECT lock_shard_resources(3, ARRAY[92448300]) DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing INSERT INTO ignoring_orphaned_shards.rep1_92448300 (id) VALUES (1) DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: executing the command locally: INSERT INTO ignoring_orphaned_shards.rep1_92448300 (id) VALUES (1) ROLLBACK; NOTICE: issuing ROLLBACK DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing ROLLBACK DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx -- Cause the orphaned shard to be local SELECT 1 FROM citus_drain_node('localhost', :master_port); NOTICE: Moving shard xxxxx from localhost:xxxxx to localhost:xxxxx ... ?column? --------------------------------------------------------------------- 1 (1 row) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448300 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448300 | 1 | 57638 92448300 | 4 | 57636 92448300 | 1 | 57637 (3 rows) -- Make sure we don't send a query to the orphaned shard if it's local BEGIN; SET LOCAL citus.log_remote_commands TO ON; SET LOCAL citus.log_local_commands TO ON; INSERT INTO rep1 VALUES (1); NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing SELECT lock_shard_resources(3, ARRAY[92448300]) DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx'); DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing INSERT INTO ignoring_orphaned_shards.rep1_92448300 (id) VALUES (1) DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing INSERT INTO ignoring_orphaned_shards.rep1_92448300 (id) VALUES (1) DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx ROLLBACK; NOTICE: issuing ROLLBACK DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx NOTICE: issuing ROLLBACK DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx SET citus.shard_replication_factor TO 1; SET citus.next_shard_id TO 92448500; CREATE TABLE range1(id int); SELECT create_distributed_table('range1', 'id', 'range'); create_distributed_table --------------------------------------------------------------------- (1 row) CALL public.create_range_partitioned_shards('range1', '{0,3}','{2,5}'); -- Move shard placement and clean it up SELECT citus_move_shard_placement(92448500, 'localhost', :worker_2_port, 'localhost', :worker_1_port, 'block_writes'); citus_move_shard_placement --------------------------------------------------------------------- (1 row) CALL citus_cleanup_orphaned_shards(); NOTICE: cleaned up 3 orphaned shards SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448300 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448300 | 1 | 57638 92448300 | 1 | 57637 (2 rows) SET citus.next_shard_id TO 92448600; CREATE TABLE range2(id int); SELECT create_distributed_table('range2', 'id', 'range'); create_distributed_table --------------------------------------------------------------------- (1 row) CALL public.create_range_partitioned_shards('range2', '{0,3}','{2,5}'); -- Mark tables co-located UPDATE pg_dist_partition SET colocationid = 30001 WHERE logicalrelid = 'range1'::regclass OR logicalrelid = 'range2'::regclass; -- Move shard placement and DON'T clean it up, now range1 and range2 are -- colocated, but only range2 has an orphaned shard. SELECT citus_move_shard_placement(92448600, 'localhost', :worker_2_port, 'localhost', :worker_1_port, 'block_writes'); citus_move_shard_placement --------------------------------------------------------------------- (1 row) SELECT shardid, shardstate, nodeport FROM pg_dist_shard_placement WHERE shardid = 92448600 ORDER BY placementid; shardid | shardstate | nodeport --------------------------------------------------------------------- 92448600 | 4 | 57638 92448600 | 1 | 57637 (2 rows) -- Make sure co-located join works SELECT * FROM range1 JOIN range2 ON range1.id = range2.id; id | id --------------------------------------------------------------------- (0 rows) -- Make sure we can create a foreign key on community edition, because -- replication factor is 1 ALTER TABLE range1 ADD CONSTRAINT range1_ref_fk FOREIGN KEY (id) REFERENCES ref(id); SET client_min_messages TO WARNING; DROP SCHEMA ignoring_orphaned_shards CASCADE;