diff options
| author | vvvv <[email protected]> | 2023-06-14 19:59:08 +0300 |
|---|---|---|
| committer | vvvv <[email protected]> | 2023-06-14 19:59:08 +0300 |
| commit | 1f28f637f5097f6ee7835de829bf4a6947849d00 (patch) | |
| tree | caed48a9b853f0087feaafda299ed42ad3ecc563 | |
| parent | 3f3f15f2e06a1f183d72c229cacf1d0f8949aa57 (diff) | |
Optimizers for PgLike to avoid Re2 if possible
| -rw-r--r-- | ydb/library/yql/core/common_opt/yql_co_pgselect.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/ydb/library/yql/core/common_opt/yql_co_pgselect.cpp b/ydb/library/yql/core/common_opt/yql_co_pgselect.cpp index 7b6dbd9dfaf..7b12850f891 100644 --- a/ydb/library/yql/core/common_opt/yql_co_pgselect.cpp +++ b/ydb/library/yql/core/common_opt/yql_co_pgselect.cpp @@ -3240,6 +3240,59 @@ TExprNode::TPtr ExpandPgSelectSublink(const TExprNode::TPtr& node, TExprContext& TExprNode::TPtr ExpandPgLike(const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& optCtx) { Y_UNUSED(optCtx); const bool insensitive = node->IsCallable("PgILike"); + if (!insensitive) { + auto pattern = node->Child(1); + if (pattern->IsCallable("PgConst") && + pattern->Tail().IsCallable("PgType") && + pattern->Tail().Head().Content() == "text") { + auto str = pattern->Head().Content(); + auto hasUnderscore = AnyOf(str, [](char c) { return c == '_'; }); + size_t countOfPercents = 0; + ForEach(str.begin(), str.end(), [&](char c) { countOfPercents += (c == '%');}); + if (!hasUnderscore && countOfPercents == 0) { + return ctx.Builder(node->Pos()) + .Callable("PgOp") + .Atom(0, "=") + .Add(1, node->ChildPtr(0)) + .Add(2, pattern) + .Seal() + .Build(); + } + + TStringBuf op; + TStringBuf arg; + if (!hasUnderscore && countOfPercents == 1 && str.StartsWith('%')) { + op = "EndsWith"; + arg = str.SubString(1, str.Size() - 1); + } + + if (!hasUnderscore && countOfPercents == 1 && str.EndsWith('%')) { + op = "StartsWith"; + arg = str.SubString(0, str.Size() - 1); + } + + if (!hasUnderscore && countOfPercents == 2 && str.StartsWith('%') && str.EndsWith('%')) { + op = "StringContains"; + arg = str.SubString(1, str.Size() - 2); + } + + if (!op.empty()) { + return ctx.Builder(node->Pos()) + .Callable("ToPg") + .Callable(0, op) + .Callable(0, "FromPg") + .Add(0, node->ChildPtr(0)) + .Seal() + .Callable(1, "String") + .Atom(0, arg) + .Seal() + .Seal() + .Seal() + .Build(); + } + } + } + auto matcher = ctx.Builder(node->Pos()) .Callable("Udf") .Atom(0, "Re2.Match") |
