diff --git a/docs/references/http_api_reference.md b/docs/references/http_api_reference.md index 81ca50f57a..3c4d5986e0 100644 --- a/docs/references/http_api_reference.md +++ b/docs/references/http_api_reference.md @@ -743,6 +743,37 @@ curl --request GET \ } ``` +## Show segments list + +Show segments list of specific table + +#### Request + +``` +curl --request GET \ + --url localhost:23820/databases/{database_name}/tables/{table_name}/segments/ \ + --header 'accept: application/json' +``` + +#### Response + +- 200 success + +``` +{ + "error_code": 0, + "table_name": "test1", + "segments": [ + { + "id": "0", + "size": "192.07KB", + "status": "Unsealed" + } + ] +} +``` + + ## Show segment Show specific segment details @@ -784,6 +815,36 @@ curl --request GET \ } ``` +## Show blocks list + +Show blocks list of specific segment + +#### Request + +``` +curl --request GET \ + --url localhost:23820/databases/{database_name}/tables/{table_name}/segments/{segment_id}/blocks/ \ + --header 'accept: application/json' +``` + +#### Response + +- 200 success + +``` +{ + "error_code": 0, + "segment_id": 0, + "blocks": [ + { + "id": "0", + "row_count": "2", + "size": "192.07KB" + } + ] +} +``` + ## Show block Show specific block detail diff --git a/src/executor/explain_physical_plan.cpp b/src/executor/explain_physical_plan.cpp index cc499919d5..70077850ab 100644 --- a/src/executor/explain_physical_plan.cpp +++ b/src/executor/explain_physical_plan.cpp @@ -1293,7 +1293,7 @@ void ExplainPhysicalPlan::Explain(const PhysicalShow *show_node, SharedPtr<Vecto result->emplace_back(MakeShared<String>(show_str)); String output_columns_str = String(intent_size, ' '); - output_columns_str += " - output columns: [path, size]"; + output_columns_str += " - output columns: [id, status, size]"; result->emplace_back(MakeShared<String>(output_columns_str)); break; } @@ -1329,7 +1329,7 @@ void ExplainPhysicalPlan::Explain(const PhysicalShow *show_node, SharedPtr<Vecto result->emplace_back(MakeShared<String>(show_str)); String output_columns_str = String(intent_size, ' '); - output_columns_str += " - output columns: [path, size]"; + output_columns_str += " - output columns: [id, size, row_count]"; result->emplace_back(MakeShared<String>(output_columns_str)); break; } diff --git a/src/executor/operator/physical_show.cpp b/src/executor/operator/physical_show.cpp index 3951a6247d..23856aea9e 100644 --- a/src/executor/operator/physical_show.cpp +++ b/src/executor/operator/physical_show.cpp @@ -207,14 +207,16 @@ void PhysicalShow::Init() { break; } case ShowType::kShowSegments: { - output_names_->reserve(2); - output_types_->reserve(2); + output_names_->reserve(3); + output_types_->reserve(3); - output_names_->emplace_back("path"); + output_names_->emplace_back("id"); + output_names_->emplace_back("status"); output_names_->emplace_back("size"); output_types_->emplace_back(bigint_type); output_types_->emplace_back(varchar_type); + output_types_->emplace_back(varchar_type); break; } case ShowType::kShowSegment: { @@ -246,14 +248,16 @@ void PhysicalShow::Init() { } case ShowType::kShowBlocks: { - output_names_->reserve(2); - output_types_->reserve(2); + output_names_->reserve(3); + output_types_->reserve(3); - output_names_->emplace_back("path"); + output_names_->emplace_back("id"); output_names_->emplace_back("size"); + output_names_->emplace_back("row_count"); + output_types_->emplace_back(bigint_type); output_types_->emplace_back(varchar_type); - output_types_->emplace_back(varchar_type); + output_types_->emplace_back(bigint_type); break; } @@ -1148,7 +1152,6 @@ void PhysicalShow::ExecuteShowColumns(QueryContext *query_context, ShowOperatorS void PhysicalShow::ExecuteShowSegments(QueryContext *query_context, ShowOperatorState *show_operator_state) { auto txn = query_context->GetTxn(); - TxnTimeStamp begin_ts = txn->BeginTS(); auto [table_entry, status] = txn->GetTableByName(db_name_, object_name_); if (!status.ok()) { @@ -1158,70 +1161,39 @@ void PhysicalShow::ExecuteShowSegments(QueryContext *query_context, ShowOperator } auto varchar_type = MakeShared<DataType>(LogicalType::kVarchar); - - Vector<SharedPtr<ColumnDef>> column_defs = { - MakeShared<ColumnDef>(0, varchar_type, "path", HashSet<ConstraintType>()), - MakeShared<ColumnDef>(1, varchar_type, "size", HashSet<ConstraintType>()), + auto bigint_type = MakeShared<DataType>(LogicalType::kBigInt); + UniquePtr<DataBlock> output_block_ptr = DataBlock::MakeUniquePtr(); + Vector<SharedPtr<DataType>> column_types{ + bigint_type, + varchar_type, + varchar_type, }; + output_block_ptr->Init(column_types); - UniquePtr<DataBlock> output_block_ptr = DataBlock::MakeUniquePtr(); - auto chuck_filling = [&](const std::function<u64(const String &)> &file_size_func, const String &path) { + for (auto &[_, segment_entry] : table_entry->segment_map()) { SizeT column_id = 0; { - Value value = Value::MakeVarchar(path); + Value value = Value::MakeBigInt(segment_entry->segment_id()); ValueExpression value_expr(value); value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]); } ++column_id; { - Value value = Value::MakeVarchar(Utility::FormatByteSize(file_size_func(path))); - + Value value = Value::MakeVarchar(SegmentEntry::SegmentStatusToString(segment_entry->status())); ValueExpression value_expr(value); value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]); } - }; - Vector<SharedPtr<DataType>> column_types{ - varchar_type, - varchar_type, - }; - output_block_ptr->Init(column_types); - if (segment_id_.has_value() && block_id_.has_value()) { - if (auto segment_entry = table_entry->GetSegmentByID(*segment_id_, begin_ts); segment_entry) { - auto *block_entry = segment_entry->GetBlockEntryByID(*block_id_).get(); - if (block_entry != nullptr) { - auto version_path = block_entry->VersionFilePath(); - - chuck_filling(LocalFileSystem::GetFileSizeByPath, version_path); - SizeT column_count = table_entry->ColumnCount(); - for (SizeT column_id = 0; column_id < column_count; ++column_id) { - auto block_column_entry = block_entry->GetColumnBlockEntry(column_id); - auto col_file_path = block_column_entry->FilePath(); - - chuck_filling(LocalFileSystem::GetFileSizeByPath, col_file_path); - for (auto &outline : block_column_entry->OutlinePaths()) { - chuck_filling(LocalFileSystem::GetFileSizeByPath, outline); - } - } - } - } - } else if (segment_id_.has_value()) { - if (auto segment_entry = table_entry->GetSegmentByID(*segment_id_, begin_ts); segment_entry) { - auto block_entry_iter = BlockEntryIter(segment_entry.get()); - for (auto *block_entry = block_entry_iter.Next(); block_entry != nullptr; block_entry = block_entry_iter.Next()) { - const auto &dir_path = *block_entry->base_dir(); - - chuck_filling(LocalFileSystem::GetFolderSizeByPath, dir_path); - } - } - } else { - for (auto &[_, segment] : table_entry->segment_map()) { // FIXME: use table_ref here. - const auto &dir_path = *segment->segment_dir(); - - chuck_filling(LocalFileSystem::GetFolderSizeByPath, dir_path); + ++column_id; + { + const auto &seg_size = Utility::FormatByteSize(LocalFileSystem::GetFolderSizeByPath(*segment_entry->segment_dir())); + Value value = Value::MakeVarchar(seg_size); + ValueExpression value_expr(value); + value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]); } } + output_block_ptr->Finalize(); show_operator_state->output_.emplace_back(std::move(output_block_ptr)); } @@ -1347,42 +1319,43 @@ void PhysicalShow::ExecuteShowBlocks(QueryContext *query_context, ShowOperatorSt return; } + auto bigint_type = MakeShared<DataType>(LogicalType::kBigInt); auto varchar_type = MakeShared<DataType>(LogicalType::kVarchar); - - Vector<SharedPtr<ColumnDef>> column_defs = { - MakeShared<ColumnDef>(0, varchar_type, "path", HashSet<ConstraintType>()), - MakeShared<ColumnDef>(1, varchar_type, "size", HashSet<ConstraintType>()), + UniquePtr<DataBlock> output_block_ptr = DataBlock::MakeUniquePtr(); + Vector<SharedPtr<DataType>> column_types{ + bigint_type, + varchar_type, + bigint_type, }; + output_block_ptr->Init(column_types); - UniquePtr<DataBlock> output_block_ptr = DataBlock::MakeUniquePtr(); - auto chuck_filling = [&](const std::function<u64(const String &)> &file_size_func, const String &path) { + auto segment_entry = table_entry->GetSegmentByID(*segment_id_, begin_ts); + if (!segment_entry) { + RecoverableError(Status::SegmentNotExist(*segment_id_)); + return; + } + auto block_entry_iter = BlockEntryIter(segment_entry.get()); + for (auto *block_entry = block_entry_iter.Next(); block_entry != nullptr; block_entry = block_entry_iter.Next()) { SizeT column_id = 0; { - Value value = Value::MakeVarchar(path); + Value value = Value::MakeBigInt(block_entry->block_id()); ValueExpression value_expr(value); value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]); } ++column_id; { - Value value = Value::MakeVarchar(Utility::FormatByteSize(file_size_func(path))); - + const auto &blk_size = Utility::FormatByteSize(LocalFileSystem::GetFolderSizeByPath(*block_entry->base_dir())); + Value value = Value::MakeVarchar(blk_size); ValueExpression value_expr(value); value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]); } - }; - Vector<SharedPtr<DataType>> column_types{ - varchar_type, - varchar_type, - }; - output_block_ptr->Init(column_types); - - if (auto segment_entry = table_entry->GetSegmentByID(*segment_id_, begin_ts); segment_entry) { - auto block_entry_iter = BlockEntryIter(segment_entry.get()); - for (auto *block_entry = block_entry_iter.Next(); block_entry != nullptr; block_entry = block_entry_iter.Next()) { - const auto& dir_path = *block_entry->base_dir(); - chuck_filling(LocalFileSystem::GetFolderSizeByPath, dir_path); + ++column_id; + { + Value value = Value::MakeBigInt(block_entry->row_count()); + ValueExpression value_expr(value); + value_expr.AppendToChunk(output_block_ptr->column_vectors[column_id]); } } diff --git a/src/main/infinity.cpp b/src/main/infinity.cpp index 4854a20841..a65eb7b377 100644 --- a/src/main/infinity.cpp +++ b/src/main/infinity.cpp @@ -422,6 +422,21 @@ QueryResult Infinity::ShowSegment(const String &db_name,const String &table_name return result; } +QueryResult Infinity::ShowSegments(const String &db_name,const String &table_name) { + UniquePtr<QueryContext> query_context_ptr = MakeUnique<QueryContext>(session_.get()); + query_context_ptr->Init(InfinityContext::instance().config(), + InfinityContext::instance().task_scheduler(), + InfinityContext::instance().storage(), + InfinityContext::instance().resource_manager(), + InfinityContext::instance().session_manager()); + UniquePtr<ShowStatement> show_statement = MakeUnique<ShowStatement>(); + show_statement->schema_name_ = db_name; + show_statement->table_name_ = table_name; + show_statement->show_type_ = ShowStmtType::kSegments; + QueryResult result = query_context_ptr->QueryStatement(show_statement.get()); + return result; +} + QueryResult Infinity::ShowBlock(const String &db_name,const String &table_name, const SegmentID &segment_id, const BlockID &block_id) { UniquePtr<QueryContext> query_context_ptr = MakeUnique<QueryContext>(session_.get()); query_context_ptr->Init(InfinityContext::instance().config(), @@ -439,6 +454,22 @@ QueryResult Infinity::ShowBlock(const String &db_name,const String &table_name, return result; } +QueryResult Infinity::ShowBlocks(const String &db_name,const String &table_name, const SegmentID &segment_id) { + UniquePtr<QueryContext> query_context_ptr = MakeUnique<QueryContext>(session_.get()); + query_context_ptr->Init(InfinityContext::instance().config(), + InfinityContext::instance().task_scheduler(), + InfinityContext::instance().storage(), + InfinityContext::instance().resource_manager(), + InfinityContext::instance().session_manager()); + UniquePtr<ShowStatement> show_statement = MakeUnique<ShowStatement>(); + show_statement->schema_name_ = db_name; + show_statement->table_name_ = table_name; + show_statement->segment_id_ = segment_id; + show_statement->show_type_ = ShowStmtType::kBlocks; + QueryResult result = query_context_ptr->QueryStatement(show_statement.get()); + return result; +} + QueryResult Infinity::Insert(const String &db_name, const String &table_name, Vector<String> *columns, Vector<Vector<ParsedExpr *> *> *values) { UniquePtr<QueryContext> query_context_ptr = MakeUnique<QueryContext>(session_.get()); query_context_ptr->Init(InfinityContext::instance().config(), diff --git a/src/main/infinity.cppm b/src/main/infinity.cppm index a0f57a4056..a24e4960ea 100644 --- a/src/main/infinity.cppm +++ b/src/main/infinity.cppm @@ -107,8 +107,12 @@ public: QueryResult ShowSegment(const String &db_name,const String &table_name, const SegmentID &segment_id); + QueryResult ShowSegments(const String &db_name,const String &table_name); + QueryResult ShowBlock(const String &db_name,const String &table_name, const SegmentID &segment_id, const BlockID &block_id); + QueryResult ShowBlocks(const String &db_name,const String &table_name, const SegmentID &segment_id); + QueryResult Insert(const String &db_name, const String &table_name, Vector<String> *columns, Vector<Vector<ParsedExpr *> *> *values); QueryResult Import(const String &db_name, const String &table_name, const String &path, ImportOptions import_options); diff --git a/src/network/http_server.cpp b/src/network/http_server.cpp index 14a4a76f00..3d7662d032 100644 --- a/src/network/http_server.cpp +++ b/src/network/http_server.cpp @@ -1389,6 +1389,98 @@ class ShowSegmentDetailHandler final : public HttpRequestHandler { } }; +class ShowSegmentsListHandler final : public HttpRequestHandler { +public: + SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + auto database_name = request->getPathVariable("database_name"); + auto table_name = request->getPathVariable("table_name"); + auto result = infinity->ShowSegments(database_name, table_name); + + HTTPStatus http_status; + nlohmann::json json_response; + + if (result.IsOk()) { + + SizeT block_rows = result.result_table_->DataBlockCount(); + auto column_cnt = result.result_table_->ColumnCount(); + 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(); + for (int row = 0; row < row_count; ++row) { + + nlohmann::json json_segment; + 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_segment[column_name] = column_value; + } + json_response["segments"].push_back(json_segment); + + } + } + json_response["table_name"] = table_name; + 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 ShowBlocksListHandler final : public HttpRequestHandler { +public: + SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final { + auto infinity = Infinity::RemoteConnect(); + DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); }); + + auto database_name = request->getPathVariable("database_name"); + auto table_name = request->getPathVariable("table_name"); + auto segment_id = std::atoi(request->getPathVariable("segment_id").get()->c_str()); + auto result = infinity->ShowBlocks(database_name, table_name, segment_id); + + HTTPStatus http_status; + nlohmann::json json_response; + + if (result.IsOk()) { + + SizeT block_rows = result.result_table_->DataBlockCount(); + auto column_cnt = result.result_table_->ColumnCount(); + 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(); + for (int row = 0; row < row_count; ++row) { + + nlohmann::json json_block; + 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_block[column_name] = column_value; + } + json_response["blocks"].push_back(json_block); + + } + } + + json_response["segment_id"] = segment_id; + 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 ShowBlockDetailHandler final : public HttpRequestHandler { public: SharedPtr<OutgoingResponse> handle(const SharedPtr<IncomingRequest> &request) final { @@ -1469,9 +1561,11 @@ void HTTPServer::Start(u16 port) { // segment router->route("GET", "/databases/{database_name}/tables/{table_name}/segments/{segment_id}", MakeShared<ShowSegmentDetailHandler>()); + router->route("GET", "/databases/{database_name}/tables/{table_name}/segments", MakeShared<ShowSegmentsListHandler>()); // block router->route("GET", "/databases/{database_name}/tables/{table_name}/segments/{segment_id}/blocks/{block_id}", MakeShared<ShowBlockDetailHandler>()); + router->route("GET", "/databases/{database_name}/tables/{table_name}/segments/{segment_id}/blocks", MakeShared<ShowBlocksListHandler>()); // variable router->route("GET", "/variables/{variable_name}", MakeShared<ShowVariableHandler>()); diff --git a/src/parser/parser.cpp b/src/parser/parser.cpp index 3fc25ab010..16deeddb81 100644 --- a/src/parser/parser.cpp +++ b/src/parser/parser.cpp @@ -4864,7 +4864,7 @@ YYLTYPE yylloc = yyloc_default; #line 1574 "parser.y" { (yyval.show_stmt) = new infinity::ShowStatement(); - (yyval.show_stmt)->show_type_ = infinity::ShowStmtType::kSegments; + (yyval.show_stmt)->show_type_ = infinity::ShowStmtType::kSegment; if((yyvsp[-2].table_name_t)->schema_name_ptr_ != nullptr) { (yyval.show_stmt)->schema_name_ = (yyvsp[-2].table_name_t)->schema_name_ptr_; free((yyvsp[-2].table_name_t)->schema_name_ptr_); @@ -4898,7 +4898,7 @@ YYLTYPE yylloc = yyloc_default; #line 1598 "parser.y" { (yyval.show_stmt) = new infinity::ShowStatement(); - (yyval.show_stmt)->show_type_ = infinity::ShowStmtType::kBlocks; + (yyval.show_stmt)->show_type_ = infinity::ShowStmtType::kBlock; if((yyvsp[-4].table_name_t)->schema_name_ptr_ != nullptr) { (yyval.show_stmt)->schema_name_ = (yyvsp[-4].table_name_t)->schema_name_ptr_; free((yyvsp[-4].table_name_t)->schema_name_ptr_); diff --git a/src/parser/parser.y b/src/parser/parser.y index 6c289f8673..56c00a196e 100644 --- a/src/parser/parser.y +++ b/src/parser/parser.y @@ -1573,7 +1573,7 @@ show_statement: SHOW DATABASES { } | SHOW TABLE table_name SEGMENT LONG_VALUE { $$ = new infinity::ShowStatement(); - $$->show_type_ = infinity::ShowStmtType::kSegments; + $$->show_type_ = infinity::ShowStmtType::kSegment; if($3->schema_name_ptr_ != nullptr) { $$->schema_name_ = $3->schema_name_ptr_; free($3->schema_name_ptr_); @@ -1597,7 +1597,7 @@ show_statement: SHOW DATABASES { } | SHOW TABLE table_name SEGMENT LONG_VALUE BLOCK LONG_VALUE { $$ = new infinity::ShowStatement(); - $$->show_type_ = infinity::ShowStmtType::kBlocks; + $$->show_type_ = infinity::ShowStmtType::kBlock; if($3->schema_name_ptr_ != nullptr) { $$->schema_name_ = $3->schema_name_ptr_; free($3->schema_name_ptr_); diff --git a/src/planner/explain_logical_plan.cpp b/src/planner/explain_logical_plan.cpp index 6a2d5205ac..465e94bd9e 100644 --- a/src/planner/explain_logical_plan.cpp +++ b/src/planner/explain_logical_plan.cpp @@ -1436,7 +1436,7 @@ void ExplainLogicalPlan::Explain(const LogicalShow *show_node, SharedPtr<Vector< } String output_columns_str = String(intent_size, ' '); - output_columns_str += " - output columns: [path, size]"; + output_columns_str += " - output columns: [id, status, size]"; result->emplace_back(MakeShared<String>(output_columns_str)); break; } @@ -1482,7 +1482,7 @@ void ExplainLogicalPlan::Explain(const LogicalShow *show_node, SharedPtr<Vector< } String output_columns_str = String(intent_size, ' '); - output_columns_str += " - output columns: [path, size]"; + output_columns_str += " - output columns: [id, size, row_count]"; result->emplace_back(MakeShared<String>(output_columns_str)); break; } diff --git a/src/planner/logical_planner.cpp b/src/planner/logical_planner.cpp index aec973d7cf..c0d89811e4 100644 --- a/src/planner/logical_planner.cpp +++ b/src/planner/logical_planner.cpp @@ -1016,9 +1016,7 @@ Status LogicalPlanner::BuildShowSegments(const ShowStatement *statement, SharedP ShowType::kShowSegments, query_context_ptr_->schema_name(), statement->table_name_, - bind_context_ptr->GenerateTableIndex(), - statement->segment_id_, - statement->block_id_); + bind_context_ptr->GenerateTableIndex()); this->logical_plan_ = logical_show; return Status::OK(); diff --git a/src/unit_test/parser/sql_statement.cpp b/src/unit_test/parser/sql_statement.cpp index 3138ef335a..675de761fe 100644 --- a/src/unit_test/parser/sql_statement.cpp +++ b/src/unit_test/parser/sql_statement.cpp @@ -263,7 +263,7 @@ TEST_F(StatementParsingTest, good_test1) { BaseStatement *statement = (*result->statements_ptr_)[0]; EXPECT_EQ(statement->type_, StatementType::kShow); auto *show_statement = (ShowStatement *)(statement); - EXPECT_EQ(show_statement->show_type_, ShowStmtType::kSegments); + EXPECT_EQ(show_statement->show_type_, ShowStmtType::kSegment); EXPECT_EQ(show_statement->table_name_, "t1"); EXPECT_EQ(show_statement->schema_name_, ""); EXPECT_EQ(show_statement->index_name_.has_value(), false); @@ -301,7 +301,7 @@ TEST_F(StatementParsingTest, good_test1) { BaseStatement *statement = (*result->statements_ptr_)[0]; EXPECT_EQ(statement->type_, StatementType::kShow); auto *show_statement = (ShowStatement *)(statement); - EXPECT_EQ(show_statement->show_type_, ShowStmtType::kBlocks); + EXPECT_EQ(show_statement->show_type_, ShowStmtType::kBlock); EXPECT_EQ(show_statement->table_name_, "t1"); EXPECT_EQ(show_statement->schema_name_, ""); EXPECT_EQ(show_statement->index_name_.has_value(), false);