diff options
author | Andrew Stitcher <astitcher@apache.org> | 2013-03-18 21:08:34 +0000 |
---|---|---|
committer | Andrew Stitcher <astitcher@apache.org> | 2013-03-18 21:08:34 +0000 |
commit | 03883ac585b8ca2f3d295790cd54b5fde209a55d (patch) | |
tree | 433a916145218352af1a6c06edebe37200d7fb8c | |
parent | b31130203c660351313fa931ea30a8b79e813fef (diff) | |
download | qpid-python-03883ac585b8ca2f3d295790cd54b5fde209a55d.tar.gz |
QPID-4624: Implement IN operator for C++ broker selectors
- Implemented parser for IN operator
- Implement In operator evaluator and unit tests
- Syntax is a bit wider than the spec allowing full expressions
in the contents of the IN expression not just strings.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1457998 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | qpid/cpp/src/qpid/broker/SelectorExpression.cpp | 52 | ||||
-rw-r--r-- | qpid/cpp/src/tests/Selector.cpp | 7 |
2 files changed, 57 insertions, 2 deletions
diff --git a/qpid/cpp/src/qpid/broker/SelectorExpression.cpp b/qpid/cpp/src/qpid/broker/SelectorExpression.cpp index 58ab756a12..2eaffd7ccb 100644 --- a/qpid/cpp/src/qpid/broker/SelectorExpression.cpp +++ b/qpid/cpp/src/qpid/broker/SelectorExpression.cpp @@ -31,8 +31,9 @@ #include <memory> #include <ostream> -#include <boost/scoped_ptr.hpp> #include <boost/lexical_cast.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/ptr_container/ptr_vector.hpp> /* * Syntax for JMS style selector expressions (informal): @@ -379,6 +380,40 @@ public: } }; +class InExpression : public BoolExpression { + boost::scoped_ptr<Expression> e; + boost::ptr_vector<Expression> l; + +public: + InExpression(Expression* e_, boost::ptr_vector<Expression>& l_) : + e(e_) + { + l.swap(l_); + } + + void repr(ostream& os) const { + os << *e << " IN ("; + for (std::size_t i = 0; i<l.size(); ++i){ + os << l[i] << (i<l.size()-1 ? ", " : ")"); + } + } + + BoolOrNone eval_bool(const SelectorEnv& env) const { + Value ve(e->eval(env)); + if (unknown(ve)) return BN_UNKNOWN; + BoolOrNone r = BN_FALSE; + for (std::size_t i = 0; i<l.size(); ++i){ + Value li(l[i].eval(env)); + if (unknown(li)) { + r = BN_UNKNOWN; + continue; + } + if (ve==li) return BN_TRUE; + } + return r; + } +}; + // Arithmetic Expression types class ArithmeticExpression : public Expression { @@ -751,6 +786,18 @@ BoolExpression* parseSpecialComparisons(Tokeniser& tokeniser, std::auto_ptr<Expr if ( !upper.get() ) return 0; return new BetweenExpression(e1.release(), lower.release(), upper.release()); } + case T_IN: { + if ( tokeniser.nextToken().type!=T_LPAREN ) return 0; + boost::ptr_vector<Expression> list; + do { + std::auto_ptr<Expression> e(parseAddExpression(tokeniser)); + if (!e.get()) return 0; + list.push_back(e.release()); + } while (tokeniser.nextToken().type==T_COMMA); + tokeniser.returnTokens(); + if ( tokeniser.nextToken().type!=T_RPAREN ) return 0; + return new InExpression(e1.release(), list); + } default: return 0; } @@ -788,7 +835,8 @@ Expression* parseComparisonExpression(Tokeniser& tokeniser) return new UnaryBooleanExpression<Expression>(¬Op, e.release()); } case T_BETWEEN: - case T_LIKE: { + case T_LIKE: + case T_IN: { tokeniser.returnTokens(); return parseSpecialComparisons(tokeniser, e1); } diff --git a/qpid/cpp/src/tests/Selector.cpp b/qpid/cpp/src/tests/Selector.cpp index 7758e3e5b0..1fc9a9b7bb 100644 --- a/qpid/cpp/src/tests/Selector.cpp +++ b/qpid/cpp/src/tests/Selector.cpp @@ -297,6 +297,7 @@ QPID_AUTO_TEST_CASE(parseString) BOOST_CHECK_NO_THROW(qb::Selector e("(354.6)")); BOOST_CHECK_NO_THROW(qb::Selector e("A is null and 'hello out there'")); BOOST_CHECK_NO_THROW(qb::Selector e("17/4>4")); + BOOST_CHECK_NO_THROW(qb::Selector e("A IN ('hello', 'there', 1 , true, (1-17))")); } class TestSelectorEnv : public qpid::broker::SelectorEnv { @@ -401,6 +402,12 @@ QPID_AUTO_TEST_CASE(comparisonEval) BOOST_CHECK(!qb::Selector("'hello'>42 and 'hello'<42 and 'hello'=42 and 'hello'<>42").eval(env)); BOOST_CHECK(qb::Selector("20 >= 19.0 and 20 > 19").eval(env)); BOOST_CHECK(qb::Selector("42 <= 42.0 and 37.0 >= 37").eval(env)); + BOOST_CHECK(qb::Selector("(A IN ('hello', 'there', 1 , true, (1-17))) IS NULL").eval(env)); + BOOST_CHECK(qb::Selector("'hello' IN ('hello', 'there', 1 , true, (1-17))").eval(env)); + BOOST_CHECK(qb::Selector("TRUE IN ('hello', 'there', 1 , true, (1-17))").eval(env)); + BOOST_CHECK(qb::Selector("-16 IN ('hello', 'there', 1 , true, (1-17))").eval(env)); + BOOST_CHECK(!qb::Selector("'hell' IN ('hello', 'there', 1 , true, (1-17))").eval(env)); + BOOST_CHECK(qb::Selector("('hell' IN ('hello', 'there', 1 , true, (1-17), A)) IS NULL").eval(env)); } QPID_AUTO_TEST_CASE(NullEval) |