diff options
author | Maksim Kita <kitaetoya@gmail.com> | 2023-06-01 14:30:12 +0000 |
---|---|---|
committer | maksim-kita <maksim-kita@yandex-team.com> | 2023-06-01 17:30:12 +0300 |
commit | 99a6a4fce57e826d1bc23bdf359bfa4b48121e36 (patch) | |
tree | c2ce28700c80d59bcf0d001cc03a7e030fc2e293 | |
parent | 0fa4c2d7731ee14f0d45501830d5d66377530e26 (diff) | |
download | ydb-99a6a4fce57e826d1bc23bdf359bfa4b48121e36.tar.gz |
"Indexes filter push down over Sort or Limit"
"Indexes filter push down over Sort or Limit"
Pull Request resolved: #197
-rw-r--r-- | ydb/core/kqp/opt/logical/kqp_opt_log.cpp | 10 | ||||
-rw-r--r-- | ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp | 142 | ||||
-rw-r--r-- | ydb/core/kqp/opt/logical/kqp_opt_log_rules.h | 4 | ||||
-rw-r--r-- | ydb/core/kqp/opt/physical/kqp_opt_phy_limit.cpp | 2 | ||||
-rw-r--r-- | ydb/core/kqp/opt/physical/kqp_opt_phy_sort.cpp | 3 | ||||
-rw-r--r-- | ydb/core/kqp/ut/common/kqp_ut_common.cpp | 5 | ||||
-rw-r--r-- | ydb/core/kqp/ut/common/kqp_ut_common.h | 2 | ||||
-rw-r--r-- | ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp | 71 | ||||
-rw-r--r-- | ydb/library/yql/core/yql_opt_utils.cpp | 9 | ||||
-rw-r--r-- | ydb/library/yql/core/yql_opt_utils.h | 6 |
10 files changed, 199 insertions, 55 deletions
diff --git a/ydb/core/kqp/opt/logical/kqp_opt_log.cpp b/ydb/core/kqp/opt/logical/kqp_opt_log.cpp index 41c8dd402e1..6fbd74f0157 100644 --- a/ydb/core/kqp/opt/logical/kqp_opt_log.cpp +++ b/ydb/core/kqp/opt/logical/kqp_opt_log.cpp @@ -35,6 +35,7 @@ public: AddHandler(0, &TDqJoin::Match, HNDL(JoinToIndexLookup)); AddHandler(0, &TCoCalcOverWindowBase::Match, HNDL(ExpandWindowFunctions)); AddHandler(0, &TCoCalcOverWindowGroup::Match, HNDL(ExpandWindowFunctions)); + AddHandler(0, &TCoFlatMap::Match, HNDL(PushExtractedPredicateToReadTable)); AddHandler(0, &TCoTop::Match, HNDL(RewriteTopSortOverIndexRead)); AddHandler(0, &TCoTopSort::Match, HNDL(RewriteTopSortOverIndexRead)); AddHandler(0, &TCoTake::Match, HNDL(RewriteTakeOverIndexRead)); @@ -49,7 +50,6 @@ public: AddHandler(0, &TCoTop::Match, HNDL(TopSortOverExtend)); AddHandler(0, &TCoTopSort::Match, HNDL(TopSortOverExtend)); - AddHandler(1, &TCoFlatMap::Match, HNDL(PushExtractedPredicateToReadTable)); AddHandler(1, &TKqlReadTableIndex::Match, HNDL(RewriteIndexRead)); AddHandler(1, &TKqlLookupIndex::Match, HNDL(RewriteLookupIndex)); AddHandler(1, &TKqlStreamLookupIndex::Match, HNDL(RewriteStreamLookupIndex)); @@ -123,14 +123,14 @@ protected: return output; } - TMaybeNode<TExprBase> RewriteTopSortOverIndexRead(TExprBase node, TExprContext& ctx) { - TExprBase output = KqpRewriteTopSortOverIndexRead(node, ctx, KqpCtx); + TMaybeNode<TExprBase> RewriteTopSortOverIndexRead(TExprBase node, TExprContext& ctx, const TGetParents& getParents) { + TExprBase output = KqpRewriteTopSortOverIndexRead(node, ctx, KqpCtx, *getParents()); DumpAppliedRule("RewriteTopSortOverIndexRead", node.Ptr(), output.Ptr(), ctx); return output; } - TMaybeNode<TExprBase> RewriteTakeOverIndexRead(TExprBase node, TExprContext& ctx) { - TExprBase output = KqpRewriteTakeOverIndexRead(node, ctx, KqpCtx); + TMaybeNode<TExprBase> RewriteTakeOverIndexRead(TExprBase node, TExprContext& ctx, const TGetParents& getParents) { + TExprBase output = KqpRewriteTakeOverIndexRead(node, ctx, KqpCtx, *getParents()); DumpAppliedRule("RewriteTakeOverIndexRead", node.Ptr(), output.Ptr(), ctx); return output; } 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 374898f93d1..19172c04397 100644 --- a/ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp +++ b/ydb/core/kqp/opt/logical/kqp_opt_log_indexes.cpp @@ -3,6 +3,7 @@ #include <ydb/core/kqp/provider/yql_kikimr_provider_impl.h> #include <ydb/library/yql/dq/opt/dq_opt_phy.h> +#include <ydb/library/yql/core/yql_opt_utils.h> namespace NKikimr::NKqp::NOpt { @@ -250,19 +251,19 @@ TExprBase DoRewriteIndexRead(const TReadMatch& read, TExprContext& ctx, TVector<TExprBase> structMembers; structMembers.reserve(keyColumnsList.Size()); - for (const auto& c : keyColumnsList) { + for (const auto& keyColumn : keyColumnsList) { auto member = Build<TCoNameValueTuple>(ctx, read.Pos()) - .Name().Build(c.Value()) + .Name().Build(keyColumn.Value()) .Value<TCoMember>() .Struct(arg) - .Name().Build(c.Value()) + .Name().Build(keyColumn.Value()) .Build() .Done(); structMembers.push_back(member); } - readIndexTable= Build<TCoMap>(ctx, read.Pos()) + readIndexTable = Build<TCoMap>(ctx, read.Pos()) .Input(readIndexTable) .Lambda() .Args({arg}) @@ -379,75 +380,138 @@ TExprBase KqpRewriteStreamLookupIndex(const TExprBase& node, TExprContext& ctx, return node; } +/// Can push flat map node to read from table using only columns available in table description +bool CanPushFlatMap(const TCoFlatMapBase& flatMap, const TKikimrTableDescription& tableDesc, const TParentsMap& parentsMap, TVector<TString> & extraColumns) { + auto flatMapLambda = flatMap.Lambda(); + if (!IsFilterFlatMap(flatMapLambda)) { + return false; + } + + const auto & flatMapLambdaArgument = flatMapLambda.Args().Arg(0).Ref(); + auto flatMapLambdaConditional = flatMapLambda.Body().Cast<TCoConditionalValueBase>(); + + TSet<TString> lambdaSubset; + if (!HaveFieldsSubset(flatMapLambdaConditional.Predicate().Ptr(), flatMapLambdaArgument, lambdaSubset, parentsMap)) { + return false; + } + + for (auto & lambdaColumn : lambdaSubset) { + auto columnIndex = tableDesc.GetKeyColumnIndex(lambdaColumn); + if (!columnIndex) { + return false; + } + } + + extraColumns.insert(extraColumns.end(), lambdaSubset.begin(), lambdaSubset.end()); + return true; +} + // The index and main table have same number of rows, so we can push a copy of TCoTopSort or TCoTake // through TKqlLookupTable. // The simplest way is to match TopSort or Take over TKqlReadTableIndex. -TExprBase KqpRewriteTopSortOverIndexRead(const TExprBase& node, TExprContext& ctx, const TKqpOptimizeContext& kqpCtx) { +// Additionally if there is TopSort or Take over filter, and filter depends only on columns available in index, +// we also push copy of filter through TKqlLookupTable. +TExprBase KqpRewriteTopSortOverIndexRead(const TExprBase& node, TExprContext& ctx, const TKqpOptimizeContext& kqpCtx, + const TParentsMap& parentsMap) { if (!node.Maybe<TCoTopBase>()) { return node; } const auto topBase = node.Maybe<TCoTopBase>().Cast(); - if (auto readTableIndex = TReadMatch::Match(topBase.Input())) { + auto maybeFlatMap = topBase.Input().Maybe<TCoFlatMap>(); + TExprBase input = maybeFlatMap ? maybeFlatMap.Cast().Input() : topBase.Input(); - const auto& tableDesc = GetTableData(*kqpCtx.Tables, kqpCtx.Cluster, readTableIndex.Table().Path()); - const auto& [indexMeta, _ ] = tableDesc.Metadata->GetIndexMetadata(TString(readTableIndex.Index().Value())); - const auto& indexDesc = kqpCtx.Tables->ExistingTable(kqpCtx.Cluster, indexMeta->Name); + auto readTableIndex = TReadMatch::Match(input); + if (!readTableIndex) + return node; - TVector<TString> sortByColumns; + const auto& tableDesc = GetTableData(*kqpCtx.Tables, kqpCtx.Cluster, readTableIndex.Table().Path()); + const auto& [indexMeta, _ ] = tableDesc.Metadata->GetIndexMetadata(TString(readTableIndex.Index().Value())); + const auto& indexDesc = kqpCtx.Tables->ExistingTable(kqpCtx.Cluster, indexMeta->Name); - if (!CanPushTopSort(topBase, indexDesc, &sortByColumns)) { - return node; - } + TVector<TString> extraColumns; + + if (maybeFlatMap && !CanPushFlatMap(maybeFlatMap.Cast(), indexDesc, parentsMap, extraColumns)) + return node; + + if (!CanPushTopSort(topBase, indexDesc, &extraColumns)) { + return node; + } - auto filter = [&ctx, &node, &topBase](const TExprBase& in) mutable { - auto newTop = Build<TCoTopBase>(ctx, node.Pos()) - .CallableName(node.Ref().Content()) + auto filter = [&](const TExprBase& in) mutable { + auto sortInput = in; + + if (maybeFlatMap) + { + sortInput = Build<TCoFlatMap>(ctx, node.Pos()) .Input(in) - .KeySelectorLambda(ctx.DeepCopyLambda(topBase.KeySelectorLambda().Ref())) - .SortDirections(topBase.SortDirections()) - .Count(topBase.Count()) + .Lambda(ctx.DeepCopyLambda(maybeFlatMap.Lambda().Ref())) .Done(); - return TExprBase(newTop); - }; - - auto lookup = DoRewriteIndexRead(readTableIndex, ctx, tableDesc, indexMeta, - kqpCtx.IsScanQuery(), sortByColumns, filter); + } - return Build<TCoTopBase>(ctx, node.Pos()) + auto newTop = Build<TCoTopBase>(ctx, node.Pos()) .CallableName(node.Ref().Content()) - .Input(lookup) + .Input(sortInput) .KeySelectorLambda(ctx.DeepCopyLambda(topBase.KeySelectorLambda().Ref())) .SortDirections(topBase.SortDirections()) .Count(topBase.Count()) .Done(); - } - return node; + return TExprBase(newTop); + }; + + auto lookup = DoRewriteIndexRead(readTableIndex, ctx, tableDesc, indexMeta, + kqpCtx.IsScanQuery(), extraColumns, filter); + + return Build<TCoTopBase>(ctx, node.Pos()) + .CallableName(node.Ref().Content()) + .Input(lookup) + .KeySelectorLambda(ctx.DeepCopyLambda(topBase.KeySelectorLambda().Ref())) + .SortDirections(topBase.SortDirections()) + .Count(topBase.Count()) + .Done(); } -TExprBase KqpRewriteTakeOverIndexRead(const TExprBase& node, TExprContext& ctx, const TKqpOptimizeContext& kqpCtx) { +TExprBase KqpRewriteTakeOverIndexRead(const TExprBase& node, TExprContext& ctx, const TKqpOptimizeContext& kqpCtx, + const TParentsMap& parentsMap) { if (!node.Maybe<TCoTake>()) { return node; } auto take = node.Maybe<TCoTake>().Cast(); - if (auto readTableIndex = TReadMatch::Match(take.Input())) { + auto maybeFlatMap = take.Input().Maybe<TCoFlatMap>(); + TExprBase input = maybeFlatMap ? maybeFlatMap.Cast().Input() : take.Input(); + + auto readTableIndex = TReadMatch::Match(input); + if (!readTableIndex) + return node; - const auto& tableDesc = GetTableData(*kqpCtx.Tables, kqpCtx.Cluster, readTableIndex.Table().Path()); - const auto& [indexMeta, _ ] = tableDesc.Metadata->GetIndexMetadata(TString(readTableIndex.Index().Value())); + const auto& tableDesc = GetTableData(*kqpCtx.Tables, kqpCtx.Cluster, readTableIndex.Table().Path()); + const auto& [indexMeta, _ ] = tableDesc.Metadata->GetIndexMetadata(TString(readTableIndex.Index().Value())); + const auto& indexDesc = kqpCtx.Tables->ExistingTable(kqpCtx.Cluster, indexMeta->Name); - auto filter = [&ctx, &node](const TExprBase& in) mutable { - // Change input for TCoTake. New input is result of TKqlReadTable. - return TExprBase(ctx.ChangeChild(*node.Ptr(), 0, in.Ptr())); - }; + TVector<TString> extraColumns; + if (maybeFlatMap && !CanPushFlatMap(maybeFlatMap.Cast(), indexDesc, parentsMap, extraColumns)) + return node; - return DoRewriteIndexRead(readTableIndex, ctx, tableDesc, indexMeta, kqpCtx.IsScanQuery(), {}, filter); - } + auto filter = [&](const TExprBase& in) mutable { + auto takeChild = in; - return node; + if (maybeFlatMap) + { + takeChild = Build<TCoFlatMap>(ctx, node.Pos()) + .Input(in) + .Lambda(ctx.DeepCopyLambda(maybeFlatMap.Lambda().Ref())) + .Done(); + } + + // Change input for TCoTake. New input is result of TKqlReadTable. + return TExprBase(ctx.ChangeChild(*node.Ptr(), 0, takeChild.Ptr())); + }; + + return DoRewriteIndexRead(readTableIndex, ctx, tableDesc, indexMeta, kqpCtx.IsScanQuery(), extraColumns, filter); } } // namespace NKikimr::NKqp::NOpt diff --git a/ydb/core/kqp/opt/logical/kqp_opt_log_rules.h b/ydb/core/kqp/opt/logical/kqp_opt_log_rules.h index ecab5b3406a..0a02d10d077 100644 --- a/ydb/core/kqp/opt/logical/kqp_opt_log_rules.h +++ b/ydb/core/kqp/opt/logical/kqp_opt_log_rules.h @@ -45,10 +45,10 @@ NYql::NNodes::TExprBase KqpRewriteLookupTable(const NYql::NNodes::TExprBase& nod const TKqpOptimizeContext& kqpCtx); NYql::NNodes::TExprBase KqpRewriteTopSortOverIndexRead(const NYql::NNodes::TExprBase& node, NYql::TExprContext&, - const TKqpOptimizeContext& kqpCtx); + const TKqpOptimizeContext& kqpCtx, const NYql::TParentsMap& parentsMap); NYql::NNodes::TExprBase KqpRewriteTakeOverIndexRead(const NYql::NNodes::TExprBase& node, NYql::TExprContext&, - const TKqpOptimizeContext& kqpCtx); + const TKqpOptimizeContext& kqpCtx, const NYql::TParentsMap& parentsMap); NYql::NNodes::TExprBase KqpDeleteOverLookup(const NYql::NNodes::TExprBase& node, NYql::TExprContext& ctx, const TKqpOptimizeContext &kqpCtx); diff --git a/ydb/core/kqp/opt/physical/kqp_opt_phy_limit.cpp b/ydb/core/kqp/opt/physical/kqp_opt_phy_limit.cpp index 77f5f426d0c..1509730963b 100644 --- a/ydb/core/kqp/opt/physical/kqp_opt_phy_limit.cpp +++ b/ydb/core/kqp/opt/physical/kqp_opt_phy_limit.cpp @@ -18,7 +18,7 @@ TExprBase KqpApplyLimitToReadTable(TExprBase node, TExprContext& ctx, const TKqp auto input = maybeSkip ? maybeSkip.Cast().Input() : take.Input(); bool isReadTable = input.Maybe<TKqpReadTable>().IsValid(); - bool isReadTableRanges = input.Maybe<TKqpReadTableRanges>().IsValid() || input.Maybe<TKqpReadOlapTableRanges>().IsValid() ; + bool isReadTableRanges = input.Maybe<TKqpReadTableRanges>().IsValid() || input.Maybe<TKqpReadOlapTableRanges>().IsValid(); if (!isReadTable && !isReadTableRanges) { return node; diff --git a/ydb/core/kqp/opt/physical/kqp_opt_phy_sort.cpp b/ydb/core/kqp/opt/physical/kqp_opt_phy_sort.cpp index 7d39948193f..5b0783775d2 100644 --- a/ydb/core/kqp/opt/physical/kqp_opt_phy_sort.cpp +++ b/ydb/core/kqp/opt/physical/kqp_opt_phy_sort.cpp @@ -51,9 +51,10 @@ TExprBase KqpRemoveRedundantSortByPk(TExprBase node, TExprContext& ctx, const TK if (!isReadTable && !isReadTableRanges) { return node; } + auto& tableDesc = kqpCtx.Tables->ExistingTable(kqpCtx.Cluster, GetReadTablePath(input, isReadTableRanges)); - if(tableDesc.Metadata->Kind == EKikimrTableKind::Olap) { + if (tableDesc.Metadata->Kind == EKikimrTableKind::Olap) { // OLAP tables are read in parallel, so we need to keep the out sort. return node; } diff --git a/ydb/core/kqp/ut/common/kqp_ut_common.cpp b/ydb/core/kqp/ut/common/kqp_ut_common.cpp index cbfaf808998..7243163aed0 100644 --- a/ydb/core/kqp/ut/common/kqp_ut_common.cpp +++ b/ydb/core/kqp/ut/common/kqp_ut_common.cpp @@ -919,7 +919,7 @@ std::vector<NJson::TJsonValue> FindPlanStages(const NJson::TJsonValue& plan) { return stages; } -void CreateSampleTablesWithIndex(TSession& session) { +void CreateSampleTablesWithIndex(TSession& session, bool populateTables) { auto res = session.ExecuteSchemeQuery(R"( --!syntax_v1 CREATE TABLE `/Root/SecondaryKeys` ( @@ -950,6 +950,9 @@ void CreateSampleTablesWithIndex(TSession& session) { )").GetValueSync(); UNIT_ASSERT_C(res.IsSuccess(), res.GetIssues().ToString()); + if (!populateTables) + return; + auto result = session.ExecuteDataQuery(R"( REPLACE INTO `KeyValue` (Key, Value) VALUES diff --git a/ydb/core/kqp/ut/common/kqp_ut_common.h b/ydb/core/kqp/ut/common/kqp_ut_common.h index c9bce432095..f24f7bc1412 100644 --- a/ydb/core/kqp/ut/common/kqp_ut_common.h +++ b/ydb/core/kqp/ut/common/kqp_ut_common.h @@ -263,7 +263,7 @@ inline void AssertSuccessResult(const NYdb::TStatus& result) { UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString()); } -void CreateSampleTablesWithIndex(NYdb::NTable::TSession& session); +void CreateSampleTablesWithIndex(NYdb::NTable::TSession& session, bool populateTables = true); // KQP proxy needs to asynchronously receive tenants info before it is able to serve requests that have // database name specified. Before that it returns errors. diff --git a/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp b/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp index 5e9d5ce8df4..5e2554d4648 100644 --- a/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp +++ b/ydb/core/kqp/ut/indexes/kqp_indexes_ut.cpp @@ -3961,6 +3961,77 @@ R"([[#;#;["Primary1"];[41u]];[["Secondary2"];[2u];["Primary2"];[42u]];[["Seconda CompareYson(R"([[[1];[1];["Payload1"]];[[5];[5];["Payload5"]]])", FormatResultSetYson(result.GetResultSet(0))); } + + Y_UNIT_TEST(IndexFilterPushDown) { + TKikimrRunner kikimr; + + auto db = kikimr.GetTableClient(); + auto session = db.CreateSession().GetValueSync().GetSession(); + CreateSampleTablesWithIndex(session, false /*populateTables*/); + + NYdb::NTable::TExecDataQuerySettings execSettings; + execSettings.CollectQueryStats(ECollectQueryStatsMode::Basic); + + auto result = session.ExecuteDataQuery(Q1_(R"( + REPLACE INTO `/Root/SecondaryKeys` (Key, Fk, Value) VALUES + (0, 0, "Value0"), + (1, 0, "Value1"), + (2, 1, "Value2"); + )"), TTxControl::BeginTx().CommitTx(), execSettings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + result = session.ExecuteDataQuery(Q1_(R"( + SELECT Fk, Value FROM `/Root/SecondaryKeys` VIEW Index WHERE Fk = CAST(0 AS UInt32) LIMIT 1; + )"), TTxControl::BeginTx().CommitTx(), execSettings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + AssertTableStats(result, "/Root/SecondaryKeys", { + .ExpectedReads = 1 + }); + + AssertTableStats(result, "/Root/SecondaryKeys/Index/indexImplTable", { + .ExpectedReads = 1 + }); + + result = session.ExecuteDataQuery(Q1_(R"( + SELECT Fk, Value FROM `/Root/SecondaryKeys` VIEW Index WHERE Fk = CAST(0 AS UInt32) AND Fk + Fk >= 0 LIMIT 1; + )"), TTxControl::BeginTx().CommitTx(), execSettings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + AssertTableStats(result, "/Root/SecondaryKeys", { + .ExpectedReads = 1 + }); + + AssertTableStats(result, "/Root/SecondaryKeys/Index/indexImplTable", { + .ExpectedReads = 1 + }); + + result = session.ExecuteDataQuery(Q1_(R"( + SELECT Fk, Value FROM `/Root/SecondaryKeys` VIEW Index WHERE Fk = CAST(0 AS UInt32) ORDER BY Fk LIMIT 1; + )"), TTxControl::BeginTx().CommitTx(), execSettings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + AssertTableStats(result, "/Root/SecondaryKeys", { + .ExpectedReads = 1 + }); + + AssertTableStats(result, "/Root/SecondaryKeys/Index/indexImplTable", { + .ExpectedReads = 1 + }); + + result = session.ExecuteDataQuery(Q1_(R"( + SELECT Fk, Value FROM `/Root/SecondaryKeys` VIEW Index WHERE Fk = CAST(0 AS UInt32) AND Fk + Fk >= 0 ORDER BY Fk LIMIT 1; + )"), TTxControl::BeginTx().CommitTx(), execSettings).ExtractValueSync(); + UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString()); + + AssertTableStats(result, "/Root/SecondaryKeys", { + .ExpectedReads = 1 + }); + + AssertTableStats(result, "/Root/SecondaryKeys/Index/indexImplTable", { + .ExpectedReads = 1 + }); + } } } diff --git a/ydb/library/yql/core/yql_opt_utils.cpp b/ydb/library/yql/core/yql_opt_utils.cpp index c2e503019c5..83acfe00c5c 100644 --- a/ydb/library/yql/core/yql_opt_utils.cpp +++ b/ydb/library/yql/core/yql_opt_utils.cpp @@ -282,9 +282,12 @@ bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TField return usedFields.size() < inputStructType->GetSize(); } -template bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TSet<TStringBuf>& usedFields, const TParentsMap& parentsMap, bool allowDependsOn); -template bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TSet<TString>& usedFields, const TParentsMap& parentsMap, bool allowDependsOn); -template bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, std::map<std::string_view, TExprNode::TPtr>& usedFields, const TParentsMap& parentsMap, bool allowDependsOn); +template bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TSet<TStringBuf>& usedFields, const TParentsMap& parentsMap, + bool allowDependsOn); +template bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TSet<TString>& usedFields, const TParentsMap& parentsMap, + bool allowDependsOn); +template bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, std::map<std::string_view, TExprNode::TPtr>& usedFields, + const TParentsMap& parentsMap, bool allowDependsOn); TExprNode::TPtr AddMembersUsedInside(const TExprNode::TPtr& start, const TExprNode& arg, TExprNode::TPtr&& members, const TParentsMap& parentsMap, TExprContext& ctx) { if (!members || !start || &arg == start.Get()) { diff --git a/ydb/library/yql/core/yql_opt_utils.h b/ydb/library/yql/core/yql_opt_utils.h index 91651a5f7b2..6c0f610777c 100644 --- a/ydb/library/yql/core/yql_opt_utils.h +++ b/ydb/library/yql/core/yql_opt_utils.h @@ -27,7 +27,8 @@ TExprNode::TPtr KeepColumnOrder(const TExprNode::TPtr& node, const TExprNode& sr // returns true if usedFields contains subset of fields template<class TFieldsSet> -bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TFieldsSet& usedFields, const TParentsMap& parentsMap, bool allowDependsOn = true); +bool HaveFieldsSubset(const TExprNode::TPtr& start, const TExprNode& arg, TFieldsSet& usedFields, const TParentsMap& parentsMap, + bool allowDependsOn = true); template<class TFieldsSet> TExprNode::TPtr FilterByFields(TPositionHandle position, const TExprNode::TPtr& input, const TFieldsSet& subsetFields, @@ -91,7 +92,8 @@ template <bool Bool> TExprNode::TPtr MakeBool(TPositionHandle position, TExprContext& ctx); TExprNode::TPtr MakeIdentityLambda(TPositionHandle position, TExprContext& ctx); -constexpr std::initializer_list<std::string_view> SkippableCallables = {"Unordered", "AssumeSorted", "AssumeUnique", "AssumeDistinct", "AssumeChopped", "AssumeColumnOrder", "AssumeAllMembersNullableAtOnce"}; +constexpr std::initializer_list<std::string_view> SkippableCallables = {"Unordered", "AssumeSorted", "AssumeUnique", "AssumeDistinct", + "AssumeChopped", "AssumeColumnOrder", "AssumeAllMembersNullableAtOnce"}; const TExprNode& SkipCallables(const TExprNode& node, const std::initializer_list<std::string_view>& skipCallables); |