aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorulya-sidorina <yulia@ydb.tech>2023-08-09 16:57:20 +0300
committerulya-sidorina <yulia@ydb.tech>2023-08-09 18:04:17 +0300
commit8f78e2428637f3c9fb20bd10336740bb06e46a26 (patch)
treea751b6a215f95f7ece593a0538ff0008cd99bf28
parent349fc04bc3f50216b2afe5528bf25d64bc305297 (diff)
downloadydb-8f78e2428637f3c9fb20bd10336740bb06e46a26.tar.gz
KIKIMR-18864: fix column order for index table reading result
-rw-r--r--ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp34
-rw-r--r--ydb/core/kqp/ut/scan/kqp_scan_ut.cpp94
-rw-r--r--ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_nonselector_aliases.sql-plan_/index_topsort_index_with_nonselector_aliases.sql.plan4
-rw-r--r--ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_selector_aliases.sql-plan_/index_topsort_index_with_selector_aliases.sql.plan4
4 files changed, 116 insertions, 20 deletions
diff --git a/ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp b/ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp
index c843c1a13d..f8818534ad 100644
--- a/ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp
+++ b/ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp
@@ -16,43 +16,45 @@ using namespace NYql::NNodes;
namespace {
TCoAtomList BuildKeyColumnsList(const TKikimrTableDescription& table, TPositionHandle pos, TExprContext& ctx) {
- TVector<TExprBase> columnsToSelect;
- columnsToSelect.reserve(table.Metadata->KeyColumnNames.size());
- for (auto key : table.Metadata->KeyColumnNames) {
- auto value = table.Metadata->Columns.at(key);
+ TSet<TString> columnsToSelect(table.Metadata->KeyColumnNames.begin(), table.Metadata->KeyColumnNames.end());
+ TVector<TExprBase> columnsList;
+ columnsList.reserve(columnsToSelect.size());
+ for (auto column : columnsToSelect) {
auto atom = Build<TCoAtom>(ctx, pos)
- .Value(value.Name)
+ .Value(column)
.Done();
- columnsToSelect.push_back(atom);
+ columnsList.emplace_back(std::move(atom));
}
return Build<TCoAtomList>(ctx, pos)
- .Add(columnsToSelect)
+ .Add(columnsList)
.Done();
}
TCoAtomList MergeColumns(const NNodes::TCoAtomList& col1, const TVector<TString>& col2, TExprContext& ctx) {
- TVector<TCoAtom> columns;
- THashSet<TString> uniqColumns;
- columns.reserve(col1.Size() + col2.size());
-
+ TMap<TString, TCoAtom> columns;
for (const auto& c : col1) {
- YQL_ENSURE(uniqColumns.emplace(c.StringValue()).second);
- columns.push_back(c);
+ YQL_ENSURE(columns.insert({c.StringValue(), c}).second);
}
for (const auto& c : col2) {
- if (uniqColumns.emplace(c).second) {
+ if (!columns.contains(c)) {
auto atom = Build<TCoAtom>(ctx, col1.Pos())
.Value(c)
.Done();
- columns.push_back(atom);
+ columns.insert({c, std::move(atom)});
}
}
+ TVector<TCoAtom> columnsList;
+ columnsList.reserve(columns.size());
+ for (auto [_, column] : columns) {
+ columnsList.emplace_back(std::move(column));
+ }
+
return Build<TCoAtomList>(ctx, col1.Pos())
- .Add(columns)
+ .Add(columnsList)
.Done();
}
diff --git a/ydb/core/kqp/ut/scan/kqp_scan_ut.cpp b/ydb/core/kqp/ut/scan/kqp_scan_ut.cpp
index 550145ef77..b8e17e1218 100644
--- a/ydb/core/kqp/ut/scan/kqp_scan_ut.cpp
+++ b/ydb/core/kqp/ut/scan/kqp_scan_ut.cpp
@@ -1823,6 +1823,100 @@ Y_UNIT_TEST_SUITE(KqpScan) {
}
}
+ Y_UNIT_TEST(SecondaryIndexCustomColumnOrder) {
+ TKikimrRunner kikimr;
+ auto db = kikimr.GetTableClient();
+ auto session = db.CreateSession().GetValueSync().GetSession();
+
+ CreateSampleTablesWithIndex(session);
+
+ { // prepare table
+ auto res = session.ExecuteSchemeQuery(R"(
+ --!syntax_v1
+ CREATE TABLE `/Root/SecondaryKeysCustomOrder` (
+ Key2 Int32,
+ Key1 String,
+ Fk2 Int32,
+ Fk1 String,
+ Value String,
+ PRIMARY KEY (Key2, Key1),
+ INDEX Index GLOBAL ON (Fk2, Fk1)
+ );
+ )").GetValueSync();
+ UNIT_ASSERT_C(res.IsSuccess(), res.GetIssues().ToString());
+
+ auto result = session.ExecuteDataQuery(R"(
+
+ REPLACE INTO `/Root/SecondaryKeysCustomOrder` (Key2, Key1, Fk2, Fk1, Value) VALUES
+ (1u, "One", 1u, "Fk1", "Value1"),
+ (2u, "Two", 2u, "Fk2", "Value2"),
+ (3u, "Three", 3u, "Fk3", Null),
+ (NULL, "Four", 4u, Null, "Value4"),
+ (5u, Null, 5u, "Fk5", "Value5");
+ )", TTxControl::BeginTx().CommitTx()).GetValueSync();
+ UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
+ }
+
+ {
+ auto itIndex = db.StreamExecuteScanQuery(R"(
+ SELECT Value, Fk1
+ FROM `/Root/SecondaryKeysCustomOrder` VIEW Index
+ WHERE Fk2 = 2u;
+ )").GetValueSync();
+
+ UNIT_ASSERT_C(itIndex.IsSuccess(), itIndex.GetIssues().ToString());
+ CompareYson(R"([
+ [["Value2"];["Fk2"]]
+ ])", StreamResultToYson(itIndex));
+ }
+
+ {
+ auto itIndex = db.StreamExecuteScanQuery(R"(
+ SELECT Value, Fk1, Key2
+ FROM `/Root/SecondaryKeysCustomOrder` VIEW Index
+ WHERE Fk2 >= 4u AND Fk1 IS NULL;
+ )").GetValueSync();
+
+ UNIT_ASSERT_C(itIndex.IsSuccess(), itIndex.GetIssues().ToString());
+ CompareYson(R"([
+ [["Value4"];#;#]
+ ])", StreamResultToYson(itIndex));
+ }
+
+ {
+ auto itIndex = db.StreamExecuteScanQuery(R"(
+ PRAGMA AnsiInForEmptyOrNullableItemsCollections;
+ SELECT Value, Fk1, Key1
+ FROM `/Root/SecondaryKeysCustomOrder` VIEW Index
+ WHERE (Fk2, Fk1) IN AsList((1u, "Fk1"), (2u, "Fk2"), (5u, "Fk5"))
+ ORDER BY Value;
+ )").GetValueSync();
+
+ UNIT_ASSERT_C(itIndex.IsSuccess(), itIndex.GetIssues().ToString());
+ CompareYson(R"([
+ [["Value1"];["Fk1"];["One"]];
+ [["Value2"];["Fk2"];["Two"]];
+ [["Value5"];["Fk5"];#]
+ ])", StreamResultToYson(itIndex));
+ }
+
+ {
+ auto itIndex = db.StreamExecuteScanQuery(R"(
+ SELECT r.Value, l.Value
+ FROM `/Root/SecondaryKeys` VIEW Index AS l
+ INNER JOIN `/Root/SecondaryKeysCustomOrder` VIEW Index AS r
+ ON l.Fk = r.Fk2 ORDER BY r.Value;
+ )").GetValueSync();
+
+ UNIT_ASSERT_C(itIndex.IsSuccess(), itIndex.GetIssues().ToString());
+ CompareYson(R"([
+ [["Value1"];["Payload1"]];
+ [["Value2"];["Payload2"]];
+ [["Value5"];["Payload5"]]
+ ])", StreamResultToYson(itIndex));
+ }
+ }
+
Y_UNIT_TEST(BoolFlag) {
auto kikimr = DefaultKikimrRunner({}, AppCfg());
diff --git a/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_nonselector_aliases.sql-plan_/index_topsort_index_with_nonselector_aliases.sql.plan b/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_nonselector_aliases.sql-plan_/index_topsort_index_with_nonselector_aliases.sql.plan
index 52d567d81a..5a1eb9c14a 100644
--- a/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_nonselector_aliases.sql-plan_/index_topsort_index_with_nonselector_aliases.sql.plan
+++ b/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_nonselector_aliases.sql-plan_/index_topsort_index_with_nonselector_aliases.sql.plan
@@ -22,9 +22,9 @@
"reads": [
{
"columns": [
- "Key1",
"Index1A",
- "Index1B"
+ "Index1B",
+ "Key1"
],
"limit": "2",
"reverse": true,
diff --git a/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_selector_aliases.sql-plan_/index_topsort_index_with_selector_aliases.sql.plan b/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_selector_aliases.sql-plan_/index_topsort_index_with_selector_aliases.sql.plan
index ea5a82d5f0..a185d5fc1c 100644
--- a/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_selector_aliases.sql-plan_/index_topsort_index_with_selector_aliases.sql.plan
+++ b/ydb/tests/functional/canonical/canondata/test_sql.TestCanonicalFolder1.test_case_index_topsort_index_with_selector_aliases.sql-plan_/index_topsort_index_with_selector_aliases.sql.plan
@@ -22,9 +22,9 @@
"reads": [
{
"columns": [
- "Key1",
"Index1A",
- "Index1B"
+ "Index1B",
+ "Key1"
],
"limit": "2",
"reverse": true,