From 5e1cacd044477b87bed311cc1fc0debedab39bab Mon Sep 17 00:00:00 2001 From: Andrew Stitcher Date: Fri, 15 Mar 2013 17:29:33 +0000 Subject: QPID-4623: Implemented parser and evaluator for BETWEEN comparisons - The implementation uses a custom between operator rather than desugaring the syntax, because we can avoid repeated evaluation of the expression bing compared that way (this will also be true for the IN comparison operator). git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1457029 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/broker/SelectorExpression.cpp | 69 ++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 19 deletions(-) (limited to 'cpp/src/qpid') diff --git a/cpp/src/qpid/broker/SelectorExpression.cpp b/cpp/src/qpid/broker/SelectorExpression.cpp index 5b8621b518..62de067396 100644 --- a/cpp/src/qpid/broker/SelectorExpression.cpp +++ b/cpp/src/qpid/broker/SelectorExpression.cpp @@ -67,8 +67,10 @@ * * ComparisonExpression ::= PrimaryExpression "IS" "NULL" | * PrimaryExpression "IS" "NOT" "NULL" | - * PrimaryExpression "LIKE" LiteralString [ "ESCAPE" LiteralString ] - * PrimaryExpression "NOT" "LIKE" LiteralString [ "ESCAPE" LiteralString ] + * PrimaryExpression "LIKE" LiteralString [ "ESCAPE" LiteralString ] | + * PrimaryExpression "NOT" "LIKE" LiteralString [ "ESCAPE" LiteralString ] | + * PrimaryExpression "BETWEEN" PrimaryExpression "AND" PrimaryExpression | + * PrimaryExpression "NOT" "BETWEEN" PrimaryExpression "AND" PrimaryExpression | * PrimaryExpression ComparisonOpsOps PrimaryExpression | * "NOT" ComparisonExpression | * "(" OrExpression ")" @@ -318,6 +320,34 @@ public: } }; +class BetweenExpression : public BoolExpression { + boost::scoped_ptr e; + boost::scoped_ptr l; + boost::scoped_ptr u; + +public: + BetweenExpression(Expression* e_, Expression* l_, Expression* u_) : + e(e_), + l(l_), + u(u_) + {} + + void repr(ostream& os) const { + os << *e << " BETWEEN " << *l << " AND " << *u; + } + + BoolOrNone eval_bool(const SelectorEnv& env) const { + Value ve(e->eval(env)); + if (unknown(ve)) return BN_UNKNOWN; + Value vl(l->eval(env)); + if (unknown(vl)) return BN_UNKNOWN; + if (veeval(env)); + if (unknown(vu)) return BN_UNKNOWN; + return BoolOrNone(ve<=vu); + } +}; + // Expression types... class Literal : public Expression { @@ -570,23 +600,25 @@ BoolExpression* parseSpecialComparisons(Tokeniser& tokeniser, std::auto_ptr lower(parsePrimaryExpression(tokeniser)); + if ( !lower.get() ) return 0; + if ( tokeniser.nextToken().type!=T_AND ) return 0; + std::auto_ptr upper(parsePrimaryExpression(tokeniser)); + if ( !upper.get() ) return 0; + return new BetweenExpression(e1.release(), lower.release(), upper.release()); + } default: return 0; } @@ -628,11 +660,10 @@ BoolExpression* parseComparisonExpression(Tokeniser& tokeniser) if (!e.get()) return 0; return new UnaryBooleanExpression(¬Op, e.release()); } + case T_BETWEEN: case T_LIKE: { tokeniser.returnTokens(); - std::auto_ptr e(parseSpecialComparisons(tokeniser, e1)); - if (!e.get()) return 0; - return e.release(); + return parseSpecialComparisons(tokeniser, e1); } default: break; -- cgit v1.2.1