Browse Source

YQL-16834 Add optional parameter of MATCH_RECOGNIZE pattern to optimize matching of unused variables

avevad 1 year ago
parent
commit
0e69bf6153

+ 1 - 0
ydb/library/yql/core/sql_types/match_recognize.h

@@ -35,6 +35,7 @@ struct TRowPatternFactor {
     uint64_t QuantityMax;
     bool Greedy;
     bool Output; //include in output with ALL ROW PER MATCH
+    bool Unused; // optimization flag; is true when the variable is not used in defines and measures
 };
 
 THashSet<TString> GetPatternVars(const TRowPattern&);

+ 2 - 2
ydb/library/yql/core/sql_types/match_recognize_ut.cpp

@@ -5,8 +5,8 @@
 using namespace NYql::NMatchRecognize;
 
 Y_UNIT_TEST_SUITE(MatchRecognizePattern){
-    auto factorVar = [](const TString & v) { return TRowPatternFactor{v, 0, 0, false, false};};
-    auto factorExpr = [](const TRowPattern& p) { return TRowPatternFactor{p, 0, 0, false, false};};
+    auto factorVar = [](const TString& v) { return TRowPatternFactor{v, 0, 0, false, false, false};};
+    auto factorExpr = [](const TRowPattern& p) { return TRowPatternFactor{p, 0, 0, false, false, false};};
     auto expected = [](std::initializer_list<TString> list) { return THashSet<TString>(list); };
     Y_UNIT_TEST(SingleVarPattern) {
         const TRowPattern pattern = {{factorVar("A")}};

+ 5 - 4
ydb/library/yql/core/yql_match_recognize.h

@@ -10,15 +10,16 @@ inline TRowPattern ConvertPattern(const TExprNode::TPtr& pattern, TExprContext &
     for (const auto& term: pattern->Children()) {
         result.push_back(TRowPatternTerm{});
         for (const auto& factor: term->Children()) {
-            YQL_ENSURE(factor->ChildrenSize() == 5, "Expect 5 args");
+            YQL_ENSURE(factor->ChildrenSize() == 6, "Expect 6 args");
             result.back().push_back(TRowPatternFactor{
                 factor->ChildRef(0)->IsAtom() ?
-                TRowPatternPrimary(TString(factor->ChildRef(0)->Content())) :
-                ConvertPattern(factor->ChildRef(0), ctx, ++nestingLevel),
+                    TRowPatternPrimary(TString(factor->ChildRef(0)->Content())) :
+                    ConvertPattern(factor->ChildRef(0), ctx, ++nestingLevel),
                 FromString<ui64>(factor->ChildRef(1)->Content()),
                 FromString<ui64>(factor->ChildRef(2)->Content()),
                 FromString<bool>(factor->ChildRef(3)->Content()),
-                FromString<bool>(factor->ChildRef(4)->Content())
+                FromString<bool>(factor->ChildRef(4)->Content()),
+                FromString<bool>(factor->ChildRef(5)->Content())
             });
         }
     }

+ 80 - 1
ydb/library/yql/core/yql_opt_match_recognize.cpp

@@ -31,6 +31,79 @@ bool IsStreaming(const TExprNode::TPtr& input, const TTypeAnnotationContext& typ
 }
 } //namespace
 
+// returns std::nullopt if all vars could be used
+std::optional<TSet<TStringBuf>> FindUsedVars(const TExprNode::TPtr& params) {
+    TSet<TStringBuf> usedVars;
+    bool allVarsUsed = false;
+
+    const auto createVisitor = [&usedVars, &allVarsUsed](const TExprNode::TPtr& varsArg) {
+        return [&varsArg, &usedVars, &allVarsUsed](const TExprNode::TPtr& node) -> bool {
+            if (node->IsCallable("Member")) {
+                if (node->ChildRef(0) == varsArg) {
+                    usedVars.insert(node->ChildRef(1)->Content());
+                    return false;
+                }
+            }
+            if (node == varsArg) {
+                allVarsUsed = true;
+            }
+            return true;
+        };
+    };
+
+    const auto& measures = params->ChildRef(0);
+    static constexpr size_t measureLambdasStartPos = 3;
+    for (size_t pos = measureLambdasStartPos; pos != measures->ChildrenSize(); pos++) {
+        const auto& lambda = measures->ChildRef(pos);
+        const auto& lambdaArgs = lambda->ChildRef(0);
+        const auto& lambdaBody = lambda->ChildRef(1);
+        const auto& varsArg = lambdaArgs->ChildRef(1);
+        NYql::VisitExpr(lambdaBody, createVisitor(varsArg));
+    }
+
+    const auto& defines = params->ChildRef(4);
+    static constexpr size_t defineLambdasStartPos = 3;
+    for (size_t pos = defineLambdasStartPos; pos != defines->ChildrenSize(); pos++) {
+        const auto& lambda = defines->ChildRef(pos);
+        const auto& lambdaArgs = lambda->ChildRef(0);
+        const auto& lambdaBody = lambda->ChildRef(1);
+        const auto& varsArg = lambdaArgs->ChildRef(1);
+        NYql::VisitExpr(lambdaBody, createVisitor(varsArg));
+    }
+
+    return allVarsUsed ? std::nullopt : std::make_optional(usedVars);
+}
+
+// usedVars can be std::nullopt if all vars could probably be used
+TExprNode::TPtr MarkUnusedPatternVars(const TExprNode::TPtr& node, TExprContext& ctx, const std::optional<TSet<TStringBuf>> &usedVars) {
+    const auto pos = node->Pos();
+    if (node->ChildrenSize() != 0 && node->ChildRef(0)->IsAtom()) {
+        const auto& varName = node->ChildRef(0)->Content();
+        bool varUsed = !usedVars.has_value() || usedVars.value().contains(varName);
+        return ctx.Builder(pos)
+            .List()
+                .Add(0, node->ChildRef(0))
+                .Add(1, node->ChildRef(1))
+                .Add(2, node->ChildRef(2))
+                .Add(3, node->ChildRef(3))
+                .Add(4, node->ChildRef(4))
+                .Add(5, ctx.NewAtom(pos, varUsed ? "0" : "1"))
+            .Seal()
+        .Build();
+    }
+    TExprNodeList newChildren;
+    for (size_t chPos = 0; chPos != node->ChildrenSize(); chPos++) {
+        newChildren.push_back(MarkUnusedPatternVars(node->ChildRef(chPos), ctx, usedVars));
+    }
+    if (node->IsCallable()) {
+        return ctx.Builder(pos).Callable(node->Content()).Add(std::move(newChildren)).Seal().Build();
+    } else if (node->IsList()) {
+        return ctx.Builder(pos).List().Add(std::move(newChildren)).Seal().Build();
+    } else { // Atom
+        return node;
+    }
+}
+
 TExprNode::TPtr ExpandMatchRecognize(const TExprNode::TPtr& node, TExprContext& ctx, TTypeAnnotationContext& typeAnnCtx) {
     YQL_ENSURE(node->IsCallable({"MatchRecognize"}));
     const auto& input = node->ChildRef(0);
@@ -55,7 +128,13 @@ TExprNode::TPtr ExpandMatchRecognize(const TExprNode::TPtr& node, TExprContext&
                     .Seal()
                     .Add(1, partitionKeySelector)
                     .Add(2, partitionColumns)
-                    .Add(3, params)
+                    .Callable(3, params->Content())
+                        .Add(0, params->ChildRef(0))
+                        .Add(1, params->ChildRef(1))
+                        .Add(2, params->ChildRef(2))
+                        .Add(3, MarkUnusedPatternVars(params->ChildRef(3), ctx, FindUsedVars(params)))
+                        .Add(4, params->ChildRef(4))
+                    .Seal()
                     .Add(4, settings)
                 .Seal()
             .Seal()

+ 3 - 2
ydb/library/yql/minikql/comp_nodes/mkql_match_recognize.cpp

@@ -484,7 +484,7 @@ TRowPattern ConvertPattern(const TRuntimeNode& pattern) {
         TVector<TRowPatternFactor> term;
         for (ui32 j = 0; j != inputTerm->GetValuesCount(); ++j) {
             const auto& inputFactor = AS_VALUE(TTupleLiteral,  inputTerm->GetValue(j));
-            MKQL_ENSURE(inputFactor->GetValuesCount() == 5, "Internal logic error");
+            MKQL_ENSURE(inputFactor->GetValuesCount() == 6, "Internal logic error");
             const auto& primary = inputFactor->GetValue(0);
             term.push_back(TRowPatternFactor{
                     primary.GetRuntimeType()->IsData() ?
@@ -493,7 +493,8 @@ TRowPattern ConvertPattern(const TRuntimeNode& pattern) {
                     AS_VALUE(TDataLiteral, inputFactor->GetValue(1))->AsValue().Get<ui64>(),
                     AS_VALUE(TDataLiteral, inputFactor->GetValue(2))->AsValue().Get<ui64>(),
                     AS_VALUE(TDataLiteral, inputFactor->GetValue(3))->AsValue().Get<bool>(),
-                    AS_VALUE(TDataLiteral, inputFactor->GetValue(4))->AsValue().Get<bool>()
+                    AS_VALUE(TDataLiteral, inputFactor->GetValue(4))->AsValue().Get<bool>(),
+                    AS_VALUE(TDataLiteral, inputFactor->GetValue(5))->AsValue().Get<bool>()
             });
         }
         result.push_back(std::move(term));

+ 13 - 9
ydb/library/yql/minikql/comp_nodes/mkql_match_recognize_nfa.h

@@ -15,7 +15,7 @@ struct TVoidTransition {
 };
 using TEpsilonTransition = size_t; //to
 using TEpsilonTransitions = std::vector<TEpsilonTransition, TMKQLAllocator<TEpsilonTransition>>;
-using TMatchedVarTransition = std::pair<ui32, size_t>; //{varIndex, to}
+using TMatchedVarTransition = std::pair<std::pair<ui32, bool>, size_t>; //{{varIndex, saveState}, to}
 using TQuantityEnterTransition = size_t; //to
 using TQuantityExitTransition = std::pair<std::pair<ui64, ui64>, std::pair<size_t, size_t>>; //{{min, max}, {foFindMore, toMatched}}
 using TNfaTransition = std::variant<
@@ -203,7 +203,7 @@ private:
         auto input = AddNode();
         auto output = AddNode();
         auto item = factor.Primary.index() == 0 ?
-                    BuildVar(varNameToIndex.at(std::get<0>(factor.Primary))) :
+                    BuildVar(varNameToIndex.at(std::get<0>(factor.Primary)), !factor.Unused) :
                     BuildTerms(std::get<1>(factor.Primary), varNameToIndex);
         if (1 == factor.QuantityMin && 1 == factor.QuantityMax) { //simple linear case
             Graph->Transitions[input] = TEpsilonTransitions{item.Input};
@@ -223,12 +223,12 @@ private:
         }
         return {input, output};
     }
-    TNfaItem BuildVar(ui32 varIndex) {
+    TNfaItem BuildVar(ui32 varIndex, bool isUsed) {
         auto input = AddNode();
         auto matchVar = AddNode();
         auto output = AddNode();
         Graph->Transitions[input] = TEpsilonTransitions({matchVar});
-        Graph->Transitions[matchVar] = std::pair{varIndex, output};
+        Graph->Transitions[matchVar] = std::pair{std::pair{varIndex, isUsed}, output};
         return {input, output};
     }
 public:
@@ -283,13 +283,17 @@ public:
             //all other transitions are handled in MakeEpsilonTransitions
             if (const auto* matchedVarTransition = std::get_if<TMatchedVarTransition>(&TransitionGraph->Transitions[s.Index])) {
                 MatchedRangesArg->SetValue(ctx, ctx.HolderFactory.Create<TMatchedVarsValue<TRange>>(ctx.HolderFactory, s.Vars));
-                const auto varIndex = matchedVarTransition->first;
+                const auto varIndex = matchedVarTransition->first.first;
                 const auto& v = Defines[varIndex]->GetValue(ctx);
                 if (v && v.Get<bool>()) {
-                    auto vars = s.Vars; //TODO get rid of this copy
-                    auto& matchedVar = vars[varIndex];
-                    Extend(matchedVar, currentRowLock);
-                    newStates.emplace(matchedVarTransition->second, std::move(vars), std::stack<ui64, std::deque<ui64, TMKQLAllocator<ui64>>>(s.Quantifiers));
+                    if (matchedVarTransition->first.second) {
+                        auto vars = s.Vars; //TODO get rid of this copy
+                        auto& matchedVar = vars[varIndex];
+                        Extend(matchedVar, currentRowLock);
+                        newStates.emplace(matchedVarTransition->second, std::move(vars), std::stack<ui64, std::deque<ui64, TMKQLAllocator<ui64>>>(s.Quantifiers));
+                    } else {
+                        newStates.emplace(matchedVarTransition->second, s.Vars, std::stack<ui64, std::deque<ui64, TMKQLAllocator<ui64>>>(s.Quantifiers));
+                    }
                 }
                 deletedStates.insert(s);
             }

+ 54 - 36
ydb/library/yql/minikql/comp_nodes/ut/mkql_match_recognize_nfa_ut.cpp

@@ -126,7 +126,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
 
     Y_UNIT_TEST(OutputStateHasNoOutputEdges) {
         TScopedAlloc alloc(__LOCATION__);
-        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false}}};
+        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false, false}}};
         const auto transitionGraph = TNfaTransitionGraphBuilder::Create(pattern, {{"A", 0}});
         const auto& output = transitionGraph->Transitions.at(transitionGraph->Output);
         UNIT_ASSERT(std::get_if<TVoidTransition>(&output));
@@ -135,25 +135,25 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         TScopedAlloc alloc(__LOCATION__);
         const TRowPattern pattern{
             {
-                TRowPatternFactor{"A", 1, 1, false, false},
-                TRowPatternFactor{"B", 1, 100, false, false},
+                TRowPatternFactor{"A", 1, 1, false, false, false},
+                TRowPatternFactor{"B", 1, 100, false, false, false},
                 TRowPatternFactor{
                     TRowPattern{
-                        {TRowPatternFactor{"C", 1, 1, false, false}},
-                        {TRowPatternFactor{"D", 1, 1, false, false}}
+                        {TRowPatternFactor{"C", 1, 1, false, false, false}},
+                        {TRowPatternFactor{"D", 1, 1, false, false, false}}
                     },
-                    1, 1, false, false
+                    1, 1, false, false, false
                 }
             },
             {
                 TRowPatternFactor{
                     TRowPattern{{
-                                    TRowPatternFactor{"E", 1, 1, false, false},
-                                    TRowPatternFactor{"F", 1, 100, false, false},
+                                    TRowPatternFactor{"E", 1, 1, false, false, false},
+                                    TRowPatternFactor{"F", 1, 100, false, false, false},
                                 }},
-                    2, 100, false, false
+                    2, 100, false, false, false
                 },
-                TRowPatternFactor{"G", 1, 1, false, false}
+                TRowPatternFactor{"G", 1, 1, false, false, false}
             }
         };
         const auto graph = TNfaTransitionGraphBuilder::Create(pattern, TNfaSetup::BuildVarLookup(pattern));
@@ -172,8 +172,8 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
     Y_UNIT_TEST(SingleEpsilonsEliminated) {
         TScopedAlloc alloc(__LOCATION__);
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1, false, false},
-            TRowPatternFactor{"B", 1, 1, false, false},
+            TRowPatternFactor{"A", 1, 1, false, false, false},
+            TRowPatternFactor{"B", 1, 1, false, false, false},
         }};
         const auto graph = TNfaTransitionGraphBuilder::Create(pattern, TNfaSetup::BuildVarLookup(pattern));
         for (size_t node = 0; node != graph->Transitions.size(); node++) {
@@ -198,7 +198,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
     Y_UNIT_TEST(SingleVarAcceptNothing) {
         TScopedAlloc alloc(__LOCATION__);
         THolderFactory holderFactory(alloc.Ref(), memUsage);
-        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false}}};
+        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false, false}}};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
         auto& ctx = setup.Ctx();
@@ -212,7 +212,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
     Y_UNIT_TEST(SingleVarAcceptEveryRow) {
         TScopedAlloc alloc(__LOCATION__);
         THolderFactory holderFactory(alloc.Ref(), memUsage);
-        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false}}};
+        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false, false}}};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
         auto& ctx = setup.Ctx();
@@ -226,7 +226,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
     Y_UNIT_TEST(SingleAlternatedVarAcceptEven) {
         TScopedAlloc alloc(__LOCATION__);
         THolderFactory holderFactory(alloc.Ref(), memUsage);
-        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false}}};
+        const TRowPattern pattern{{TRowPatternFactor{"A", 1, 1, false, false, false}}};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
         auto& ctx = setup.Ctx();
@@ -242,7 +242,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         TScopedAlloc alloc(__LOCATION__);
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         // "A{4, 6}"
-        const TRowPattern pattern{{TRowPatternFactor{"A", 4, 6, false, false}}};
+        const TRowPattern pattern{{TRowPatternFactor{"A", 4, 6, false, false, false}}};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
         auto& ctx = setup.Ctx();
@@ -274,9 +274,9 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         // "A A A"
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1, false, false},
-            TRowPatternFactor{"A", 1, 1, false, false},
-            TRowPatternFactor{"A", 1, 1, false, false}
+            TRowPatternFactor{"A", 1, 1, false, false, false},
+            TRowPatternFactor{"A", 1, 1, false, false, false},
+            TRowPatternFactor{"A", 1, 1, false, false, false}
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -295,8 +295,8 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"A B"
         const TRowPattern pattern{{
-                TRowPatternFactor{"A", 1, 1, false, false},
-                TRowPatternFactor{"B", 1, 1, false, false},
+                TRowPatternFactor{"A", 1, 1, false, false, false},
+                TRowPatternFactor{"B", 1, 1, false, false, false},
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -316,8 +316,8 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"A | B"
         const TRowPattern pattern{
-              {TRowPatternFactor{"A", 1, 1, false, false}},
-              {TRowPatternFactor{"B", 1, 1, false, false}},
+              {TRowPatternFactor{"A", 1, 1, false, false, false}},
+              {TRowPatternFactor{"B", 1, 1, false, false, false}},
         };
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -340,7 +340,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"Any*"
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1000000000, false, false},
+            TRowPatternFactor{"A", 1, 1000000000, false, false, false},
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -359,6 +359,24 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         UNIT_ASSERT_VALUES_EQUAL(inputSize * (inputSize + 1) / 2, totalMatches);
     }
 
+    Y_UNIT_TEST(UnusedVarIgnored) {
+        TScopedAlloc alloc(__LOCATION__);
+        THolderFactory holderFactory(alloc.Ref(), memUsage);
+        const TRowPattern pattern{{
+            TRowPatternFactor{"ANY", 1, 100, false, false, true},
+        }};
+        TNfaSetup setup{pattern};
+        auto& defineA = setup.Defines.at(0);
+        auto& ctx = setup.Ctx();
+        defineA->SetValue(ctx, NUdf::TUnboxedValuePod{true});
+        TSparseList list;
+        const size_t inputSize = 100;
+        for (size_t i = 0; i != inputSize; ++i) {
+            setup.Nfa.ProcessRow(list.Append(NUdf::TUnboxedValue{}), ctx);
+            UNIT_ASSERT_EQUAL(0, setup.Nfa.GetMatched().value()[0].size());
+        }
+    }
+
     //Pattern: A*
     //Input: intermittent series events that match A
     Y_UNIT_TEST(AStar) {
@@ -366,7 +384,7 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"A*"
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1000000000, false, false},
+            TRowPatternFactor{"A", 1, 1000000000, false, false, false},
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -403,9 +421,9 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"A ANY* B"
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1, false, false},
-            TRowPatternFactor{"ANY", 1, 1000000000, false, false},
-            TRowPatternFactor{"B", 1, 1, false, false},
+            TRowPatternFactor{"A", 1, 1, false, false, false},
+            TRowPatternFactor{"ANY", 1, 1000000000, false, false, false},
+            TRowPatternFactor{"B", 1, 1, false, false, false},
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -432,9 +450,9 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"A ANY* B"
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1, false, false},
-            TRowPatternFactor{"ANY", 1, 1000000000, false, false},
-            TRowPatternFactor{"B", 1, 1, false, false},
+            TRowPatternFactor{"A", 1, 1, false, false, false},
+            TRowPatternFactor{"ANY", 1, 1000000000, false, false, false},
+            TRowPatternFactor{"B", 1, 1, false, false, false},
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);
@@ -478,11 +496,11 @@ Y_UNIT_TEST_SUITE(MatchRecognizeNfa) {
         THolderFactory holderFactory(alloc.Ref(), memUsage);
         //"A ANY* B ANY* C"
         const TRowPattern pattern{{
-            TRowPatternFactor{"A", 1, 1, false, false},
-            TRowPatternFactor{"ANY", 1, 1000000000, false, false},
-            TRowPatternFactor{"B", 1, 1, false, false},
-            TRowPatternFactor{"ANY", 1, 1000000000, false, false},
-            TRowPatternFactor{"C", 1, 1, false, false},
+            TRowPatternFactor{"A", 1, 1, false, false, false},
+            TRowPatternFactor{"ANY", 1, 1000000000, false, false, false},
+            TRowPatternFactor{"B", 1, 1, false, false, false},
+            TRowPatternFactor{"ANY", 1, 1000000000, false, false, false},
+            TRowPatternFactor{"C", 1, 1, false, false, false},
         }};
         TNfaSetup setup{pattern};
         auto& defineA = setup.Defines.at(0);

+ 1 - 0
ydb/library/yql/minikql/mkql_program_builder.cpp

@@ -5826,6 +5826,7 @@ TRuntimeNode PatternToRuntimeNode(const TRowPattern& pattern, const TProgramBuil
             factorBuilder.Add(programBuilder.NewDataLiteral<ui64>(factor.QuantityMax));
             factorBuilder.Add(programBuilder.NewDataLiteral<bool>(factor.Greedy));
             factorBuilder.Add(programBuilder.NewDataLiteral<bool>(factor.Output));
+            factorBuilder.Add(programBuilder.NewDataLiteral<bool>(factor.Unused));
             termBuilder.Add({factorBuilder.Build(), true});
         }
         patternBuilder.Add({termBuilder.Build(), true});

+ 1 - 0
ydb/library/yql/sql/v1/match_recognize.cpp

@@ -128,6 +128,7 @@ private:
                 BuildQuotedAtom(pos, ToString(factor.QuantityMax)),
                 BuildQuotedAtom(pos, ToString(factor.Greedy)),
                 BuildQuotedAtom(pos, ToString(factor.Output)),
+                BuildQuotedAtom(pos, ToString(factor.Unused))
         });
     }
 

+ 1 - 1
ydb/library/yql/sql/v1/sql_match_recognize.cpp

@@ -310,7 +310,7 @@ NYql::NMatchRecognize::TRowPatternTerm TSqlMatchRecognizeClause::ParsePatternTer
                     Y_ABORT("You should change implementation according to grammar changes");
             }
         }
-        term.push_back(NYql::NMatchRecognize::TRowPatternFactor{std::move(primary), quantityMin, quantityMax, greedy, output});
+        term.push_back(NYql::NMatchRecognize::TRowPatternFactor{std::move(primary), quantityMin, quantityMax, greedy, output, false});
     }
     return term;
 }

Some files were not shown because too many files changed in this diff