summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Stitcher <astitcher@apache.org>2013-03-18 21:08:34 +0000
committerAndrew Stitcher <astitcher@apache.org>2013-03-18 21:08:34 +0000
commit03883ac585b8ca2f3d295790cd54b5fde209a55d (patch)
tree433a916145218352af1a6c06edebe37200d7fb8c
parentb31130203c660351313fa931ea30a8b79e813fef (diff)
downloadqpid-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.cpp52
-rw-r--r--qpid/cpp/src/tests/Selector.cpp7
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>(&notOp, 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)