This is an automated email from the ASF dual-hosted git repository.

twice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new 74281828 feat(search): add support for command FT.DROPINDEX (#2353)
74281828 is described below

commit 74281828726a6f23f7f192fce496545a83c44aef
Author: Twice <[email protected]>
AuthorDate: Tue Jun 4 00:25:10 2024 +0900

    feat(search): add support for command FT.DROPINDEX (#2353)
---
 src/commands/cmd_search.cc   | 15 ++++++++++++++-
 src/search/index_manager.h   | 42 ++++++++++++++++++++++++++++++++++++++----
 src/search/indexer.cc        | 14 ++++++++++++++
 src/search/indexer.h         |  2 ++
 src/search/search_encoding.h | 36 ++++++++++++++++++++++++++++++++++++
 5 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/src/commands/cmd_search.cc b/src/commands/cmd_search.cc
index bf6444dc..a74f69a6 100644
--- a/src/commands/cmd_search.cc
+++ b/src/commands/cmd_search.cc
@@ -278,10 +278,23 @@ class CommandFTList : public Commander {
   };
 };
 
+class CommandFTDrop : public Commander {
+  Status Execute(Server *srv, Connection *conn, std::string *output) override {
+    const auto &index_name = args_[1];
+
+    GET_OR_RET(srv->index_mgr.Drop(index_name, conn->GetNamespace()));
+
+    output->append(SimpleString("OK"));
+
+    return Status::OK();
+  };
+};
+
 REDIS_REGISTER_COMMANDS(MakeCmdAttr<CommandFTCreate>("ft.create", -2, "write 
exclusive no-multi no-script", 0, 0, 0),
                         MakeCmdAttr<CommandFTSearchSQL>("ft.searchsql", 2, 
"read-only", 0, 0, 0),
                         MakeCmdAttr<CommandFTSearch>("ft.search", -3, 
"read-only", 0, 0, 0),
                         MakeCmdAttr<CommandFTInfo>("ft.info", 2, "read-only", 
0, 0, 0),
-                        MakeCmdAttr<CommandFTList>("ft._list", 1, "read-only", 
0, 0, 0));
+                        MakeCmdAttr<CommandFTList>("ft._list", 1, "read-only", 
0, 0, 0),
+                        MakeCmdAttr<CommandFTDrop>("ft.dropindex", 2, "write 
exclusive no-multi no-script", 0, 0, 0));
 
 }  // namespace redis
diff --git a/src/search/index_manager.h b/src/search/index_manager.h
index a4174dbd..32e1a275 100644
--- a/src/search/index_manager.h
+++ b/src/search/index_manager.h
@@ -70,7 +70,7 @@ struct IndexManager {
       IndexMetadata metadata;
       auto index_meta_value = iter->value();
       if (auto s = metadata.Decode(&index_meta_value); !s.ok()) {
-        return {Status::NotOK, fmt::format("fail to decode index metadata for 
index: {}", index_name)};
+        return {Status::NotOK, fmt::format("fail to decode index metadata for 
index {}: {}", index_name, s.ToString())};
       }
 
       auto index_key = SearchKey(ns, index_name.ToStringView());
@@ -78,13 +78,13 @@ struct IndexManager {
       if (auto s = storage->Get(storage->DefaultMultiGetOptions(), 
storage->GetCFHandle(ColumnFamilyID::Search),
                                 index_key.ConstructIndexPrefixes(), 
&prefix_value);
           !s.ok()) {
-        return {Status::NotOK, fmt::format("fail to find index prefixes for 
index: {}", index_name)};
+        return {Status::NotOK, fmt::format("fail to find index prefixes for 
index {}: {}", index_name, s.ToString())};
       }
 
       IndexPrefixes prefixes;
       Slice prefix_slice = prefix_value;
       if (auto s = prefixes.Decode(&prefix_slice); !s.ok()) {
-        return {Status::NotOK, fmt::format("fail to decode index prefixes for 
index: {}", index_name)};
+        return {Status::NotOK, fmt::format("fail to decode index prefixes for 
index {}: {}", index_name, s.ToString())};
       }
 
       auto info = std::make_unique<kqir::IndexInfo>(index_name.ToString(), 
metadata, ns);
@@ -164,7 +164,7 @@ struct IndexManager {
     }
 
     if (auto s = storage->Write(storage->DefaultWriteOptions(), 
batch->GetWriteBatch()); !s.ok()) {
-      return {Status::NotOK, "failed to write index metadata"};
+      return {Status::NotOK, fmt::format("failed to write index metadata: {}", 
s.ToString())};
     }
 
     IndexUpdater updater(info.get());
@@ -204,6 +204,40 @@ struct IndexManager {
 
     return results;
   }
+
+  Status Drop(std::string_view index_name, const std::string &ns) {
+    auto iter = index_map.Find(index_name, ns);
+    if (iter == index_map.end()) {
+      return {Status::NotOK, "index not found"};
+    }
+
+    auto info = iter->second.get();
+    indexer->Remove(info);
+
+    SearchKey index_key(info->ns, info->name);
+    auto cf = storage->GetCFHandle(ColumnFamilyID::Search);
+
+    auto batch = storage->GetWriteBatchBase();
+
+    batch->Delete(cf, index_key.ConstructIndexMeta());
+    batch->Delete(cf, index_key.ConstructIndexPrefixes());
+
+    auto begin = index_key.ConstructAllFieldMetaBegin();
+    auto end = index_key.ConstructAllFieldMetaEnd();
+    batch->DeleteRange(cf, begin, end);
+
+    begin = index_key.ConstructAllFieldDataBegin();
+    end = index_key.ConstructAllFieldDataEnd();
+    batch->DeleteRange(cf, begin, end);
+
+    if (auto s = storage->Write(storage->DefaultWriteOptions(), 
batch->GetWriteBatch()); !s.ok()) {
+      return {Status::NotOK, fmt::format("failed to delete index metadata and 
data: {}", s.ToString())};
+    }
+
+    index_map.erase(iter);
+
+    return Status::OK();
+  }
 };
 
 }  // namespace redis
diff --git a/src/search/indexer.cc b/src/search/indexer.cc
index cc4735a0..0ee1b39d 100644
--- a/src/search/indexer.cc
+++ b/src/search/indexer.cc
@@ -270,6 +270,20 @@ void GlobalIndexer::Add(IndexUpdater updater) {
   updater_list.push_back(updater);
 }
 
+void GlobalIndexer::Remove(const kqir::IndexInfo *index) {
+  for (auto iter = prefix_map.begin(); iter != prefix_map.end();) {
+    if (iter->info == index) {
+      iter = prefix_map.erase(iter);
+    } else {
+      ++iter;
+    }
+  }
+
+  updater_list.erase(std::remove_if(updater_list.begin(), updater_list.end(),
+                                    [index](IndexUpdater updater) { return 
updater.info == index; }),
+                     updater_list.end());
+}
+
 StatusOr<GlobalIndexer::RecordResult> GlobalIndexer::Record(std::string_view 
key, const std::string &ns) {
   if (updater_list.empty()) {
     return Status::NoPrefixMatched;
diff --git a/src/search/indexer.h b/src/search/indexer.h
index 33cea303..2bc7471b 100644
--- a/src/search/indexer.h
+++ b/src/search/indexer.h
@@ -103,6 +103,8 @@ struct GlobalIndexer {
   explicit GlobalIndexer(engine::Storage *storage) : storage(storage) {}
 
   void Add(IndexUpdater updater);
+  void Remove(const kqir::IndexInfo *index);
+
   StatusOr<RecordResult> Record(std::string_view key, const std::string &ns);
   static Status Update(const RecordResult &original);
 };
diff --git a/src/search/search_encoding.h b/src/search/search_encoding.h
index 5b4cf739..68e248bb 100644
--- a/src/search/search_encoding.h
+++ b/src/search/search_encoding.h
@@ -120,6 +120,42 @@ struct SearchKey {
     return dst;
   }
 
+  std::string ConstructAllFieldMetaBegin() const {
+    std::string dst;
+    PutNamespace(&dst);
+    PutType(&dst, SearchSubkeyType::FIELD_META);
+    PutIndex(&dst);
+    PutFixed32(&dst, 0);
+    return dst;
+  }
+
+  std::string ConstructAllFieldMetaEnd() const {
+    std::string dst;
+    PutNamespace(&dst);
+    PutType(&dst, SearchSubkeyType::FIELD_META);
+    PutIndex(&dst);
+    PutFixed32(&dst, (uint32_t)(-1));
+    return dst;
+  }
+
+  std::string ConstructAllFieldDataBegin() const {
+    std::string dst;
+    PutNamespace(&dst);
+    PutType(&dst, SearchSubkeyType::FIELD);
+    PutIndex(&dst);
+    PutFixed32(&dst, 0);
+    return dst;
+  }
+
+  std::string ConstructAllFieldDataEnd() const {
+    std::string dst;
+    PutNamespace(&dst);
+    PutType(&dst, SearchSubkeyType::FIELD);
+    PutIndex(&dst);
+    PutFixed32(&dst, (uint32_t)(-1));
+    return dst;
+  }
+
   std::string ConstructTagFieldData(std::string_view tag, std::string_view 
key) const {
     std::string dst;
     PutNamespace(&dst);

Reply via email to