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 717e52f3 feat(search): add a flag to dump DOT graphs in FT.EXPLAINSQL 
(#2366)
717e52f3 is described below

commit 717e52f3c142939fe36f427cbf9a9b143f2f516f
Author: Twice <[email protected]>
AuthorDate: Sat Jun 15 16:16:52 2024 +0900

    feat(search): add a flag to dump DOT graphs in FT.EXPLAINSQL (#2366)
---
 src/commands/cmd_search.cc | 41 ++++++++++++++++++++++++++++++++++++-----
 src/search/index_manager.h |  6 ------
 src/search/ir.h            |  4 ++--
 3 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/src/commands/cmd_search.cc b/src/commands/cmd_search.cc
index 14569477..618e0cf6 100644
--- a/src/commands/cmd_search.cc
+++ b/src/commands/cmd_search.cc
@@ -19,18 +19,21 @@
  */
 
 #include <memory>
+#include <sstream>
 #include <variant>
 
 #include "commander.h"
 #include "commands/command_parser.h"
 #include "search/index_info.h"
 #include "search/ir.h"
+#include "search/ir_dot_dumper.h"
 #include "search/plan_executor.h"
 #include "search/redis_query_transformer.h"
 #include "search/search_encoding.h"
 #include "search/sql_transformer.h"
 #include "server/redis_reply.h"
 #include "server/server.h"
+#include "string_util.h"
 #include "tao/pegtl/string_input.hpp"
 
 namespace redis {
@@ -153,17 +156,45 @@ static void DumpQueryResult(const 
std::vector<kqir::ExecutorContext::RowType> &r
 }
 
 class CommandFTExplainSQL : public Commander {
+  Status Parse(const std::vector<std::string> &args) override {
+    if (args.size() == 3) {
+      if (util::EqualICase(args[2], "simple")) {
+        format_ = SIMPLE;
+      } else if (util::EqualICase(args[2], "dot")) {
+        format_ = DOT_GRAPH;
+      } else {
+        return {Status::NotOK, "output format should be SIMPLE or DOT"};
+      }
+    }
+
+    if (args.size() > 3) {
+      return {Status::NotOK, "more arguments than expected"};
+    }
+
+    return Status::OK();
+  }
+
   Status Execute(Server *srv, Connection *conn, std::string *output) override {
     const auto &sql = args_[1];
 
     auto ir = GET_OR_RET(kqir::sql::ParseToIR(kqir::peg::string_input(sql, 
"ft.explainsql")));
 
-    auto result = GET_OR_RET(srv->index_mgr.Explain(std::move(ir), 
conn->GetNamespace()));
+    auto plan = GET_OR_RET(srv->index_mgr.GeneratePlan(std::move(ir), 
conn->GetNamespace()));
 
-    output->append(BulkString(result));
+    if (format_ == SIMPLE) {
+      output->append(BulkString(plan->Dump()));
+    } else if (format_ == DOT_GRAPH) {
+      std::ostringstream ss;
+      kqir::DotDumper dumper(ss);
+
+      dumper.Dump(plan.get());
+      output->append(BulkString(ss.str()));
+    }
 
     return Status::OK();
   };
+
+  enum OutputFormat { SIMPLE, DOT_GRAPH } format_ = SIMPLE;
 };
 
 class CommandFTSearchSQL : public Commander {
@@ -233,9 +264,9 @@ class CommandFTExplain : public Commander {
 
   Status Execute(Server *srv, Connection *conn, std::string *output) override {
     CHECK(ir_);
-    auto result = GET_OR_RET(srv->index_mgr.Explain(std::move(ir_), 
conn->GetNamespace()));
+    auto plan = GET_OR_RET(srv->index_mgr.GeneratePlan(std::move(ir_), 
conn->GetNamespace()));
 
-    output->append(redis::SimpleString(result));
+    output->append(redis::BulkString(plan->Dump()));
 
     return Status::OK();
   };
@@ -330,7 +361,7 @@ class CommandFTDrop : public Commander {
 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<CommandFTExplainSQL>("ft.explainsql", 2, 
"read-only", 0, 0, 0),
+                        MakeCmdAttr<CommandFTExplainSQL>("ft.explainsql", -2, 
"read-only", 0, 0, 0),
                         MakeCmdAttr<CommandFTExplain>("ft.explain", -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),
diff --git a/src/search/index_manager.h b/src/search/index_manager.h
index 0d76765a..1d744704 100644
--- a/src/search/index_manager.h
+++ b/src/search/index_manager.h
@@ -194,12 +194,6 @@ struct IndexManager {
     return plan_op;
   }
 
-  StatusOr<std::string> Explain(std::unique_ptr<kqir::Node> ir, const 
std::string &ns) const {
-    auto plan_op = GET_OR_RET(GeneratePlan(std::move(ir), ns));
-
-    return plan_op->Dump();
-  }
-
   StatusOr<std::vector<kqir::ExecutorContext::RowType>> 
Search(std::unique_ptr<kqir::Node> ir,
                                                                const 
std::string &ns) const {
     auto plan_op = GET_OR_RET(GeneratePlan(std::move(ir), ns));
diff --git a/src/search/ir.h b/src/search/ir.h
index be235e0d..4007890e 100644
--- a/src/search/ir.h
+++ b/src/search/ir.h
@@ -363,7 +363,7 @@ struct SelectClause : Node {
 
   explicit SelectClause(std::vector<std::unique_ptr<FieldRef>> &&fields) : 
fields(std::move(fields)) {}
 
-  std::string_view Name() const override { return "SelectExpr"; }
+  std::string_view Name() const override { return "SelectClause"; }
   std::string Dump() const override {
     if (fields.empty()) return "select *";
     return fmt::format("select {}", util::StringJoin(fields, [](const auto &v) 
{ return v->Dump(); }));
@@ -412,7 +412,7 @@ struct SearchExpr : Node {
         limit(std::move(limit)),
         sort_by(std::move(sort_by)) {}
 
-  std::string_view Name() const override { return "SearchStmt"; }
+  std::string_view Name() const override { return "SearchExpr"; }
   std::string Dump() const override {
     std::string opt;
     if (sort_by) opt += " " + sort_by->Dump();

Reply via email to