29
29
#include < unordered_map>
30
30
#include < regex>
31
31
32
+ #include < ydb/library/yql/utils/log/log.h>
33
+
34
+
32
35
namespace NKikimr {
33
36
namespace NKqp {
34
37
@@ -1015,6 +1018,10 @@ class TxPlanSerializer {
1015
1018
operatorId = Visit (maybeExtend.Cast (), planNode);
1016
1019
} else if (auto maybeToFlow = TMaybeNode<TCoToFlow>(node)) {
1017
1020
operatorId = Visit (maybeToFlow.Cast (), planNode);
1021
+ } else if (auto maybeAssumeSorted = TMaybeNode<TCoAssumeSorted>(node)) {
1022
+ operatorId = Visit (maybeAssumeSorted.Cast (), planNode);
1023
+ } else if (auto maybeMember = TMaybeNode<TCoMember>(node)) {
1024
+ operatorId = Visit (maybeMember.Cast (), planNode);
1018
1025
} else if (auto maybeIter = TMaybeNode<TCoIterator>(node)) {
1019
1026
operatorId = Visit (maybeIter.Cast (), planNode);
1020
1027
} else if (auto maybePartitionByKey = TMaybeNode<TCoPartitionByKey>(node)) {
@@ -1183,6 +1190,56 @@ class TxPlanSerializer {
1183
1190
return AddOperator (planNode, " ConstantExpr" , std::move (op));
1184
1191
}
1185
1192
1193
+ TMaybe<std::variant<ui32, TArgContext>> Visit (const TCoAssumeSorted& assumeSorted, TQueryPlanNode& planNode) {
1194
+ const auto precomputeValue = NPlanUtils::PrettyExprStr (assumeSorted.Input ());
1195
+
1196
+ TOperator op;
1197
+ op.Properties [" Name" ] = " AssumeSorted" ;
1198
+
1199
+ if (auto maybeResultBinding = ContainResultBinding (precomputeValue)) {
1200
+ auto [txId, resId] = *maybeResultBinding;
1201
+ planNode.CteRefName = TStringBuilder () << " precompute_" << txId << " _" << resId;
1202
+ op.Properties [" AssumeSorted" ] = *planNode.CteRefName ;
1203
+ } else {
1204
+ auto inputs = Visit (assumeSorted.Input ().Ptr (), planNode);
1205
+ if (inputs.size () == 1 ) {
1206
+ return inputs[0 ];
1207
+ } else {
1208
+ return TMaybe<std::variant<ui32, TArgContext>> ();
1209
+ }
1210
+ }
1211
+
1212
+ return AddOperator (planNode, " ConstantExpr" , std::move (op));
1213
+ }
1214
+
1215
+ TMaybe<std::variant<ui32, TArgContext>> Visit (const TCoMember& member, TQueryPlanNode& planNode) {
1216
+ const auto memberValue = NPlanUtils::PrettyExprStr (member.Struct ());
1217
+
1218
+ TOperator op;
1219
+ op.Properties [" Name" ] = " Member" ;
1220
+
1221
+ if (auto maybeResultBinding = ContainResultBinding (memberValue)) {
1222
+ auto [txId, resId] = *maybeResultBinding;
1223
+ planNode.CteRefName = TStringBuilder () << " precompute_" << txId << " _" << resId;
1224
+ op.Properties [" Member" ] = *planNode.CteRefName ;
1225
+ } else {
1226
+ auto inputs = Visit (member.Struct ().Ptr (), planNode);
1227
+ if (inputs.size () == 1 ) {
1228
+ return inputs[0 ];
1229
+ } else {
1230
+ return TMaybe<std::variant<ui32, TArgContext>> ();
1231
+ }
1232
+ }
1233
+
1234
+ if (std::find_if (planNode.Operators .begin (), planNode.Operators .end (), [op](const auto & x) {
1235
+ return x.Properties .at (" Name" )==" Member" && x.Properties .at (" Member" )==op.Properties .at (" Member" );
1236
+ })) {
1237
+ return TMaybe<std::variant<ui32, TArgContext>> ();
1238
+ }
1239
+
1240
+ return AddOperator (planNode, " ConstantExpr" , std::move (op));
1241
+ }
1242
+
1186
1243
std::variant<ui32, TArgContext> Visit (const TCoIterator& iter, TQueryPlanNode& planNode) {
1187
1244
const auto iterValue = NPlanUtils::PrettyExprStr (iter.List ());
1188
1245
@@ -1825,6 +1882,8 @@ void BuildPlanIndex(NJson::TJsonValue& plan, THashMap<int, NJson::TJsonValue>& p
1825
1882
auto pos = precomputeName.find (" precompute" );
1826
1883
if (pos != TString::npos) {
1827
1884
precomputes[precomputeName.substr (pos)] = plan;
1885
+ } else if (precomputeName.size ()>=4 && precomputeName.find (" CTE " ) != TString::npos) {
1886
+ precomputes[precomputeName.substr (4 )] = plan;
1828
1887
}
1829
1888
}
1830
1889
@@ -1872,6 +1931,11 @@ NJson::TJsonValue ReconstructQueryPlanRec(const NJson::TJsonValue& plan,
1872
1931
1873
1932
NJson::TJsonValue result;
1874
1933
result[" PlanNodeId" ] = currentNodeId;
1934
+
1935
+ // if (plan.GetMapSafe().contains("PlanNodeId")) {
1936
+ // YQL_CLOG(TRACE, CoreDq) << "Recursed into " << plan.GetMapSafe().at("PlanNodeId").GetIntegerSafe() << ", constructed: " << currentNodeId;
1937
+ // }
1938
+
1875
1939
if (plan.GetMapSafe ().contains (" PlanNodeType" )) {
1876
1940
result[" PlanNodeType" ] = plan.GetMapSafe ().at (" PlanNodeType" ).GetStringSafe ();
1877
1941
}
@@ -1889,7 +1953,7 @@ NJson::TJsonValue ReconstructQueryPlanRec(const NJson::TJsonValue& plan,
1889
1953
return result;
1890
1954
}
1891
1955
1892
- if (plan.GetMapSafe ().at (" Node Type" ) == " TableLookup" ) {
1956
+ if (plan.GetMapSafe ().at (" Node Type" ). GetStringSafe () == " TableLookup" ) {
1893
1957
NJson::TJsonValue newOps;
1894
1958
NJson::TJsonValue op;
1895
1959
@@ -1905,20 +1969,32 @@ NJson::TJsonValue ReconstructQueryPlanRec(const NJson::TJsonValue& plan,
1905
1969
}
1906
1970
1907
1971
for (auto p : plan.GetMapSafe ().at (" Plans" ).GetArraySafe ()) {
1908
- if (p.GetMapSafe ().at (" Node Type" ).GetStringSafe ().find (" Precompute" ) == TString::npos) {
1972
+ if (!p.GetMapSafe ().contains (" Operators" ) && p.GetMapSafe ().contains (" CTE Name" )) {
1973
+ auto precompute = p.GetMapSafe ().at (" CTE Name" ).GetStringSafe ();
1974
+ if (precomputes.contains (precompute)) {
1975
+ // YQL_CLOG(TRACE, CoreDq) << "Following precompute: " << precompute ;
1976
+ planInputs.AppendValue (ReconstructQueryPlanRec (precomputes.at (precompute), 0 , planIndex, precomputes, nodeCounter));
1977
+ } // else {
1978
+ // YQL_CLOG(TRACE, CoreDq) << "Didn't find precompute: " << precompute ;
1979
+ // }
1980
+ } else if (p.GetMapSafe ().at (" Node Type" ).GetStringSafe ().find (" Precompute" ) == TString::npos) {
1909
1981
planInputs.AppendValue (ReconstructQueryPlanRec (p, 0 , planIndex, precomputes, nodeCounter));
1910
1982
}
1911
1983
}
1912
1984
result[" Plans" ] = planInputs;
1913
1985
return result;
1914
1986
}
1915
1987
1916
- if (plan.GetMapSafe ().contains (" CTE Name" ) && plan.GetMapSafe ().at (" Node Type" ) == " ConstantExpr" ) {
1988
+ if (plan.GetMapSafe ().contains (" CTE Name" ) && plan.GetMapSafe ().at (" Node Type" ). GetStringSafe () == " ConstantExpr" ) {
1917
1989
auto precompute = plan.GetMapSafe ().at (" CTE Name" ).GetStringSafe ();
1918
1990
if (!precomputes.contains (precompute)) {
1919
- result[" Node Type" ] = " ConstantExpr" ;
1991
+ // YQL_CLOG(TRACE, CoreDq) << "Didn't find precompute: " << precompute ;
1992
+
1993
+ result[" Node Type" ] = plan.GetMapSafe ().at (" Node Type" );
1920
1994
return result;
1921
1995
}
1996
+ // YQL_CLOG(TRACE, CoreDq) << "Following precompute: " << precompute ;
1997
+
1922
1998
return ReconstructQueryPlanRec (precomputes.at (precompute), 0 , planIndex, precomputes, nodeCounter);
1923
1999
}
1924
2000
@@ -1930,6 +2006,11 @@ NJson::TJsonValue ReconstructQueryPlanRec(const NJson::TJsonValue& plan,
1930
2006
auto opName = op.GetMapSafe ().at (" Name" ).GetStringSafe ();
1931
2007
1932
2008
for (auto opInput : op.GetMapSafe ().at (" Inputs" ).GetArraySafe ()) {
2009
+ // Sometimes we have inputs for these operators, don't process them
2010
+ if (opName == " TablePointLookup" ) {
2011
+ break ;
2012
+ }
2013
+
1933
2014
if (opInput.GetMapSafe ().contains (" ExternalPlanNodeId" )) {
1934
2015
auto inputPlanKey = opInput.GetMapSafe ().at (" ExternalPlanNodeId" ).GetIntegerSafe ();
1935
2016
auto inputPlan = planIndex.at (inputPlanKey);
@@ -1938,8 +2019,9 @@ NJson::TJsonValue ReconstructQueryPlanRec(const NJson::TJsonValue& plan,
1938
2019
auto inputPlanId = opInput.GetMapSafe ().at (" InternalOperatorId" ).GetIntegerSafe ();
1939
2020
planInputs.push_back ( ReconstructQueryPlanRec (plan, inputPlanId, planIndex, precomputes, nodeCounter));
1940
2021
}
1941
- // temp hack
1942
- if (opName == " Filter" ) {
2022
+
2023
+ // Sometimes we have multiple inputs for these operators, break after the first one
2024
+ if (opName == " Filter" || opName == " TopSort" ) {
1943
2025
break ;
1944
2026
}
1945
2027
}
@@ -1948,17 +2030,31 @@ NJson::TJsonValue ReconstructQueryPlanRec(const NJson::TJsonValue& plan,
1948
2030
op.GetMapSafe ().erase (" Inputs" );
1949
2031
}
1950
2032
1951
- if (op.GetMapSafe ().contains (" Input" ) || op.GetMapSafe ().contains (" ToFlow" )) {
2033
+ if (op.GetMapSafe ().contains (" Input" )
2034
+ || op.GetMapSafe ().contains (" ToFlow" )
2035
+ || op.GetMapSafe ().contains (" Member" )
2036
+ || op.GetMapSafe ().contains (" AssumeSorted" )
2037
+ || op.GetMapSafe ().contains (" Iterator" )) {
2038
+
1952
2039
TString maybePrecompute = " " ;
1953
2040
if (op.GetMapSafe ().contains (" Input" )) {
1954
2041
maybePrecompute = op.GetMapSafe ().at (" Input" ).GetStringSafe ();
1955
2042
} else if (op.GetMapSafe ().contains (" ToFlow" )) {
1956
2043
maybePrecompute = op.GetMapSafe ().at (" ToFlow" ).GetStringSafe ();
2044
+ } else if (op.GetMapSafe ().contains (" Member" )) {
2045
+ maybePrecompute = op.GetMapSafe ().at (" Member" ).GetStringSafe ();
2046
+ } else if (op.GetMapSafe ().contains (" AssumeSorted" )) {
2047
+ maybePrecompute = op.GetMapSafe ().at (" AssumeSorted" ).GetStringSafe ();
2048
+ } else if (op.GetMapSafe ().contains (" Iterator" )) {
2049
+ maybePrecompute = op.GetMapSafe ().at (" Iterator" ).GetStringSafe ();
1957
2050
}
1958
2051
1959
2052
if (precomputes.contains (maybePrecompute)) {
2053
+ // YQL_CLOG(TRACE, CoreDq) << "Following precompute: " << maybePrecompute ;
1960
2054
planInputs.push_back (ReconstructQueryPlanRec (precomputes.at (maybePrecompute), 0 , planIndex, precomputes, nodeCounter));
1961
- }
2055
+ } // else {
2056
+ // YQL_CLOG(TRACE, CoreDq) << "Didn't find precompute: " << maybePrecompute ;
2057
+ // }
1962
2058
}
1963
2059
1964
2060
result[" Node Type" ] = opName;
@@ -1988,7 +2084,9 @@ NJson::TJsonValue SimplifyQueryPlan(NJson::TJsonValue& plan) {
1988
2084
" Stage" ,
1989
2085
" Iterator" ,
1990
2086
" PartitionByKey" ,
1991
- " ToFlow"
2087
+ " ToFlow" ,
2088
+ " Member" ,
2089
+ " AssumeSorted"
1992
2090
};
1993
2091
1994
2092
THashMap<int , NJson::TJsonValue> planIndex;
0 commit comments