From 4834a902d43d02004245d8eca2f576ff9b5e8ae1 Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <132966438+Ami11111@users.noreply.github.com> Date: Sun, 29 Sep 2024 13:31:00 +0800 Subject: [PATCH] More show commad for http (#1939) ### What problem does this PR solve? - add show and set command for session variables for http - fix show global variables bug Issue link:#1937 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [x] New Feature (non-breaking change which adds functionality) --- python/infinity_http.py | 2 +- src/executor/operator/physical_show.cpp | 3 +- src/network/http_server.cpp | 152 +++++++++++++++++++++++- 3 files changed, 150 insertions(+), 7 deletions(-) diff --git a/python/infinity_http.py b/python/infinity_http.py index 17ed3af43f..f300c0fa8e 100644 --- a/python/infinity_http.py +++ b/python/infinity_http.py @@ -533,7 +533,7 @@ def add_columns(self, columns_definition = {}): tmp[param_name.lower()] = columns_definition[col][param_name] fields.append(tmp) d = self.set_up_data([], {"fields": fields}) - r = self.request(url, "put", h, d) + r = self.request(url, "post", h, d) return self.get_database_result(r) def drop_columns(self, column_name: list[str] | str): diff --git a/src/executor/operator/physical_show.cpp b/src/executor/operator/physical_show.cpp index 10e60a7736..c8324b1693 100644 --- a/src/executor/operator/physical_show.cpp +++ b/src/executor/operator/physical_show.cpp @@ -4520,7 +4520,8 @@ void PhysicalShow::ExecuteShowGlobalVariables(QueryContext *query_context, ShowO break; } case GlobalVariable::kFollowerNum: { - if(InfinityContext::instance().cluster_manager()->ThisNode()->node_role_ == NodeRole::kLeader) { + if(InfinityContext::instance().IsClusterRole() + && InfinityContext::instance().cluster_manager()->ThisNode()->node_role_ == NodeRole::kLeader) { { // option name Value value = Value::MakeVarchar(var_name); diff --git a/src/network/http_server.cpp b/src/network/http_server.cpp index 20686a0eac..d77fdde317 100644 --- a/src/network/http_server.cpp +++ b/src/network/http_server.cpp @@ -3095,6 +3095,146 @@ class SetGlobalVariableHandler final : public HttpRequestHandler { } }; +class ShowSessionVariablesHandler final : public HttpRequestHandler { +public: + SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + auto result = infinity->ShowVariables(SetScope::kSession); + + nlohmann::json json_response; + HTTPStatus http_status; + + if (result.IsOk()) { + json_response["error_code"] = 0; + DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); // Assume the variables output data only included in one data block + auto row_count = data_block->row_count(); + for (int row = 0; row < row_count; ++row) { + // variable name + Value name_value = data_block->GetValue(0, row); + const String& config_name = name_value.ToString(); + // variable value + Value value = data_block->GetValue(1, row); + const String &config_value = value.ToString(); + json_response[config_name] = config_value; + } + http_status = HTTPStatus::CODE_200; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; + } + return ResponseFactory::createResponse(http_status, json_response.dump()); + } +}; + +class ShowSessionVariableHandler final : public HttpRequestHandler { +public: + SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + auto variable_name = request->getPathVariable("variable_name"); + auto result = infinity->ShowVariable(variable_name, SetScope::kSession); + + nlohmann::json json_response; + HTTPStatus http_status; + + if (result.IsOk()) { + json_response["error_code"] = 0; + DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); + Value value = data_block->GetValue(0, 0); + const String &variable_value = value.ToString(); + json_response[variable_name] = variable_value; + + http_status = HTTPStatus::CODE_200; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; + } + return ResponseFactory::createResponse(http_status, json_response.dump()); + } +}; + +class SetSessionVariableHandler final : public HttpRequestHandler { +public: + SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + nlohmann::json json_response; + HTTPStatus http_status; + QueryResult result; + + String data_body = request->readBodyToString(); + try { + + nlohmann::json http_body_json = nlohmann::json::parse(data_body); + if(http_body_json.size() != 1) { + json_response["error_code"] = 3076; + json_response["error_message"] = "No variable will be set"; + http_status = HTTPStatus::CODE_500; + return ResponseFactory::createResponse(http_status, json_response.dump()); + } + + for (const auto &set_variable : http_body_json.items()) { + String var_name = set_variable.key(); + const auto &var_value = set_variable.value(); + switch (var_value.type()) { + case nlohmann::json::value_t::boolean: { + bool bool_value = var_value.template get(); + result = infinity->SetVariableOrConfig(var_name, bool_value, SetScope::kSession); + break; + } + case nlohmann::json::value_t::number_integer: { + i64 integer_value = var_value.template get(); + result = infinity->SetVariableOrConfig(var_name, integer_value, SetScope::kSession); + break; + } + case nlohmann::json::value_t::number_unsigned: { + i64 integer_value = var_value.template get(); + result = infinity->SetVariableOrConfig(var_name, integer_value, SetScope::kSession); + break; + } + case nlohmann::json::value_t::number_float: { + f64 double_value = var_value.template get(); + result = infinity->SetVariableOrConfig(var_name, double_value, SetScope::kSession); + break; + } + case nlohmann::json::value_t::string: { + String str_value = var_value.template get(); + result = infinity->SetVariableOrConfig(var_name, str_value, SetScope::kSession); + break; + } + case nlohmann::json::value_t::array: + case nlohmann::json::value_t::object: + case nlohmann::json::value_t::binary: + case nlohmann::json::value_t::null: + case nlohmann::json::value_t::discarded: { + json_response["error_code"] = ErrorCode::kInvalidExpression; + json_response["error_message"] = fmt::format("Invalid set variable expression"); + return ResponseFactory::createResponse(http_status, json_response.dump()); + } + } + } + } catch (nlohmann::json::exception &e) { + json_response["error_code"] = ErrorCode::kInvalidJsonFormat; + json_response["error_message"] = e.what(); + } + if (result.IsOk()) { + json_response["error_code"] = 0; + http_status = HTTPStatus::CODE_200; + } else { + json_response["error_code"] = result.ErrorCode(); + json_response["error_message"] = result.ErrorMsg(); + http_status = HTTPStatus::CODE_500; + } + return ResponseFactory::createResponse(http_status, json_response.dump()); + } +}; + class SetConfigHandler final : public HttpRequestHandler { public: SharedPtr handle(const SharedPtr &request) final { @@ -3220,7 +3360,7 @@ void HTTPServer::Start(const String& ip_address, u16 port) { router->route("PUT", "/databases/{database_name}/tables/{table_name}/indexes/{index_name}", MakeShared()); // alter - router->route("PUT", "/databases/{database_name}/tables/{table_name}/columns", MakeShared()); + router->route("POST", "/databases/{database_name}/tables/{table_name}/columns", MakeShared()); router->route("DELETE", "/databases/{database_name}/tables/{table_name}/columns", MakeShared()); // segment @@ -3243,10 +3383,12 @@ void HTTPServer::Start(const String& ip_address, u16 port) { router->route("POST", "/configs", MakeShared()); // variable - router->route("GET", "/variables", MakeShared()); - router->route("GET", "/variables/{variable_name}", MakeShared()); - - router->route("POST", "/variables", MakeShared()); + router->route("GET", "/variables/global", MakeShared()); + router->route("GET", "/variables/global/{variable_name}", MakeShared()); + router->route("SET", "/variables/global", MakeShared()); + router->route("GET", "/variables/session", MakeShared()); + router->route("GET", "/variables/session/{variable_name}", MakeShared()); + router->route("SET", "/variables/session", MakeShared()); SharedPtr connection_provider = HttpConnectionProvider::createShared({ip_address, port, WebAddress::IP_4}); SharedPtr connection_handler = HttpConnectionHandler::createShared(router);