mirror of https://github.com/citusdata/citus.git
1096 lines
43 KiB
PL/PgSQL
1096 lines
43 KiB
PL/PgSQL
-- Due to a race condition that happens in TransferShards() when the same shard id
|
|
-- is used to create the same shard on a different worker node, need to call
|
|
-- citus_cleanup_orphaned_resources() to clean up any orphaned resources before
|
|
-- running the tests.
|
|
--
|
|
-- See https://github.com/citusdata/citus/pull/7180#issuecomment-1706786615.
|
|
|
|
SET client_min_messages TO WARNING;
|
|
CALL citus_cleanup_orphaned_resources();
|
|
RESET client_min_messages;
|
|
|
|
-- Returns true if all placement groups within given shard group are isolated.
|
|
--
|
|
-- Not created in isolate_placement schema because it's dropped a few times during the test.
|
|
CREATE OR REPLACE FUNCTION verify_placements_in_shard_group_isolated(
|
|
qualified_table_name text,
|
|
shard_group_index bigint)
|
|
RETURNS boolean
|
|
AS $func$
|
|
DECLARE
|
|
v_result boolean;
|
|
BEGIN
|
|
SELECT bool_and(has_separate_node) INTO v_result
|
|
FROM citus_shards
|
|
JOIN (
|
|
SELECT shardids FROM public.get_enumerated_shard_groups(qualified_table_name) WHERE shardgroupindex = shard_group_index
|
|
) q
|
|
ON (shardid = ANY(q.shardids));
|
|
RETURN v_result;
|
|
END;
|
|
$func$ LANGUAGE plpgsql;
|
|
|
|
CREATE SCHEMA isolate_placement;
|
|
SET search_path TO isolate_placement;
|
|
|
|
-- test null input
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(0, NULL);
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(NULL, false);
|
|
|
|
SET citus.shard_replication_factor TO 1;
|
|
SET citus.next_shard_id TO 2000000;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
-- test with user that doesn't have permission to execute the function
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(shardid, true) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
|
|
DROP TABLE single_shard_1;
|
|
|
|
CREATE ROLE test_user_isolate_placement WITH LOGIN;
|
|
GRANT ALL ON SCHEMA isolate_placement TO test_user_isolate_placement;
|
|
ALTER SYSTEM SET citus.enable_manual_metadata_changes_for_user TO 'test_user_isolate_placement';
|
|
SELECT pg_reload_conf();
|
|
SELECT pg_sleep(0.1);
|
|
SET ROLE test_user_isolate_placement;
|
|
|
|
-- test invalid shard id
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(0, true);
|
|
|
|
-- test null needs_separate_node
|
|
SELECT citus_internal_add_shard_metadata(
|
|
relation_id=>0,
|
|
shard_id=>0,
|
|
storage_type=>'0',
|
|
shard_min_value=>'0',
|
|
shard_max_value=>'0',
|
|
needs_separate_node=>null);
|
|
|
|
RESET ROLE;
|
|
REVOKE ALL ON SCHEMA isolate_placement FROM test_user_isolate_placement;
|
|
DROP USER test_user_isolate_placement;
|
|
ALTER SYSTEM RESET citus.enable_manual_metadata_changes_for_user;
|
|
SELECT pg_reload_conf();
|
|
SELECT pg_sleep(0.1);
|
|
|
|
SET search_path TO isolate_placement;
|
|
SET citus.shard_replication_factor TO 1;
|
|
SET citus.next_shard_id TO 2001000;
|
|
|
|
CREATE USER mysuperuser superuser;
|
|
SET ROLE mysuperuser;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE USER regularuser;
|
|
GRANT USAGE ON SCHEMA isolate_placement TO regularuser;
|
|
ALTER SYSTEM SET citus.enable_manual_metadata_changes_for_user TO 'regularuser';
|
|
SELECT pg_reload_conf();
|
|
SELECT pg_sleep(0.1);
|
|
|
|
SET ROLE regularuser;
|
|
|
|
-- throws an error as the user is not the owner of the table
|
|
SELECT citus_shard_property_set(shardid) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(shardid, true) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
|
|
-- assign all tables to regularuser
|
|
RESET ROLE;
|
|
SELECT result FROM run_command_on_all_nodes($$ REASSIGN OWNED BY mysuperuser TO regularuser; $$);
|
|
|
|
SET ROLE regularuser;
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.single_shard_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(shardid, false) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.single_shard_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT citus_internal_shard_group_set_needsseparatenode(shardid, true) FROM pg_dist_shard WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
|
|
DROP TABLE single_shard_1;
|
|
RESET ROLE;
|
|
REVOKE USAGE ON SCHEMA isolate_placement FROM regularuser;
|
|
ALTER SYSTEM RESET citus.enable_manual_metadata_changes_for_user;
|
|
SELECT pg_reload_conf();
|
|
SELECT pg_sleep(0.1);
|
|
DROP ROLE regularuser, mysuperuser;
|
|
|
|
SET search_path TO isolate_placement;
|
|
|
|
SET citus.next_shard_id TO 2002000;
|
|
SET citus.shard_count TO 32;
|
|
SET citus.shard_replication_factor TO 1;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT 1 FROM citus_add_node('localhost', :master_port, groupid => 0);
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SET citus.shard_replication_factor TO 2;
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int);
|
|
CREATE TABLE dist_3(a int);
|
|
SELECT create_distributed_table('dist_1', 'a');
|
|
SELECT create_distributed_table('dist_2', 'a', colocate_with=>'dist_1');
|
|
SELECT create_distributed_table('dist_3', 'a', colocate_with=>'dist_1');
|
|
|
|
SET citus.shard_replication_factor TO 1;
|
|
|
|
-- none of the placements have been marked as needsseparatenode yet
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[2] AS shardgroup_5_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 5 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_5_shardid, anti_affinity=>true);
|
|
|
|
SELECT shardids[3] AS shardgroup_10_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 10 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_10_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[1] AS shardgroup_3_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 3 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_3_shardid, anti_affinity=>false);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[1] AS shardgroup_10_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 10 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_10_shardid, anti_affinity=>false);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[1] AS shardgroup_5_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 5 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_5_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
-- test metadata sync
|
|
|
|
-- first, need to re-create them with shard_replication_factor = 1 because we will first remove worker_2
|
|
|
|
DROP TABLE dist_1, dist_2, dist_3;
|
|
|
|
SELECT 1 FROM citus_remove_node('localhost', :worker_2_port);
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int);
|
|
CREATE TABLE dist_3(a int);
|
|
SELECT create_distributed_table('dist_1', 'a');
|
|
SELECT create_distributed_table('dist_2', 'a', colocate_with=>'dist_1');
|
|
SELECT create_distributed_table('dist_3', 'a', colocate_with=>'dist_1');
|
|
|
|
SELECT 1 FROM citus_add_node('localhost', :worker_2_port);
|
|
|
|
SELECT shardids[1] AS shardgroup_5_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 5 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_5_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
CREATE TABLE dist_4(a int);
|
|
SELECT create_distributed_table('dist_4', 'a', colocate_with=>'dist_1');
|
|
|
|
CREATE TABLE dist_4_concurrently(a int);
|
|
SELECT create_distributed_table_concurrently('dist_4_concurrently', 'a', colocate_with=>'dist_1');
|
|
|
|
-- Placements of a new distributed table created within the same colocated
|
|
-- group inherit needsseparatenode from the colocated placements too.
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
DROP TABLE dist_4, dist_4_concurrently;
|
|
|
|
-- Returns source and target node ids that can be used to perform a
|
|
-- shard transfer for one of the placements of given shard.
|
|
CREATE OR REPLACE FUNCTION get_candidate_node_for_shard_transfer(
|
|
p_shardid bigint)
|
|
RETURNS TABLE (source_nodeid integer, target_nodeid integer)
|
|
SET search_path TO 'pg_catalog, public'
|
|
AS $func$
|
|
DECLARE
|
|
v_source_nodeids integer[];
|
|
v_target_nodeid integer;
|
|
BEGIN
|
|
SELECT array_agg(nodeid) INTO v_source_nodeids
|
|
FROM pg_dist_shard
|
|
JOIN pg_dist_placement USING (shardid)
|
|
JOIN pg_dist_node USING (groupid)
|
|
WHERE noderole = 'primary' AND shardid = p_shardid;
|
|
|
|
IF v_source_nodeids IS NULL
|
|
THEN
|
|
RAISE EXCEPTION 'could not determine the source node of shard %', p_shardid;
|
|
END IF;
|
|
|
|
SELECT nodeid INTO v_target_nodeid
|
|
FROM pg_dist_node
|
|
WHERE isactive AND shouldhaveshards AND noderole='primary' AND
|
|
nodeid NOT IN (SELECT unnest(v_source_nodeids))
|
|
LIMIT 1;
|
|
|
|
IF v_target_nodeid IS NULL
|
|
THEN
|
|
RAISE EXCEPTION 'could not determine a node to transfer the placement to';
|
|
END IF;
|
|
|
|
RETURN QUERY SELECT v_source_nodeids[1], v_target_nodeid;
|
|
END;
|
|
$func$ LANGUAGE plpgsql;
|
|
|
|
SELECT shardids[1] AS shardgroup_15_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 15 \gset
|
|
|
|
SELECT citus_move_shard_placement(:shardgroup_5_shardid, source_nodeid, target_nodeid, 'block_writes')
|
|
FROM get_candidate_node_for_shard_transfer(:shardgroup_5_shardid);
|
|
|
|
SELECT citus_move_shard_placement(:shardgroup_15_shardid, source_nodeid, target_nodeid, 'block_writes')
|
|
FROM get_candidate_node_for_shard_transfer(:shardgroup_15_shardid);
|
|
|
|
-- so that citus_copy_shard_placement works
|
|
UPDATE pg_dist_partition SET repmodel = 'c' WHERE logicalrelid = 'isolate_placement.dist_1'::regclass;
|
|
|
|
SELECT citus_copy_shard_placement(:shardgroup_5_shardid, source_nodeid, target_nodeid, 'block_writes')
|
|
FROM get_candidate_node_for_shard_transfer(:shardgroup_5_shardid);
|
|
|
|
SELECT citus_copy_shard_placement(:shardgroup_15_shardid, source_nodeid, target_nodeid, 'block_writes')
|
|
FROM get_candidate_node_for_shard_transfer(:shardgroup_15_shardid);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
DROP TABLE dist_1, dist_2, dist_3;
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int);
|
|
SELECT create_distributed_table('dist_1', 'a', shard_count=>3);
|
|
SELECT create_distributed_table('dist_2', 'a', colocate_with=>'dist_1');
|
|
|
|
SELECT shardids[1] AS shardgroup_3_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 3 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_3_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
-- so that replicate_table_shards works
|
|
UPDATE pg_dist_partition SET repmodel = 'c' WHERE logicalrelid = 'isolate_placement.dist_1'::regclass;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT replicate_table_shards('isolate_placement.dist_1', shard_replication_factor=>2, shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
DROP TABLE dist_1, dist_2;
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int);
|
|
SELECT create_distributed_table('dist_1', 'a');
|
|
SELECT create_distributed_table('dist_2', 'a', colocate_with=>'dist_1');
|
|
|
|
SELECT shardids[1] AS shardgroup_9_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 9 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_9_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT nodeid AS worker_1_node FROM pg_dist_node WHERE nodeport=:worker_1_port \gset
|
|
SELECT nodeid AS worker_2_node FROM pg_dist_node WHERE nodeport=:worker_2_port \gset
|
|
|
|
SELECT pg_catalog.citus_split_shard_by_split_points(
|
|
:shardgroup_9_shardid,
|
|
ARRAY[((shardminvalue::bigint + shardmaxvalue::bigint) / 2)::text],
|
|
ARRAY[:worker_1_node, :worker_2_node],
|
|
'block_writes')
|
|
FROM pg_dist_shard
|
|
WHERE shardid = :shardgroup_9_shardid;
|
|
|
|
-- We shouldn't see shard group 9 because shard-split operation doesn't
|
|
-- preserve needsseparatenode flag when splitting the shard.
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[1] AS shardgroup_12_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 12 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_12_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[1] AS shardgroup_10_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 10 \gset
|
|
|
|
SELECT pg_catalog.citus_split_shard_by_split_points(
|
|
:shardgroup_10_shardid,
|
|
ARRAY[((shardminvalue::bigint + shardmaxvalue::bigint) / 2)::text],
|
|
ARRAY[:worker_1_node, :worker_2_node],
|
|
'block_writes')
|
|
FROM pg_dist_shard
|
|
WHERE shardid = :shardgroup_10_shardid;
|
|
|
|
-- We should see old shard group 12 (now as 13 due to split
|
|
-- of a prior shard) because it's not the one we splitted.
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
CREATE TABLE dist_3(a int);
|
|
SELECT create_distributed_table('dist_3', 'a', colocate_with=>'none');
|
|
|
|
SELECT shardids[1] AS shardgroup_17_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_3')
|
|
WHERE shardgroupindex = 17 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_17_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_3')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
-- verify that shard key value 100 is stored on shard group 17
|
|
select get_shard_id_for_distribution_column('dist_3', 100) = :shardgroup_17_shardid;
|
|
|
|
SELECT 1 FROM isolate_tenant_to_new_shard('dist_3', 100, shard_transfer_mode => 'block_writes');
|
|
|
|
-- We shouldn't see shard group 17 because isolate_tenant_to_new_shard doesn't
|
|
-- preserve needsseparatenode flag when splitting the shard.
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_3')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
SELECT shardids[1] AS shardgroup_18_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_3')
|
|
WHERE shardgroupindex = 18 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_18_shardid, anti_affinity=>true);
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_3')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
-- verify that shard key value 1000 is _not_ stored on shard group 18
|
|
SELECT get_shard_id_for_distribution_column('dist_3', 1000) != :shardgroup_18_shardid;
|
|
|
|
SELECT 1 FROM isolate_tenant_to_new_shard('dist_3', 1000, shard_transfer_mode => 'block_writes');
|
|
|
|
-- We should see shard group 18 (now as 20 due to split of a prior shard)
|
|
-- because it's not the one we splitted.
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_3')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
SELECT shardids[1] AS shardgroup_1_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.single_shard_1')
|
|
WHERE shardgroupindex = 1 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_1_shardid, anti_affinity=>true);
|
|
|
|
-- noop
|
|
SELECT citus_shard_property_set(:shardgroup_1_shardid, NULL);
|
|
SELECT citus_shard_property_set(:shardgroup_1_shardid);
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'single_shard_1');
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.single_shard_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
-- test invalid input
|
|
SELECT citus_shard_property_set(NULL, anti_affinity=>true);
|
|
SELECT citus_shard_property_set(0, anti_affinity=>true);
|
|
SELECT citus_shard_property_set(NULL, anti_affinity=>false);
|
|
SELECT citus_shard_property_set(0, anti_affinity=>false);
|
|
|
|
-- we verify whether shard exists even if anti_affinity is not provided
|
|
SELECT citus_shard_property_set(0, anti_affinity=>NULL);
|
|
|
|
CREATE TABLE append_table (a int, b int);
|
|
SELECT create_distributed_table('append_table', 'a', 'append');
|
|
SELECT 1 FROM master_create_empty_shard('append_table');
|
|
|
|
CREATE TYPE composite_key_type AS (f1 int, f2 text);
|
|
CREATE TABLE range_table(key composite_key_type, value int);
|
|
SELECT create_distributed_table('range_table', 'key', 'range');
|
|
CALL public.create_range_partitioned_shards('range_table', '{"(0,a)","(25,a)"}','{"(24,z)","(49,z)"}');
|
|
|
|
CREATE TABLE ref_table(a int);
|
|
SELECT create_reference_table('ref_table');
|
|
|
|
CREATE TABLE local_table(a int);
|
|
SELECT citus_add_local_table_to_metadata('local_table');
|
|
|
|
-- all should fail
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'append_table'::regclass LIMIT 1;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'range_table'::regclass LIMIT 1;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'ref_table'::regclass LIMIT 1;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid = 'local_table'::regclass LIMIT 1;
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'append_table'::regclass LIMIT 1;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'range_table'::regclass LIMIT 1;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'ref_table'::regclass LIMIT 1;
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid = 'local_table'::regclass LIMIT 1;
|
|
|
|
DROP TABLE range_table;
|
|
DROP TYPE composite_key_type;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
DROP SCHEMA isolate_placement CASCADE;
|
|
|
|
CREATE SCHEMA isolate_placement;
|
|
SET search_path TO isolate_placement;
|
|
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int);
|
|
SELECT create_distributed_table('dist_1', 'a', shard_count=>4);
|
|
SELECT create_distributed_table('dist_2', 'a', colocate_with=>'dist_1');
|
|
|
|
CREATE TABLE dist_non_colocated(a int);
|
|
SELECT create_distributed_table('dist_non_colocated', 'a', shard_count=>4, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE append_table (a int, b int);
|
|
SELECT create_distributed_table('append_table', 'a', 'append');
|
|
SELECT 1 FROM master_create_empty_shard('append_table');
|
|
|
|
CREATE TABLE range_table(a int, b int);
|
|
SELECT create_distributed_table('range_table', 'a', 'range');
|
|
CALL public.create_range_partitioned_shards('range_table', '{"0","25"}','{"26","50"}');
|
|
|
|
CREATE TABLE reference_table_1(a int);
|
|
SELECT create_reference_table('reference_table_1');
|
|
|
|
CREATE TABLE local_table_1(a int);
|
|
SELECT citus_add_local_table_to_metadata('local_table_1');
|
|
|
|
SELECT shardids[1] AS shardgroup_1_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex = 1 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_1_shardid, anti_affinity=>true);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
CREATE TABLE reference_table_2(a int);
|
|
SELECT create_reference_table('reference_table_2');
|
|
|
|
CREATE TABLE local_table_2(a int);
|
|
SELECT citus_add_local_table_to_metadata('local_table_2');
|
|
|
|
-- make sure that we still have placements for both reference tables on all nodes
|
|
SELECT COUNT(DISTINCT(groupid))=3 FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) WHERE logicalrelid = 'reference_table_1'::regclass;
|
|
SELECT COUNT(DISTINCT(groupid))=3 FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) WHERE logicalrelid = 'reference_table_2'::regclass;
|
|
|
|
-- sanity check for local tables
|
|
SELECT groupid = 0 FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) WHERE logicalrelid = 'local_table_1'::regclass;
|
|
SELECT groupid = 0 FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) WHERE logicalrelid = 'local_table_2'::regclass;
|
|
|
|
CREATE TABLE dist_post_non_colocated(a int);
|
|
SELECT create_distributed_table('dist_post_non_colocated', 'a', shard_count=>4, colocate_with=>'none');
|
|
|
|
CREATE TABLE dist_post_concurrently_non_colocated(a int);
|
|
SELECT create_distributed_table_concurrently('dist_post_concurrently_non_colocated', 'a', shard_count=>4, colocate_with=>'none');
|
|
|
|
CREATE TABLE dist_post_colocated(a int);
|
|
SELECT create_distributed_table('dist_post_colocated', 'a', colocate_with=>'dist_1');
|
|
|
|
CREATE TABLE dist_post_concurrently_colocated(a int);
|
|
SELECT create_distributed_table_concurrently('dist_post_concurrently_colocated', 'a', colocate_with=>'dist_1');
|
|
|
|
CREATE TABLE single_shard_post(a int);
|
|
SELECT create_distributed_table('single_shard_post', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE append_table_post(a int, b int);
|
|
SELECT create_distributed_table('append_table_post', 'a', 'append');
|
|
SELECT 1 FROM master_create_empty_shard('append_table_post');
|
|
|
|
CREATE TABLE range_table_post(a int, b int);
|
|
SELECT create_distributed_table('range_table_post', 'a', 'range');
|
|
CALL public.create_range_partitioned_shards('range_table_post', '{"0","25"}','{"26","50"}');
|
|
|
|
SELECT result FROM run_command_on_all_nodes($$
|
|
SELECT * FROM public.get_colocated_shards_needisolatednode('isolate_placement.dist_1')
|
|
$$)
|
|
ORDER BY result;
|
|
|
|
-- Make sure that the node that contains shard-group 1 of isolate_placement.dist_1
|
|
-- doesn't have any other placements.
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1);
|
|
|
|
SET client_min_messages TO ERROR;
|
|
SELECT citus_drain_node('localhost', :worker_1_port, shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT citus_set_node_property('localhost', :worker_1_port, 'shouldhaveshards', true);
|
|
|
|
-- drain node should have failed and the node should still have the same set of placements
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1);
|
|
|
|
SET client_min_messages TO ERROR;
|
|
SELECT citus_drain_node('localhost', :worker_2_port, shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT citus_set_node_property('localhost', :worker_2_port, 'shouldhaveshards', true);
|
|
|
|
-- drain node should have failed and the node should still have the same set of placements
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1);
|
|
|
|
CREATE TABLE dist_3(a int);
|
|
SELECT create_distributed_table('dist_3', 'a', colocate_with=>'dist_1');
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1);
|
|
|
|
SET citus.shard_replication_factor TO 2;
|
|
|
|
CREATE TABLE dist_replicated(a int);
|
|
|
|
-- fails as we only have one node that's not used to isolate a shard placement group
|
|
SELECT create_distributed_table('dist_replicated', 'a', shard_count=>4, colocate_with=>'none');
|
|
|
|
SET citus.shard_replication_factor TO 1;
|
|
|
|
CREATE TABLE dist_to_be_replicated(a int);
|
|
SELECT create_distributed_table('dist_to_be_replicated', 'a', shard_count=>4, colocate_with=>'none');
|
|
|
|
UPDATE pg_dist_partition SET repmodel = 'c' WHERE logicalrelid = 'isolate_placement.dist_to_be_replicated'::regclass;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
-- fails as we only have one node that's not used to isolate a shard placement group
|
|
SELECT replicate_table_shards('isolate_placement.dist_to_be_replicated', shard_replication_factor=>2, shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT citus_set_node_property('localhost', :master_port, 'shouldhaveshards', true);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
-- succeeds as now we have two nodes that are not used to isolate a shard placement group
|
|
SELECT replicate_table_shards('isolate_placement.dist_to_be_replicated', shard_replication_factor=>2, shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1);
|
|
|
|
SELECT DISTINCT(table_name::regclass::text)
|
|
FROM citus_shards
|
|
JOIN pg_class ON (oid = table_name)
|
|
WHERE relnamespace = 'isolate_placement'::regnamespace AND has_separate_node
|
|
ORDER BY 1;
|
|
|
|
SELECT bool_or(has_separate_node) = false
|
|
FROM citus_shards
|
|
JOIN (
|
|
SELECT unnest(shardids) shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_1')
|
|
WHERE shardgroupindex != 1
|
|
) shards_except_group_1 USING (shardid);
|
|
|
|
DROP TABLE dist_to_be_replicated;
|
|
|
|
SELECT citus_drain_node('localhost', :master_port, shard_transfer_mode=>'block_writes');
|
|
|
|
DROP TABLE dist_replicated;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
DROP SCHEMA isolate_placement CASCADE;
|
|
|
|
CREATE SCHEMA isolate_placement;
|
|
SET search_path TO isolate_placement;
|
|
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass, 'single_shard_2'::regclass);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
-- fails
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
SELECT create_distributed_table('dist_1', 'a', shard_count=>4);
|
|
|
|
CREATE TABLE single_shard_3(a int);
|
|
SELECT create_distributed_table('single_shard_3', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE append_table (a int, b int);
|
|
SELECT create_distributed_table('append_table', 'a', 'append');
|
|
SELECT 1 FROM master_create_empty_shard('append_table');
|
|
|
|
CREATE TABLE range_table(a int, b int);
|
|
SELECT create_distributed_table('range_table', 'a', 'range');
|
|
CALL public.create_range_partitioned_shards('range_table', '{"0","25"}','{"26","50"}');
|
|
|
|
-- succeeds
|
|
|
|
CREATE TABLE reference_table_1(a int);
|
|
SELECT create_reference_table('reference_table_1');
|
|
|
|
CREATE TABLE local_table_1(a int);
|
|
SELECT citus_add_local_table_to_metadata('local_table_1');
|
|
|
|
CREATE TABLE single_shard_4(a int);
|
|
SELECT create_distributed_table('single_shard_4', null, colocate_with=>'single_shard_1');
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1);
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_2', 1);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
DROP SCHEMA isolate_placement CASCADE;
|
|
|
|
CREATE SCHEMA isolate_placement;
|
|
SET search_path TO isolate_placement;
|
|
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
-- Make sure that we don't assume that a node is used to isolate a shard placement
|
|
-- group just because it contains a single shard placement group.
|
|
CREATE TABLE single_shard_3(a int);
|
|
SELECT create_distributed_table('single_shard_3', null, colocate_with=>'none');
|
|
|
|
SET client_min_messages TO WARNING;
|
|
DROP SCHEMA isolate_placement CASCADE;
|
|
|
|
CREATE SCHEMA isolate_placement;
|
|
SET search_path TO isolate_placement;
|
|
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT citus_set_node_property('localhost', :master_port, 'shouldhaveshards', true);
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int); -- will replicate this
|
|
CREATE TABLE dist_3(a int);
|
|
SELECT create_distributed_table('dist_1', 'a', shard_count=>1);
|
|
SELECT create_distributed_table('dist_2', 'a', shard_count=>1, colocate_with=>'none');
|
|
SELECT create_distributed_table('dist_3', 'a', shard_count=>1, colocate_with=>'none');
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('dist_1'::regclass, 'dist_2'::regclass);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
-- so that replicate_table_shards works
|
|
UPDATE pg_dist_partition SET repmodel = 'c' WHERE logicalrelid = 'isolate_placement.dist_2'::regclass;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
-- succeeds but breaks the isolation requirement for either of dist_1 or dist_2 ..
|
|
SELECT replicate_table_shards('isolate_placement.dist_2', shard_replication_factor=>2, shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
-- .. so check the xor of the isolation requirements for dist_1 and dist_2
|
|
SELECT (public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1) OR public.verify_placements_in_shard_group_isolated('isolate_placement.dist_2', 1)) = true AND
|
|
(public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1) AND public.verify_placements_in_shard_group_isolated('isolate_placement.dist_2', 1)) = false;
|
|
|
|
DROP TABLE dist_1, dist_2, dist_3;
|
|
|
|
SELECT citus_drain_node('localhost', :master_port, shard_transfer_mode=>'block_writes');
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
SELECT create_distributed_table('dist_1', 'a', shard_count=>4);
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass);
|
|
|
|
SELECT groupid AS single_shard_1_group_id FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass \gset
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1);
|
|
|
|
-- show that we try to isolate placements where they were staying at the time rebalancer is invoked
|
|
SELECT groupid = :single_shard_1_group_id FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass;
|
|
|
|
DROP TABLE dist_1, single_shard_1, single_shard_2;
|
|
|
|
SET citus.shard_replication_factor TO 2;
|
|
|
|
CREATE TABLE dist_1(a int);
|
|
CREATE TABLE dist_2(a int);
|
|
|
|
SELECT citus_set_node_property('localhost', :master_port, 'shouldhaveshards', true);
|
|
|
|
SELECT create_distributed_table('dist_1', 'a', shard_count=>1);
|
|
SELECT create_distributed_table('dist_2', 'a', colocate_with=>'dist_1');
|
|
|
|
SET citus.shard_replication_factor TO 1;
|
|
|
|
SELECT shardids[1] AS shardgroup_1_shardid
|
|
FROM public.get_enumerated_shard_groups('isolate_placement.dist_2')
|
|
WHERE shardgroupindex = 1 \gset
|
|
|
|
SELECT citus_shard_property_set(:shardgroup_1_shardid, anti_affinity=>true);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.dist_1', 1) = true;
|
|
|
|
DROP TABLE dist_1, dist_2;
|
|
|
|
SELECT citus_drain_node('localhost', :master_port, shard_transfer_mode=>'block_writes');
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_3(a int);
|
|
SELECT create_distributed_table('single_shard_3', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_4(a int);
|
|
SELECT create_distributed_table('single_shard_4', null, colocate_with=>'none');
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1);
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_2'::regclass);
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>false) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_2', 1);
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1) = false;
|
|
|
|
DROP TABLE single_shard_1, single_shard_2, single_shard_3, single_shard_4;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
-- this would be placed on the same node as single_shard_1
|
|
CREATE TABLE single_shard_3(a int);
|
|
SELECT create_distributed_table('single_shard_3', null, colocate_with=>'none');
|
|
|
|
DROP TABLE single_shard_2;
|
|
|
|
SELECT shardid, nodeid INTO single_shard_3_shardid_nodeid
|
|
FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) JOIN pg_dist_node USING (groupid)
|
|
WHERE logicalrelid = 'isolate_placement.single_shard_3'::regclass AND noderole = 'primary';
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass);
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_3'::regclass);
|
|
|
|
-- tell rebalancer that single_shard_3 cannot be placed on the node where it is currently placed
|
|
CREATE OR REPLACE FUNCTION test_shard_allowed_on_node(p_shardid bigint, p_nodeid int)
|
|
RETURNS boolean AS
|
|
$$
|
|
SELECT
|
|
CASE
|
|
WHEN (p_shardid = shardid and p_nodeid = nodeid) THEN false
|
|
ELSE true
|
|
END
|
|
FROM single_shard_3_shardid_nodeid;
|
|
$$ LANGUAGE sql;
|
|
|
|
INSERT INTO pg_catalog.pg_dist_rebalance_strategy(
|
|
name,
|
|
default_strategy,
|
|
shard_cost_function,
|
|
node_capacity_function,
|
|
shard_allowed_on_node_function,
|
|
default_threshold,
|
|
minimum_threshold,
|
|
improvement_threshold
|
|
)
|
|
VALUES (
|
|
'test_isolate_placement',
|
|
false,
|
|
'citus_shard_cost_1',
|
|
'citus_node_capacity_1',
|
|
'isolate_placement.test_shard_allowed_on_node',
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(rebalance_strategy := 'test_isolate_placement', shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
-- test_shard_allowed_on_node() didn't cause rebalance_table_shards() to fail.
|
|
--
|
|
-- Right now single_shard_1 & single_shard_3 are placed on the same node. And
|
|
-- due to order we follow when assigning nodes to placement groups that need an
|
|
-- isolated node, we will try placing single_shard_1 to the node where it is
|
|
-- currently placed, and then we will try placing single_shard_3 to some other
|
|
-- node (as its current node is already assigned to single_shard_1), not to the
|
|
-- one we disallowed in test_shard_allowed_on_node().
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1);
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_3', 1);
|
|
|
|
DROP TABLE single_shard_3_shardid_nodeid;
|
|
DELETE FROM pg_catalog.pg_dist_rebalance_strategy WHERE name='test_isolate_placement';
|
|
|
|
DROP TABLE single_shard_1, single_shard_3;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
-- this would be placed on the same node as single_shard_1
|
|
CREATE TABLE single_shard_3(a int);
|
|
SELECT create_distributed_table('single_shard_3', null, colocate_with=>'none');
|
|
|
|
DROP TABLE single_shard_2;
|
|
|
|
SELECT shardid, nodeid INTO single_shard_3_shardid_nodeid
|
|
FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) JOIN pg_dist_node USING (groupid)
|
|
WHERE logicalrelid = 'isolate_placement.single_shard_3'::regclass AND noderole = 'primary';
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass);
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_3'::regclass);
|
|
|
|
-- Same test above but this time we tell rebalancer that single_shard_3 cannot be placed
|
|
-- on any node except the one where it is currently placed.
|
|
CREATE OR REPLACE FUNCTION test_shard_allowed_on_node(p_shardid bigint, p_nodeid int)
|
|
RETURNS boolean AS
|
|
$$
|
|
SELECT
|
|
CASE
|
|
WHEN (p_shardid = shardid and p_nodeid != nodeid) THEN false
|
|
ELSE true
|
|
END
|
|
FROM single_shard_3_shardid_nodeid;
|
|
$$ LANGUAGE sql;
|
|
|
|
INSERT INTO pg_catalog.pg_dist_rebalance_strategy(
|
|
name,
|
|
default_strategy,
|
|
shard_cost_function,
|
|
node_capacity_function,
|
|
shard_allowed_on_node_function,
|
|
default_threshold,
|
|
minimum_threshold,
|
|
improvement_threshold
|
|
)
|
|
VALUES (
|
|
'test_isolate_placement',
|
|
false,
|
|
'citus_shard_cost_1',
|
|
'citus_node_capacity_1',
|
|
'isolate_placement.test_shard_allowed_on_node',
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
|
|
SET client_min_messages TO ERROR;
|
|
SELECT rebalance_table_shards(rebalance_strategy := 'test_isolate_placement', shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
-- This time, test_shard_allowed_on_node() caused rebalance_table_shards() to
|
|
-- fail.
|
|
--
|
|
-- Right now single_shard_1 & single_shard_3 are placed on the same node. And
|
|
-- due to order we follow when assigning nodes to placement groups that need an
|
|
-- isolated node, we will try placing single_shard_1 to the node where it is
|
|
-- currently placed, and then we will try placing single_shard_3 to some other
|
|
-- node (as its current node is already assigned to single_shard_1). However,
|
|
-- test_shard_allowed_on_node() doesn't allow that.
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1) = false;
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_3', 1) = false;
|
|
|
|
DROP TABLE single_shard_3_shardid_nodeid;
|
|
DELETE FROM pg_catalog.pg_dist_rebalance_strategy WHERE name='test_isolate_placement';
|
|
|
|
DROP TABLE single_shard_1, single_shard_3;
|
|
|
|
CREATE TABLE single_shard_1(a int);
|
|
SELECT create_distributed_table('single_shard_1', null, colocate_with=>'none');
|
|
|
|
CREATE TABLE single_shard_2(a int);
|
|
SELECT create_distributed_table('single_shard_2', null, colocate_with=>'none');
|
|
|
|
-- this would be placed on the same node as single_shard_1
|
|
CREATE TABLE single_shard_3(a int);
|
|
SELECT create_distributed_table('single_shard_3', null, colocate_with=>'none');
|
|
|
|
DROP TABLE single_shard_2;
|
|
|
|
SELECT shardid, nodeid INTO single_shard_1_shardid_nodeid
|
|
FROM pg_dist_shard JOIN pg_dist_placement USING (shardid) JOIN pg_dist_node USING (groupid)
|
|
WHERE logicalrelid = 'isolate_placement.single_shard_1'::regclass AND noderole = 'primary';
|
|
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_1'::regclass);
|
|
SELECT citus_shard_property_set(shardid, anti_affinity=>true) FROM pg_dist_shard WHERE logicalrelid IN ('single_shard_3'::regclass);
|
|
|
|
-- tell rebalancer that single_shard_1 cannot be placed on the node where it is currently placed
|
|
CREATE OR REPLACE FUNCTION test_shard_allowed_on_node(p_shardid bigint, p_nodeid int)
|
|
RETURNS boolean AS
|
|
$$
|
|
SELECT
|
|
CASE
|
|
WHEN (p_shardid = shardid and p_nodeid = nodeid) THEN false
|
|
ELSE true
|
|
END
|
|
FROM single_shard_1_shardid_nodeid;
|
|
$$ LANGUAGE sql;
|
|
|
|
INSERT INTO pg_catalog.pg_dist_rebalance_strategy(
|
|
name,
|
|
default_strategy,
|
|
shard_cost_function,
|
|
node_capacity_function,
|
|
shard_allowed_on_node_function,
|
|
default_threshold,
|
|
minimum_threshold,
|
|
improvement_threshold
|
|
)
|
|
VALUES (
|
|
'test_isolate_placement',
|
|
false,
|
|
'citus_shard_cost_1',
|
|
'citus_node_capacity_1',
|
|
'isolate_placement.test_shard_allowed_on_node',
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
|
|
SET client_min_messages TO WARNING;
|
|
SELECT rebalance_table_shards(rebalance_strategy := 'test_isolate_placement', shard_transfer_mode=>'block_writes');
|
|
SET client_min_messages TO NOTICE;
|
|
|
|
-- This time, test_shard_allowed_on_node() didn't cause rebalance_table_shards() to
|
|
-- emit a warning.
|
|
--
|
|
-- Right now single_shard_1 & single_shard_3 are placed on the same node. And
|
|
-- due to order we follow when assigning nodes to placement groups that need an
|
|
-- isolated node, we will try placing single_shard_1 to the node where it is
|
|
-- currently placed but this is not possible due to test_shard_allowed_on_node().
|
|
-- But this is not a problem because we will take the specified rebalancer strategy
|
|
-- into the account when assigning nodes to placements that need separate nodes and
|
|
-- will try to place it to a different node. Then we will try placing single_shard_3
|
|
-- to the node where it is currently placed, and this is ok.
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_1', 1) = true;
|
|
SELECT public.verify_placements_in_shard_group_isolated('isolate_placement.single_shard_3', 1) = true;
|
|
|
|
DROP TABLE single_shard_1_shardid_nodeid;
|
|
DELETE FROM pg_catalog.pg_dist_rebalance_strategy WHERE name='test_isolate_placement';
|
|
|
|
DROP TABLE single_shard_1, single_shard_3;
|
|
|
|
SET client_min_messages TO WARNING;
|
|
DROP SCHEMA isolate_placement CASCADE;
|
|
DROP FUNCTION public.verify_placements_in_shard_group_isolated(text, bigint);
|
|
|
|
SELECT citus_remove_node('localhost', :master_port);
|