@ -3918,6 +3918,94 @@ TEST_F(DBBasicTestWithTimestamp, IterSeekToLastWithIterateUpperbound) {
ASSERT_FALSE ( iter - > Valid ( ) ) ;
ASSERT_OK ( iter - > status ( ) ) ;
}
TEST_F ( DBBasicTestWithTimestamp , TimestampFilterTableReadOnGet ) {
Options options = CurrentOptions ( ) ;
options . env = env_ ;
options . create_if_missing = true ;
options . statistics = ROCKSDB_NAMESPACE : : CreateDBStatistics ( ) ;
const size_t kTimestampSize = Timestamp ( 0 , 0 ) . size ( ) ;
TestComparator test_cmp ( kTimestampSize ) ;
options . comparator = & test_cmp ;
BlockBasedTableOptions bbto ;
bbto . block_size = 100 ;
options . table_factory . reset ( NewBlockBasedTableFactory ( bbto ) ) ;
DestroyAndReopen ( options ) ;
// Put
// Create two SST files
// file1: key => [1, 3], timestamp => [10, 20]
// file2, key => [2, 4], timestamp => [30, 40]
{
WriteOptions write_opts ;
std : : string write_ts = Timestamp ( 10 , 0 ) ;
ASSERT_OK ( db_ - > Put ( write_opts , Key1 ( 1 ) , write_ts , " value1 " ) ) ;
write_ts = Timestamp ( 20 , 0 ) ;
ASSERT_OK ( db_ - > Put ( write_opts , Key1 ( 3 ) , write_ts , " value3 " ) ) ;
ASSERT_OK ( Flush ( ) ) ;
write_ts = Timestamp ( 30 , 0 ) ;
ASSERT_OK ( db_ - > Put ( write_opts , Key1 ( 2 ) , write_ts , " value2 " ) ) ;
write_ts = Timestamp ( 40 , 0 ) ;
ASSERT_OK ( db_ - > Put ( write_opts , Key1 ( 4 ) , write_ts , " value4 " ) ) ;
ASSERT_OK ( Flush ( ) ) ;
}
// Get with timestamp
{
auto prev_checked_events = options . statistics - > getTickerCount (
Tickers : : TIMESTAMP_FILTER_TABLE_CHECKED ) ;
auto prev_filtered_events = options . statistics - > getTickerCount (
Tickers : : TIMESTAMP_FILTER_TABLE_FILTERED ) ;
// key=3 (ts=20) does not exist at timestamp=1
std : : string read_ts_str = Timestamp ( 1 , 0 ) ;
Slice read_ts_slice = Slice ( read_ts_str ) ;
ReadOptions read_opts ;
read_opts . timestamp = & read_ts_slice ;
std : : string value_from_get = " " ;
std : : string timestamp_from_get = " " ;
auto status =
db_ - > Get ( read_opts , Key1 ( 3 ) , & value_from_get , & timestamp_from_get ) ;
ASSERT_TRUE ( status . IsNotFound ( ) ) ;
ASSERT_EQ ( value_from_get , std : : string ( " " ) ) ;
ASSERT_EQ ( timestamp_from_get , std : : string ( " " ) ) ;
// key=3 is in the key ranges for both files, so both files will be queried.
// The table read was skipped because the timestamp is out of the table
// range, i.e.., 1 < [10,20], [30,40].
// The tickers increase by 2 due to 2 files.
ASSERT_EQ ( prev_checked_events + 2 ,
options . statistics - > getTickerCount (
Tickers : : TIMESTAMP_FILTER_TABLE_CHECKED ) ) ;
ASSERT_EQ ( prev_filtered_events + 2 ,
options . statistics - > getTickerCount (
Tickers : : TIMESTAMP_FILTER_TABLE_FILTERED ) ) ;
// key=3 (ts=20) exists at timestamp = 25
read_ts_str = Timestamp ( 25 , 0 ) ;
read_ts_slice = Slice ( read_ts_str ) ;
read_opts . timestamp = & read_ts_slice ;
ASSERT_OK (
db_ - > Get ( read_opts , Key1 ( 3 ) , & value_from_get , & timestamp_from_get ) ) ;
ASSERT_EQ ( " value3 " , value_from_get ) ;
ASSERT_EQ ( Timestamp ( 20 , 0 ) , timestamp_from_get ) ;
// file1 was not skipped, because the timestamp is in range, [10,20] < 25.
// file2 was skipped, because the timestamp is not in range, 25 < [30,40].
// So the checked ticker increase by 2 due to 2 files;
// filtered ticker increase by 1 because file2 was skipped
ASSERT_EQ ( prev_checked_events + 4 ,
options . statistics - > getTickerCount (
Tickers : : TIMESTAMP_FILTER_TABLE_CHECKED ) ) ;
ASSERT_EQ ( prev_filtered_events + 3 ,
options . statistics - > getTickerCount (
Tickers : : TIMESTAMP_FILTER_TABLE_FILTERED ) ) ;
}
Close ( ) ;
}
} // namespace ROCKSDB_NAMESPACE
int main ( int argc , char * * argv ) {