From 293d1e8ed448c6009f78199577a71f6daf536317 Mon Sep 17 00:00:00 2001 From: Daniil Demin Date: Wed, 12 Feb 2025 12:32:47 +0000 Subject: [PATCH 1/4] describe actors for external data sources and tables --- .../rpc_describe_external_data_source.cpp | 89 +++++++++++++++++++ .../rpc_describe_external_table.cpp | 87 ++++++++++++++++++ ydb/core/grpc_services/service_table.h | 2 + ydb/core/grpc_services/ya.make | 2 + .../jaeger_tracing/request_discriminator.cpp | 2 + .../jaeger_tracing/request_discriminator.h | 2 + ydb/services/ydb/ydb_table.cpp | 2 + 7 files changed, 186 insertions(+) create mode 100644 ydb/core/grpc_services/rpc_describe_external_data_source.cpp create mode 100644 ydb/core/grpc_services/rpc_describe_external_table.cpp diff --git a/ydb/core/grpc_services/rpc_describe_external_data_source.cpp b/ydb/core/grpc_services/rpc_describe_external_data_source.cpp new file mode 100644 index 000000000000..e8adcfe0b32f --- /dev/null +++ b/ydb/core/grpc_services/rpc_describe_external_data_source.cpp @@ -0,0 +1,89 @@ +#include "rpc_scheme_base.h" +#include "service_table.h" + +#include +#include +#include + +namespace NKikimr::NGRpcService { + +using namespace NActors; + +using TEvDescribeExternalDataSourceRequest = TGrpcRequestOperationCall< + Ydb::Table::DescribeExternalDataSourceRequest, + Ydb::Table::DescribeExternalDataSourceResponse +>; + +class TDescribeExternalDataSourceRPC : public TRpcSchemeRequestActor { + using TBase = TRpcSchemeRequestActor; + +public: + TDescribeExternalDataSourceRPC(IRequestOpCtx* msg) + : TBase(msg) + {} + + void Bootstrap(const TActorContext &ctx) { + TBase::Bootstrap(ctx); + + const auto* request = GetProtoRequest(); + const auto& path = request->path(); + const auto paths = NKikimr::SplitPath(path); + if (paths.empty()) { + Request_->RaiseIssue(NYql::TIssue("Invalid path")); + return Reply(Ydb::StatusIds::BAD_REQUEST, ctx); + } + + auto navigate = MakeHolder(); + navigate->DatabaseName = CanonizePath(Request_->GetDatabaseName().GetOrElse("")); + auto& entry = navigate->ResultSet.emplace_back(); + entry.Path = std::move(paths); + entry.Operation = NSchemeCache::TSchemeCacheNavigate::OpTable; + entry.SyncVersion = true; + + Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvNavigateKeySet(navigate)); + Become(&TDescribeExternalDataSourceRPC::StateWork); + } + +private: + void StateWork(TAutoPtr& ev) { + switch (ev->GetTypeRewrite()) { + HFunc(TEvTxProxySchemeCache::TEvNavigateKeySetResult, Handle); + default: TBase::StateWork(ev); + } + } + + void Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev, const TActorContext& ctx) { + const auto* navigate = ev->Get()->Request.Get(); + + if (navigate->ResultSet.size() != 1) { + return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); + } + const auto& entry = navigate->ResultSet.front(); + + if (navigate->ErrorCount > 0) { + switch (entry.Status) { + case NSchemeCache::TSchemeCacheNavigate::EStatus::PathErrorUnknown: + case NSchemeCache::TSchemeCacheNavigate::EStatus::RootUnknown: + return Reply(Ydb::StatusIds::SCHEME_ERROR, ctx); + default: + return Reply(Ydb::StatusIds::UNAVAILABLE, ctx); + } + } + if (entry.Status != NSchemeCache::TSchemeCacheNavigate::EStatus::Ok) { + // an invariant is broken: error count is equal to zero, but the status is not ok + return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); + } + + // to do: fill the entire description from the received navigation entry + Ydb::Table::DescribeExternalDataSourceResult description; + const auto& properties = entry.ExternalDataSourceInfo->Description.GetProperties().GetProperties(); + description.mutable_properties()->insert(properties.begin(), properties.end()); + return ReplyWithResult(Ydb::StatusIds::SUCCESS, description, ctx); + } +}; + +void DoDescribeExternalDataSourceRequest(std::unique_ptr p, const IFacilityProvider& f) { + f.RegisterActor(new TDescribeExternalDataSourceRPC(p.release())); +} + +} diff --git a/ydb/core/grpc_services/rpc_describe_external_table.cpp b/ydb/core/grpc_services/rpc_describe_external_table.cpp new file mode 100644 index 000000000000..a7cfdb3b4bd8 --- /dev/null +++ b/ydb/core/grpc_services/rpc_describe_external_table.cpp @@ -0,0 +1,87 @@ +#include "rpc_scheme_base.h" +#include "service_table.h" + +#include +#include +#include + +namespace NKikimr::NGRpcService { + +using namespace NActors; + +using TEvDescribeExternalTableRequest = TGrpcRequestOperationCall< + Ydb::Table::DescribeExternalTableRequest, + Ydb::Table::DescribeExternalTableResponse +>; + +class TDescribeExternalTableRPC : public TRpcSchemeRequestActor { + using TBase = TRpcSchemeRequestActor; + +public: + TDescribeExternalTableRPC(IRequestOpCtx* msg) + : TBase(msg) + {} + + void Bootstrap(const TActorContext &ctx) { + TBase::Bootstrap(ctx); + + const auto* request = GetProtoRequest(); + const auto& path = request->path(); + const auto paths = NKikimr::SplitPath(path); + if (paths.empty()) { + Request_->RaiseIssue(NYql::TIssue("Invalid path")); + return Reply(Ydb::StatusIds::BAD_REQUEST, ctx); + } + + auto navigate = MakeHolder(); + navigate->DatabaseName = CanonizePath(Request_->GetDatabaseName().GetOrElse("")); + auto& entry = navigate->ResultSet.emplace_back(); + entry.Path = std::move(paths); + entry.Operation = NSchemeCache::TSchemeCacheNavigate::OpTable; + entry.SyncVersion = true; + + Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvNavigateKeySet(navigate)); + Become(&TDescribeExternalTableRPC::StateWork); + } + +private: + void StateWork(TAutoPtr& ev) { + switch (ev->GetTypeRewrite()) { + HFunc(TEvTxProxySchemeCache::TEvNavigateKeySetResult, Handle); + default: TBase::StateWork(ev); + } + } + + void Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev, const TActorContext& ctx) { + const auto* navigate = ev->Get()->Request.Get(); + + if (navigate->ResultSet.size() != 1) { + return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); + } + const auto& entry = navigate->ResultSet.front(); + + if (navigate->ErrorCount > 0) { + switch (entry.Status) { + case NSchemeCache::TSchemeCacheNavigate::EStatus::PathErrorUnknown: + case NSchemeCache::TSchemeCacheNavigate::EStatus::RootUnknown: + return Reply(Ydb::StatusIds::SCHEME_ERROR, ctx); + default: + return Reply(Ydb::StatusIds::UNAVAILABLE, ctx); + } + } + if (entry.Status != NSchemeCache::TSchemeCacheNavigate::EStatus::Ok) { + // an invariant is broken: error count is equal to zero, but the status is not ok + return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); + } + + // to do: fill the description from the received navigation entry + Ydb::Table::DescribeExternalTableResult description; + return ReplyWithResult(Ydb::StatusIds::SUCCESS, description, ctx); + } +}; + +void DoDescribeExternalTableRequest(std::unique_ptr p, const IFacilityProvider& f) { + f.RegisterActor(new TDescribeExternalTableRPC(p.release())); +} + +} diff --git a/ydb/core/grpc_services/service_table.h b/ydb/core/grpc_services/service_table.h index 23053b1b0193..e2cc73e1bcb8 100644 --- a/ydb/core/grpc_services/service_table.h +++ b/ydb/core/grpc_services/service_table.h @@ -16,6 +16,8 @@ void DoCopyTableRequest(std::unique_ptr p, const IFacilityProvide void DoCopyTablesRequest(std::unique_ptr p, const IFacilityProvider& f); void DoRenameTablesRequest(std::unique_ptr p, const IFacilityProvider& f); void DoDescribeTableRequest(std::unique_ptr p, const IFacilityProvider& f); +void DoDescribeExternalDataSourceRequest(std::unique_ptr p, const IFacilityProvider& f); +void DoDescribeExternalTableRequest(std::unique_ptr p, const IFacilityProvider& f); void DoCreateSessionRequest(std::unique_ptr p, const IFacilityProvider& f); void DoDeleteSessionRequest(std::unique_ptr p, const IFacilityProvider& f); void DoKeepAliveRequest(std::unique_ptr p, const IFacilityProvider& f); diff --git a/ydb/core/grpc_services/ya.make b/ydb/core/grpc_services/ya.make index bd7d0a737703..be849cc6046b 100644 --- a/ydb/core/grpc_services/ya.make +++ b/ydb/core/grpc_services/ya.make @@ -37,6 +37,8 @@ SRCS( rpc_describe_path.cpp rpc_describe_table.cpp rpc_describe_table_options.cpp + rpc_describe_external_data_source.cpp + rpc_describe_external_table.cpp rpc_drop_coordination_node.cpp rpc_drop_table.cpp rpc_discovery.cpp diff --git a/ydb/core/jaeger_tracing/request_discriminator.cpp b/ydb/core/jaeger_tracing/request_discriminator.cpp index f2298a778178..73f46bec1321 100644 --- a/ydb/core/jaeger_tracing/request_discriminator.cpp +++ b/ydb/core/jaeger_tracing/request_discriminator.cpp @@ -42,6 +42,8 @@ extern const THashMap NameToRequestType = { {"Table.StreamExecuteScanQuery", ERequestType::TABLE_STREAMEXECUTESCANQUERY}, {"Table.StreamReadTable", ERequestType::TABLE_STREAMREADTABLE}, {"Table.ReadRows", ERequestType::TABLE_READROWS}, + {"Table.DescribeExternalDataSource", ERequestType::TABLE_DESCRIBEEXTERNALDATASOURCE}, + {"Table.DescribeExternalTable", ERequestType::TABLE_DESCRIBEEXTERNALTABLE}, {"Query.ExecuteQuery", ERequestType::QUERY_EXECUTEQUERY}, {"Query.ExecuteScript", ERequestType::QUERY_EXECUTESCRIPT}, diff --git a/ydb/core/jaeger_tracing/request_discriminator.h b/ydb/core/jaeger_tracing/request_discriminator.h index fac53d9ea391..c02f08281cc4 100644 --- a/ydb/core/jaeger_tracing/request_discriminator.h +++ b/ydb/core/jaeger_tracing/request_discriminator.h @@ -47,6 +47,8 @@ enum class ERequestType: size_t { TABLE_STREAMEXECUTESCANQUERY, TABLE_STREAMREADTABLE, TABLE_READROWS, + TABLE_DESCRIBEEXTERNALDATASOURCE, + TABLE_DESCRIBEEXTERNALTABLE, QUERY_EXECUTEQUERY, QUERY_EXECUTESCRIPT, diff --git a/ydb/services/ydb/ydb_table.cpp b/ydb/services/ydb/ydb_table.cpp index 37067b16e358..0acf4dc966cf 100644 --- a/ydb/services/ydb/ydb_table.cpp +++ b/ydb/services/ydb/ydb_table.cpp @@ -85,6 +85,8 @@ void TGRpcYdbTableService::SetupIncomingRequests(NYdbGrpc::TLoggerPtr logger) { ADD_REQUEST_LIMIT(CreateTable, DoCreateTableRequest, Rps, CREATETABLE) ADD_REQUEST_LIMIT(DropTable, DoDropTableRequest, Rps, DROPTABLE) ADD_REQUEST_LIMIT(DescribeTable, DoDescribeTableRequest, Rps, DESCRIBETABLE) + ADD_REQUEST_LIMIT(DescribeExternalDataSource, DoDescribeExternalDataSourceRequest, Rps, DESCRIBEEXTERNALDATASOURCE) + ADD_REQUEST_LIMIT(DescribeExternalTable, DoDescribeExternalTableRequest, Rps, DESCRIBEEXTERNALTABLE) ADD_REQUEST_LIMIT(CopyTable, DoCopyTableRequest, Rps, COPYTABLE) ADD_REQUEST_LIMIT(CopyTables, DoCopyTablesRequest, Rps, COPYTABLES) ADD_REQUEST_LIMIT(RenameTables, DoRenameTablesRequest, Rps, RENAMETABLES) From 9807afd8ea8d1e97a0ab9fc415b9f5efbee4b351 Mon Sep 17 00:00:00 2001 From: Daniil Demin Date: Wed, 12 Feb 2025 13:14:06 +0000 Subject: [PATCH 2/4] ydb scheme describe for external data sources / external tables --- .../ydb_cli/commands/ydb_service_scheme.cpp | 34 +++++++++++++++++++ .../lib/ydb_cli/commands/ydb_service_scheme.h | 6 ++++ .../ydb-cpp-sdk/client/proto/accessor.h | 2 ++ .../cpp/src/client/table/proto_accessor.cpp | 8 +++++ 4 files changed, 50 insertions(+) diff --git a/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp b/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp index ffe64c89d893..a385eb38367e 100644 --- a/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp +++ b/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp @@ -283,6 +283,10 @@ int TCommandDescribe::PrintPathResponse(TDriver& driver, const NScheme::TDescrib return DescribeReplication(driver); case NScheme::ESchemeEntryType::View: return DescribeView(driver); + case NScheme::ESchemeEntryType::ExternalDataSource: + return DescribeExternalDataSource(driver); + case NScheme::ESchemeEntryType::ExternalTable: + return DescribeExternalTable(driver); default: return DescribeEntryDefault(entry); } @@ -615,6 +619,36 @@ int TCommandDescribe::DescribeView(const TDriver& driver) { return PrintDescription(this, OutputFormat, result, &TCommandDescribe::PrintViewResponsePretty); } +int TCommandDescribe::PrintExternalDataSourceResponsePretty(const NYdb::NTable::TExternalDataSourceDescription& description) const { + Cout << "\nProperties:\n" << "to be done..." << Endl; + return EXIT_SUCCESS; +} + +int TCommandDescribe::DescribeExternalDataSource(const TDriver& driver) { + NTable::TTableClient client(driver); + const auto sessionResult = client.CreateSession().ExtractValueSync(); + NStatusHelpers::ThrowOnErrorOrPrintIssues(sessionResult); + const auto description = sessionResult.GetSession().DescribeExternalDataSource(Path).ExtractValueSync(); + NStatusHelpers::ThrowOnErrorOrPrintIssues(description); + + return PrintDescription(this, OutputFormat, description.GetExternalDataSourceDescription(), &TCommandDescribe::PrintExternalDataSourceResponsePretty); +} + +int TCommandDescribe::PrintExternalTableResponsePretty(const NYdb::NTable::TExternalTableDescription& description) const { + Cout << "\nProperties:\n" << "to be done..." << Endl; + return EXIT_SUCCESS; +} + +int TCommandDescribe::DescribeExternalTable(const TDriver& driver) { + NTable::TTableClient client(driver); + const auto sessionResult = client.CreateSession().ExtractValueSync(); + NStatusHelpers::ThrowOnErrorOrPrintIssues(sessionResult); + const auto result = sessionResult.GetSession().DescribeExternalTable(Path).ExtractValueSync(); + NStatusHelpers::ThrowOnErrorOrPrintIssues(result); + + return PrintDescription(this, OutputFormat, result.GetExternalTableDescription(), &TCommandDescribe::PrintExternalTableResponsePretty); +} + namespace { void PrintColumns(const NTable::TTableDescription& tableDescription) { if (!tableDescription.GetTableColumns().size()) { diff --git a/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.h b/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.h index cfd2b9df2065..26bd5e62f6f2 100644 --- a/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.h +++ b/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.h @@ -105,6 +105,12 @@ class TCommandDescribe : public TYdbOperationCommand, public TCommandWithPath, p int DescribeView(const TDriver& driver); int PrintViewResponsePretty(const NYdb::NView::TDescribeViewResult& result) const; + int DescribeExternalDataSource(const TDriver& driver); + int PrintExternalDataSourceResponsePretty(const NYdb::NTable::TExternalDataSourceDescription& result) const; + + int DescribeExternalTable(const TDriver& driver); + int PrintExternalTableResponsePretty(const NYdb::NTable::TExternalTableDescription& result) const; + int TryTopicConsumerDescribeOrFail(NYdb::TDriver& driver, const NScheme::TDescribePathResult& result); std::pair ParseTopicConsumer() const; int PrintConsumerResponsePretty(const NYdb::NTopic::TConsumerDescription& description) const; diff --git a/ydb/public/sdk/cpp/include/ydb-cpp-sdk/client/proto/accessor.h b/ydb/public/sdk/cpp/include/ydb-cpp-sdk/client/proto/accessor.h index 7d928dedc280..e786e81f904e 100644 --- a/ydb/public/sdk/cpp/include/ydb-cpp-sdk/client/proto/accessor.h +++ b/ydb/public/sdk/cpp/include/ydb-cpp-sdk/client/proto/accessor.h @@ -43,6 +43,8 @@ class TProtoAccessor { static ::google::protobuf::Map* GetProtoMapPtr(TParams& params); static const Ydb::TableStats::QueryStats& GetProto(const NTable::TQueryStats& queryStats); static const Ydb::Table::DescribeTableResult& GetProto(const NTable::TTableDescription& tableDescription); + static const Ydb::Table::DescribeExternalDataSourceResult& GetProto(const NTable::TExternalDataSourceDescription&); + static const Ydb::Table::DescribeExternalTableResult& GetProto(const NTable::TExternalTableDescription&); static const Ydb::Topic::DescribeTopicResult& GetProto(const NYdb::NTopic::TTopicDescription& topicDescription); static const Ydb::Topic::DescribeConsumerResult& GetProto(const NYdb::NTopic::TConsumerDescription& consumerDescription); static const Ydb::Monitoring::SelfCheckResult& GetProto(const NYdb::NMonitoring::TSelfCheckResult& selfCheckResult); diff --git a/ydb/public/sdk/cpp/src/client/table/proto_accessor.cpp b/ydb/public/sdk/cpp/src/client/table/proto_accessor.cpp index 98224b2578d7..131c50943fd6 100644 --- a/ydb/public/sdk/cpp/src/client/table/proto_accessor.cpp +++ b/ydb/public/sdk/cpp/src/client/table/proto_accessor.cpp @@ -12,6 +12,14 @@ const Ydb::Table::DescribeTableResult& TProtoAccessor::GetProto(const NTable::TT return tableDescription.GetProto(); } +const Ydb::Table::DescribeExternalDataSourceResult& TProtoAccessor::GetProto(const NTable::TExternalDataSourceDescription& description) { + return description.GetProto(); +} + +const Ydb::Table::DescribeExternalTableResult& TProtoAccessor::GetProto(const NTable::TExternalTableDescription& description) { + return description.GetProto(); +} + NTable::TQueryStats TProtoAccessor::FromProto(const Ydb::TableStats::QueryStats& queryStats) { return NTable::TQueryStats(queryStats); } From 2a419a889967a9e8d8b9e2e8a5c6b49534e47d6e Mon Sep 17 00:00:00 2001 From: Daniil Demin Date: Thu, 13 Feb 2025 13:53:14 +0000 Subject: [PATCH 3/4] review fixes: no pretty format for the externals --- ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp b/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp index a385eb38367e..eff8b0528bdd 100644 --- a/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp +++ b/ydb/public/lib/ydb_cli/commands/ydb_service_scheme.cpp @@ -620,7 +620,7 @@ int TCommandDescribe::DescribeView(const TDriver& driver) { } int TCommandDescribe::PrintExternalDataSourceResponsePretty(const NYdb::NTable::TExternalDataSourceDescription& description) const { - Cout << "\nProperties:\n" << "to be done..." << Endl; + // to do return EXIT_SUCCESS; } @@ -635,7 +635,7 @@ int TCommandDescribe::DescribeExternalDataSource(const TDriver& driver) { } int TCommandDescribe::PrintExternalTableResponsePretty(const NYdb::NTable::TExternalTableDescription& description) const { - Cout << "\nProperties:\n" << "to be done..." << Endl; + // to do return EXIT_SUCCESS; } From b872b0cd752c03e1530a336e606048f9331bee67 Mon Sep 17 00:00:00 2001 From: Daniil Demin Date: Thu, 13 Feb 2025 15:13:12 +0000 Subject: [PATCH 4/4] review fix: send describe request straight to the SchemeShard --- .../rpc_describe_external_data_source.cpp | 96 ++++++++++--------- .../rpc_describe_external_table.cpp | 94 +++++++++--------- 2 files changed, 98 insertions(+), 92 deletions(-) diff --git a/ydb/core/grpc_services/rpc_describe_external_data_source.cpp b/ydb/core/grpc_services/rpc_describe_external_data_source.cpp index e8adcfe0b32f..caa5814f49cd 100644 --- a/ydb/core/grpc_services/rpc_describe_external_data_source.cpp +++ b/ydb/core/grpc_services/rpc_describe_external_data_source.cpp @@ -1,13 +1,13 @@ #include "rpc_scheme_base.h" #include "service_table.h" -#include #include #include namespace NKikimr::NGRpcService { using namespace NActors; +using namespace NYql; using TEvDescribeExternalDataSourceRequest = TGrpcRequestOperationCall< Ydb::Table::DescribeExternalDataSourceRequest, @@ -18,67 +18,69 @@ class TDescribeExternalDataSourceRPC : public TRpcSchemeRequestActor; public: - TDescribeExternalDataSourceRPC(IRequestOpCtx* msg) - : TBase(msg) - {} - - void Bootstrap(const TActorContext &ctx) { - TBase::Bootstrap(ctx); - - const auto* request = GetProtoRequest(); - const auto& path = request->path(); - const auto paths = NKikimr::SplitPath(path); - if (paths.empty()) { - Request_->RaiseIssue(NYql::TIssue("Invalid path")); - return Reply(Ydb::StatusIds::BAD_REQUEST, ctx); - } - auto navigate = MakeHolder(); - navigate->DatabaseName = CanonizePath(Request_->GetDatabaseName().GetOrElse("")); - auto& entry = navigate->ResultSet.emplace_back(); - entry.Path = std::move(paths); - entry.Operation = NSchemeCache::TSchemeCacheNavigate::OpTable; - entry.SyncVersion = true; + using TBase::TBase; - Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvNavigateKeySet(navigate)); - Become(&TDescribeExternalDataSourceRPC::StateWork); + void Bootstrap() { + DescribeScheme(); } private: - void StateWork(TAutoPtr& ev) { + + void DescribeScheme() { + auto ev = std::make_unique(); + SetAuthToken(ev, *Request_); + SetDatabase(ev.get(), *Request_); + ev->Record.MutableDescribePath()->SetPath(GetProtoRequest()->path()); + + Send(MakeTxProxyID(), ev.release()); + Become(&TDescribeExternalDataSourceRPC::StateDescribeScheme); + } + + STATEFN(StateDescribeScheme) { switch (ev->GetTypeRewrite()) { - HFunc(TEvTxProxySchemeCache::TEvNavigateKeySetResult, Handle); - default: TBase::StateWork(ev); + HFunc(NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult, Handle); + default: + return TBase::StateWork(ev); } } - void Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev, const TActorContext& ctx) { - const auto* navigate = ev->Get()->Request.Get(); + void Handle(NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult::TPtr& ev, const TActorContext& ctx) { + const auto& record = ev->Get()->GetRecord(); + const auto& pathDescription = record.GetPathDescription(); - if (navigate->ResultSet.size() != 1) { - return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); + if (record.HasReason()) { + Request_->RaiseIssue(TIssue(record.GetReason())); } - const auto& entry = navigate->ResultSet.front(); - if (navigate->ErrorCount > 0) { - switch (entry.Status) { - case NSchemeCache::TSchemeCacheNavigate::EStatus::PathErrorUnknown: - case NSchemeCache::TSchemeCacheNavigate::EStatus::RootUnknown: + switch (record.GetStatus()) { + case NKikimrScheme::StatusSuccess: { + if (pathDescription.GetSelf().GetPathType() != NKikimrSchemeOp::EPathTypeExternalDataSource) { + Request_->RaiseIssue(TIssue( + TStringBuilder() << "Unexpected path type: " << pathDescription.GetSelf().GetPathType() + )); + return Reply(Ydb::StatusIds::SCHEME_ERROR, ctx); + } + + return ReplyWithResult( + Ydb::StatusIds::SUCCESS, + Ydb::Table::DescribeExternalDataSourceResult(), // to do: convert private protobuf to public + ctx + ); + } + case NKikimrScheme::StatusPathDoesNotExist: + case NKikimrScheme::StatusSchemeError: return Reply(Ydb::StatusIds::SCHEME_ERROR, ctx); - default: + + case NKikimrScheme::StatusAccessDenied: + return Reply(Ydb::StatusIds::UNAUTHORIZED, ctx); + + case NKikimrScheme::StatusNotAvailable: return Reply(Ydb::StatusIds::UNAVAILABLE, ctx); - } - } - if (entry.Status != NSchemeCache::TSchemeCacheNavigate::EStatus::Ok) { - // an invariant is broken: error count is equal to zero, but the status is not ok - return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); - } - // to do: fill the entire description from the received navigation entry - Ydb::Table::DescribeExternalDataSourceResult description; - const auto& properties = entry.ExternalDataSourceInfo->Description.GetProperties().GetProperties(); - description.mutable_properties()->insert(properties.begin(), properties.end()); - return ReplyWithResult(Ydb::StatusIds::SUCCESS, description, ctx); + default: + return Reply(Ydb::StatusIds::GENERIC_ERROR, ctx); + } } }; diff --git a/ydb/core/grpc_services/rpc_describe_external_table.cpp b/ydb/core/grpc_services/rpc_describe_external_table.cpp index a7cfdb3b4bd8..68c26bad01a3 100644 --- a/ydb/core/grpc_services/rpc_describe_external_table.cpp +++ b/ydb/core/grpc_services/rpc_describe_external_table.cpp @@ -1,13 +1,13 @@ #include "rpc_scheme_base.h" #include "service_table.h" -#include #include #include namespace NKikimr::NGRpcService { using namespace NActors; +using namespace NYql; using TEvDescribeExternalTableRequest = TGrpcRequestOperationCall< Ydb::Table::DescribeExternalTableRequest, @@ -18,65 +18,69 @@ class TDescribeExternalTableRPC : public TRpcSchemeRequestActor; public: - TDescribeExternalTableRPC(IRequestOpCtx* msg) - : TBase(msg) - {} - - void Bootstrap(const TActorContext &ctx) { - TBase::Bootstrap(ctx); - - const auto* request = GetProtoRequest(); - const auto& path = request->path(); - const auto paths = NKikimr::SplitPath(path); - if (paths.empty()) { - Request_->RaiseIssue(NYql::TIssue("Invalid path")); - return Reply(Ydb::StatusIds::BAD_REQUEST, ctx); - } - auto navigate = MakeHolder(); - navigate->DatabaseName = CanonizePath(Request_->GetDatabaseName().GetOrElse("")); - auto& entry = navigate->ResultSet.emplace_back(); - entry.Path = std::move(paths); - entry.Operation = NSchemeCache::TSchemeCacheNavigate::OpTable; - entry.SyncVersion = true; + using TBase::TBase; - Send(MakeSchemeCacheID(), new TEvTxProxySchemeCache::TEvNavigateKeySet(navigate)); - Become(&TDescribeExternalTableRPC::StateWork); + void Bootstrap() { + DescribeScheme(); } private: - void StateWork(TAutoPtr& ev) { + + void DescribeScheme() { + auto ev = std::make_unique(); + SetAuthToken(ev, *Request_); + SetDatabase(ev.get(), *Request_); + ev->Record.MutableDescribePath()->SetPath(GetProtoRequest()->path()); + + Send(MakeTxProxyID(), ev.release()); + Become(&TDescribeExternalTableRPC::StateDescribeScheme); + } + + STATEFN(StateDescribeScheme) { switch (ev->GetTypeRewrite()) { - HFunc(TEvTxProxySchemeCache::TEvNavigateKeySetResult, Handle); - default: TBase::StateWork(ev); + HFunc(NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult, Handle); + default: + return TBase::StateWork(ev); } } - void Handle(TEvTxProxySchemeCache::TEvNavigateKeySetResult::TPtr& ev, const TActorContext& ctx) { - const auto* navigate = ev->Get()->Request.Get(); + void Handle(NSchemeShard::TEvSchemeShard::TEvDescribeSchemeResult::TPtr& ev, const TActorContext& ctx) { + const auto& record = ev->Get()->GetRecord(); + const auto& pathDescription = record.GetPathDescription(); - if (navigate->ResultSet.size() != 1) { - return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); + if (record.HasReason()) { + Request_->RaiseIssue(TIssue(record.GetReason())); } - const auto& entry = navigate->ResultSet.front(); - if (navigate->ErrorCount > 0) { - switch (entry.Status) { - case NSchemeCache::TSchemeCacheNavigate::EStatus::PathErrorUnknown: - case NSchemeCache::TSchemeCacheNavigate::EStatus::RootUnknown: + switch (record.GetStatus()) { + case NKikimrScheme::StatusSuccess: { + if (pathDescription.GetSelf().GetPathType() != NKikimrSchemeOp::EPathTypeExternalTable) { + Request_->RaiseIssue(TIssue( + TStringBuilder() << "Unexpected path type: " << pathDescription.GetSelf().GetPathType() + )); + return Reply(Ydb::StatusIds::SCHEME_ERROR, ctx); + } + + return ReplyWithResult( + Ydb::StatusIds::SUCCESS, + Ydb::Table::DescribeExternalTableResult(), // to do: convert private proto to public + ctx + ); + } + case NKikimrScheme::StatusPathDoesNotExist: + case NKikimrScheme::StatusSchemeError: return Reply(Ydb::StatusIds::SCHEME_ERROR, ctx); - default: + + case NKikimrScheme::StatusAccessDenied: + return Reply(Ydb::StatusIds::UNAUTHORIZED, ctx); + + case NKikimrScheme::StatusNotAvailable: return Reply(Ydb::StatusIds::UNAVAILABLE, ctx); - } - } - if (entry.Status != NSchemeCache::TSchemeCacheNavigate::EStatus::Ok) { - // an invariant is broken: error count is equal to zero, but the status is not ok - return Reply(Ydb::StatusIds::INTERNAL_ERROR, ctx); - } - // to do: fill the description from the received navigation entry - Ydb::Table::DescribeExternalTableResult description; - return ReplyWithResult(Ydb::StatusIds::SUCCESS, description, ctx); + default: + return Reply(Ydb::StatusIds::GENERIC_ERROR, ctx); + } } };