aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorqrort <31865255+qrort@users.noreply.github.com>2024-02-23 18:21:51 +0300
committerGitHub <noreply@github.com>2024-02-23 18:21:51 +0300
commit509834b7c24b6ed6755f56a639082685d68d541a (patch)
treeeaeed828fc70ab08755a3156885d8e350e8cfadc
parent333feede63ea492968b7dc2fb822aae172567a99 (diff)
downloadydb-509834b7c24b6ed6755f56a639082685d68d541a.tar.gz
resolves #2078: sort YdbResults via ColumnHints (#2210)
-rw-r--r--ydb/core/kqp/query_compiler/kqp_query_compiler.cpp23
-rw-r--r--ydb/core/kqp/ut/pg/kqp_pg_ut.cpp62
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