diff options
author | qrort <31865255+qrort@users.noreply.github.com> | 2024-02-23 18:21:51 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-23 18:21:51 +0300 |
commit | 509834b7c24b6ed6755f56a639082685d68d541a (patch) | |
tree | eaeed828fc70ab08755a3156885d8e350e8cfadc | |
parent | 333feede63ea492968b7dc2fb822aae172567a99 (diff) | |
download | ydb-509834b7c24b6ed6755f56a639082685d68d541a.tar.gz |
resolves #2078: sort YdbResults via ColumnHints (#2210)
-rw-r--r-- | ydb/core/kqp/query_compiler/kqp_query_compiler.cpp | 23 | ||||
-rw-r--r-- | ydb/core/kqp/ut/pg/kqp_pg_ut.cpp | 62 |
2 files changed, 78 insertions, 7 deletions
diff --git a/ydb/core/kqp/query_compiler/kqp_query_compiler.cpp b/ydb/core/kqp/query_compiler/kqp_query_compiler.cpp index 3e75c1b9ba4..e287ea95511 100644 --- a/ydb/core/kqp/query_compiler/kqp_query_compiler.cpp +++ b/ydb/core/kqp/query_compiler/kqp_query_compiler.cpp @@ -520,12 +520,27 @@ public: return false; } - auto resultMeta = queryBindingProto.MutableResultSetMeta(); + auto resultMetaColumns = queryBindingProto.MutableResultSetMeta()->Mutablecolumns(); + for (size_t i = 0; i < kikimrProto.GetStruct().MemberSize(); i++) { + resultMetaColumns->Add(); + } + + THashMap<TString, int> columnOrder; + columnOrder.reserve(kikimrProto.GetStruct().MemberSize()); + if (!txResult.GetColumnHints().empty()) { + YQL_ENSURE(txResult.GetColumnHints().size() == (int)kikimrProto.GetStruct().MemberSize()); + for (int i = 0; i < txResult.GetColumnHints().size(); i++) { + const auto& hint = txResult.GetColumnHints().at(i); + columnOrder[TString(hint)] = i; + } + } + int id = 0; for (const auto& column : kikimrProto.GetStruct().GetMember()) { - auto columnMeta = resultMeta->add_columns(); - columnMeta->set_name(column.GetName()); - ConvertMiniKQLTypeToYdbType(column.GetType(), *columnMeta->mutable_type()); + int bindingColumnId = columnOrder.count(column.GetName()) ? columnOrder.at(column.GetName()) : id++; + auto& columnMeta = resultMetaColumns->at(bindingColumnId); + columnMeta.Setname(column.GetName()); + ConvertMiniKQLTypeToYdbType(column.GetType(), *columnMeta.mutable_type()); } } diff --git a/ydb/core/kqp/ut/pg/kqp_pg_ut.cpp b/ydb/core/kqp/ut/pg/kqp_pg_ut.cpp index 5f01ec1ef5d..ca24fb05096 100644 --- a/ydb/core/kqp/ut/pg/kqp_pg_ut.cpp +++ b/ydb/core/kqp/ut/pg/kqp_pg_ut.cpp @@ -1,4 +1,8 @@ -#include "ydb/public/sdk/cpp/client/ydb_proto/accessor.h" +#include <ydb/core/kqp/common/events/events.h> +#include <ydb/core/kqp/common/simple/services.h> +#include <ydb/core/kqp/executer_actor/kqp_executer.h> + +#include <ydb/public/sdk/cpp/client/ydb_proto/accessor.h> #include <ydb/core/kqp/ut/common/kqp_ut_common.h> #include <ydb/library/yql/parser/pg_catalog/catalog.h> @@ -9,7 +13,6 @@ extern "C" { -#include "postgres.h" #include "catalog/pg_type_d.h" } @@ -3853,7 +3856,7 @@ Y_UNIT_TEST_SUITE(KqpPg) { INSERT INTO RecompileTable (id) VALUES (1); )", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync(); UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); - + result = db.ExecuteQuery(R"( DROP TABLE RecompileTable; )", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync(); @@ -4037,6 +4040,59 @@ Y_UNIT_TEST_SUITE(KqpPg) { CompareYson(R"([])", FormatResultSetYson(result.GetResultSet(0))); } } + + Y_UNIT_TEST(ExplainColumnsReorder) { + TPortManager tp; + ui16 mbusport = tp.GetPort(2134); + auto settings = Tests::TServerSettings(mbusport) + .SetDomainName("Root") + .SetUseRealThreads(false); + + Tests::TServer::TPtr server = new Tests::TServer(settings); + + auto runtime = server->GetRuntime(); + auto sender = runtime->AllocateEdgeActor(); + auto kqpProxy = MakeKqpProxyID(runtime->GetNodeId(0)); + + InitRoot(server, sender); + + auto createSession = [&]() { + runtime->Send(new IEventHandle(kqpProxy, sender, new TEvKqp::TEvCreateSessionRequest())); + auto reply = runtime->GrabEdgeEventRethrow<TEvKqp::TEvCreateSessionResponse>(sender); + auto record = reply->Get()->Record; + UNIT_ASSERT_VALUES_EQUAL(record.GetYdbStatus(), Ydb::StatusIds::SUCCESS); + return record.GetResponse().GetSessionId(); + }; + + auto sendQuery = [&](const TString& queryText) { + auto ev = std::make_unique<NKqp::TEvKqp::TEvQueryRequest>(); + ev->Record.MutableRequest()->SetAction(NKikimrKqp::QUERY_ACTION_EXPLAIN); + ev->Record.MutableRequest()->SetType(NKikimrKqp::QUERY_TYPE_SQL_GENERIC_QUERY); + ev->Record.MutableRequest()->SetQuery(queryText); + ev->Record.MutableRequest()->SetSyntax(::Ydb::Query::Syntax::SYNTAX_PG); + ev->Record.MutableRequest()->SetKeepSession(false); + ActorIdToProto(sender, ev->Record.MutableRequestActorId()); + + runtime->Send(new IEventHandle(kqpProxy, sender, ev.release())); + return runtime->GrabEdgeEventRethrow<TEvKqp::TEvQueryResponse>(sender); + }; + + createSession(); + + auto reply = sendQuery(R"( + SELECT 2 y, 1 x; + )"); + + UNIT_ASSERT_VALUES_EQUAL(reply->Get()->Record.GetRef().GetYdbStatus(), Ydb::StatusIds::SUCCESS); + UNIT_ASSERT_VALUES_EQUAL(reply->Get()->Record.GetRef().GetResponse().GetYdbResults().size(), 1); + Cerr << reply->Get()->Record.GetRef().GetResponse().DebugString() << Endl; + auto ydbResults = reply->Get()->Record.GetRef().GetResponse().GetYdbResults(); + TVector <TString> colNames = {"y", "x"}; + UNIT_ASSERT_VALUES_EQUAL(colNames.size(), ydbResults.begin()->Getcolumns().size()); + for (size_t i = 0; i < colNames.size(); i++) { + UNIT_ASSERT_VALUES_EQUAL(ydbResults.begin()->Getcolumns().at(i).Getname(), colNames[i]); + } + } } } // namespace NKqp |