@@ -685,45 +685,40 @@ TFilterOpsLevels PredicatePushdown(const TExprBase& predicate, const TExprNode&
685
685
}
686
686
687
687
TOLAPPredicateNode WrapPredicates (const std::vector<TOLAPPredicateNode>& predicates, TExprContext& ctx, TPositionHandle pos) {
688
+ TOLAPPredicateNode result;
688
689
if (predicates.empty ()) {
689
- return {};
690
- }
691
-
692
- if (const auto predicatesSize = predicates.size (); 1U == predicatesSize) {
693
- return predicates.front ();
690
+ result.ExprNode = MakeBool<true >(pos, ctx);;
691
+ } else if (predicates.size () == 1 ) {
692
+ result = predicates.front ();
694
693
} else {
695
694
TOLAPPredicateNode result;
696
695
result.Children = predicates;
697
696
result.CanBePushed = true ;
698
697
699
698
TVector<NNodes::TExprBase> exprNodes;
700
- exprNodes.reserve (predicatesSize );
699
+ exprNodes.reserve (predicates. size () );
701
700
for (const auto & pred : predicates) {
702
701
exprNodes.emplace_back (pred.ExprNode );
703
702
result.CanBePushed &= pred.CanBePushed ;
704
703
}
705
704
result.ExprNode = NNodes::Build<NNodes::TCoAnd>(ctx, pos)
706
705
.Add (exprNodes)
707
706
.Done ().Ptr ();
708
- return result;
709
707
}
708
+ return result;
710
709
}
711
710
712
- void SplitForPartialPushdown (const TOLAPPredicateNode& predicateTree, TOLAPPredicateNode& predicatesToPush, TOLAPPredicateNode& remainingPredicates,
713
- TExprContext& ctx, TPositionHandle pos)
711
+ std::pair<std::vector<TOLAPPredicateNode>, std::vector<TOLAPPredicateNode>> SplitForPartialPushdown (const TOLAPPredicateNode& predicateTree)
714
712
{
715
713
if (predicateTree.CanBePushed ) {
716
- predicatesToPush = predicateTree;
717
- remainingPredicates.ExprNode = MakeBool<true >(pos, ctx);
718
- return ;
714
+ return {{predicateTree}, {}};
719
715
}
720
716
721
717
if (!TCoAnd::Match (predicateTree.ExprNode .Get ())) {
722
718
// We can partially pushdown predicates from AND operator only.
723
719
// For OR operator we would need to have several read operators which is not acceptable.
724
720
// TODO: Add support for NOT(op1 OR op2), because it expands to (!op1 AND !op2).
725
- remainingPredicates = predicateTree;
726
- return ;
721
+ return {{}, {predicateTree}};
727
722
}
728
723
729
724
bool isFoundNotStrictOp = false ;
@@ -738,8 +733,7 @@ void SplitForPartialPushdown(const TOLAPPredicateNode& predicateTree, TOLAPPredi
738
733
remaining.emplace_back (predicate);
739
734
}
740
735
}
741
- predicatesToPush = WrapPredicates (pushable, ctx, pos);
742
- remainingPredicates = WrapPredicates (remaining, ctx, pos);
736
+ return {pushable, remaining};
743
737
}
744
738
745
739
} // anonymous namespace end
@@ -763,6 +757,7 @@ TExprBase KqpPushOlapFilter(TExprBase node, TExprContext& ctx, const TKqpOptimiz
763
757
}
764
758
765
759
const auto & lambda = flatmap.Lambda ();
760
+ const auto & lambdaArg = lambda.Args ().Arg (0 ).Ref ();
766
761
767
762
YQL_CLOG (TRACE, ProviderKqp) << " Initial OLAP lambda: " << KqpExprToPrettyString (lambda, ctx);
768
763
@@ -775,35 +770,53 @@ TExprBase KqpPushOlapFilter(TExprBase node, TExprContext& ctx, const TKqpOptimiz
775
770
auto predicate = optionaIf.Predicate ();
776
771
auto value = optionaIf.Value ();
777
772
778
- if constexpr (NSsa::RuntimeVersion >= 5U ) {
779
- TExprNode::TPtr afterPeephole;
780
- bool hasNonDeterministicFunctions;
781
- if (const auto status = PeepHoleOptimizeNode (optionaIf.Ptr (), afterPeephole, ctx, typesCtx, nullptr , hasNonDeterministicFunctions);
782
- status != IGraphTransformer::TStatus::Ok) {
783
- YQL_CLOG (ERROR, ProviderKqp) << " Peephole OLAP failed." << Endl << ctx.IssueManager .GetIssues ().ToString ();
784
- return node;
785
- }
786
-
787
- const TCoIf simplified (std::move (afterPeephole));
788
- predicate = simplified.Predicate ();
789
- value = simplified.ThenValue ().Cast <TCoJust>().Input ();
790
- }
791
-
792
773
TOLAPPredicateNode predicateTree;
793
774
predicateTree.ExprNode = predicate.Ptr ();
794
- const auto & lambdaArg = lambda.Args ().Arg (0 ).Ref ();
795
775
CollectPredicates (predicate, predicateTree, &lambdaArg, read .Process ().Body ());
796
776
YQL_ENSURE (predicateTree.IsValid (), " Collected OLAP predicates are invalid" );
797
777
798
- TOLAPPredicateNode predicatesToPush, remainingPredicates;
799
- SplitForPartialPushdown (predicateTree, predicatesToPush, remainingPredicates, ctx, node.Pos ());
800
- if (!predicatesToPush.IsValid ()) {
778
+ auto [pushable, remaining] = SplitForPartialPushdown (predicateTree);
779
+
780
+ if constexpr (NSsa::RuntimeVersion >= 5U ) {
781
+ if (!remaining.empty ()) {
782
+ const auto remainingPredicates = WrapPredicates (remaining, ctx, node.Pos ());
783
+ const auto recoveredOptinalIfForNonPushedDownPredicates = Build<TCoOptionalIf>(ctx, node.Pos ())
784
+ .Predicate <TCoLambda>()
785
+ .Args (lambda.Args ())
786
+ .Body (remainingPredicates.ExprNode )
787
+ .Build ()
788
+ .Build ();
789
+ TExprNode::TPtr afterPeephole;
790
+ bool hasNonDeterministicFunctions;
791
+ if (const auto status = PeepHoleOptimizeNode (optionaIf.Ptr (), afterPeephole, ctx, typesCtx, nullptr , hasNonDeterministicFunctions);
792
+ status != IGraphTransformer::TStatus::Ok) {
793
+ YQL_CLOG (ERROR, ProviderKqp) << " Peephole OLAP failed." << Endl << ctx.IssueManager .GetIssues ().ToString ();
794
+ return node;
795
+ }
796
+ const TCoIf simplified (std::move (afterPeephole));
797
+ predicate = simplified.Predicate ();
798
+ value = simplified.ThenValue ().Cast <TCoJust>().Input ();
799
+
800
+ TOLAPPredicateNode predicateTree;
801
+ predicateTree.ExprNode = predicate.Ptr ();
802
+ CollectPredicates (predicate, predicateTree, &lambdaArg, read .Process ().Body ());
803
+ YQL_ENSURE (predicateTree.IsValid (), " Collected OLAP predicates are invalid" );
804
+
805
+ auto [pushable2, remaining2] = SplitForPartialPushdown (predicateTree);
806
+ for (auto & p: pushable2) {
807
+ pushable.emplace_back (std::move (p));
808
+ }
809
+ remaining = std::move (remaining2);
810
+ }
811
+ }
812
+
813
+ if (pushable.empty ()) {
801
814
return node;
802
815
}
803
816
804
- YQL_ENSURE (predicatesToPush.IsValid (), " Predicates to push is invalid" );
805
- YQL_ENSURE (remainingPredicates.IsValid (), " Remaining predicates is invalid" );
806
817
818
+ const auto predicatesToPush = WrapPredicates (pushable, ctx, node.Pos ());
819
+ const auto remainingPredicates = WrapPredicates (remaining, ctx, node.Pos ());
807
820
const auto pushedFilters = PredicatePushdown (TExprBase (predicatesToPush.ExprNode ), lambdaArg, ctx, node.Pos ());
808
821
// Temporary fix for https://st.yandex-team.ru/KIKIMR-22560
809
822
// YQL_ENSURE(pushedFilters.IsValid(), "Pushed predicate should be always valid!");
0 commit comments