diff --git a/c++/include/orc/sargs/SearchArgument.hh b/c++/include/orc/sargs/SearchArgument.hh index 6493840a92..2fa3ea04cb 100644 --- a/c++/include/orc/sargs/SearchArgument.hh +++ b/c++/include/orc/sargs/SearchArgument.hh @@ -251,6 +251,12 @@ namespace orc { * @return the new SearchArgument */ virtual std::unique_ptr build() = 0; + + /** + * Add a maybe leaf to the current item on the stack. + * @return this + */ + virtual SearchArgumentBuilder& maybe() = 0; }; /** diff --git a/c++/src/sargs/SearchArgument.cc b/c++/src/sargs/SearchArgument.cc index 83d4af2435..ff0ba1e2d5 100644 --- a/c++/src/sargs/SearchArgument.cc +++ b/c++/src/sargs/SearchArgument.cc @@ -272,6 +272,12 @@ namespace orc { return *this; } + SearchArgumentBuilder& SearchArgumentBuilderImpl::maybe() { + TreeNode& parent = currTree_.front(); + parent->addChild(std::make_shared(TruthValue::YES_NO_NULL)); + return *this; + } + /** * Recursively explore the tree to find the leaves that are still reachable * after optimizations. diff --git a/c++/src/sargs/SearchArgument.hh b/c++/src/sargs/SearchArgument.hh index 1963c993d6..7d663f7349 100644 --- a/c++/src/sargs/SearchArgument.hh +++ b/c++/src/sargs/SearchArgument.hh @@ -275,6 +275,12 @@ namespace orc { */ std::unique_ptr build() override; + /** + * Add a maybe leaf to the current item on the stack. + * @return this + */ + SearchArgumentBuilder& maybe() override; + private: SearchArgumentBuilder& start(ExpressionTree::Operator op); size_t addLeaf(PredicateLeaf leaf); diff --git a/c++/test/TestSearchArgument.cc b/c++/test/TestSearchArgument.cc index e51ee1e8b5..09904139cb 100644 --- a/c++/test/TestSearchArgument.cc +++ b/c++/test/TestSearchArgument.cc @@ -490,4 +490,36 @@ namespace orc { EXPECT_THROW(invalidNode->evaluate(leaves), std::invalid_argument); } + TEST(TestSearchArgument, testMaybe) { + auto expectedSarg = + SearchArgumentFactory::newBuilder() + ->startNot() + .startOr() + .isNull("x", PredicateDataType::LONG) + .between("y", PredicateDataType::DECIMAL, Literal(10, 3, 0), Literal(200, 3, 1)) + .in("z", PredicateDataType::LONG, + {Literal(static_cast(1)), Literal(static_cast(2)), + Literal(static_cast(3))}) + .nullSafeEquals("a", PredicateDataType::STRING, Literal("stinger", 7)) + .end() + .end() + .build(); + + auto sargWithMaybe = + SearchArgumentFactory::newBuilder() + ->startNot() + .startOr() + .isNull("x", PredicateDataType::LONG) + .between("y", PredicateDataType::DECIMAL, Literal(10, 3, 0), Literal(200, 3, 1)) + .in("z", PredicateDataType::LONG, + {Literal(static_cast(1)), Literal(static_cast(2)), + Literal(static_cast(3))}) + .maybe() + .nullSafeEquals("a", PredicateDataType::STRING, Literal("stinger", 7)) + .end() + .end() + .build(); + EXPECT_EQ(expectedSarg->toString(), sargWithMaybe->toString()); + } + } // namespace orc