Skip to content

Commit

Permalink
handle duplicate keys in transactions
Browse files Browse the repository at this point in the history
fix #4
  • Loading branch information
benoitc committed Jan 4, 2015
1 parent 4a689dd commit 32c0b05
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 6 deletions.
12 changes: 12 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Changelog of cowdb
------------------

0.4.2 - 2014/01/04

- Internally uses the CBT library for all of our btree usages.
- fix: handle duplicate keys in transactions (#4)

0.4.1 - 2014/08/17

- New license. CowDB is now released under the Mozilla Public License v2.0
- cowdb now uses the C4.1 (Collective Code Construction Contract) process for
contributions.
- move code from bitbucket to github.

0.4.0 - 2014/06/30

- rename cowdb:db_info/1 to cowdb:database_info/1
Expand Down
19 changes: 14 additions & 5 deletions src/cowdb_updater.erl
Original file line number Diff line number Diff line change
Expand Up @@ -380,12 +380,21 @@ run_transaction([{add, Key, Value} | Rest], {ToAdd, ToRem}, Log, TransactId,
%% only keep a reference so we don't have the value multiple time.
{ok, Pos, Size} = cbt_file:append_term_crc32(Fd, Value),
Value1 = {Key, {Pos, Size}, TransactId, Ts},
run_transaction(Rest, {[{Key, Value1} | ToAdd], ToRem},
%% make sure to replace duplicates
ToAdd2 = lists:keystore(Key, 1, ToAdd, {Key, Value1}),
run_transaction(Rest, {ToAdd2, ToRem},
[{add, Value1} | Log], TransactId, Ts, Db);
run_transaction([{remove, Key} | Rest], {ToAdd, ToRem}, Log, TransactId, Ts, Db) ->
%% remove a key
run_transaction(Rest, {ToAdd, [Key | ToRem]}, [{remove, Key} | Log],
TransactId, Ts, Db);
run_transaction([{remove, Key} | Rest], {ToAdd, ToRem}, Log, TransactId, Ts,
Db) ->
case lists:member(Key, ToRem) of
true ->
%% duplicate, continue
run_transaction(Rest, {ToAdd, ToRem}, Log, TransactId, Ts, Db);
false ->
%% remove a key
run_transaction(Rest, {ToAdd, [Key | ToRem]}, [{remove, Key} | Log],
TransactId, Ts, Db)
end;
run_transaction([{fn, Func} | Rest], AddRemove, Log, TransactId, Ts, Db) ->
%% execute a transaction function
case cowdb_util:apply(Func, [Db]) of
Expand Down
19 changes: 18 additions & 1 deletion test/cowdb_basic_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ basic_ops_test_() ->
fun should_fold_range/1,
fun should_cancel_transact_fun/1,
fun should_error_transact_fun/1,
fun shoudl_catch_transact_fun_error/1
fun shoudl_catch_transact_fun_error/1,
fun should_handle_duplicate_kvs/1,
fun should_handle_delete_with_duplicate_keys/1
])
}.

Expand Down Expand Up @@ -250,3 +252,18 @@ shoudl_catch_transact_fun_error(Db) ->
end,
Reply = cowdb:transact(Db, [{fn, TransactFun}]),
?_assertMatch(badarg, Reply).


should_handle_duplicate_kvs(Db) ->
{ok, Tx} = cowdb:transact(Db, [{add, a, 1},
{add, a, 3}]),
?assertEqual(1, Tx),
?_assertMatch([{ok, {a, 3}}], cowdb:mget(Db, [a])).

should_handle_delete_with_duplicate_keys(Db) ->
{ok, 1} = cowdb:mput(Db, [{a, 1}, {b, 2}, {c, 3}]),
?assertMatch([{ok, {a, 1}}, {ok, {b, 2}}, {ok, {c, 3}}],
cowdb:mget(Db, [a, b, c])),
{ok, 2} = cowdb:mdelete(Db, [a, a, b, c]),
?_assertMatch([not_found, not_found, not_found],
cowdb:mget(Db, [a, b, c])).

0 comments on commit 32c0b05

Please sign in to comment.