@@ -8650,6 +8650,121 @@ TEST_F(UserDefinedIndexTest, ReverseMultiScanTest) {
86508650 ASSERT_OK (DestroyDB (dbname, options));
86518651}
86528652
8653+ TEST_F (UserDefinedIndexTest, RangeDelete) {
8654+ Options options;
8655+ BlockBasedTableOptions table_options;
8656+ options.num_levels = 50 ;
8657+ options.compaction_style = kCompactionStyleUniversal ;
8658+ options.disable_auto_compactions = true ;
8659+ std::string dbname = test::PerThreadDBPath (" user_defined_index_test" );
8660+ std::string ingest_file = dbname + " test.sst" ;
8661+
8662+ // Set up the user-defined index factory
8663+ auto user_defined_index_factory =
8664+ std::make_shared<TestUserDefinedIndexFactory>();
8665+ table_options.user_defined_index_factory = user_defined_index_factory;
8666+
8667+ // Set up custom flush block policy that flushes every 3 keys
8668+ table_options.flush_block_policy_factory =
8669+ std::make_shared<CustomFlushBlockPolicyFactory>();
8670+
8671+ options.table_factory .reset (NewBlockBasedTableFactory (table_options));
8672+
8673+ auto create_ingestion_data_file = [&](const std::string& filename) {
8674+ std::unique_ptr<SstFileWriter> writer;
8675+ writer.reset (new SstFileWriter (EnvOptions (), options));
8676+ ASSERT_OK (writer->Open (filename));
8677+ // Add 100 keys
8678+ for (int i = 0 ; i < 100 ; i++) {
8679+ std::stringstream ss;
8680+ ss << std::setw (2 ) << std::setfill (' 0' ) << i;
8681+ std::string key = " key" + ss.str ();
8682+ std::string value = " value" + ss.str ();
8683+ ASSERT_OK (writer->Put (key, value));
8684+ }
8685+ ASSERT_OK (writer->Finish ());
8686+ writer.reset ();
8687+ };
8688+
8689+ // Create first ingestion file with data
8690+ create_ingestion_data_file (ingest_file + " _0" );
8691+
8692+ // Create second ingestion file with range delete only that covers the first
8693+ // file to delete all of its keys.
8694+ {
8695+ std::unique_ptr<SstFileWriter> writer;
8696+ writer.reset (new SstFileWriter (EnvOptions (), options));
8697+ ASSERT_OK (writer->Open (ingest_file + " _1" ));
8698+ ASSERT_OK (writer->DeleteRange (" key" , " keyz" ));
8699+ ASSERT_OK (writer->Finish ());
8700+ writer.reset ();
8701+ }
8702+
8703+ // Create the second ingestion file with data
8704+ create_ingestion_data_file (ingest_file + " _2" );
8705+
8706+ std::unique_ptr<DB > db;
8707+ options.create_if_missing = true ;
8708+ Status s = DB::Open (options, dbname, &db);
8709+ ASSERT_OK (s);
8710+ ASSERT_TRUE (db != nullptr );
8711+ ColumnFamilyHandle* cfh = nullptr ;
8712+ ASSERT_OK (db->CreateColumnFamily (options, " new_cf" , &cfh));
8713+
8714+ IngestExternalFileOptions ifo;
8715+ // ingest first data file key00~key99
8716+ s = db->IngestExternalFile (cfh, {ingest_file + " _0" }, ifo);
8717+ ASSERT_OK (s);
8718+ // ingest delete range (key-keyz) and new data file (key00-key99) together
8719+ s = db->IngestExternalFile (cfh, {ingest_file + " _1" , ingest_file + " _2" },
8720+ ifo);
8721+ ASSERT_OK (s);
8722+
8723+ ReadOptions ro;
8724+ std::unique_ptr<Iterator> iter (db->NewIterator (ro, cfh));
8725+ ASSERT_NE (iter, nullptr );
8726+ ASSERT_OK (iter->status ());
8727+
8728+ std::vector<Slice> range = {
8729+ Slice (" key10" ),
8730+ Slice (" key25" ),
8731+ Slice (" key80" ),
8732+ Slice (" key95" ),
8733+ };
8734+
8735+ Slice ub (" " );
8736+ ro.iterate_upper_bound = &ub;
8737+ iter.reset (db->NewIterator (ro, cfh));
8738+ ASSERT_NE (iter, nullptr );
8739+ MultiScanArgs scan_opts (options.comparator );
8740+ std::unordered_map<std::string, std::string> property_bag;
8741+ property_bag[" count" ] = std::to_string (9 );
8742+
8743+ std::vector<std::vector<char >> decoded_ranges;
8744+ for (size_t i = 0 ; i < range.size () / 2 ; i++) {
8745+ scan_opts.insert (range[i * 2 ], range[i * 2 + 1 ],
8746+ std::optional (property_bag));
8747+ }
8748+ iter->Prepare (scan_opts);
8749+
8750+ for (size_t i = 0 ; i < range.size () / 2 ; i++) {
8751+ // Update upper bound before each seek
8752+ ub = range[2 * i + 1 ];
8753+ auto key_count = 0 ;
8754+ for (iter->Seek (range[i * 2 ]); iter->Valid (); iter->Next ()) {
8755+ key_count++;
8756+ }
8757+ ASSERT_OK (iter->status ());
8758+ ASSERT_EQ (key_count, 15 );
8759+ }
8760+
8761+ iter.reset ();
8762+
8763+ ASSERT_OK (db->DestroyColumnFamilyHandle (cfh));
8764+ ASSERT_OK (db->Close ());
8765+ ASSERT_OK (DestroyDB (dbname, options));
8766+ }
8767+
86538768} // namespace ROCKSDB_NAMESPACE
86548769
86558770int main (int argc, char ** argv) {
0 commit comments