diff --git a/docs/references/http_api_reference.mdx b/docs/references/http_api_reference.mdx index 1218f5e42..436f76baf 100644 --- a/docs/references/http_api_reference.mdx +++ b/docs/references/http_api_reference.mdx @@ -2635,7 +2635,150 @@ A `500` HTTP status code indicates an error condition. The response includes a J --- +## Show transactions +**GET** `/instance/transactions` + +Shows running transactions on database. + +### Request + +- Method: GET +- URL: `/instance/transactions` +- Headers: `accept: application/json` + +#### Request example + +```shell +curl --request GET \ + --url http://localhost:23820/instance/transactions \ + --header 'accept: application/json' +``` + +### Response + + + + +The response includes a JSON object like the following: + +```shell +{ + "error_code":0, + "transactions": [ + { + "transaction_id":"27275", + "transaction_text":"" + }, + { + "transaction_id":"27274", + "transaction_text":"" + } + ] +} +``` + +- `"error_code"`: `integer` + `0`: The operation succeeds. + + + + +A `500` HTTP status code indicates an error condition. The response includes a JSON object like the following: + +```shell +{ + "error_code": 2005, + "error_message": "Not support in maintenance mode" +} +``` + +- `"error_code"`: `integer` + A non-zero value indicates a specific error condition. +- `"error_message"`: `string` + When `error_code` is non-zero, `"error_message"` provides additional details about the error. + + + + +--- + +## Show transaction + +**GET** `/instance/transactions/{trasaction_id}` + +Shows running transactions on database by transaction_id. + +### Request + +- Method: GET +- URL: `/instance/transactions` +- Headers: `accept: application/json` + +#### Request example + +```shell +curl --request GET \ + --url http://localhost:23820/instance/transactions/{transaction_id} \ + --header 'accept: application/json' +``` + +#### Request parameters + +- `transaction_id`: (*Path parameter*) + The id of the running transaction. + +### Response + + + + +The response includes a JSON object like the following: + +```shell +{ + "error_code":0, + "transaction": { + "transaction_id":"27275", + "transaction_text":"" + } +} +``` + +- `"error_code"`: `integer` + `0`: The operation succeeds. + + + + +A `500` HTTP status code indicates an error condition. The response includes a JSON object like the following: + +```shell +{ + "error_code": 2005, + "error_message": "Not support in maintenance mode" +} +``` + +- `"error_code"`: `integer` + A non-zero value indicates a specific error condition. +- `"error_message"`: `string` + When `error_code` is non-zero, `"error_message"` provides additional details about the error. + + + + +--- ## Admin set node role diff --git a/src/network/http_server.cpp b/src/network/http_server.cpp index 67c116dc4..0b02e6251 100644 --- a/src/network/http_server.cpp +++ b/src/network/http_server.cpp @@ -3590,6 +3590,116 @@ class ShowFullCheckpointHandler final : public HttpRequestHandler { } }; + +class ShowQueryHandler final : public HttpRequestHandler { +public: +SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + nlohmann::json json_response; + nlohmann::json json_table; + HTTPStatus http_status; + String query_id = request->getPathVariable("query_id"); + QueryResult result = infinity->Query(fmt::format("show query {}", query_id)); + + if (result.IsOk()) { + DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); + auto column_cnt = result.result_table_->ColumnCount(); + for (SizeT col = 0; col < column_cnt; ++col) { + const String &column_name = result.result_table_->GetColumnNameById(col); + Value value = data_block->GetValue(col, 0); + const String &column_value = value.ToString(); + json_table[column_name] = column_value; + } + json_response["query"] = json_table; + 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 ShowTransactionsHandler 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 = infinity->Query("show transactions"); + + if (result.IsOk()) { + SizeT block_rows = result.result_table_->DataBlockCount(); + for (SizeT block_id = 0; block_id < block_rows; ++block_id) { + DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get(); + auto row_count = data_block->row_count(); + auto column_cnt = result.result_table_->ColumnCount(); + for (int row = 0; row < row_count; ++row) { + nlohmann::json json_table; + for (SizeT col = 0; col < column_cnt; ++col) { + const String &column_name = result.result_table_->GetColumnNameById(col); + Value value = data_block->GetValue(col, row); + const String &column_value = value.ToString(); + json_table[column_name] = column_value; + } + json_response["transactions"].push_back(json_table); + } + } + 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 ShowTransactionHandler final : public HttpRequestHandler { +public: +SharedPtr handle(const SharedPtr &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + nlohmann::json json_response; + nlohmann::json json_table; + HTTPStatus http_status; + String transaction_id = request->getPathVariable("transaction_id"); + QueryResult result = infinity->Query(fmt::format("show transaction {}", transaction_id)); + + if (result.IsOk()) { + DataBlock *data_block = result.result_table_->GetDataBlockById(0).get(); + auto column_cnt = result.result_table_->ColumnCount(); + for (SizeT col = 0; col < column_cnt; ++col) { + const String &column_name = result.result_table_->GetColumnNameById(col); + Value value = data_block->GetValue(col, 0); + const String &column_value = value.ToString(); + json_table[column_name] = column_value; + } + json_response["error_code"] = 0; + json_response["transaction"]= json_table; + 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 AdminShowCurrentNodeHandler final : public HttpRequestHandler { public: SharedPtr handle(const SharedPtr &request) final { @@ -3926,6 +4036,9 @@ void HTTPServer::Start(const String &ip_address, u16 port) { router->route("GET", "/instance/logs", MakeShared()); router->route("GET", "/instance/delta_checkpoint", MakeShared()); router->route("GET", "/instance/global_checkpoint", MakeShared()); + router->route("GET", "/instance/queries/{query_id}", MakeShared()); + router->route("GET", "/instance/transactions", MakeShared()); + router->route("GET", "/instance/transactions/{transaction_id}", MakeShared()); // variable router->route("GET", "/variables/global", MakeShared());