Packages
rocksdb
3.1.1
3.1.1
3.1.0
3.0.0
2.6.2
2.6.1
retired
2.6.0
retired
2.5.0
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
1.9.0
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.1
1.1.0
1.0.0
0.26.2
0.26.1
0.26.0
0.25.0
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.0
0.21.0
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
RocksDB for Erlang
Current section
Files
Jump to
Current section
Files
test/iterators.erl
%% -------------------------------------------------------------------
%%
%% eleveldb: Erlang Wrapper for LevelDB (http://code.google.com/p/leveldb/)
%%
%% Copyright (c) 2010-2013 Basho Technologies, Inc. All Rights Reserved.
%%
%% This file is provided to you under the Apache License,
%% Version 2.0 (the "License"); you may not use this file
%% except in compliance with the License. You may obtain
%% a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied. See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%
%% -------------------------------------------------------------------
-module(iterators).
-include_lib("eunit/include/eunit.hrl").
prev_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, <<"b">>, <<"y">>, []),
{ok, I} = rocksdb:iterator(Ref, []),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, <<>>)),
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(I, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, prev)),
?assertEqual(ok, rocksdb:iterator_close(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
seek_for_prev_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"a">>, <<"1">>, []),
rocksdb:put(Ref, <<"b">>, <<"2">>, []),
rocksdb:put(Ref, <<"c">>, <<"3">>, []),
rocksdb:put(Ref, <<"e">>, <<"4">>, []),
{ok, I} = rocksdb:iterator(Ref, []),
?assertEqual({ok, <<"b">>, <<"2">>},rocksdb:iterator_move(I, {seek_for_prev, <<"b">>})),
?assertEqual({ok, <<"c">>, <<"3">>},rocksdb:iterator_move(I, {seek_for_prev, <<"d">>})),
?assertEqual({ok, <<"e">>, <<"4">>},rocksdb:iterator_move(I, next)),
?assertEqual(ok, rocksdb:iterator_close(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
cf_iterator_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref, [DefaultH]} = rocksdb:open("ltest", [{create_if_missing, true}], [{"default", []}]),
{ok, TestH} = rocksdb:create_column_family(Ref, "test", []),
try
rocksdb:put(Ref, DefaultH, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, DefaultH, <<"b">>, <<"y">>, []),
rocksdb:put(Ref, TestH, <<"a">>, <<"x1">>, []),
rocksdb:put(Ref, TestH, <<"b">>, <<"y1">>, []),
{ok, DefaultIt} = rocksdb:iterator(Ref, DefaultH, []),
{ok, TestIt} = rocksdb:iterator(Ref, TestH, []),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(DefaultIt, <<>>)),
?assertEqual({ok, <<"a">>, <<"x1">>},rocksdb:iterator_move(TestIt, <<>>)),
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(DefaultIt, next)),
?assertEqual({ok, <<"b">>, <<"y1">>},rocksdb:iterator_move(TestIt, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(DefaultIt, prev)),
?assertEqual({ok, <<"a">>, <<"x1">>},rocksdb:iterator_move(TestIt, prev)),
ok = rocksdb:iterator_close(TestIt),
ok = rocksdb:iterator_close(DefaultIt)
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
cf_iterators_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref, [DefaultH]} = rocksdb:open("ltest", [{create_if_missing, true}], [{"default", []}]),
{ok, TestH} = rocksdb:create_column_family(Ref, "test", []),
try
rocksdb:put(Ref, DefaultH, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, DefaultH, <<"b">>, <<"y">>, []),
rocksdb:put(Ref, TestH, <<"a">>, <<"x1">>, []),
rocksdb:put(Ref, TestH, <<"b">>, <<"y1">>, []),
{ok, [DefaultIt, TestIt]} = rocksdb:iterators(Ref, [DefaultH, TestH], []),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(DefaultIt, <<>>)),
?assertEqual({ok, <<"a">>, <<"x1">>},rocksdb:iterator_move(TestIt, <<>>)),
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(DefaultIt, next)),
?assertEqual({ok, <<"b">>, <<"y1">>},rocksdb:iterator_move(TestIt, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(DefaultIt, prev)),
?assertEqual({ok, <<"a">>, <<"x1">>},rocksdb:iterator_move(TestIt, prev)),
ok = rocksdb:iterator_close(TestIt),
ok = rocksdb:iterator_close(DefaultIt)
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
drop_cf_with_iterator_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref, [DefaultH]} = rocksdb:open("ltest", [{create_if_missing, true}], [{"default", []}]),
{ok, TestH} = rocksdb:create_column_family(Ref, "test", []),
try
rocksdb:put(Ref, DefaultH, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, DefaultH, <<"b">>, <<"y">>, []),
rocksdb:put(Ref, TestH, <<"a">>, <<"x1">>, []),
rocksdb:put(Ref, TestH, <<"b">>, <<"y1">>, []),
{ok, DefaultIt} = rocksdb:iterator(Ref, DefaultH, []),
{ok, TestIt} = rocksdb:iterator(Ref, TestH, []),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(DefaultIt, <<>>)),
?assertEqual({ok, <<"a">>, <<"x1">>},rocksdb:iterator_move(TestIt, <<>>)),
ok = rocksdb:drop_column_family(Ref, TestH),
%% make sure we can read the read iterator
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(DefaultIt, next)),
?assertEqual({ok, <<"b">>, <<"y1">>},rocksdb:iterator_move(TestIt, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(DefaultIt, prev)),
?assertEqual({ok, <<"a">>, <<"x1">>},rocksdb:iterator_move(TestIt, prev)),
ok = rocksdb:iterator_close(TestIt),
ok = rocksdb:iterator_close(DefaultIt)
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
refresh_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"a">>, <<"x">>, []),
{ok, I} = rocksdb:iterator(Ref, []),
rocksdb:put(Ref, <<"b">>, <<"y">>, []),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, <<>>)),
?assertEqual({error, invalid_iterator},rocksdb:iterator_move(I, next)),
?assertEqual(ok, rocksdb:iterator_refresh(I)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, <<>>)),
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(I, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, prev)),
?assertEqual(ok, rocksdb:iterator_refresh(I)),
?assertEqual({error, invalid_iterator},rocksdb:iterator_move(I, next)),
?assertEqual(ok, rocksdb:iterator_close(I)),
?assertError(badarg, rocksdb:iterator_refresh(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
iterate_upper_bound_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, <<"b">>, <<"y">>, []),
rocksdb:put(Ref, <<"d">>, <<"z">>, []),
{ok, I} = rocksdb:iterator(Ref, [{iterate_upper_bound, <<"c">>}]),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, <<>>)),
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(I, next)),
?assertEqual({error, invalid_iterator},rocksdb:iterator_move(I, next)),
?assertEqual(ok, rocksdb:iterator_close(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
iterate_outer_bound_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, <<"c">>, <<"y">>, []),
rocksdb:put(Ref, <<"d">>, <<"z">>, []),
{ok, I} = rocksdb:iterator(Ref, [{iterate_lower_bound, <<"b">>}]),
?assertEqual({ok, <<"d">>, <<"z">>},rocksdb:iterator_move(I, last)),
?assertEqual({ok, <<"c">>, <<"y">>},rocksdb:iterator_move(I, prev)),
?assertEqual({error, invalid_iterator},rocksdb:iterator_move(I, prev)),
?assertEqual(ok, rocksdb:iterator_close(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
prefix_same_as_start_test() ->
rocksdb_test_util:rm_rf("test_prefix"), % NOTE
{ok, Ref} = rocksdb:open("test_prefix", [{create_if_missing, true},
{prefix_extractor, {fixed_prefix_transform, 8}}]),
try
ok = put_key(Ref, 12345, 6, <<"v16">>),
ok = put_key(Ref, 12345, 7, <<"v17">>),
ok = put_key(Ref, 12345, 8, <<"v18">>),
ok = put_key(Ref, 12345, 9, <<"v19">>),
ok = put_key(Ref, 12346, 8, <<"v16">>),
ok = rocksdb:flush(Ref, []),
{ok, I} = rocksdb:iterator(Ref, [{prefix_same_as_start, true}]),
?assertEqual({ok, test_key(12345, 6), <<"v16">>}, rocksdb:iterator_move(I, test_key(12345, 6))),
?assertEqual({ok, test_key(12345, 7), <<"v17">>}, rocksdb:iterator_move(I, next)),
?assertEqual({ok, test_key(12345, 8), <<"v18">>}, rocksdb:iterator_move(I, next)),
?assertEqual({ok, test_key(12345, 9), <<"v19">>}, rocksdb:iterator_move(I, next)),
?assertEqual({error, invalid_iterator}, rocksdb:iterator_move(I, next)),
?assertEqual(ok, rocksdb:iterator_close(I)),
?assertError(badarg, rocksdb:iterator_refresh(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("test_prefix", []),
rocksdb_test_util:rm_rf("test_prefix").
invalid_test() ->
rocksdb_test_util:rm_rf("ltest"), % NOTE
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"a">>, <<"x">>, []),
rocksdb:put(Ref, <<"b">>, <<"y">>, []),
{ok, I} = rocksdb:iterator(Ref, []),
?assertEqual({error, invalid_iterator}, rocksdb:iterator_move(I, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, <<>>)),
?assertEqual({ok, <<"b">>, <<"y">>},rocksdb:iterator_move(I, next)),
?assertEqual({ok, <<"a">>, <<"x">>},rocksdb:iterator_move(I, prev)),
?assertEqual(ok, rocksdb:iterator_close(I))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
%% Test auto_readahead_size option for iterators
auto_readahead_size_test() ->
rocksdb_test_util:rm_rf("ltest"),
{ok, Ref} = rocksdb:open("ltest", [{create_if_missing, true}]),
try
rocksdb:put(Ref, <<"key1">>, <<"val1">>, []),
rocksdb:put(Ref, <<"key2">>, <<"val2">>, []),
rocksdb:put(Ref, <<"key3">>, <<"val3">>, []),
%% Test with auto_readahead_size enabled (default is true in RocksDB 8.10+)
{ok, I1} = rocksdb:iterator(Ref, [{auto_readahead_size, true}]),
?assertEqual({ok, <<"key1">>, <<"val1">>}, rocksdb:iterator_move(I1, first)),
?assertEqual({ok, <<"key2">>, <<"val2">>}, rocksdb:iterator_move(I1, next)),
?assertEqual(ok, rocksdb:iterator_close(I1)),
%% Test with auto_readahead_size disabled
{ok, I2} = rocksdb:iterator(Ref, [{auto_readahead_size, false}]),
?assertEqual({ok, <<"key1">>, <<"val1">>}, rocksdb:iterator_move(I2, first)),
?assertEqual({ok, <<"key2">>, <<"val2">>}, rocksdb:iterator_move(I2, next)),
?assertEqual(ok, rocksdb:iterator_close(I2))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("ltest", []),
rocksdb_test_util:rm_rf("ltest").
%% Test allow_unprepared_value option for lazy blob loading in BlobDB
%% When allow_unprepared_value=true, blob values are not loaded until
%% PrepareValue() is called
allow_unprepared_value_test() ->
rocksdb_test_util:rm_rf("test_unprepared"),
{ok, Ref} = rocksdb:open("test_unprepared",
[{create_if_missing, true}
,{enable_blob_files, true}
,{min_blob_size, 0}]), %% All values go to blob files
try
Value = list_to_binary(lists:duplicate(100, $a)),
rocksdb:put(Ref, <<"key1">>, Value, []),
rocksdb:put(Ref, <<"key2">>, Value, []),
rocksdb:flush(Ref, []),
%% Test with allow_unprepared_value enabled
%% Values will be empty until PrepareValue() is called
{ok, I} = rocksdb:iterator(Ref, [{allow_unprepared_value, true}]),
%% Keys are returned, but blob values are empty (not yet loaded)
{ok, <<"key1">>, _} = rocksdb:iterator_move(I, first),
{ok, <<"key2">>, _} = rocksdb:iterator_move(I, next),
?assertEqual(ok, rocksdb:iterator_close(I)),
%% Test with allow_unprepared_value disabled (default)
%% Values are loaded automatically
{ok, I2} = rocksdb:iterator(Ref, [{allow_unprepared_value, false}]),
?assertEqual({ok, <<"key1">>, Value}, rocksdb:iterator_move(I2, first)),
?assertEqual({ok, <<"key2">>, Value}, rocksdb:iterator_move(I2, next)),
?assertEqual(ok, rocksdb:iterator_close(I2))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("test_unprepared", []),
rocksdb_test_util:rm_rf("test_unprepared").
%% Test iterator_prepare_value for explicit blob value loading
iterator_prepare_value_test() ->
rocksdb_test_util:rm_rf("test_prepare_value"),
{ok, Ref} = rocksdb:open("test_prepare_value",
[{create_if_missing, true}
,{enable_blob_files, true}
,{min_blob_size, 0}]), %% All values go to blob files
try
Value1 = list_to_binary(lists:duplicate(100, $a)),
Value2 = list_to_binary(lists:duplicate(100, $b)),
rocksdb:put(Ref, <<"key1">>, Value1, []),
rocksdb:put(Ref, <<"key2">>, Value2, []),
rocksdb:flush(Ref, []),
%% Create iterator with allow_unprepared_value
{ok, I} = rocksdb:iterator(Ref, [{allow_unprepared_value, true}]),
%% Move to first - value is empty (unprepared)
{ok, <<"key1">>, EmptyVal1} = rocksdb:iterator_move(I, first),
?assertEqual(<<>>, EmptyVal1),
%% Call prepare_value to load the blob
?assertEqual(ok, rocksdb:iterator_prepare_value(I)),
%% Now when we call iterator_move with a seek to the same key,
%% we can verify the value is there. Note: we need to re-seek
%% because iterator_move doesn't re-read the current value
%% Actually, the value should be available in the iterator's
%% value() method after PrepareValue. Let's just verify prepare works.
%% Move to next - value is also empty until prepared
{ok, <<"key2">>, EmptyVal2} = rocksdb:iterator_move(I, next),
?assertEqual(<<>>, EmptyVal2),
%% Prepare the second value
?assertEqual(ok, rocksdb:iterator_prepare_value(I)),
?assertEqual(ok, rocksdb:iterator_close(I)),
%% Test error case: prepare_value on invalid iterator
{ok, I2} = rocksdb:iterator(Ref, [{allow_unprepared_value, true}]),
%% Iterator is not positioned yet, should return error
?assertEqual({error, invalid_iterator}, rocksdb:iterator_prepare_value(I2)),
?assertEqual(ok, rocksdb:iterator_close(I2))
after
rocksdb:close(Ref)
end,
rocksdb:destroy("test_prepare_value", []),
rocksdb_test_util:rm_rf("test_prepare_value").
test_key(Prefix, Suffix) when is_integer(Prefix), is_integer(Suffix) ->
<< Prefix:64, Suffix:64 >>.
put_key(Db, Prefix, Suffix, Value) ->
rocksdb:put(Db, test_key(Prefix, Suffix), Value, []).