@@ -451,7 +451,7 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
451
451
452
452
TStringBuilder builder;
453
453
454
- if (name == " Iterator" || name == " Member" ) {
454
+ if (name == " Iterator" || name == " Member" || name == " ToFlow " ) {
455
455
builder << " Reference" ;
456
456
} else {
457
457
builder << name;
@@ -461,11 +461,25 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
461
461
if (auto * limitNode = subNode.GetValueByPath (" Limit" )) {
462
462
builder << " : " << limitNode->GetStringSafe ();
463
463
}
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
+ }
464
478
} else if (name == " Filter" ) {
465
479
if (auto * predicateNode = subNode.GetValueByPath (" Predicate" )) {
466
480
auto filter = predicateNode->GetStringSafe ();
467
481
prevFilter = filter;
468
- while (true ) {
482
+ while (true ) {
469
483
auto p = filter.find (" item." );
470
484
if (p == filter.npos ) {
471
485
break ;
@@ -482,14 +496,110 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
482
496
}
483
497
builder << " : " << filter;
484
498
}
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" ) {
486
590
if (auto * limitNode = subNode.GetValueByPath (" Limit" )) {
487
- builder << " , Limit: " << limitNode->GetStringSafe ();
591
+ auto limit = limitNode->GetStringSafe ();
592
+ if (limit) {
593
+ builder << " , Limit: " << limit;
594
+ }
488
595
}
489
596
if (auto * topSortByNode = subNode.GetValueByPath (" TopSortBy" )) {
490
- builder << " , TopSortBy: " << topSortByNode->GetStringSafe ();
597
+ auto topSortBy = topSortByNode->GetStringSafe ();
598
+ if (topSortBy) {
599
+ builder << " , TopSortBy: " << topSortBy;
600
+ }
491
601
}
492
- } else if (name == " Iterator" || name == " Member" ) {
602
+ } else if (name == " Iterator" || name == " Member" || name == " ToFlow " ) {
493
603
if (auto * referenceNode = subNode.GetValueByPath (name)) {
494
604
auto referenceName = referenceNode->GetStringSafe ();
495
605
references.insert (referenceName);
@@ -640,6 +750,7 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
640
750
}
641
751
if (planNodeType == " Connection" ) {
642
752
auto * keyColumnsNode = plan.GetValueByPath (" KeyColumns" );
753
+ auto * sortColumnsNode = plan.GetValueByPath (" SortColumns" );
643
754
if (auto * subNode = plan.GetValueByPath (" Plans" )) {
644
755
for (auto & plan : subNode->GetArray ()) {
645
756
TString nodeType;
@@ -659,6 +770,11 @@ void TPlan::LoadStage(std::shared_ptr<TStage> stage, const NJson::TJsonValue& no
659
770
stage->Connections .back ()->KeyColumns .push_back (keyColumn.GetStringSafe ());
660
771
}
661
772
}
773
+ if (sortColumnsNode) {
774
+ for (auto & sortColumn : sortColumnsNode->GetArray ()) {
775
+ stage->Connections .back ()->SortColumns .push_back (sortColumn.GetStringSafe ());
776
+ }
777
+ }
662
778
663
779
if (auto * planNodeIdNode = plan.GetValueByPath (" PlanNodeId" )) {
664
780
auto planNodeId = planNodeIdNode->GetStringRobust ();
@@ -758,8 +874,9 @@ void TPlan::LoadSource(std::shared_ptr<TSource> source, const NJson::TJsonValue&
758
874
builder << " " << sourceTypeNode->GetStringSafe ();
759
875
}
760
876
if (auto * nameNode = subNode.GetValueByPath (" Name" )) {
761
- builder << " " << nameNode->GetStringSafe () << " ( " ;
877
+ builder << " " << nameNode->GetStringSafe ();
762
878
}
879
+ builder << " (" ;
763
880
if (auto * readColumnsNode = subNode.GetValueByPath (" ReadColumns" )) {
764
881
bool firstColumn = true ;
765
882
for (const auto & subNode : readColumnsNode->GetArray ()) {
@@ -1038,8 +1155,9 @@ void TPlan::PrintSvg(ui64 maxTime, ui32& offsetY, TStringBuilder& background, TS
1038
1155
if (!s->Info .empty ()) {
1039
1156
for (auto text : s->Info ) {
1040
1157
canvas
1158
+ << " <g><title>" << text << " </title>"
1041
1159
<< " <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;
1043
1161
y0 += (INTERNAL_TEXT_HEIGHT + INTERNAL_GAP_Y);
1044
1162
}
1045
1163
} else {
@@ -1295,6 +1413,18 @@ void TPlan::PrintSvg(ui64 maxTime, ui32& offsetY, TStringBuilder& background, TS
1295
1413
canvas << k;
1296
1414
}
1297
1415
}
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
+ }
1298
1428
canvas
1299
1429
<< " </title>" << Endl
1300
1430
<< " <polygon points='" << x + INTERNAL_WIDTH << " ," << y + INTERNAL_HEIGHT << " "
0 commit comments