Skip to content

Commit bb0e22c

Browse files
uzhastikkardymonds
andauthored
YQ-3824 Shared reading: fix is not distinct from with optional fiel… (#11424)
Co-authored-by: Dmitry Kardymon <kardymon-d@ydb.tech>
1 parent 6f2c9d0 commit bb0e22c

File tree

5 files changed

+50
-12
lines changed

5 files changed

+50
-12
lines changed

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,23 @@ bool SqlInCanBePushed(const TCoSqlIn& sqlIn, const TExprNode* lambdaArg, const T
456456
return true;
457457
}
458458

459+
bool IsDistinctCanBePushed(const TExprBase& predicate, const TExprNode* lambdaArg, const TExprBase& lambdaBody, const TSettings& settings) {
460+
if (predicate.Ref().ChildrenSize() != 2 ) {
461+
return false;
462+
}
463+
auto expr1 = TExprBase(predicate.Ref().Child(0));
464+
auto expr2 = TExprBase(predicate.Ref().Child(1));
465+
if (!CheckExpressionNodeForPushdown(expr1, lambdaArg, settings)
466+
|| !CheckExpressionNodeForPushdown(expr2, lambdaArg, settings)) {
467+
return false;
468+
}
469+
if (!settings.IsEnabled(TSettings::EFeatureFlag::DoNotCheckCompareArgumentsTypes)
470+
&& !IsComparableTypes(expr1, expr2, false, lambdaBody.Ptr()->GetTypeAnn(), settings)) {
471+
return false;
472+
}
473+
return true;
474+
}
475+
459476
bool SafeCastCanBePushed(const TCoFlatMap& flatmap, const TExprNode* lambdaArg, const TSettings& settings) {
460477
/*
461478
* There are three ways of comparison in following format:
@@ -595,6 +612,9 @@ void CollectPredicates(const TExprBase& predicate, TPredicateNode& predicateTree
595612
} else if (settings.IsEnabled(TSettings::EFeatureFlag::InOperator) && predicate.Maybe<TCoSqlIn>()) {
596613
auto sqlIn = predicate.Cast<TCoSqlIn>();
597614
predicateTree.CanBePushed = SqlInCanBePushed(sqlIn, lambdaArg, lambdaBody, settings);
615+
} else if (settings.IsEnabled(TSettings::EFeatureFlag::IsDistinctOperator) &&
616+
(predicate.Ref().IsCallable({"IsNotDistinctFrom", "IsDistinctFrom"}))) {
617+
predicateTree.CanBePushed = IsDistinctCanBePushed(predicate, lambdaArg, lambdaBody, settings);
598618
} else {
599619
predicateTree.CanBePushed = false;
600620
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ struct TSettings {
2626
DoNotCheckCompareArgumentsTypes = 1 << 16,
2727
TimestampCtor = 1 << 17,
2828
JustPassthroughOperators = 1 << 18, // if + coalesce + just
29-
InOperator = 1 << 19 // IN()
29+
InOperator = 1 << 19, // IN()
30+
IsDistinctOperator = 1 << 20 // IS NOT DISTINCT FROM / IS DISTINCT FROM
3031
};
3132

3233
explicit TSettings(NLog::EComponent logComponent)

ydb/library/yql/providers/generic/provider/yql_generic_predicate_pushdown.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,17 @@ namespace NYql {
193193
return true;
194194
}
195195

196+
bool SerializeIsNotDistinctFrom(const TExprBase& predicate, TPredicate* predicateProto, const TCoArgument& arg, TStringBuilder& err, bool invert) {
197+
if (predicate.Ref().ChildrenSize() != 2) {
198+
err << "unknown predicate, expected 2, children size " << predicate.Ref().ChildrenSize();
199+
return false;
200+
}
201+
TPredicate::TComparison* proto = predicateProto->mutable_comparison();
202+
proto->set_operation(!invert ? TPredicate::TComparison::IND : TPredicate::TComparison::ID);
203+
return SerializeExpression(TExprBase(predicate.Ref().Child(0)), proto->mutable_left_value(), arg, err)
204+
&& SerializeExpression(TExprBase(predicate.Ref().Child(1)), proto->mutable_right_value(), arg, err);
205+
}
206+
196207
bool SerializeAnd(const TCoAnd& andExpr, TPredicate* proto, const TCoArgument& arg, TStringBuilder& err, ui64 depth) {
197208
auto* dstProto = proto->mutable_conjunction();
198209
for (const auto& child : andExpr.Ptr()->Children()) {
@@ -251,6 +262,12 @@ namespace NYql {
251262
if (auto sqlIn = predicate.Maybe<TCoSqlIn>()) {
252263
return SerializeSqlIn(sqlIn.Cast(), proto, arg, err);
253264
}
265+
if (predicate.Ref().IsCallable("IsNotDistinctFrom")) {
266+
return SerializeIsNotDistinctFrom(predicate, proto, arg, err, false);
267+
}
268+
if (predicate.Ref().IsCallable("IsDistinctFrom")) {
269+
return SerializeIsNotDistinctFrom(predicate, proto, arg, err, true);
270+
}
254271
if (auto sqlIf = predicate.Maybe<TCoIf>()) {
255272
return SerializeSqlIf(sqlIf.Cast(), proto, arg, err, depth);
256273
}

ydb/library/yql/providers/pq/provider/yql_pq_logical_opt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace {
3030
: NPushdown::TSettings(NLog::EComponent::ProviderGeneric)
3131
{
3232
using EFlag = NPushdown::TSettings::EFeatureFlag;
33-
Enable(EFlag::ExpressionAsPredicate | EFlag::ArithmeticalExpressions | EFlag::ImplicitConversionToInt64 | EFlag::StringTypes | EFlag::LikeOperator | EFlag::DoNotCheckCompareArgumentsTypes | EFlag::InOperator | EFlag::JustPassthroughOperators);
33+
Enable(EFlag::ExpressionAsPredicate | EFlag::ArithmeticalExpressions | EFlag::ImplicitConversionToInt64 | EFlag::StringTypes | EFlag::LikeOperator | EFlag::DoNotCheckCompareArgumentsTypes | EFlag::InOperator | EFlag::IsDistinctOperator | EFlag::JustPassthroughOperators);
3434
}
3535
};
3636

ydb/tests/fq/yds/test_row_dispatcher.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,20 +348,20 @@ def test_filters_optional_field(self, kikimr, client):
348348
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `data` = \\"hello2\\"')
349349
filter = 'flag'
350350
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `flag`')
351-
# filter = ' event IS NOT DISTINCT FROM "event2"'
352-
# self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `event` IS NOT DISTINCT FROM \\"event2\\"')
353-
# filter = ' event IS DISTINCT FROM "event1"'
354-
# self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `event` IS DISTINCT FROM \\"event1\\"')
355-
# filter = ' field1 IS DISTINCT FROM field2'
356-
# self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `field1` IS DISTINCT FROM `field2`')
351+
filter = ' event IS NOT DISTINCT FROM "event2"'
352+
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `event` IS NOT DISTINCT FROM \\"event2\\"')
353+
filter = ' event IS DISTINCT FROM "event1"'
354+
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `event` IS DISTINCT FROM \\"event1\\"')
355+
filter = ' field1 IS DISTINCT FROM field2'
356+
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `field1` IS DISTINCT FROM `field2`')
357357
filter = 'event IN ("event2")'
358358
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `event` IN (\\"event2\\")')
359359
filter = 'event IN ("1", "2", "3", "4", "5", "6", "7", "event2")'
360360
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE `event` IN (\\"1\\"')
361-
# filter = ' event IS DISTINCT FROM data AND event IN ("1", "2", "3", "4", "5", "6", "7", "event2")'
362-
# self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE (`event` IS DISTINCT FROM `data` AND `event` IN (\\"1\\"')
363-
# filter = ' IF(event == "event2", event IS DISTINCT FROM data, FALSE)'
364-
# self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE IF(`event` == "event2", `event` IS DISTINCT FROM `data`, FALSE)')
361+
filter = ' event IS DISTINCT FROM data AND event IN ("1", "2", "3", "4", "5", "6", "7", "event2")'
362+
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE (`event` IS DISTINCT FROM `data` AND COALESCE(`event` IN (\\"1\\"')
363+
filter = ' IF(event == "event2", event IS DISTINCT FROM data, FALSE)'
364+
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE IF(COALESCE(`event` = \\"event2\\", FALSE), `event` IS DISTINCT FROM `data`, FALSE)')
365365
filter = ' COALESCE(event = "event2", TRUE)'
366366
self.run_and_check(kikimr, client, sql + filter, data, expected, 'predicate: WHERE COALESCE(`event` = \\"event2\\", TRUE)')
367367
filter = ' COALESCE(event = "event2", data = "hello2", TRUE)'

0 commit comments

Comments
 (0)