Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
235 changes: 177 additions & 58 deletions ydb/core/kqp/opt/kqp_query_plan.cpp

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions ydb/core/kqp/ut/federated_query/s3/kqp_s3_plan_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ Y_UNIT_TEST_SUITE(KqpS3PlanTest) {
UNIT_ASSERT(NJson::ReadJsonTree(*queryResult.GetStats()->GetPlan(), &plan));

const auto& stagePlan = plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0];
UNIT_ASSERT_VALUES_EQUAL(stagePlan["Node Type"].GetStringSafe(), "Stage-Source");
const auto& sourceOp = stagePlan["Operators"].GetArraySafe()[0];
UNIT_ASSERT_VALUES_EQUAL(stagePlan["Node Type"].GetStringSafe(), "Stage");
const auto& sourceOp = stagePlan["Plans"][0]["Operators"].GetArraySafe()[0];
UNIT_ASSERT_VALUES_EQUAL(sourceOp["ExternalDataSource"].GetStringSafe(), "external_data_source");
UNIT_ASSERT_VALUES_EQUAL(sourceOp["Format"].GetStringSafe(), "json_each_row");
UNIT_ASSERT_VALUES_EQUAL(sourceOp["Name"].GetStringSafe(), "Parse from external data source");
Expand Down Expand Up @@ -150,10 +150,11 @@ Y_UNIT_TEST_SUITE(KqpS3PlanTest) {
UNIT_ASSERT_VALUES_EQUAL(sinkOp["ExternalDataSource"].GetStringSafe(), "write_data_source");
UNIT_ASSERT_VALUES_EQUAL(sinkOp["Compression"].GetStringSafe(), "gzip");

const auto& readStagePlan = plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0];
UNIT_ASSERT_VALUES_EQUAL(readStagePlan["Node Type"].GetStringSafe(), "Limit-Source");
const auto& sourceOp = readStagePlan["Operators"].GetArraySafe()[1];
const auto& readStagePlan = plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0];
UNIT_ASSERT_VALUES_EQUAL(readStagePlan["Node Type"].GetStringSafe(), "Source");
const auto& sourceOp = readStagePlan["Operators"].GetArraySafe()[0];
UNIT_ASSERT_VALUES_EQUAL(sourceOp["ExternalDataSource"].GetStringSafe(), "read_data_source");

UNIT_ASSERT_VALUES_EQUAL(sourceOp["RowsLimitHint"].GetStringSafe(), "10");
UNIT_ASSERT_VALUES_EQUAL(sourceOp["ReadColumns"].GetArraySafe()[0].GetStringSafe(), "key");
UNIT_ASSERT_VALUES_EQUAL(sourceOp["ReadColumns"].GetArraySafe()[1].GetStringSafe(), "value");
Expand Down
4 changes: 2 additions & 2 deletions ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,10 +249,10 @@ Y_UNIT_TEST_SUITE(KqpIndexMetadata) {
auto indexTableAccess = CountPlanNodesByKv(plan, "Table", "tg/tg_index/indexImplTable");
UNIT_ASSERT_VALUES_EQUAL(indexTableAccess, 1);

auto filterOnIndex = CountPlanNodesByKv(plan, "Node Type", "Limit-Filter-TableRangeScan");
auto filterOnIndex = CountPlanNodesByKv(plan, "Node Type", "Limit-Filter");
UNIT_ASSERT_VALUES_EQUAL(filterOnIndex, 1);

auto limitFilterNode = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter-TableRangeScan");
auto limitFilterNode = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter");
auto val = FindPlanNodes(limitFilterNode, "Limit");
UNIT_ASSERT_VALUES_EQUAL(val.size(), 1);
UNIT_ASSERT_VALUES_EQUAL(val[0], "11");
Expand Down
2 changes: 1 addition & 1 deletion ydb/core/kqp/ut/opt/kqp_ne_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2073,7 +2073,7 @@ Y_UNIT_TEST_SUITE(KqpNewEngine) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableFullScan");
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT(node.IsDefined());

TStringBuilder readLimitValue;
Expand Down
89 changes: 32 additions & 57 deletions ydb/core/kqp/ut/opt/kqp_sort_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableFullScan"); // without `Sort`
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan"); // without `Sort`
UNIT_ASSERT(node.IsDefined());
auto read = FindPlanNodeByKv(node, "Name", "TableFullScan");
UNIT_ASSERT(read.IsDefined());
Expand Down Expand Up @@ -60,13 +61,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter-TableRangeScan"); // without `Sort`
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "Filter-TableRangeScan"); // without `Sort`
}
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableRangeScan"); // without `Sort`
}
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan"); // without `Sort`
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
auto read = FindPlanNodeByKv(node, "Name", "TableRangeScan");
UNIT_ASSERT(read.IsDefined());
Expand Down Expand Up @@ -100,7 +96,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableFullScan"); // without `Sort`
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan"); // without `Sort`
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
auto read = FindPlanNodeByKv(node, "Name", "TableFullScan");
UNIT_ASSERT(read.IsDefined());
Expand Down Expand Up @@ -137,7 +134,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "TopSort-TableFullScan");
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
UNIT_ASSERT(!node.GetMapSafe().contains("Reverse"));
}
Expand Down Expand Up @@ -173,13 +171,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter-TableRangeScan");
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "Filter-TableRangeScan");
}
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableRangeScan");
}
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
auto read = FindPlanNodeByKv(node, "Name", "TableRangeScan");
UNIT_ASSERT(read.IsDefined());
Expand Down Expand Up @@ -218,12 +211,13 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableFullScan");
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
auto read = FindPlanNodeByKv(node, "Name", "TableFullScan");
UNIT_ASSERT(read.IsDefined());
UNIT_ASSERT(read.GetMapSafe().contains("Reverse"));
auto limit = FindPlanNodeByKv(node, "Name", "Limit");
auto limit = FindPlanNodeByKv(plan, "Name", "Limit");
UNIT_ASSERT(limit.IsDefined());
UNIT_ASSERT(limit.GetMapSafe().contains("Limit"));
}
Expand Down Expand Up @@ -258,26 +252,15 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter-TableRangeScan");
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "Filter-TableRangeScan");
}
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableRangeScan");
}
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");

UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
auto read = FindPlanNodeByKv(node, "Name", "TableRangeScan");
UNIT_ASSERT(read.IsDefined());
UNIT_ASSERT(read.GetMapSafe().contains("Reverse"));
auto limit = FindPlanNodeByKv(node, "Name", "Limit");
if (!limit.IsDefined()) {
limit = FindPlanNodeByKv(node, "Name", "Filter");
UNIT_ASSERT(limit.GetMapSafe().contains("Limit"));
} else {
UNIT_ASSERT(limit.IsDefined());
UNIT_ASSERT(limit.GetMapSafe().contains("Limit"));
UNIT_ASSERT_C(result.GetAst().Contains("'\"ItemsLimit\""), result.GetAst());
}

UNIT_ASSERT_C(result.GetAst().Contains("'\"ItemsLimit\""), result.GetAst());
}

{
Expand Down Expand Up @@ -311,7 +294,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableFullScan");
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
auto read = FindPlanNodeByKv(node, "Name", "TableFullScan");
UNIT_ASSERT(read.IsDefined());
Expand Down Expand Up @@ -358,10 +342,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "TopSort-TableRangeScan");
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "TopSort-Filter-TableRangeScan");
}
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
}

Expand Down Expand Up @@ -415,10 +397,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "TopSort-TableRangeScan");
if (!node.IsDefined()) {
node = FindPlanNodeByKv(plan, "Node Type", "TopSort-Filter-TableRangeScan");
}
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
}

Expand Down Expand Up @@ -920,7 +900,8 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-TableFullScan");
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
}

Expand Down Expand Up @@ -966,8 +947,10 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
auto node = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter-TableFullScan");
Cout << plan;
auto node = FindPlanNodeByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT_C(node.IsDefined(), result.GetPlan());
node = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter");
auto limit = FindPlanNodeByKv(node, "Limit", "Min(1001,$limit)");
UNIT_ASSERT(limit.IsDefined());
}
Expand Down Expand Up @@ -1053,20 +1036,12 @@ Y_UNIT_TEST_SUITE(KqpSort) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(result.GetPlan(), &plan, true);
Cout << plan;

auto tableRangeRead = FindPlanNodeByKv(plan, "Node Type", "Limit-Filter-TableRangeScan");
size_t lookupIndex = 2;
if (!tableRangeRead.IsDefined()) {
tableRangeRead = FindPlanNodeByKv(plan, "Node Type", "Limit-TableRangeScan");
lookupIndex = 1;
}
auto tableRangeRead = FindPlanNodeByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT(tableRangeRead.IsDefined());

auto& limitOp = tableRangeRead.GetMapSafe().at("Operators").GetArraySafe().at(0).GetMapSafe();
UNIT_ASSERT_VALUES_EQUAL("Limit", limitOp.at("Name").GetStringSafe());
UNIT_ASSERT_VALUES_EQUAL("$limit", limitOp.at("Limit").GetStringSafe());

auto& rangeReadOp = tableRangeRead.GetMapSafe().at("Operators").GetArraySafe().at(lookupIndex).GetMapSafe();
auto& rangeReadOp = tableRangeRead.GetMapSafe().at("Operators").GetArraySafe().at(0).GetMapSafe();
UNIT_ASSERT_VALUES_EQUAL("TableRangeScan", rangeReadOp.at("Name").GetStringSafe());
UNIT_ASSERT_VALUES_EQUAL("index", rangeReadOp.at("Table").GetStringSafe());
}
Expand Down
18 changes: 12 additions & 6 deletions ydb/core/kqp/ut/perf/kqp_query_perf_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,13 @@ Y_UNIT_TEST_SUITE(KqpQueryPerf) {
NJson::ReadJsonTree(stats.query_plan(), &plan, true);

auto stages = FindPlanStages(plan);
UNIT_ASSERT_VALUES_EQUAL(stages.size(), 1);
UNIT_ASSERT_VALUES_EQUAL(stages.size(), 2);

i64 totalTasks = 0;
for (const auto& stage : stages) {
totalTasks += stage.GetMapSafe().at("Stats").GetMapSafe().at("Tasks").GetIntegerSafe();
if (stage.GetMapSafe().contains("Stats")) {
totalTasks += stage.GetMapSafe().at("Stats").GetMapSafe().at("Tasks").GetIntegerSafe();
}
}

UNIT_ASSERT_VALUES_EQUAL(totalTasks, 1);
Expand Down Expand Up @@ -224,11 +226,13 @@ Y_UNIT_TEST_SUITE(KqpQueryPerf) {
NJson::ReadJsonTree(stats.query_plan(), &plan, true);

auto stages = FindPlanStages(plan);
UNIT_ASSERT_VALUES_EQUAL(stages.size(), 3);
UNIT_ASSERT_VALUES_EQUAL(stages.size(), 4);

i64 totalTasks = 0;
for (const auto& stage : stages) {
totalTasks += stage.GetMapSafe().at("Stats").GetMapSafe().at("Tasks").GetIntegerSafe();
if (stage.GetMapSafe().contains("Stats")) {
totalTasks += stage.GetMapSafe().at("Stats").GetMapSafe().at("Tasks").GetIntegerSafe();
}
}
UNIT_ASSERT_VALUES_EQUAL(totalTasks, 3);
}
Expand Down Expand Up @@ -269,11 +273,13 @@ Y_UNIT_TEST_SUITE(KqpQueryPerf) {
NJson::ReadJsonTree(stats.query_plan(), &plan, true);

auto stages = FindPlanStages(plan);
UNIT_ASSERT_VALUES_EQUAL(stages.size(), 2);
UNIT_ASSERT_VALUES_EQUAL(stages.size(), 3);

i64 totalTasks = 0;
for (const auto& stage : stages) {
totalTasks += stage.GetMapSafe().at("Stats").GetMapSafe().at("Tasks").GetIntegerSafe();
if (stage.GetMapSafe().contains("Stats")) {
totalTasks += stage.GetMapSafe().at("Stats").GetMapSafe().at("Tasks").GetIntegerSafe();
}
}
UNIT_ASSERT_VALUES_EQUAL(totalTasks, 2);
}
Expand Down
9 changes: 3 additions & 6 deletions ydb/core/kqp/ut/query/kqp_explain_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,17 +526,14 @@ Y_UNIT_TEST_SUITE(KqpExplain) {
auto deletesCount = CountPlanNodesByKv(plan, "Node Type", "Delete-ConstantExpr");
UNIT_ASSERT_VALUES_EQUAL(deletesCount, 1);

auto fullScansCount = CountPlanNodesByKv(plan, "Node Type", "TableFullScan") +
CountPlanNodesByKv(plan, "Node Type", "Stage-TableFullScan");
auto fullScansCount = CountPlanNodesByKv(plan, "Node Type", "TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(fullScansCount, 1);

auto rangeScansCount = CountPlanNodesByKv(plan, "Node Type", "TableRangeScan") +
CountPlanNodesByKv(plan, "Name", "TableRangeScan");
auto rangeScansCount = CountPlanNodesByKv(plan, "Node Type", "TableRangeScan");
UNIT_ASSERT_VALUES_EQUAL(rangeScansCount, 1);

ui32 lookupsCount = 0;
lookupsCount = CountPlanNodesByKv(plan, "Node Type", "Stage-TablePointLookup");
lookupsCount += CountPlanNodesByKv(plan, "Node Type", "TablePointLookup-ConstantExpr");
lookupsCount = CountPlanNodesByKv(plan, "Node Type", "TablePointLookup-ConstantExpr");
UNIT_ASSERT_VALUES_EQUAL(lookupsCount, 1);

/* check tables section */
Expand Down
14 changes: 8 additions & 6 deletions ydb/core/kqp/ut/query/kqp_limits_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,9 +849,10 @@ Y_UNIT_TEST_SUITE(KqpLimits) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(*result.GetStats()->GetPlan(), &plan, true);
Cout << plan;

UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "Aggregate-TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Tables"][0].GetStringSafe(), "ManyShardsTable");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Tables"][0].GetStringSafe(), "ManyShardsTable");
UNIT_ASSERT(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Stats"]["Tasks"].GetIntegerSafe() < 100);
UNIT_ASSERT(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Stats"]["Tasks"].GetIntegerSafe() > 1);
}
Expand Down Expand Up @@ -887,8 +888,8 @@ Y_UNIT_TEST_SUITE(KqpLimits) {
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "Merge");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["SortColumns"].GetArraySafe()[0], "Key (Asc)");

UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "Collect-TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Tables"][0].GetStringSafe(), "ManyShardsTable");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Tables"][0].GetStringSafe(), "ManyShardsTable");
UNIT_ASSERT(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Stats"]["Tasks"].GetIntegerSafe() < 100);
UNIT_ASSERT(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Stats"]["Tasks"].GetIntegerSafe() > 1);

Expand Down Expand Up @@ -927,15 +928,16 @@ Y_UNIT_TEST_SUITE(KqpLimits) {

NJson::TJsonValue plan;
NJson::ReadJsonTree(*result.GetStats()->GetPlan(), &plan, true);
Cout << plan;

UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Node Type"].GetStringSafe(), "Query");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Node Type"].GetStringSafe(), "ResultSet");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "Limit");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "Merge");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["SortColumns"].GetArraySafe()[0], "Key (Asc)");

UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "Limit-TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Tables"][0].GetStringSafe(), "ManyShardsTable");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Node Type"].GetStringSafe(), "TableFullScan");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Tables"][0].GetStringSafe(), "ManyShardsTable");
UNIT_ASSERT_VALUES_EQUAL(plan["Plan"]["Plans"][0]["Plans"][0]["Plans"][0]["Plans"][0]["Stats"]["Tasks"].GetIntegerSafe(), 1);

const auto resultSet = result.GetResultSet(0);
Expand Down
Loading