Improve consistency, add test cases for change_table_type()
This commit is contained in:
@@ -19,6 +19,10 @@
|
||||
, online_encoding_migration/1
|
||||
, online_encoding_migration_restart/1
|
||||
, online_encoding_migration_interrupt/1
|
||||
, change_table_type_sync/1
|
||||
, change_table_type_async/1
|
||||
, change_table_type_schema_only/1
|
||||
, change_table_type_no_change/1
|
||||
]).
|
||||
|
||||
-include_lib("common_test/include/ct.hrl").
|
||||
@@ -37,7 +41,11 @@ groups() ->
|
||||
, migrate_with_encoding_change
|
||||
, online_encoding_migration
|
||||
, online_encoding_migration_restart
|
||||
, online_encoding_migration_interrupt ]}
|
||||
, online_encoding_migration_interrupt
|
||||
, change_table_type_sync
|
||||
, change_table_type_async
|
||||
, change_table_type_schema_only
|
||||
, change_table_type_no_change ]}
|
||||
].
|
||||
|
||||
init_per_suite(Config) ->
|
||||
@@ -238,6 +246,115 @@ online_encoding_migration_interrupt(_Config) ->
|
||||
101 = length(Objs),
|
||||
ok.
|
||||
|
||||
%% =====================================================================
|
||||
%% change_table_type/3 and /4
|
||||
%% =====================================================================
|
||||
|
||||
%% change_table_type/3 defaults to wait=true: copy + finalize in one call.
|
||||
%% set (term keys) -> ordered_set implies default sext key encoding migration.
|
||||
change_table_type_sync(_Config) ->
|
||||
ok = create_tab(ctt_s, [{attributes, [k, v]}]),
|
||||
set = mnesia:table_info(ctt_s, type),
|
||||
[mrdb:insert(ctt_s, {ctt_s, I, I * 2}) || I <- lists:seq(1, 40)],
|
||||
Ref0 = mrdb:get_ref(ctt_s),
|
||||
{term, _} = maps:get(encoding, Ref0),
|
||||
set = maps:get(type, maps:get(properties, Ref0)),
|
||||
ok = mnesia_rocksdb_admin:change_table_type(
|
||||
rdb, ctt_s, #{type => ordered_set, report => false}),
|
||||
idle = mnesia_rocksdb_admin:migration_status(ctt_s),
|
||||
Ref1 = mrdb:get_ref(ctt_s),
|
||||
false = maps:is_key(migration, Ref1),
|
||||
{sext, _} = maps:get(encoding, Ref1),
|
||||
ordered_set = maps:get(type, maps:get(properties, Ref1)),
|
||||
ordered_set = maps:get(semantics, Ref1),
|
||||
ordered_set = mnesia:table_info(ctt_s, type),
|
||||
assert_mrdb_encoding_up(ctt_s, {sext, {value, term}}),
|
||||
Objs = lists:sort(mrdb:select(ctt_s, [{'_', [], ['$_']}])),
|
||||
40 = length(Objs),
|
||||
{ok, _} = mrdb:rdb_get(Ref1, sext:encode(1), []),
|
||||
%% Writes after change use ordered_set / sext
|
||||
ok = mrdb:insert(ctt_s, {ctt_s, 100, 200}),
|
||||
{ctt_s, 100, 200} = lists:keyfind(100, 2, mrdb:select(ctt_s, [{'_', [], ['$_']}])),
|
||||
{ok, _} = mrdb:rdb_get(mrdb:get_ref(ctt_s), sext:encode(100), []),
|
||||
ok.
|
||||
|
||||
%% change_table_type/4 defaults to wait=false: start only; finalize manually.
|
||||
change_table_type_async(_Config) ->
|
||||
ok = create_tab(ctt_a, [{attributes, [k, v]}]),
|
||||
[mrdb:insert(ctt_a, {ctt_a, I, I}) || I <- lists:seq(1, 25)],
|
||||
Self = self(),
|
||||
ok = mnesia_rocksdb_admin:change_table_type(
|
||||
rdb, ctt_a, #{type => ordered_set, encoding => {sext, {value, term}}},
|
||||
Self),
|
||||
%% Dual-write should be on immediately; type not cut over yet.
|
||||
#{migration := _} = mrdb:get_ref(ctt_a),
|
||||
set = mnesia:table_info(ctt_a, type),
|
||||
{term, _} = maps:get(encoding, mrdb:get_ref(ctt_a)),
|
||||
mrdb:insert(ctt_a, {ctt_a, 50, 50}),
|
||||
mrdb:delete(ctt_a, 3),
|
||||
ok = wait_copy_done(ctt_a, 100),
|
||||
ok = mnesia_rocksdb_admin:finalize_migration(rdb, ctt_a),
|
||||
idle = mnesia_rocksdb_admin:migration_status(ctt_a),
|
||||
Ref1 = mrdb:get_ref(ctt_a),
|
||||
false = maps:is_key(migration, Ref1),
|
||||
{sext, _} = maps:get(encoding, Ref1),
|
||||
ordered_set = mnesia:table_info(ctt_a, type),
|
||||
ordered_set = maps:get(type, maps:get(properties, Ref1)),
|
||||
Objs = lists:sort(mrdb:select(ctt_a, [{'_', [], ['$_']}])),
|
||||
false = lists:keymember(3, 2, Objs),
|
||||
true = lists:keymember(50, 2, Objs),
|
||||
%% 25 - 1 delete + 1 insert = 25
|
||||
25 = length(Objs),
|
||||
{ok, _} = mrdb:rdb_get(Ref1, sext:encode(50), []),
|
||||
ok.
|
||||
|
||||
%% Type change only when encoding already matches the default for the new type
|
||||
%% (set with sext -> ordered_set with same sext): schema/metadata, no CF copy.
|
||||
change_table_type_schema_only(_Config) ->
|
||||
ok = create_tab(ctt_so,
|
||||
[{attributes, [k, v]},
|
||||
{user_properties,
|
||||
[{mrdb_encoding, {sext, {value, term}}}]}]),
|
||||
set = mnesia:table_info(ctt_so, type),
|
||||
Ref0 = mrdb:get_ref(ctt_so),
|
||||
{sext, _} = maps:get(encoding, Ref0),
|
||||
CfGen0 = maps:get(cf_gen, Ref0, 0),
|
||||
[mrdb:insert(ctt_so, {ctt_so, I, I}) || I <- lists:seq(1, 10)],
|
||||
ok = mnesia_rocksdb_admin:change_table_type(
|
||||
rdb, ctt_so, #{type => ordered_set, report => false}),
|
||||
idle = mnesia_rocksdb_admin:migration_status(ctt_so),
|
||||
Ref1 = mrdb:get_ref(ctt_so),
|
||||
false = maps:is_key(migration, Ref1),
|
||||
{sext, _} = maps:get(encoding, Ref1),
|
||||
CfGen0 = maps:get(cf_gen, Ref1, 0),
|
||||
ordered_set = mnesia:table_info(ctt_so, type),
|
||||
ordered_set = maps:get(type, maps:get(properties, Ref1)),
|
||||
ordered_set = maps:get(semantics, Ref1),
|
||||
10 = length(mrdb:select(ctt_so, [{'_', [], ['$_']}])),
|
||||
{ok, _} = mrdb:rdb_get(Ref1, sext:encode(1), []),
|
||||
ok.
|
||||
|
||||
%% Idempotent / no-op errors.
|
||||
change_table_type_no_change(_Config) ->
|
||||
ok = create_tab(ctt_nc, [{attributes, [k, v]}]),
|
||||
set = mnesia:table_info(ctt_nc, type),
|
||||
{error, no_change} =
|
||||
mnesia_rocksdb_admin:change_table_type(
|
||||
rdb, ctt_nc, #{type => set, report => false}),
|
||||
%% Same encoding as live ref
|
||||
{term, ValEnc} = maps:get(encoding, mrdb:get_ref(ctt_nc)),
|
||||
{error, no_change} =
|
||||
mnesia_rocksdb_admin:change_table_type(
|
||||
rdb, ctt_nc, #{encoding => {term, ValEnc}, report => false}),
|
||||
ok.
|
||||
|
||||
assert_mrdb_encoding_up(Tab, Enc) ->
|
||||
UPs = mnesia:table_info(Tab, user_properties),
|
||||
{mrdb_encoding, Enc} = lists:keyfind(mrdb_encoding, 1, UPs),
|
||||
#{properties := #{user_properties := UPMap}} = mrdb:get_ref(Tab),
|
||||
{mrdb_encoding, Enc} = maps:get(mrdb_encoding, UPMap),
|
||||
ok.
|
||||
|
||||
ok({ok, Value}) -> Value.
|
||||
|
||||
tr_opts() ->
|
||||
|
||||
Reference in New Issue
Block a user