Title
RocksDB prefix extractor incorrectly includes timestamp in versioned index keys
Issue
RocksDBIndex uses iterator.seek(keyBuffer) with ReadOptions.setPrefixSameAsStart(true) to find entries by logical index key prefix. However, the column family in RocksDBFactory currently configures the fixed-length prefix extractor to include the encoded timestamp suffix.
This makes the RocksDB prefix definition inconsistent with the lookup logic:
- Logical lookup prefix should be:
- indexId + userKey when multiCF=false
- userKey when multiCF=true
- Current prefix extractor effectively includes:
- indexId + userKey + encodedTimestamp
As a result, seeking with one version of a key may fail to find another version with the same logical key but a different timestamp, and iterator.isValid() can return false unexpectedly.
Proposed fix
Update RocksDBFactory.createCFDescriptor() so that:
- multiCF=false: prefix length is keyLen + Long.BYTES
- multiCF=true: prefix length is keyLen
Do not include the encoded timestamp in the extracted prefix.
Regression coverage
Add a test that inserts one version of a key and verifies that iterator.seek() on another version with the same logical prefix still lands on the stored key.
Title
RocksDB prefix extractor incorrectly includes timestamp in versioned index keys
Issue
RocksDBIndex uses iterator.seek(keyBuffer) with ReadOptions.setPrefixSameAsStart(true) to find entries by logical index key prefix. However, the column family in RocksDBFactory currently configures the fixed-length prefix extractor to include the encoded timestamp suffix.
This makes the RocksDB prefix definition inconsistent with the lookup logic:
As a result, seeking with one version of a key may fail to find another version with the same logical key but a different timestamp, and iterator.isValid() can return false unexpectedly.
Proposed fix
Update RocksDBFactory.createCFDescriptor() so that:
Do not include the encoded timestamp in the extracted prefix.
Regression coverage
Add a test that inserts one version of a key and verifies that iterator.seek() on another version with the same logical prefix still lands on the stored key.