Skip to content

Commit e05f787

Browse files
authored
Show YDB Table names, columns in Timeline etc (#10134)
1 parent bff272f commit e05f787

File tree

2 files changed

+139
-8
lines changed

2 files changed

+139
-8
lines changed

ydb/public/lib/ydb_cli/common/plan2svg.cpp

Lines changed: 138 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
451451

452452
TStringBuilder builder;
453453

454-
if (name == "Iterator" || name == "Member") {
454+
if (name == "Iterator" || name == "Member" || name == "ToFlow") {
455455
builder << "Reference";
456456
} else {
457457
builder << name;
@@ -461,11 +461,25 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
461461
if (auto* limitNode = subNode.GetValueByPath("Limit")) {
462462
builder << ": " << limitNode->GetStringSafe();
463463
}
464+
} else if (name == "Sort") {
465+
if (auto* sortByNode = subNode.GetValueByPath("SortBy")) {
466+
auto sortBy = sortByNode->GetStringSafe();
467+
while (true) {
468+
auto p = sortBy.find("row.");
469+
if (p == sortBy.npos) {
470+
break;
471+
}
472+
sortBy.erase(p, 4);
473+
}
474+
if (sortBy) {
475+
builder << " by " << sortBy;
476+
}
477+
}
464478
} else if (name == "Filter") {
465479
if (auto* predicateNode = subNode.GetValueByPath("Predicate")) {
466480
auto filter = predicateNode->GetStringSafe();
467481
prevFilter = filter;
468-
while(true) {
482+
while (true) {
469483
auto p = filter.find("item.");
470484
if (p == filter.npos) {
471485
break;
@@ -482,14 +496,110 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
482496
}
483497
builder << ": " << filter;
484498
}
485-
} else if (name == "TopSort") {
499+
} else if (name == "Aggregate") {
500+
if (auto* aggregationNode = subNode.GetValueByPath("Aggregation")) {
501+
auto aggr = aggregationNode->GetStringSafe();
502+
if (aggr) {
503+
if (aggr.StartsWith("{")) {
504+
aggr.erase(aggr.begin());
505+
}
506+
if (aggr.EndsWith("}")) {
507+
aggr.erase(aggr.end() - 1);
508+
}
509+
while (true) {
510+
auto p = aggr.find("_yql_agg_");
511+
if (p == aggr.npos) {
512+
break;
513+
}
514+
auto l = 9;
515+
auto p1 = aggr.begin() + p + l;
516+
while (p1 != aggr.end() && *p1 >= '0' && *p1 <= '9') {
517+
p1++;
518+
l++;
519+
}
520+
auto yqlAgg = aggr.substr(p, l);
521+
if (p1 != aggr.end() && *p1 == ':') {
522+
p1++;
523+
l++;
524+
if (p1 != aggr.end() && *p1 == ' ') {
525+
p1++;
526+
l++;
527+
}
528+
}
529+
aggr.erase(p, l);
530+
531+
auto extraChars = 7;
532+
p = aggr.find(",state." + yqlAgg);
533+
if (p == aggr.npos) {
534+
p = aggr.find("state." + yqlAgg + ",");
535+
}
536+
if (p == aggr.npos) {
537+
p = aggr.find("state." + yqlAgg);
538+
extraChars = 6;
539+
}
540+
if (p != aggr.npos) {
541+
aggr.erase(p, yqlAgg.size() + extraChars);
542+
}
543+
}
544+
while (true) {
545+
auto p = aggr.find("item.");
546+
if (p == aggr.npos) {
547+
break;
548+
}
549+
aggr.erase(p, 5);
550+
}
551+
builder << " " << aggr;
552+
}
553+
}
554+
if (auto* groupByNode = subNode.GetValueByPath("GroupBy")) {
555+
auto groupBy = groupByNode->GetStringSafe();
556+
while (true) {
557+
auto p = groupBy.find("item.");
558+
if (p == groupBy.npos) {
559+
break;
560+
}
561+
groupBy.erase(p, 5);
562+
}
563+
if (groupBy) {
564+
builder << ", Group By: " << groupBy;
565+
}
566+
}
567+
} else if (name == "TableFullScan") {
568+
if (auto* tableNode = subNode.GetValueByPath("Table")) {
569+
auto table = tableNode->GetStringSafe();
570+
auto n = table.find_last_of('/');
571+
if (n != table.npos) {
572+
table = table.substr(n + 1);
573+
}
574+
builder << " " << table;
575+
}
576+
builder << "(";
577+
if (auto* readColumnsNode = subNode.GetValueByPath("ReadColumns")) {
578+
bool firstColumn = true;
579+
for (const auto& subNode : readColumnsNode->GetArray()) {
580+
if (firstColumn) {
581+
firstColumn = false;
582+
} else {
583+
builder << ", ";
584+
}
585+
builder << subNode.GetStringSafe();
586+
}
587+
}
588+
builder << ")";
589+
} else if (name == "TopSort" || name == "Top") {
486590
if (auto* limitNode = subNode.GetValueByPath("Limit")) {
487-
builder << ", Limit: " << limitNode->GetStringSafe();
591+
auto limit = limitNode->GetStringSafe();
592+
if (limit) {
593+
builder << ", Limit: " << limit;
594+
}
488595
}
489596
if (auto* topSortByNode = subNode.GetValueByPath("TopSortBy")) {
490-
builder << ", TopSortBy: " << topSortByNode->GetStringSafe();
597+
auto topSortBy = topSortByNode->GetStringSafe();
598+
if (topSortBy) {
599+
builder << ", TopSortBy: " << topSortBy;
600+
}
491601
}
492-
} else if (name == "Iterator" || name == "Member") {
602+
} else if (name == "Iterator" || name == "Member" || name == "ToFlow") {
493603
if (auto* referenceNode = subNode.GetValueByPath(name)) {
494604
auto referenceName = referenceNode->GetStringSafe();
495605
references.insert(referenceName);
@@ -640,6 +750,7 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
640750
}
641751
if (planNodeType == "Connection") {
642752
auto* keyColumnsNode = plan.GetValueByPath("KeyColumns");
753+
auto* sortColumnsNode = plan.GetValueByPath("SortColumns");
643754
if (auto* subNode = plan.GetValueByPath("Plans")) {
644755
for (auto& plan : subNode->GetArray()) {
645756
TString nodeType;
@@ -659,6 +770,11 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
659770
stage->Connections.back()->KeyColumns.push_back(keyColumn.GetStringSafe());
660771
}
661772
}
773+
if (sortColumnsNode) {
774+
for (auto& sortColumn : sortColumnsNode->GetArray()) {
775+
stage->Connections.back()->SortColumns.push_back(sortColumn.GetStringSafe());
776+
}
777+
}
662778

663779
if (auto* planNodeIdNode = plan.GetValueByPath("PlanNodeId")) {
664780
auto planNodeId = planNodeIdNode->GetStringRobust();
@@ -758,8 +874,9 @@ void TPlan::LoadSource(std::shared_ptr<TSource> source, const NJson::TJsonValue&
758874
builder << " " << sourceTypeNode->GetStringSafe();
759875
}
760876
if (auto* nameNode = subNode.GetValueByPath("Name")) {
761-
builder << " " << nameNode->GetStringSafe() << "(";
877+
builder << " " << nameNode->GetStringSafe();
762878
}
879+
builder << "(";
763880
if (auto* readColumnsNode = subNode.GetValueByPath("ReadColumns")) {
764881
bool firstColumn = true;
765882
for (const auto& subNode : readColumnsNode->GetArray()) {
@@ -1038,8 +1155,9 @@ void TPlan::PrintSvg(ui64 maxTime, ui32& offsetY, TStringBuilder& background, TS
10381155
if (!s->Info.empty()) {
10391156
for (auto text : s->Info) {
10401157
canvas
1158+
<< "<g><title>" << text << "</title>"
10411159
<< "<text clip-path='url(#clipTextPath)' font-family='Verdana' font-size='" << INTERNAL_TEXT_HEIGHT << "px' fill='" << Config.Palette.StageText << "' x='" << s->IndentX + INTERNAL_WIDTH + 2
1042-
<< "' y='" << y0 << "'>" << text << "</text>" << Endl;
1160+
<< "' y='" << y0 << "'>" << text << "</text>" << "</g>" << Endl;
10431161
y0 += (INTERNAL_TEXT_HEIGHT + INTERNAL_GAP_Y);
10441162
}
10451163
} else {
@@ -1295,6 +1413,18 @@ void TPlan::PrintSvg(ui64 maxTime, ui32& offsetY, TStringBuilder& background, TS
12951413
canvas << k;
12961414
}
12971415
}
1416+
if (!c->SortColumns.empty()) {
1417+
canvas << " SortColumns: ";
1418+
bool first = true;
1419+
for (auto s : c->SortColumns) {
1420+
if (first) {
1421+
first = false;
1422+
} else {
1423+
canvas << ", ";
1424+
}
1425+
canvas << s;
1426+
}
1427+
}
12981428
canvas
12991429
<< "</title>" << Endl
13001430
<< " <polygon points='" << x + INTERNAL_WIDTH << "," << y + INTERNAL_HEIGHT << " "

ydb/public/lib/ydb_cli/common/plan2svg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class TConnection {
9090
std::shared_ptr<TSingleMetric> InputBytes;
9191
std::shared_ptr<TSingleMetric> InputRows;
9292
std::vector<std::string> KeyColumns;
93+
std::vector<std::string> SortColumns;
9394
bool CteConnection = false;
9495
ui32 CteIndentX = 0;
9596
ui32 CteOffsetY = 0;

0 commit comments

Comments
 (0)