diff options
author | makostrov <makostrov@yandex-team.com> | 2023-10-22 14:14:32 +0300 |
---|---|---|
committer | makostrov <makostrov@yandex-team.com> | 2023-10-22 14:34:29 +0300 |
commit | 12d1c39c9c20ca46bd4a788422bb653ebdfdef58 (patch) | |
tree | 3dbc85d6aac84b2fddb63f7bea5a2e9d2b2aa02f | |
parent | 24a44df2ab01109cefd64d4bfad05c66e7ebd2af (diff) | |
download | ydb-12d1c39c9c20ca46bd4a788422bb653ebdfdef58.tar.gz |
Вернуть в explain запроса ReplayMessage дополнительную диагностику со схемой
KIKIMR-19690
Стоит не забыть про название флага в API CollectFullDiagnostics
И отправлять данные не в бинарном ReplayMessage, а в каком-то читаемом для пользователя формате
-rw-r--r-- | ydb/core/grpc_services/rpc_explain_data_query.cpp | 2 | ||||
-rw-r--r-- | ydb/core/kqp/common/compilation/events.h | 8 | ||||
-rw-r--r-- | ydb/core/kqp/common/events/query.h | 4 | ||||
-rw-r--r-- | ydb/core/kqp/compile_service/kqp_compile_service.cpp | 12 | ||||
-rw-r--r-- | ydb/core/kqp/session_actor/kqp_query_state.cpp | 5 | ||||
-rw-r--r-- | ydb/core/kqp/session_actor/kqp_query_state.h | 6 | ||||
-rw-r--r-- | ydb/core/kqp/session_actor/kqp_session_actor.cpp | 46 | ||||
-rw-r--r-- | ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp | 62 | ||||
-rw-r--r-- | ydb/core/protos/kqp.proto | 2 | ||||
-rw-r--r-- | ydb/core/protos/kqp_physical.proto | 1 | ||||
-rw-r--r-- | ydb/public/api/protos/ydb_table.proto | 2 | ||||
-rw-r--r-- | ydb/public/lib/ydb_cli/commands/ydb_service_table.cpp | 15 | ||||
-rw-r--r-- | ydb/public/lib/ydb_cli/commands/ydb_service_table.h | 1 | ||||
-rw-r--r-- | ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp | 5 | ||||
-rw-r--r-- | ydb/public/sdk/cpp/client/ydb_table/table.cpp | 8 | ||||
-rw-r--r-- | ydb/public/sdk/cpp/client/ydb_table/table.h | 8 |
16 files changed, 147 insertions, 40 deletions
diff --git a/ydb/core/grpc_services/rpc_explain_data_query.cpp b/ydb/core/grpc_services/rpc_explain_data_query.cpp index 1b25b9e1c16..129ac5468bb 100644 --- a/ydb/core/grpc_services/rpc_explain_data_query.cpp +++ b/ydb/core/grpc_services/rpc_explain_data_query.cpp @@ -68,6 +68,7 @@ public: ev->Record.MutableRequest()->SetAction(NKikimrKqp::QUERY_ACTION_EXPLAIN); ev->Record.MutableRequest()->SetType(NKikimrKqp::QUERY_TYPE_SQL_DML); ev->Record.MutableRequest()->SetQuery(req->yql_text()); + ev->Record.MutableRequest()->SetCollectDiagnostics(req->Getcollect_full_diagnostics()); ctx.Send(NKqp::MakeKqpProxyID(ctx.SelfID.NodeId()), ev.Release()); } @@ -83,6 +84,7 @@ public: Ydb::Table::ExplainQueryResult queryResult; queryResult.set_query_ast(kqpResponse.GetQueryAst()); queryResult.set_query_plan(kqpResponse.GetQueryPlan()); + queryResult.set_query_full_diagnostics(kqpResponse.GetQueryDiagnostics()); ReplyWithResult(Ydb::StatusIds::SUCCESS, issueMessage, queryResult, ctx); } else { diff --git a/ydb/core/kqp/common/compilation/events.h b/ydb/core/kqp/common/compilation/events.h index f06eb09e4fe..68a25564137 100644 --- a/ydb/core/kqp/common/compilation/events.h +++ b/ydb/core/kqp/common/compilation/events.h @@ -16,7 +16,7 @@ struct TEvCompileRequest: public TEventLocal<TEvCompileRequest, TKqpEvents::EvCo TMaybe<TKqpQueryId>&& query, bool keepInCache, TInstant deadline, TKqpDbCountersPtr dbCounters, std::shared_ptr<std::atomic<bool>> intrestedInResult, const TIntrusivePtr<TUserRequestContext>& userRequestContext, NLWTrace::TOrbit orbit = {}, - TKqpTempTablesState::TConstPtr tempTablesState = nullptr) + TKqpTempTablesState::TConstPtr tempTablesState = nullptr, bool collectDiagnostics = false) : UserToken(userToken) , Uid(uid) , Query(std::move(query)) @@ -27,6 +27,7 @@ struct TEvCompileRequest: public TEventLocal<TEvCompileRequest, TKqpEvents::EvCo , Orbit(std::move(orbit)) , TempTablesState(std::move(tempTablesState)) , IntrestedInResult(std::move(intrestedInResult)) + , CollectDiagnostics(collectDiagnostics) { Y_ENSURE(Uid.Defined() != Query.Defined()); } @@ -45,6 +46,8 @@ struct TEvCompileRequest: public TEventLocal<TEvCompileRequest, TKqpEvents::EvCo TKqpTempTablesState::TConstPtr TempTablesState; std::shared_ptr<std::atomic<bool>> IntrestedInResult; + + bool CollectDiagnostics = false; }; struct TEvRecompileRequest: public TEventLocal<TEvRecompileRequest, TKqpEvents::EvRecompileRequest> { @@ -80,8 +83,9 @@ struct TEvRecompileRequest: public TEventLocal<TEvRecompileRequest, TKqpEvents:: }; struct TEvCompileResponse: public TEventLocal<TEvCompileResponse, TKqpEvents::EvCompileResponse> { - TEvCompileResponse(const TKqpCompileResult::TConstPtr& compileResult, NLWTrace::TOrbit orbit = {}) + TEvCompileResponse(const TKqpCompileResult::TConstPtr& compileResult, NLWTrace::TOrbit orbit = {}, const std::optional<TString>& replayMessage = std::nullopt) : CompileResult(compileResult) + , ReplayMessage(replayMessage) , Orbit(std::move(orbit)) { } diff --git a/ydb/core/kqp/common/events/query.h b/ydb/core/kqp/common/events/query.h index a73a6e9e0a7..59fbac0e00e 100644 --- a/ydb/core/kqp/common/events/query.h +++ b/ydb/core/kqp/common/events/query.h @@ -233,6 +233,10 @@ public: return ParametersSize; } + bool GetCollectDiagnostics() const { + return Record.GetRequest().GetCollectDiagnostics(); + } + ui32 CalculateSerializedSize() const override { PrepareRemote(); return Record.ByteSize(); diff --git a/ydb/core/kqp/compile_service/kqp_compile_service.cpp b/ydb/core/kqp/compile_service/kqp_compile_service.cpp index dcba8b3c1e5..eb6eb9adc0c 100644 --- a/ydb/core/kqp/compile_service/kqp_compile_service.cpp +++ b/ydb/core/kqp/compile_service/kqp_compile_service.cpp @@ -552,6 +552,8 @@ private: Counters->ReportQueryCacheHit(dbCounters, false); + CollectDiagnostics = request.CollectDiagnostics; + LWTRACK(KqpCompileServiceEnqueued, ev->Get()->Orbit, ev->Get()->Query ? ev->Get()->Query->UserSid : 0); @@ -683,7 +685,7 @@ private: for (auto& request : requests) { LWTRACK(KqpCompileServiceGetCompilation, request.Orbit, request.Query.UserSid, compileActorId.ToString()); Reply(request.Sender, compileResult, compileStats, ctx, - request.Cookie, std::move(request.Orbit), std::move(request.CompileServiceSpan)); + request.Cookie, std::move(request.Orbit), std::move(request.CompileServiceSpan), (CollectDiagnostics ? ev->Get()->ReplayMessage : std::nullopt)); } } else { if (QueryCache.FindByUid(compileResult->Uid, false)) { @@ -693,7 +695,7 @@ private: LWTRACK(KqpCompileServiceGetCompilation, compileRequest.Orbit, compileRequest.Query.UserSid, compileActorId.ToString()); Reply(compileRequest.Sender, compileResult, compileStats, ctx, - compileRequest.Cookie, std::move(compileRequest.Orbit), std::move(compileRequest.CompileServiceSpan)); + compileRequest.Cookie, std::move(compileRequest.Orbit), std::move(compileRequest.CompileServiceSpan), (CollectDiagnostics ? ev->Get()->ReplayMessage : std::nullopt)); } catch (const std::exception& e) { LogException("TEvCompileResponse", ev->Sender, e, ctx); @@ -787,7 +789,7 @@ private: void Reply(const TActorId& sender, const TKqpCompileResult::TConstPtr& compileResult, const NKqpProto::TKqpStatsCompile& compileStats, const TActorContext& ctx, ui64 cookie, - NLWTrace::TOrbit orbit, NWilson::TSpan span) + NLWTrace::TOrbit orbit, NWilson::TSpan span, const std::optional<TString>& replayMessage = std::nullopt) { const auto& query = compileResult->Query; LWTRACK(KqpCompileServiceReply, @@ -800,7 +802,7 @@ private: << ", queryUid: " << compileResult->Uid << ", status:" << compileResult->Status); - auto responseEv = MakeHolder<TEvKqp::TEvCompileResponse>(compileResult, std::move(orbit)); + auto responseEv = MakeHolder<TEvKqp::TEvCompileResponse>(compileResult, std::move(orbit), replayMessage); responseEv->Stats.CopyFrom(compileStats); if (span) { @@ -859,6 +861,8 @@ private: TKqpRequestsQueue RequestsQueue; std::shared_ptr<IQueryReplayBackendFactory> QueryReplayFactory; std::optional<TKqpFederatedQuerySetup> FederatedQuerySetup; + + bool CollectDiagnostics = false; }; IActor* CreateKqpCompileService(const TTableServiceConfig& tableServiceConfig, const TQueryServiceConfig& queryServiceConfig, diff --git a/ydb/core/kqp/session_actor/kqp_query_state.cpp b/ydb/core/kqp/session_actor/kqp_query_state.cpp index 073f2ea4aa2..5f10ea120fc 100644 --- a/ydb/core/kqp/session_actor/kqp_query_state.cpp +++ b/ydb/core/kqp/session_actor/kqp_query_state.cpp @@ -117,6 +117,9 @@ bool TKqpQueryState::SaveAndCheckCompileResult(TEvKqp::TEvCompileResponse* ev) { CompileStats.Swap(&ev->Stats); PreparedQuery = CompileResult->PreparedQuery; + if (ev->ReplayMessage) { + ReplayMessage = *ev->ReplayMessage; + } return true; } @@ -161,7 +164,7 @@ std::unique_ptr<TEvKqp::TEvCompileRequest> TKqpQueryState::BuildCompileRequest(s } return std::make_unique<TEvKqp::TEvCompileRequest>(UserToken, uid, - std::move(query), keepInCache, compileDeadline, DbCounters, std::move(cookie), UserRequestContext, std::move(Orbit), TempTablesState); + std::move(query), keepInCache, compileDeadline, DbCounters, std::move(cookie), UserRequestContext, std::move(Orbit), TempTablesState, GetCollectDiagnostics()); } std::unique_ptr<TEvKqp::TEvRecompileRequest> TKqpQueryState::BuildReCompileRequest(std::shared_ptr<std::atomic<bool>> cookie) { diff --git a/ydb/core/kqp/session_actor/kqp_query_state.h b/ydb/core/kqp/session_actor/kqp_query_state.h index ec96d32d892..53e348baf18 100644 --- a/ydb/core/kqp/session_actor/kqp_query_state.h +++ b/ydb/core/kqp/session_actor/kqp_query_state.h @@ -113,6 +113,8 @@ public: TKqpTempTablesState::TConstPtr TempTablesState; + TString ReplayMessage; + NKikimrKqp::EQueryAction GetAction() const { return RequestEv->GetAction(); } @@ -424,6 +426,10 @@ public: return RequestEv->GetArena(); } + bool GetCollectDiagnostics() { + return RequestEv->GetCollectDiagnostics(); + } + //// Topic ops //// void AddOffsetsToTransaction(); bool TryMergeTopicOffsets(const NTopic::TTopicOperations &operations, TString& message); diff --git a/ydb/core/kqp/session_actor/kqp_session_actor.cpp b/ydb/core/kqp/session_actor/kqp_session_actor.cpp index bdcf88e4d7d..2f6dcf2f4aa 100644 --- a/ydb/core/kqp/session_actor/kqp_session_actor.cpp +++ b/ydb/core/kqp/session_actor/kqp_session_actor.cpp @@ -122,26 +122,26 @@ struct TKqpCleanupCtx { class TKqpSessionActor : public TActorBootstrapped<TKqpSessionActor> { -class TTimerGuard { -public: - TTimerGuard(TKqpSessionActor* this_) - : This(this_) - { - if (This->QueryState) { - YQL_ENSURE(!This->QueryState->CurrentTimer); - This->QueryState->CurrentTimer.emplace(); + class TTimerGuard { + public: + TTimerGuard(TKqpSessionActor* this_) + : This(this_) + { + if (This->QueryState) { + YQL_ENSURE(!This->QueryState->CurrentTimer); + This->QueryState->CurrentTimer.emplace(); + } } - } - ~TTimerGuard() { - if (This->QueryState) { - This->QueryState->ResetTimer(); + ~TTimerGuard() { + if (This->QueryState) { + This->QueryState->ResetTimer(); + } } - } -private: - TKqpSessionActor* This; -}; + private: + TKqpSessionActor* This; + }; public: static constexpr NKikimrServices::TActivity::EType ActorActivityType() { @@ -388,6 +388,7 @@ public: ); switch (action) { + case NKikimrKqp::QUERY_ACTION_EXPLAIN: case NKikimrKqp::QUERY_ACTION_EXECUTE: case NKikimrKqp::QUERY_ACTION_PREPARE: case NKikimrKqp::QUERY_ACTION_EXECUTE_PREPARED: { @@ -421,18 +422,6 @@ public: case NKikimrKqp::QUERY_ACTION_COMMIT_TX: return CommitTx(); - case NKikimrKqp::QUERY_ACTION_EXPLAIN: { - auto type = QueryState->GetType(); - if (type != NKikimrKqp::QUERY_TYPE_SQL_GENERIC_QUERY && - type != NKikimrKqp::QUERY_TYPE_SQL_GENERIC_CONCURRENT_QUERY && - type != NKikimrKqp::QUERY_TYPE_SQL_GENERIC_SCRIPT) - { - return ForwardRequest(ev); - } - - break; - } - // not supported yet case NKikimrKqp::QUERY_ACTION_VALIDATE: case NKikimrKqp::QUERY_ACTION_PARSE: @@ -1639,6 +1628,7 @@ public: response.SetQueryPlan(preparedQuery->GetPhysicalQuery().GetQueryPlan()); response.SetQueryAst(preparedQuery->GetPhysicalQuery().GetQueryAst()); + response.SetQueryDiagnostics(QueryState->ReplayMessage); const auto& phyQuery = QueryState->PreparedQuery->GetPhysicalQuery(); FillColumnsMeta(phyQuery, response); diff --git a/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp b/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp index b4a4f340754..0606d80dab8 100644 --- a/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp +++ b/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp @@ -1719,6 +1719,68 @@ Y_UNIT_TEST_SUITE(KqpIndexes) { } } + Y_UNIT_TEST(ExplainCollectFullDiagnostics) { + auto setting = NKikimrKqp::TKqpSetting(); + auto serverSettings = TKikimrSettings() + .SetKqpSettings({setting}); + + TKikimrRunner kikimr(serverSettings); + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + + { + auto tableBuilder = db.GetTableBuilder(); + tableBuilder + .AddNullableColumn("Key", EPrimitiveType::Int64) + .AddNullableColumn("Index2", EPrimitiveType::Int64) + .AddNullableColumn("Value", EPrimitiveType::String); + tableBuilder.SetPrimaryKeyColumns(TVector<TString>{"Key"}); + tableBuilder.AddSecondaryIndex("Index", TVector<TString>{"Index2"}); + auto result = session.CreateTable("/Root/TestTable", tableBuilder.Build()).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL(result.IsTransportError(), false); + UNIT_ASSERT_VALUES_EQUAL(result.GetStatus(), EStatus::SUCCESS); + } + + { + const TString query(Q1_(R"( + SELECT * FROM `/Root/TestTable` VIEW Index as t ORDER BY t.Index2 DESC; + )")); + + { + auto settings = TExplainDataQuerySettings(); + settings.WithCollectFullDiagnostics(true); + + auto result = session.ExplainDataQuery( + query, settings) + .ExtractValueSync(); + + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString().c_str()); + + UNIT_ASSERT_C(result.GetAst().Contains("'('\"Reverse\")"), result.GetAst()); + + UNIT_ASSERT_C(!result.GetDiagnostics().empty(), "Query result diagnostics is empty"); + + TStringStream in; + in << result.GetDiagnostics(); + NJson::TJsonValue value; + ReadJsonTree(&in, &value); + + UNIT_ASSERT_C(value.IsMap(), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_id"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("version"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_text"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_parameter_types"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("table_metadata"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("created_at"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_syntax"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_database"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_cluster"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_plan"), "Incorrect Diagnostics"); + UNIT_ASSERT_C(value.Has("query_type"), "Incorrect Diagnostics"); + } + } + } + Y_UNIT_TEST(SecondaryIndexOrderBy2) { auto setting = NKikimrKqp::TKqpSetting(); auto serverSettings = TKikimrSettings() diff --git a/ydb/core/protos/kqp.proto b/ydb/core/protos/kqp.proto index 97da279a9e4..ef14b52776d 100644 --- a/ydb/core/protos/kqp.proto +++ b/ydb/core/protos/kqp.proto @@ -107,6 +107,7 @@ message TQueryRequest { map<string, Ydb.TypedValue> YdbParameters = 24; optional bool IsInternalCall = 25; optional Ydb.Query.Syntax Syntax = 26; + optional bool CollectDiagnostics = 27; } message TKqpPathIdProto { @@ -263,6 +264,7 @@ message TQueryResponse { optional NKqpProto.TKqpStatsQuery QueryStats = 12; repeated Ydb.ResultSet YdbResults = 13; optional TTopicOperationsResponse TopicOperations = 14; + optional string QueryDiagnostics = 15; } message TEvQueryResponse { diff --git a/ydb/core/protos/kqp_physical.proto b/ydb/core/protos/kqp_physical.proto index 92ce2f435dc..59fd591e11c 100644 --- a/ydb/core/protos/kqp_physical.proto +++ b/ydb/core/protos/kqp_physical.proto @@ -454,4 +454,5 @@ message TKqpPhyQuery { repeated TKqpTableInfo TableInfos = 8; bool HasUncommittedChangesRead = 9; + string QueryDiagnostics = 10; } diff --git a/ydb/public/api/protos/ydb_table.proto b/ydb/public/api/protos/ydb_table.proto index c6d0bb1b6c1..bcb02e05407 100644 --- a/ydb/public/api/protos/ydb_table.proto +++ b/ydb/public/api/protos/ydb_table.proto @@ -853,6 +853,7 @@ message ExplainDataQueryRequest { // SQL text to explain string yql_text = 2; Ydb.Operations.OperationParams operation_params = 3; + bool collect_full_diagnostics = 4; } message ExplainDataQueryResponse { @@ -863,6 +864,7 @@ message ExplainDataQueryResponse { message ExplainQueryResult { string query_ast = 1; string query_plan = 2; + string query_full_diagnostics = 3; } // Prepare given program to execute diff --git a/ydb/public/lib/ydb_cli/commands/ydb_service_table.cpp b/ydb/public/lib/ydb_cli/commands/ydb_service_table.cpp index 37d8878cc79..818bc2620c9 100644 --- a/ydb/public/lib/ydb_cli/commands/ydb_service_table.cpp +++ b/ydb/public/lib/ydb_cli/commands/ydb_service_table.cpp @@ -14,6 +14,7 @@ #include <util/string/split.h> #include <util/folder/path.h> #include <util/folder/dirut.h> +#include <util/generic/guid.h> #include <math.h> @@ -687,6 +688,8 @@ void TCommandExplain::Config(TConfig& config) { .NoArgument().SetFlag(&Analyze); config.Opts->AddLongOption("flame-graph", "Builds resource usage flame graph, based on analyze info") .RequiredArgument("PATH").StoreResult(&FlameGraphPath); + config.Opts->AddLongOption("collect-diagnostics", "Collects diagnostics and saves it to file") + .StoreTrue(&CollectFullDiagnostics); AddFormats(config, { EOutputFormat::Pretty, @@ -757,14 +760,24 @@ int TCommandExplain::Run(TConfig& config) { ast = proto.query_ast(); } } else if (QueryType == "data" && !Analyze) { + NTable::TExplainDataQuerySettings settings(FillSettings(NTable::TExplainDataQuerySettings())); + if (CollectFullDiagnostics) { + settings.WithCollectFullDiagnostics(true); + } + NTable::TExplainQueryResult result = GetSession(config).ExplainDataQuery( Query, - FillSettings(NTable::TExplainDataQuerySettings()) + settings ).GetValueSync(); ThrowOnError(result); planJson = result.GetPlan(); ast = result.GetAst(); + if (CollectFullDiagnostics) { + TFileOutput file(TStringBuilder() << "diagnostics_" << TGUID::Create().AsGuidString() << ".txt"); + file << result.GetDiagnostics(); + } + } else { throw TMisuseException() << "Unknown query type for explain."; } diff --git a/ydb/public/lib/ydb_cli/commands/ydb_service_table.h b/ydb/public/lib/ydb_cli/commands/ydb_service_table.h index 52c1bd65564..1c2fa2ce713 100644 --- a/ydb/public/lib/ydb_cli/commands/ydb_service_table.h +++ b/ydb/public/lib/ydb_cli/commands/ydb_service_table.h @@ -133,6 +133,7 @@ private: TString QueryType; bool Analyze = false; TMaybe<TString> FlameGraphPath; + bool CollectFullDiagnostics = false; }; class TCommandReadTable : public TYdbCommand, public TCommandWithPath, diff --git a/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp b/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp index 7a8da53c996..bb85e97b783 100644 --- a/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp +++ b/ydb/public/sdk/cpp/client/ydb_table/impl/table_client.cpp @@ -700,6 +700,7 @@ TAsyncExplainDataQueryResult TTableClient::TImpl::ExplainDataQuery(const TSessio auto request = MakeOperationRequest<Ydb::Table::ExplainDataQueryRequest>(settings); request.set_session_id(session.GetId()); request.set_yql_text(query); + request.set_collect_full_diagnostics(settings.WithCollectFullDiagnostics_); auto promise = NewPromise<TExplainQueryResult>(); @@ -707,14 +708,16 @@ TAsyncExplainDataQueryResult TTableClient::TImpl::ExplainDataQuery(const TSessio (google::protobuf::Any* any, TPlainStatus status) mutable { TString ast; TString plan; + TString diagnostics; if (any) { Ydb::Table::ExplainQueryResult result; any->UnpackTo(&result); ast = result.query_ast(); plan = result.query_plan(); + diagnostics = result.query_full_diagnostics(); } TExplainQueryResult val(TStatus(std::move(status)), - std::move(plan), std::move(ast)); + std::move(plan), std::move(ast), std::move(diagnostics)); promise.SetValue(std::move(val)); }; diff --git a/ydb/public/sdk/cpp/client/ydb_table/table.cpp b/ydb/public/sdk/cpp/client/ydb_table/table.cpp index 54419be40c0..6033ec6438b 100644 --- a/ydb/public/sdk/cpp/client/ydb_table/table.cpp +++ b/ydb/public/sdk/cpp/client/ydb_table/table.cpp @@ -2017,10 +2017,11 @@ bool TPrepareQueryResult::IsQueryFromCache() const { //////////////////////////////////////////////////////////////////////////////// -TExplainQueryResult::TExplainQueryResult(TStatus&& status, TString&& plan, TString&& ast) +TExplainQueryResult::TExplainQueryResult(TStatus&& status, TString&& plan, TString&& ast, TString&& diagnostics) : TStatus(std::move(status)) , Plan_(std::move(plan)) , Ast_(std::move(ast)) + , Diagnostics_(std::move(diagnostics)) {} const TString& TExplainQueryResult::GetPlan() const { @@ -2033,6 +2034,11 @@ const TString& TExplainQueryResult::GetAst() const { return Ast_; } +const TString& TExplainQueryResult::GetDiagnostics() const { + CheckStatusOk("TExplainQueryResult::GetDiagnostics"); + return Diagnostics_; +} + //////////////////////////////////////////////////////////////////////////////// TDescribeTableResult::TDescribeTableResult(TStatus&& status, Ydb::Table::DescribeTableResult&& desc, diff --git a/ydb/public/sdk/cpp/client/ydb_table/table.h b/ydb/public/sdk/cpp/client/ydb_table/table.h index 06300e9ce75..375b7d114ce 100644 --- a/ydb/public/sdk/cpp/client/ydb_table/table.h +++ b/ydb/public/sdk/cpp/client/ydb_table/table.h @@ -1524,7 +1524,9 @@ struct TDescribeTableSettings : public TOperationRequestSettings<TDescribeTableS FLUENT_SETTING_DEFAULT(bool, WithPartitionStatistics, false); }; -struct TExplainDataQuerySettings : public TOperationRequestSettings<TExplainDataQuerySettings> {}; +struct TExplainDataQuerySettings : public TOperationRequestSettings<TExplainDataQuerySettings> { + FLUENT_SETTING_DEFAULT(bool, WithCollectFullDiagnostics, false); +}; struct TPrepareDataQuerySettings : public TOperationRequestSettings<TPrepareDataQuerySettings> {}; @@ -1778,14 +1780,16 @@ private: //! Represents result of ExplainDataQuery call class TExplainQueryResult : public TStatus { public: - TExplainQueryResult(TStatus&& status, TString&& plan, TString&& ast); + TExplainQueryResult(TStatus&& status, TString&& plan, TString&& ast, TString&& diagnostics); const TString& GetPlan() const; const TString& GetAst() const; + const TString& GetDiagnostics() const; private: TString Plan_; TString Ast_; + TString Diagnostics_; }; //! Represents result of DescribeTable call |