Skip to content

Commit 2eae73d

Browse files
authored
Merge #14222 (#14274)
1 parent d16ba9b commit 2eae73d

19 files changed

+1618
-569
lines changed

ydb/library/yql/providers/common/pushdown/collection.cpp

Lines changed: 524 additions & 434 deletions
Large diffs are not rendered by default.

ydb/library/yql/providers/common/pushdown/collection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace NYql::NPushdown {
99

1010
// Collects subpredicate that we can then push down
1111
void CollectPredicates(const NNodes::TExprBase& predicate, TPredicateNode& predicateTree,
12-
const TExprNode* lambdaArg, const NNodes::TExprBase& lambdaBody,
12+
const NNodes::TExprBase& lambdaArg, const NNodes::TExprBase& lambdaBody,
1313
const TSettings& settings);
1414

1515
} // namespace NYql::NPushdown
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include "predicate_node.h"
2+
3+
#include <ydb/library/yql/utils/log/log.h>
4+
#include <ydb/library/yql/core/expr_nodes/yql_expr_nodes.h>
5+
#include <ydb/library/yql/providers/common/provider/yql_provider.h>
6+
#include <ydb/library/yql/providers/common/pushdown/collection.h>
7+
8+
namespace NYql::NPushdown {
9+
10+
using namespace NNodes;
11+
12+
namespace {
13+
14+
TPredicateNode SplitForPartialPushdown(const NPushdown::TPredicateNode& predicateTree, TExprContext& ctx, TPositionHandle pos, const TSettings& settings) {
15+
if (predicateTree.CanBePushed) {
16+
return predicateTree;
17+
}
18+
19+
if (predicateTree.Op != NPushdown::EBoolOp::And && (!settings.IsEnabled(TSettings::EFeatureFlag::SplitOrOperator) || predicateTree.Op != NPushdown::EBoolOp::Or)) {
20+
// Predicate can't be split, so return invalid value and skip this branch
21+
return NPushdown::TPredicateNode();
22+
}
23+
24+
std::vector<NPushdown::TPredicateNode> pushable;
25+
for (auto& predicate : predicateTree.Children) {
26+
NPushdown::TPredicateNode pushablePredicate = SplitForPartialPushdown(predicate, ctx, pos, settings);
27+
if (pushablePredicate.IsValid()) {
28+
pushable.emplace_back(pushablePredicate);
29+
} else if (predicateTree.Op == NPushdown::EBoolOp::Or) {
30+
// One of the OR branch was invalid, so the whole predicate is invalid
31+
return NPushdown::TPredicateNode();
32+
}
33+
}
34+
35+
NPushdown::TPredicateNode predicateToPush;
36+
predicateToPush.SetPredicates(pushable, ctx, pos, predicateTree.Op);
37+
return predicateToPush;
38+
}
39+
40+
}
41+
42+
NPushdown::TPredicateNode MakePushdownNode(const NNodes::TCoLambda& lambda, TExprContext& ctx, const TPositionHandle& pos, const TSettings& settings) {
43+
auto lambdaArg = lambda.Args().Arg(0).Ptr();
44+
45+
YQL_LOG(TRACE) << "Push filter. Initial filter lambda: " << NCommon::ExprToPrettyString(ctx, lambda.Ref());
46+
47+
auto maybeOptionalIf = lambda.Body().Maybe<TCoOptionalIf>();
48+
if (!maybeOptionalIf.IsValid()) { // Nothing to push
49+
return {};
50+
}
51+
52+
TCoOptionalIf optionalIf = maybeOptionalIf.Cast();
53+
NPushdown::TPredicateNode predicateTree(optionalIf.Predicate());
54+
NPushdown::CollectPredicates(optionalIf.Predicate(), predicateTree, TExprBase(lambdaArg), TExprBase(lambdaArg), settings);
55+
YQL_ENSURE(predicateTree.IsValid(), "Collected filter predicates are invalid");
56+
57+
return SplitForPartialPushdown(predicateTree, ctx, pos, settings);
58+
}
59+
60+
TMaybeNode<TCoLambda> MakePushdownPredicate(const TCoLambda& lambda, TExprContext& ctx, const TPositionHandle& pos, const TSettings& settings) {
61+
NPushdown::TPredicateNode predicateToPush = MakePushdownNode(lambda, ctx, pos, settings);
62+
if (!predicateToPush.IsValid()) {
63+
return {};
64+
}
65+
66+
// clang-format off
67+
auto newFilterLambda = Build<TCoLambda>(ctx, pos)
68+
.Args({"filter_row"})
69+
.Body<TExprApplier>()
70+
.Apply(predicateToPush.ExprNode.Cast())
71+
.With(lambda.Args().Arg(0), "filter_row")
72+
.Build()
73+
.Done();
74+
// clang-format on
75+
76+
YQL_LOG(INFO) << "Push filter lambda: " << NCommon::ExprToPrettyString(ctx, *newFilterLambda.Ptr());
77+
return newFilterLambda;
78+
}
79+
80+
} // namespace NYql::NPushdown
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include "predicate_node.h"
4+
5+
#include <ydb/library/yql/ast/yql_expr.h>
6+
#include <ydb/library/yql/ast/yql_pos_handle.h>
7+
#include <ydb/library/yql/core/expr_nodes/yql_expr_nodes.h>
8+
#include <ydb/library/yql/core/expr_nodes_gen/yql_expr_nodes_gen.h>
9+
10+
namespace NYql::NPushdown {
11+
12+
NPushdown::TPredicateNode MakePushdownNode(const NNodes::TCoLambda& lambda, TExprContext& ctx, const TPositionHandle& pos, const TSettings& settings);
13+
NNodes::TMaybeNode<NNodes::TCoLambda> MakePushdownPredicate(const NNodes::TCoLambda& lambda, TExprContext& ctx, const TPositionHandle& pos, const TSettings& settings);
14+
15+
} // namespace NYql::NPushdown

ydb/library/yql/providers/common/pushdown/predicate_node.cpp

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,48 @@ bool TPredicateNode::IsValid() const {
3030
return res && ExprNode.IsValid();
3131
}
3232

33-
void TPredicateNode::SetPredicates(const std::vector<TPredicateNode>& predicates, TExprContext& ctx, TPositionHandle pos) {
33+
bool TPredicateNode::IsEmpty() const {
34+
if (!ExprNode || !IsValid()) {
35+
return true;
36+
}
37+
if (const auto maybeBool = ExprNode.Maybe<NNodes::TCoBool>()) {
38+
return TStringBuf(maybeBool.Cast().Literal()) == "true"sv;
39+
}
40+
return false;
41+
}
42+
43+
void TPredicateNode::SetPredicates(const std::vector<TPredicateNode>& predicates, TExprContext& ctx, TPositionHandle pos, EBoolOp op) {
3444
auto predicatesSize = predicates.size();
3545
if (predicatesSize == 0) {
3646
return;
37-
} else if (predicatesSize == 1) {
47+
}
48+
if (predicatesSize == 1) {
3849
*this = predicates[0];
39-
} else {
40-
Op = EBoolOp::And;
41-
Children = predicates;
42-
CanBePushed = true;
43-
44-
TVector<NNodes::TExprBase> exprNodes;
45-
exprNodes.reserve(predicatesSize);
46-
for (auto& pred : predicates) {
47-
exprNodes.emplace_back(pred.ExprNode.Cast());
48-
CanBePushed &= pred.CanBePushed;
49-
}
50-
ExprNode = NNodes::Build<NNodes::TCoAnd>(ctx, pos)
51-
.Add(exprNodes)
52-
.Done();
50+
return;
51+
}
52+
53+
Op = op;
54+
Children = predicates;
55+
CanBePushed = true;
56+
57+
TVector<NNodes::TExprBase> exprNodes;
58+
exprNodes.reserve(predicatesSize);
59+
for (auto& pred : predicates) {
60+
exprNodes.emplace_back(pred.ExprNode.Cast());
61+
CanBePushed &= pred.CanBePushed;
62+
}
63+
64+
switch (op) {
65+
case EBoolOp::And:
66+
ExprNode = NNodes::Build<NNodes::TCoAnd>(ctx, pos).Add(exprNodes).Done();
67+
break;
68+
69+
case EBoolOp::Or:
70+
ExprNode = NNodes::Build<NNodes::TCoOr>(ctx, pos).Add(exprNodes).Done();
71+
break;
72+
73+
default:
74+
throw yexception() << "Unsupported operator for predicate node creation: " << static_cast<int>(op);
5375
}
5476
}
5577

ydb/library/yql/providers/common/pushdown/predicate_node.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ struct TPredicateNode {
2323
~TPredicateNode();
2424

2525
bool IsValid() const;
26-
void SetPredicates(const std::vector<TPredicateNode>& predicates, TExprContext& ctx, TPositionHandle pos);
26+
bool IsEmpty() const;
27+
void SetPredicates(const std::vector<TPredicateNode>& predicates, TExprContext& ctx, TPositionHandle pos, EBoolOp op);
2728

2829
NNodes::TMaybeNode<NNodes::TExprBase> ExprNode;
2930
std::vector<TPredicateNode> Children;

ydb/library/yql/providers/common/pushdown/settings.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,16 @@ void TSettings::Enable(ui64 flagsMask, bool set) {
1010
}
1111
}
1212

13+
void TSettings::EnableFunction(const TString& functionName) {
14+
EnabledFunctions.insert(functionName);
15+
}
16+
1317
bool TSettings::IsEnabled(EFeatureFlag flagMask) const {
1418
return (FeatureFlags & flagMask) != 0;
1519
}
1620

21+
bool TSettings::IsEnabledFunction(const TString& functionName) const {
22+
return EnabledFunctions.contains(functionName);
23+
}
24+
1725
} // namespace NYql::NPushdown

ydb/library/yql/providers/common/pushdown/settings.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <util/system/types.h>
55

6+
#include <unordered_set>
7+
68
namespace NYql::NPushdown {
79

810
struct TSettings {
@@ -25,7 +27,20 @@ struct TSettings {
2527
UnaryOperators = 1 << 15, // -, Abs, Size
2628
DoNotCheckCompareArgumentsTypes = 1 << 16,
2729
TimestampCtor = 1 << 17,
28-
JustPassthroughOperators = 1 << 18 // if + coalesce + just
30+
JustPassthroughOperators = 1 << 18, // if + coalesce + just
31+
InOperator = 1 << 19, // IN()
32+
IsDistinctOperator = 1 << 20, // IS NOT DISTINCT FROM / IS DISTINCT FROM
33+
DivisionExpressions = 1 << 21, // %, / -- NOTE: division by zero is not handled and also pushdown
34+
35+
// Option which enables partial pushdown for sequence of OR
36+
// For example next predicate:
37+
// ($A AND $B) OR ($C AND $D)
38+
// May be partially pushdowned as:
39+
// $A OR $C
40+
// In case of unsupported / complicated expressions $B and $D
41+
SplitOrOperator = 1 << 22,
42+
ToBytesFromStringExpressions = 1 << 23, // ToBytes(string like)
43+
FlatMapOverOptionals = 1 << 24 // FlatMap(Optional<T>, Lmabda (T) -> Optional<U>)
2944
};
3045

3146
explicit TSettings(NLog::EComponent logComponent)
@@ -37,15 +52,20 @@ struct TSettings {
3752

3853
void Enable(ui64 flagsMask, bool set = true);
3954

55+
void EnableFunction(const TString& functionName);
56+
4057
bool IsEnabled(EFeatureFlag flagMask) const;
4158

59+
bool IsEnabledFunction(const TString& functionName) const;
60+
4261
NLog::EComponent GetLogComponent() const {
4362
return LogComponent;
4463
}
4564

4665
private:
4766
const NLog::EComponent LogComponent;
4867
ui64 FeatureFlags = 0;
68+
std::unordered_set<TString> EnabledFunctions;
4969
};
5070

5171
} // namespace NYql::NPushdown
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "predicate_node.h"
2+
3+
#include <ydb/library/yql/core/expr_nodes/yql_expr_nodes.h>
4+
#include <ydb/library/yql/core/yql_expr_type_annotation.h>
5+
6+
namespace NYql::NPushdown {
7+
8+
IGraphTransformer::TStatus AnnotateFilterPredicate(const TExprNode::TPtr& input, size_t childIndex, const TStructExprType* itemType, TExprContext& ctx) {
9+
if (childIndex >= input->ChildrenSize()) {
10+
return IGraphTransformer::TStatus::Error;
11+
}
12+
13+
auto& filterLambda = input->ChildRef(childIndex);
14+
if (!EnsureLambda(*filterLambda, ctx)) {
15+
return IGraphTransformer::TStatus::Error;
16+
}
17+
18+
if (!UpdateLambdaAllArgumentsTypes(filterLambda, {itemType}, ctx)) {
19+
return IGraphTransformer::TStatus::Error;
20+
}
21+
22+
if (const auto* filterLambdaType = filterLambda->GetTypeAnn()) {
23+
if (filterLambdaType->GetKind() != ETypeAnnotationKind::Data) {
24+
return IGraphTransformer::TStatus::Error;
25+
}
26+
const TDataExprType* dataExprType = static_cast<const TDataExprType*>(filterLambdaType);
27+
if (dataExprType->GetSlot() != EDataSlot::Bool) {
28+
return IGraphTransformer::TStatus::Error;
29+
}
30+
} else {
31+
return IGraphTransformer::TStatus::Repeat;
32+
}
33+
return IGraphTransformer::TStatus::Ok;
34+
}
35+
36+
} // namespace NYql::NPushdown
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include <ydb/library/yql/ast/yql_expr.h>
4+
#include <ydb/library/yql/ast/yql_pos_handle.h>
5+
#include <ydb/library/yql/core/expr_nodes_gen/yql_expr_nodes_gen.h>
6+
#include <ydb/library/yql/core/yql_graph_transformer.h>
7+
8+
namespace NYql::NPushdown {
9+
10+
IGraphTransformer::TStatus AnnotateFilterPredicate(
11+
const TExprNode::TPtr& input,
12+
size_t childIndex,
13+
const TStructExprType* itemType,
14+
TExprContext& ctx);
15+
16+
17+
} // namespace NYql::NPushdown

ydb/library/yql/providers/common/pushdown/ya.make

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ SRCS(
44
collection.cpp
55
predicate_node.cpp
66
settings.cpp
7+
type_ann.cpp
8+
physical_opt.cpp
79
)
810

911
PEERDIR(

0 commit comments

Comments
 (0)