diff options
| author | Andrew Stitcher <astitcher@apache.org> | 2013-03-15 17:29:33 +0000 |
|---|---|---|
| committer | Andrew Stitcher <astitcher@apache.org> | 2013-03-15 17:29:33 +0000 |
| commit | 5e1cacd044477b87bed311cc1fc0debedab39bab (patch) | |
| tree | 2697f2583d07e9bc30df6b6b9cb0cb7375a2f6a7 /cpp/src/qpid | |
| parent | 2a9ffab152272e1f752508f995630c755a39eb79 (diff) | |
| download | qpid-python-5e1cacd044477b87bed311cc1fc0debedab39bab.tar.gz | |
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
Diffstat (limited to 'cpp/src/qpid')
| -rw-r--r-- | cpp/src/qpid/broker/SelectorExpression.cpp | 69 |
1 files changed, 50 insertions, 19 deletions
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<Expression> e; + boost::scoped_ptr<Expression> l; + boost::scoped_ptr<Expression> 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 (ve<vl) return BN_FALSE; + Value vu(u->eval(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<Expr switch (tokeniser.nextToken().type) { case T_LIKE: { const Token t = tokeniser.nextToken(); - if ( t.type==T_STRING ) { - // Check for "ESCAPE" - if ( tokeniser.nextToken().type==T_ESCAPE ) { - const Token e = tokeniser.nextToken(); - if ( e.type==T_STRING ) { - return new LikeExpression(e1.release(), t.val, e.val); - } else { - return 0; - } - } else { - tokeniser.returnTokens(); - return new LikeExpression(e1.release(), t.val); - } + if ( t.type!=T_STRING ) return 0; + // Check for "ESCAPE" + if ( tokeniser.nextToken().type==T_ESCAPE ) { + const Token e = tokeniser.nextToken(); + if ( e.type!=T_STRING ) return 0; + return new LikeExpression(e1.release(), t.val, e.val); } else { - return 0; + tokeniser.returnTokens(); + return new LikeExpression(e1.release(), t.val); } } + case T_BETWEEN: { + std::auto_ptr<Expression> lower(parsePrimaryExpression(tokeniser)); + if ( !lower.get() ) return 0; + if ( tokeniser.nextToken().type!=T_AND ) return 0; + std::auto_ptr<Expression> 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<BoolExpression>(¬Op, e.release()); } + case T_BETWEEN: case T_LIKE: { tokeniser.returnTokens(); - std::auto_ptr<BoolExpression> e(parseSpecialComparisons(tokeniser, e1)); - if (!e.get()) return 0; - return e.release(); + return parseSpecialComparisons(tokeniser, e1); } default: break; |
