Skip to content

Commit 4c09b8e

Browse files
committed
fix posting list merge operator in batch_merge, bump to 2.4.1
- Fix atom comparison in ParseOperand to use enif_is_identical() instead of direct == comparison. Atoms decoded via enif_binary_to_term require proper NIF comparison functions. - Add posting_list_batch_merge_test to verify batch operations work correctly
1 parent 48cfd8d commit 4c09b8e

File tree

5 files changed

+54
-4
lines changed

5 files changed

+54
-4
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## erlang-rocksdb 2.4.1, released on 2026/01/04
2+
3+
### Bug Fixes
4+
5+
- fix posting list merge operator not recognizing operands in `batch_merge`:
6+
- Fixed atom comparison in `ParseOperand` to use `enif_is_identical()` instead of direct `==` comparison
7+
- Atoms decoded via `enif_binary_to_term` require proper NIF comparison functions
8+
- Added `posting_list_batch_merge_test` to verify batch operations work correctly
9+
110
## erlang-rocksdb 2.4.0, released on 2026/01/04
211

312
### New Features

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![Build Status](https://github.com/EnkiMultimedia/erlang-rocksdb/workflows/build/badge.svg)](https://github.com/EnkiMultimedia/erlang-rocksdb/actions?query=workflow%3Abuild)
44
[![Hex pm](http://img.shields.io/hexpm/v/rocksdb.svg?style=flat)](https://hex.pm/packages/rocksdb)
55

6-
**Current version: 2.4.0**
6+
**Current version: 2.4.1**
77

88
Copyright (c) 2016-2026 Benoît Chesneau
99

c_src/posting_list_merge_operator.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ namespace erocksdb {
125125
return false;
126126
}
127127

128-
if (tuple[0] == ATOM_POSTING_ADD) {
128+
if (enif_is_identical(tuple[0], ATOM_POSTING_ADD)) {
129129
is_tombstone = false;
130-
} else if (tuple[0] == ATOM_POSTING_DELETE) {
130+
} else if (enif_is_identical(tuple[0], ATOM_POSTING_DELETE)) {
131131
is_tombstone = true;
132132
} else {
133133
enif_free_env(env);

src/rocksdb.app.src

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
{application, rocksdb,
1818
[
1919
{description, "RocksDB for Erlang"},
20-
{vsn, "2.4.0"},
20+
{vsn, "2.4.1"},
2121
{registered, []},
2222
{applications, [
2323
kernel,

test/posting_list.erl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,47 @@ posting_list_delete_test() ->
7676
rocksdb:destroy(DbPath, []),
7777
rocksdb_test_util:rm_rf(DbPath).
7878

79+
posting_list_batch_merge_test() ->
80+
DbPath = "posting_list_batch_merge.test",
81+
rocksdb_test_util:rm_rf(DbPath),
82+
{ok, Db} = rocksdb:open(DbPath, [
83+
{create_if_missing, true},
84+
{merge_operator, posting_list_merge_operator}
85+
]),
86+
87+
%% Create a batch with posting list operations
88+
{ok, Batch} = rocksdb:batch(),
89+
ok = rocksdb:batch_merge(Batch, <<"term1">>, {posting_add, <<"doc1">>}),
90+
ok = rocksdb:batch_merge(Batch, <<"term1">>, {posting_add, <<"doc2">>}),
91+
ok = rocksdb:batch_merge(Batch, <<"term1">>, {posting_add, <<"doc3">>}),
92+
ok = rocksdb:batch_merge(Batch, <<"term2">>, {posting_add, <<"doc1">>}),
93+
ok = rocksdb:batch_merge(Batch, <<"term2">>, {posting_add, <<"doc2">>}),
94+
%% Delete doc2 from term1 in the same batch
95+
ok = rocksdb:batch_merge(Batch, <<"term1">>, {posting_delete, <<"doc2">>}),
96+
97+
%% Write the batch
98+
ok = rocksdb:write_batch(Db, Batch, []),
99+
ok = rocksdb:release_batch(Batch),
100+
101+
%% Verify term1: should have doc1 and doc3 (doc2 was deleted)
102+
{ok, Bin1} = rocksdb:get(Db, <<"term1">>, []),
103+
Keys1 = rocksdb:posting_list_keys(Bin1),
104+
?assert(lists:member(<<"doc1">>, Keys1)),
105+
?assertNot(lists:member(<<"doc2">>, Keys1)),
106+
?assert(lists:member(<<"doc3">>, Keys1)),
107+
?assertEqual(2, rocksdb:posting_list_count(Bin1)),
108+
109+
%% Verify term2: should have doc1 and doc2
110+
{ok, Bin2} = rocksdb:get(Db, <<"term2">>, []),
111+
Keys2 = rocksdb:posting_list_keys(Bin2),
112+
?assert(lists:member(<<"doc1">>, Keys2)),
113+
?assert(lists:member(<<"doc2">>, Keys2)),
114+
?assertEqual(2, rocksdb:posting_list_count(Bin2)),
115+
116+
ok = rocksdb:close(Db),
117+
rocksdb:destroy(DbPath, []),
118+
rocksdb_test_util:rm_rf(DbPath).
119+
79120
posting_list_compaction_test() ->
80121
%% Test that merge operator cleans up tombstones during merge
81122
%% Tombstones are removed during reads (FullMergeV2) and compaction (PartialMergeMulti)

0 commit comments

Comments
 (0)