RocksDB supports row update operations through the MergeOperator interface. I am trying to understand better
how the AssociativeMergeOperator works.
The merge implementation of the associative merge operator is expected to provide the following method:
// Gives the client a way to express the read -> modify -> write semantics
// key: (IN) The key that's associated with this merge operation.
// existing_value:(IN) null indicates the key does not exist before this op
// value: (IN) the value to update/merge the existing_value with
// new_value: (OUT) Client is responsible for filling the merge result here
// logger: (IN) Client could use this to log errors during merge.
//
// Return true on success. Return false failure / error / corruption.
virtual bool Merge(const Slice& key,
const Slice* existing_value,
const Slice& value,
std::string* new_value,
Logger* logger) const = 0;
If one compares this with the interface of the full MergeOperator::FullMerge method, one sees that method instead receives a collection of operands. In fact the associative merge operator also seems to be receiving operands, it is just the argument called value, which is literally the "value" argument slice passed to DB::Merge(WriteOptions&, ColumnFamilyHandle*, const Slice& key, const Slice& value_operand). Both existing_value and new_value are actual input and output values, and as far as I can understand, they can never represent operands.
Suppose the merge operation supports just adding or removing ids from a list. In this case operands are semantically things like:
previous value: []
operand: "append(id=3)"
new value: [3]
previous value: [3]
operand: "append(id=7)"
new value: [3, 7]
previous value: [3, 7]
operand: "remove(id=3)"
new value: [7]
in which the corresponding merge operations are invoked like:
db->Merge(WriteOptions(), cf, keySlice, SliceFrom("append(id=3)"));
db->Merge(WriteOptions(), cf, keySlice, SliceFrom("append(id=7)"));
db->Merge(WriteOptions(), cf, keySlice, SliceFrom("remove(id=3)"));
Does this approach in any way violate the expectations of an associative merge operator? If it does, why?