Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions ydb/core/kqp/opt/physical/kqp_opt_phy_olap_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,13 @@ NYql::NNodes::TCoUtf8 RemoveJsonPathUnnecessaryQuote(const NYql::NNodes::TCoUtf8
return node;
}

TExprBase UnwrapOptionalTKqpOlapApplyColumnArg(const TExprBase& node) {
if (const auto& maybeColumnArg = node.Maybe<TKqpOlapApplyColumnArg>()) {
return maybeColumnArg.Cast().ColumnName();
}
return node;
}

} //namespace

std::vector<TExprBase> ConvertComparisonNode(const TExprBase& nodeIn, const TExprNode& argument, TExprContext& ctx, TPositionHandle pos, bool allowApply)
Expand All @@ -351,7 +358,10 @@ std::vector<TExprBase> ConvertComparisonNode(const TExprBase& nodeIn, const TExp
}

if (auto maybeMember = node.Maybe<TCoMember>()) {
return maybeMember.Cast().Name();
return Build<TKqpOlapApplyColumnArg>(ctx, pos)
.TableRowType(ExpandType(argument.Pos(), *argument.GetTypeAnn(), ctx))
.ColumnName(maybeMember.Cast().Name())
.Done();
}

if (auto maybeJsonValue = node.Maybe<TCoJsonValue>()) {
Expand Down Expand Up @@ -397,8 +407,8 @@ std::vector<TExprBase> ConvertComparisonNode(const TExprBase& nodeIn, const TExp
if (const auto params = ExtractBinaryFunctionParameters(arithmetic, argument, ctx, pos, allowApply)) {
return Build<TKqpOlapFilterBinaryOp>(ctx, pos)
.Operator().Value(arithmetic.Ref().Content(), TNodeFlags::Default).Build()
.Left(params->first)
.Right(params->second)
.Left(UnwrapOptionalTKqpOlapApplyColumnArg(params->first))
.Right(UnwrapOptionalTKqpOlapApplyColumnArg(params->second))
.Done();
}
}
Expand All @@ -410,7 +420,7 @@ std::vector<TExprBase> ConvertComparisonNode(const TExprBase& nodeIn, const TExp
YQL_ENSURE(oper.to_lower());
return Build<TKqpOlapFilterUnaryOp>(ctx, pos)
.Operator().Value(oper, TNodeFlags::Default).Build()
.Arg(params.front())
.Arg(UnwrapOptionalTKqpOlapApplyColumnArg(params.front()))
.Done();
}
}
Expand Down Expand Up @@ -540,8 +550,8 @@ TExprBase BuildOneElementComparison(const std::pair<TExprBase, TExprBase>& param

return Build<TKqpOlapFilterBinaryOp>(ctx, pos)
.Operator().Value(compareOperator, TNodeFlags::Default).Build()
.Left(parameter.first)
.Right(parameter.second)
.Left(UnwrapOptionalTKqpOlapApplyColumnArg(parameter.first))
.Right(UnwrapOptionalTKqpOlapApplyColumnArg(parameter.second))
.Done();
}

Expand Down Expand Up @@ -602,8 +612,8 @@ TMaybeNode<TExprBase> ComparisonPushdown(const std::vector<std::pair<TExprBase,
for (ui32 j = 0; j < i; ++j) {
andConditions.emplace_back(Build<TKqpOlapFilterBinaryOp>(ctx, pos)
.Operator().Value("eq", TNodeFlags::Default).Build()
.Left(parameters[j].first)
.Right(parameters[j].second)
.Left(UnwrapOptionalTKqpOlapApplyColumnArg(parameters[j].first))
.Right(UnwrapOptionalTKqpOlapApplyColumnArg(parameters[j].second))
.Done());
}

Expand Down
2 changes: 1 addition & 1 deletion ydb/core/kqp/opt/physical/predicate_collector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ bool CheckComparisonParametersForPushdown(const TCoCompare& compare, const TExpr
}
}

if (options.PushdownSubstring) { //EnableSimpleIlikePushdown FF
if (options.PushdownSubstring) {
if (IgnoreCaseSubstringMatchFunctions.contains(compare.CallableName())) {
const auto& right = compare.Right().Ref();
YQL_ENSURE(right.IsCallable("String") || right.IsCallable("Utf8"));
Expand Down
101 changes: 101 additions & 0 deletions ydb/core/kqp/ut/olap/kqp_olap_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,107 @@ Y_UNIT_TEST_SUITE(KqpOlap) {
UNIT_ASSERT_C(ast.find("KqpOlapFilter") != std::string::npos,
TStringBuilder() << "Predicate wasn't pushed down. Query: " << query);
}

Y_UNIT_TEST(PredicatePushdown_SimpleAsciiILike) {
NKikimrConfig::TAppConfig appConfig;
appConfig.MutableTableServiceConfig()->SetEnableOlapSink(true);
auto settings = TKikimrSettings()
.SetAppConfig(appConfig)
.SetWithSampleTables(false);
TKikimrRunner kikimr(settings);

{
auto tableClient = kikimr.GetTableClient();
auto session = tableClient.CreateSession().GetValueSync().GetSession();
const auto res = session.ExecuteSchemeQuery(R"(
CREATE TABLE `/Root/foo` (
id Int64 NOT NULL,
str String,
u_str Utf8,
json JsonDocument,
PRIMARY KEY(id)
)
WITH (STORE = COLUMN);
)").GetValueSync();
UNIT_ASSERT(res.IsSuccess());
}

auto queryClient = kikimr.GetQueryClient();
auto session = queryClient.GetSession().GetValueSync().GetSession();
{
const auto res = session.ExecuteQuery(R"(
INSERT INTO `/Root/foo` (id, str, u_str) VALUES
(1, "hello", "hello")
)", NYdb::NQuery::TTxControl::NoTx()).GetValueSync();
UNIT_ASSERT_C(res.IsSuccess(), res.GetIssues());
}

std::vector<TString> predicates = {
"str ILIKE 'hell%'",
"str ILIKE 'Hell%'",
"str ILIKE 'Hello%'",
"str ILIKE '%lo'",
"str ILIKE '%Lo'",
"str ILIKE '%Lo%'",
"str ILIKE '%eLLo%'",
"str ILIKE '%HeLLo%'",
"str ILIKE '%LLL%'",
"u_str ILIKE 'hell%'",
"u_str ILIKE 'Hell%'",
"u_str ILIKE 'Hello%'",
"u_str ILIKE '%lo'",
"u_str ILIKE '%Lo'",
"u_str ILIKE '%Lo%'",
"u_str ILIKE '%eLLo%'",
"u_str ILIKE '%HeLLo%'",
"u_str ILIKE '%LLL%'",
};

std::vector<TString> expectedResults = {
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[[1]]",
"[]",
};

UNIT_ASSERT_EQUAL(expectedResults.size(), predicates.size());

for (ui32 i = 0; i < predicates.size(); ++i) {
const auto& query = TString(R"(
PRAGMA OptimizeSimpleILike;
PRAGMA AnsiLike;
SELECT id FROM `/Root/foo` WHERE
)") + predicates[i];
Cerr
<< "QUERY " << i << Endl
<< query << Endl;

const auto res = session
.ExecuteQuery(query, NYdb::NQuery::TTxControl::NoTx(),
NYdb::NQuery::TExecuteQuerySettings().StatsMode(NQuery::EStatsMode::Full))
.ExtractValueSync();
UNIT_ASSERT_C(res.IsSuccess(), res.GetIssues());

const auto ast = res.GetStats()->GetAst();
UNIT_ASSERT_C(ast->find("KqpOlapFilter") != std::string::npos, TStringBuilder() << "ILIKE not pushed down. Query: " << query);
CompareYson(FormatResultSetYson(res.GetResultSet(0)), expectedResults[i]);
}
}

Y_UNIT_TEST(PredicatePushdown_MixStrictAndNotStrict) {
auto settings = TKikimrSettings()
.SetWithSampleTables(false);
Expand Down
Loading