From 3ac885705d9fa36870c1b059e1089c158fa66285 Mon Sep 17 00:00:00 2001 From: Quan Date: Fri, 16 Jun 2023 16:22:46 +0800 Subject: [PATCH] new feature: sql expression CONTAINS support (#6864) --- .../expression/ComparisonExpression.java | 84 ++ .../filter/parser/ParseException.java | 2 +- .../filter/parser/SelectorParser.java | 755 ++++++++---------- .../rocketmq/filter/parser/SelectorParser.jj | 13 +- .../parser/SelectorParserConstants.java | 15 +- .../parser/SelectorParserTokenManager.java | 176 ++-- .../filter/parser/SimpleCharStream.java | 2 +- .../apache/rocketmq/filter/parser/Token.java | 2 +- .../rocketmq/filter/parser/TokenMgrError.java | 2 +- .../rocketmq/filter/ExpressionTest.java | 318 ++++++++ .../apache/rocketmq/filter/ParserTest.java | 4 +- 11 files changed, 887 insertions(+), 486 deletions(-) diff --git a/filter/src/main/java/org/apache/rocketmq/filter/expression/ComparisonExpression.java b/filter/src/main/java/org/apache/rocketmq/filter/expression/ComparisonExpression.java index b793cdf9762..ff9d84af01c 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/expression/ComparisonExpression.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/expression/ComparisonExpression.java @@ -69,6 +69,90 @@ public static BooleanExpression createNotBetween(Expression value, Expression le return LogicExpression.createOR(createLessThan(value, left), createGreaterThan(value, right)); } + static class ContainsExpression extends UnaryExpression implements BooleanExpression { + + String search; + + public ContainsExpression(Expression right, String search) { + super(right); + this.search = search; + } + + public String getExpressionSymbol() { + return "CONTAINS"; + } + + public Object evaluate(EvaluationContext message) throws Exception { + + if (search == null || search.length() == 0) { + return Boolean.FALSE; + } + + Object rv = this.getRight().evaluate(message); + + if (rv == null) { + return Boolean.FALSE; + } + + if (!(rv instanceof String)) { + return Boolean.FALSE; + } + + return ((String)rv).contains(search) ? Boolean.TRUE : Boolean.FALSE; + } + + public boolean matches(EvaluationContext message) throws Exception { + Object object = evaluate(message); + return object != null && object == Boolean.TRUE; + } + } + + static class NotContainsExpression extends UnaryExpression implements BooleanExpression { + + String search; + + public NotContainsExpression(Expression right, String search) { + super(right); + this.search = search; + } + + public String getExpressionSymbol() { + return "NOT CONTAINS"; + } + + public Object evaluate(EvaluationContext message) throws Exception { + + if (search == null || search.length() == 0) { + return Boolean.FALSE; + } + + Object rv = this.getRight().evaluate(message); + + if (rv == null) { + return Boolean.FALSE; + } + + if (!(rv instanceof String)) { + return Boolean.FALSE; + } + + return ((String)rv).contains(search) ? Boolean.FALSE : Boolean.TRUE; + } + + public boolean matches(EvaluationContext message) throws Exception { + Object object = evaluate(message); + return object != null && object == Boolean.TRUE; + } + } + + public static BooleanExpression createContains(Expression left, String search) { + return new ContainsExpression(left, search); + } + + public static BooleanExpression createNotContains(Expression left, String search) { + return new NotContainsExpression(left, search); + } + @SuppressWarnings({"rawtypes", "unchecked"}) public static BooleanExpression createInFilter(Expression left, List elements) { diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/ParseException.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/ParseException.java index 0a327bea1c0..39762509e0d 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/ParseException.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/ParseException.java @@ -202,4 +202,4 @@ static String add_escapes(String str) { } } -/* JavaCC - OriginalChecksum=4c829b0daa2c9af00ddafe2441eb9097 (do not edit this line) */ +/* JavaCC - OriginalChecksum=60cf9c227a487e4be49599bc903f0a6a (do not edit this line) */ diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.java index 5658391fd5e..d23e6ee9759 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.java @@ -41,10 +41,10 @@ public class SelectorParser implements SelectorParserConstants { private static final Cache PARSE_CACHE = CacheBuilder.newBuilder().maximumSize(100).build(); - // private static final String CONVERT_STRING_EXPRESSIONS_PREFIX = "convert_string_expressions:"; +// private static final String CONVERT_STRING_EXPRESSIONS_PREFIX = "convert_string_expressions:"; public static BooleanExpression parse(String sql) throws MQFilterException { - // sql = "("+sql+")"; +// sql = "("+sql+")"; Object result = PARSE_CACHE.getIfPresent(sql); if (result instanceof MQFilterException) { throw (MQFilterException) result; @@ -52,14 +52,14 @@ public static BooleanExpression parse(String sql) throws MQFilterException { return (BooleanExpression) result; } else { - // boolean convertStringExpressions = false; - // if( sql.startsWith(CONVERT_STRING_EXPRESSIONS_PREFIX)) { - // convertStringExpressions = true; - // sql = sql.substring(CONVERT_STRING_EXPRESSIONS_PREFIX.length()); - // } - // if( convertStringExpressions ) { - // ComparisonExpression.CONVERT_STRING_EXPRESSIONS.set(true); - // } +// boolean convertStringExpressions = false; +// if( sql.startsWith(CONVERT_STRING_EXPRESSIONS_PREFIX)) { +// convertStringExpressions = true; +// sql = sql.substring(CONVERT_STRING_EXPRESSIONS_PREFIX.length()); +// } +// if( convertStringExpressions ) { +// ComparisonExpression.CONVERT_STRING_EXPRESSIONS.set(true); +// } ComparisonExpression.CONVERT_STRING_EXPRESSIONS.set(true); try { @@ -71,9 +71,9 @@ public static BooleanExpression parse(String sql) throws MQFilterException { throw t; } finally { ComparisonExpression.CONVERT_STRING_EXPRESSIONS.remove(); - // if( convertStringExpressions ) { - // ComparisonExpression.CONVERT_STRING_EXPRESSIONS.remove(); - // } +// if( convertStringExpressions ) { +// ComparisonExpression.CONVERT_STRING_EXPRESSIONS.remove(); +// } } } } @@ -114,8 +114,7 @@ final public BooleanExpression JmsSelector() throws ParseException { Expression left = null; left = orExpression(); { - if (true) - return asBooleanExpression(left); + if (true) return asBooleanExpression(left); } throw new Error("Missing return statement in function"); } @@ -138,8 +137,7 @@ final public Expression orExpression() throws ParseException { left = LogicExpression.createOR(asBooleanExpression(left), asBooleanExpression(right)); } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -162,8 +160,7 @@ final public Expression andExpression() throws ParseException { left = LogicExpression.createAND(asBooleanExpression(left), asBooleanExpression(right)); } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -176,21 +173,21 @@ final public Expression equalityExpression() throws ParseException { while (true) { switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { case IS: - case 22: case 23: + case 24: break; default: jjLa1[2] = jjGen; break label_3; } switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { - case 22: - jj_consume_token(22); + case 23: + jj_consume_token(23); right = comparisonExpression(); left = ComparisonExpression.createEqual(left, right); break; - case 23: - jj_consume_token(23); + case 24: + jj_consume_token(24); right = comparisonExpression(); left = ComparisonExpression.createNotEqual(left, right); break; @@ -217,8 +214,7 @@ final public Expression equalityExpression() throws ParseException { } } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -238,111 +234,127 @@ final public Expression comparisonExpression() throws ParseException { case NOT: case BETWEEN: case IN: - case 24: + case CONTAINS: case 25: case 26: case 27: + case 28: break; default: jjLa1[5] = jjGen; break label_4; } switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { - case 24: - jj_consume_token(24); - right = unaryExpr(); - left = ComparisonExpression.createGreaterThan(left, right); - break; case 25: jj_consume_token(25); right = unaryExpr(); - left = ComparisonExpression.createGreaterThanEqual(left, right); + left = ComparisonExpression.createGreaterThan(left, right); break; case 26: jj_consume_token(26); right = unaryExpr(); - left = ComparisonExpression.createLessThan(left, right); + left = ComparisonExpression.createGreaterThanEqual(left, right); break; case 27: jj_consume_token(27); right = unaryExpr(); + left = ComparisonExpression.createLessThan(left, right); + break; + case 28: + jj_consume_token(28); + right = unaryExpr(); left = ComparisonExpression.createLessThanEqual(left, right); break; - case BETWEEN: - jj_consume_token(BETWEEN); - low = unaryExpr(); - jj_consume_token(AND); - high = unaryExpr(); - left = ComparisonExpression.createBetween(left, low, high); + case CONTAINS: + jj_consume_token(CONTAINS); + t = stringLitteral(); + left = ComparisonExpression.createContains(left, t); break; default: jjLa1[8] = jjGen; if (jj_2_2(2)) { jj_consume_token(NOT); - jj_consume_token(BETWEEN); - low = unaryExpr(); - jj_consume_token(AND); - high = unaryExpr(); - left = ComparisonExpression.createNotBetween(left, low, high); + jj_consume_token(CONTAINS); + t = stringLitteral(); + left = ComparisonExpression.createNotContains(left, t); } else { switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { - case IN: - jj_consume_token(IN); - jj_consume_token(28); - t = stringLitteral(); - list = new ArrayList(); - list.add(t); - label_5: - while (true) { - switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { - case 29: - break; - default: - jjLa1[6] = jjGen; - break label_5; - } - jj_consume_token(29); - t = stringLitteral(); - list.add(t); - } - jj_consume_token(30); - left = ComparisonExpression.createInFilter(left, list); + case BETWEEN: + jj_consume_token(BETWEEN); + low = unaryExpr(); + jj_consume_token(AND); + high = unaryExpr(); + left = ComparisonExpression.createBetween(left, low, high); break; default: jjLa1[9] = jjGen; if (jj_2_3(2)) { jj_consume_token(NOT); - jj_consume_token(IN); - jj_consume_token(28); - t = stringLitteral(); - list = new ArrayList(); - list.add(t); - label_6: - while (true) { - switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { - case 29: - break; - default: - jjLa1[7] = jjGen; - break label_6; - } - jj_consume_token(29); - t = stringLitteral(); - list.add(t); - } - jj_consume_token(30); - left = ComparisonExpression.createNotInFilter(left, list); + jj_consume_token(BETWEEN); + low = unaryExpr(); + jj_consume_token(AND); + high = unaryExpr(); + left = ComparisonExpression.createNotBetween(left, low, high); } else { - jj_consume_token(-1); - throw new ParseException(); + switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { + case IN: + jj_consume_token(IN); + jj_consume_token(29); + t = stringLitteral(); + list = new ArrayList(); + list.add(t); + label_5: + while (true) { + switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { + case 30: + break; + default: + jjLa1[6] = jjGen; + break label_5; + } + jj_consume_token(30); + t = stringLitteral(); + list.add(t); + } + jj_consume_token(31); + left = ComparisonExpression.createInFilter(left, list); + break; + default: + jjLa1[10] = jjGen; + if (jj_2_4(2)) { + jj_consume_token(NOT); + jj_consume_token(IN); + jj_consume_token(29); + t = stringLitteral(); + list = new ArrayList(); + list.add(t); + label_6: + while (true) { + switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { + case 30: + break; + default: + jjLa1[7] = jjGen; + break label_6; + } + jj_consume_token(30); + t = stringLitteral(); + list.add(t); + } + jj_consume_token(31); + left = ComparisonExpression.createNotInFilter(left, list); + } else { + jj_consume_token(-1); + throw new ParseException(); + } + } } } } } } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -350,13 +362,13 @@ final public Expression comparisonExpression() throws ParseException { final public Expression unaryExpr() throws ParseException { String s = null; Expression left = null; - if (jj_2_4(2147483647)) { - jj_consume_token(31); + if (jj_2_5(2147483647)) { + jj_consume_token(32); left = unaryExpr(); } else { switch ((jjNtk == -1) ? jj_ntk() : jjNtk) { - case 32: - jj_consume_token(32); + case 33: + jj_consume_token(33); left = unaryExpr(); left = UnaryExpression.createNegate(left); break; @@ -372,18 +384,17 @@ final public Expression unaryExpr() throws ParseException { case FLOATING_POINT_LITERAL: case STRING_LITERAL: case ID: - case 28: + case 29: left = primaryExpr(); break; default: - jjLa1[10] = jjGen; + jjLa1[11] = jjGen; jj_consume_token(-1); throw new ParseException(); } } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -402,19 +413,18 @@ final public Expression primaryExpr() throws ParseException { case ID: left = variable(); break; - case 28: - jj_consume_token(28); + case 29: + jj_consume_token(29); left = orExpression(); - jj_consume_token(30); + jj_consume_token(31); break; default: - jjLa1[11] = jjGen; + jjLa1[12] = jjGen; jj_consume_token(-1); throw new ParseException(); } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -449,13 +459,12 @@ final public ConstantExpression literal() throws ParseException { left = BooleanConstantExpression.NULL; break; default: - jjLa1[12] = jjGen; + jjLa1[13] = jjGen; jj_consume_token(-1); throw new ParseException(); } { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -474,8 +483,7 @@ final public String stringLitteral() throws ParseException { rc.append(c); } { - if (true) - return rc.toString(); + if (true) return rc.toString(); } throw new Error("Missing return statement in function"); } @@ -486,8 +494,7 @@ final public PropertyExpression variable() throws ParseException { t = jj_consume_token(ID); left = new PropertyExpression(t.image); { - if (true) - return left; + if (true) return left; } throw new Error("Missing return statement in function"); } @@ -540,94 +547,26 @@ private boolean jj_2_4(int xla) { } } - private boolean jj_3R_7() { - Token xsp; - xsp = jjScanpos; - if (jj_3R_8()) { - jjScanpos = xsp; - if (jj_3R_9()) { - jjScanpos = xsp; - if (jj_3R_10()) { - jjScanpos = xsp; - if (jj_3R_11()) - return true; - } - } - } - return false; - } - - private boolean jj_3R_43() { - if (jj_scan_token(29)) - return true; - if (jj_3R_27()) - return true; - return false; - } - - private boolean jj_3R_24() { - if (jj_scan_token(NULL)) - return true; - return false; - } - - private boolean jj_3R_35() { - if (jj_scan_token(IS)) - return true; - if (jj_scan_token(NOT)) - return true; - if (jj_scan_token(NULL)) - return true; - return false; - } - - private boolean jj_3_1() { - if (jj_scan_token(IS)) - return true; - if (jj_scan_token(NULL)) + private boolean jj_2_5(int xla) { + jjLa = xla; + jjLastpos = jjScanpos = token; + try { + return !jj_3_5(); + } catch (LookaheadSuccess ls) { return true; - return false; + } finally { + jj_save(4, xla); + } } - private boolean jj_3R_23() { - if (jj_scan_token(FALSE)) - return true; + private boolean jj_3R_21() { + if (jj_scan_token(FLOATING_POINT_LITERAL)) return true; return false; } private boolean jj_3R_34() { - if (jj_scan_token(23)) - return true; - if (jj_3R_30()) - return true; - return false; - } - - private boolean jj_3R_22() { - if (jj_scan_token(TRUE)) - return true; - return false; - } - - private boolean jj_3_3() { - if (jj_scan_token(NOT)) - return true; - if (jj_scan_token(IN)) - return true; - if (jj_scan_token(28)) - return true; - if (jj_3R_27()) - return true; - Token xsp; - while (true) { - xsp = jjScanpos; - if (jj_3R_43()) { - jjScanpos = xsp; - break; - } - } - if (jj_scan_token(30)) - return true; + if (jj_scan_token(24)) return true; + if (jj_3R_30()) return true; return false; } @@ -640,8 +579,7 @@ private boolean jj_3R_31() { jjScanpos = xsp; if (jj_3_1()) { jjScanpos = xsp; - if (jj_3R_35()) - return true; + if (jj_3R_35()) return true; } } } @@ -649,78 +587,47 @@ private boolean jj_3R_31() { } private boolean jj_3R_33() { - if (jj_scan_token(22)) - return true; - if (jj_3R_30()) - return true; - return false; - } - - private boolean jj_3R_42() { - if (jj_scan_token(29)) - return true; - if (jj_3R_27()) - return true; - return false; - } - - private boolean jj_3R_21() { - if (jj_scan_token(FLOATING_POINT_LITERAL)) - return true; + if (jj_scan_token(23)) return true; + if (jj_3R_30()) return true; return false; } private boolean jj_3R_20() { - if (jj_scan_token(DECIMAL_LITERAL)) - return true; + if (jj_scan_token(DECIMAL_LITERAL)) return true; return false; } - private boolean jj_3R_28() { - if (jj_3R_30()) - return true; + private boolean jj_3R_42() { + if (jj_scan_token(IN)) return true; + if (jj_scan_token(29)) return true; + if (jj_3R_27()) return true; Token xsp; while (true) { xsp = jjScanpos; - if (jj_3R_31()) { + if (jj_3R_43()) { jjScanpos = xsp; break; } } + if (jj_scan_token(31)) return true; return false; } - private boolean jj_3R_41() { - if (jj_scan_token(IN)) - return true; - if (jj_scan_token(28)) - return true; - if (jj_3R_27()) - return true; + private boolean jj_3R_19() { + if (jj_3R_27()) return true; + return false; + } + + private boolean jj_3R_28() { + if (jj_3R_30()) return true; Token xsp; while (true) { xsp = jjScanpos; - if (jj_3R_42()) { + if (jj_3R_31()) { jjScanpos = xsp; break; } } - if (jj_scan_token(30)) - return true; - return false; - } - - private boolean jj_3R_19() { - if (jj_3R_27()) - return true; - return false; - } - - private boolean jj_3R_29() { - if (jj_scan_token(AND)) - return true; - if (jj_3R_28()) - return true; return false; } @@ -737,8 +644,7 @@ private boolean jj_3R_16() { jjScanpos = xsp; if (jj_3R_23()) { jjScanpos = xsp; - if (jj_3R_24()) - return true; + if (jj_3R_24()) return true; } } } @@ -747,35 +653,61 @@ private boolean jj_3R_16() { return false; } + private boolean jj_3_3() { + if (jj_scan_token(NOT)) return true; + if (jj_scan_token(BETWEEN)) return true; + if (jj_3R_7()) return true; + if (jj_scan_token(AND)) return true; + if (jj_3R_7()) return true; + return false; + } + + private boolean jj_3R_41() { + if (jj_scan_token(BETWEEN)) return true; + if (jj_3R_7()) return true; + if (jj_scan_token(AND)) return true; + if (jj_3R_7()) return true; + return false; + } + + private boolean jj_3R_29() { + if (jj_scan_token(AND)) return true; + if (jj_3R_28()) return true; + return false; + } + private boolean jj_3_2() { - if (jj_scan_token(NOT)) - return true; - if (jj_scan_token(BETWEEN)) - return true; - if (jj_3R_7()) - return true; - if (jj_scan_token(AND)) - return true; - if (jj_3R_7()) - return true; + if (jj_scan_token(NOT)) return true; + if (jj_scan_token(CONTAINS)) return true; + if (jj_3R_27()) return true; + return false; + } + + private boolean jj_3R_15() { + if (jj_scan_token(29)) return true; + if (jj_3R_18()) return true; + if (jj_scan_token(31)) return true; + return false; + } + + private boolean jj_3R_14() { + if (jj_3R_17()) return true; + return false; + } + + private boolean jj_3R_13() { + if (jj_3R_16()) return true; return false; } private boolean jj_3R_40() { - if (jj_scan_token(BETWEEN)) - return true; - if (jj_3R_7()) - return true; - if (jj_scan_token(AND)) - return true; - if (jj_3R_7()) - return true; + if (jj_scan_token(CONTAINS)) return true; + if (jj_3R_27()) return true; return false; } private boolean jj_3R_25() { - if (jj_3R_28()) - return true; + if (jj_3R_28()) return true; Token xsp; while (true) { xsp = jjScanpos; @@ -787,77 +719,62 @@ private boolean jj_3R_25() { return false; } - private boolean jj_3R_39() { - if (jj_scan_token(27)) - return true; - if (jj_3R_7()) - return true; + private boolean jj_3R_17() { + if (jj_scan_token(ID)) return true; return false; } - private boolean jj_3R_15() { - if (jj_scan_token(28)) - return true; - if (jj_3R_18()) - return true; - if (jj_scan_token(30)) - return true; + private boolean jj_3R_12() { + Token xsp; + xsp = jjScanpos; + if (jj_3R_13()) { + jjScanpos = xsp; + if (jj_3R_14()) { + jjScanpos = xsp; + if (jj_3R_15()) return true; + } + } return false; } - private boolean jj_3R_14() { - if (jj_3R_17()) - return true; + private boolean jj_3R_39() { + if (jj_scan_token(28)) return true; + if (jj_3R_7()) return true; return false; } private boolean jj_3R_38() { - if (jj_scan_token(26)) - return true; - if (jj_3R_7()) - return true; + if (jj_scan_token(27)) return true; + if (jj_3R_7()) return true; return false; } - private boolean jj_3R_13() { - if (jj_3R_16()) - return true; + private boolean jj_3R_11() { + if (jj_3R_12()) return true; return false; } private boolean jj_3R_26() { - if (jj_scan_token(OR)) - return true; - if (jj_3R_25()) - return true; + if (jj_scan_token(OR)) return true; + if (jj_3R_25()) return true; return false; } - private boolean jj_3R_17() { - if (jj_scan_token(ID)) - return true; + private boolean jj_3R_37() { + if (jj_scan_token(26)) return true; + if (jj_3R_7()) return true; return false; } - private boolean jj_3R_37() { - if (jj_scan_token(25)) - return true; - if (jj_3R_7()) - return true; + private boolean jj_3_5() { + if (jj_scan_token(32)) return true; + if (jj_3R_7()) return true; return false; } - private boolean jj_3R_12() { - Token xsp; - xsp = jjScanpos; - if (jj_3R_13()) { - jjScanpos = xsp; - if (jj_3R_14()) { - jjScanpos = xsp; - if (jj_3R_15()) - return true; - } - } + private boolean jj_3R_10() { + if (jj_scan_token(NOT)) return true; + if (jj_3R_7()) return true; return false; } @@ -878,8 +795,13 @@ private boolean jj_3R_32() { jjScanpos = xsp; if (jj_3R_41()) { jjScanpos = xsp; - if (jj_3_3()) - return true; + if (jj_3_3()) { + jjScanpos = xsp; + if (jj_3R_42()) { + jjScanpos = xsp; + if (jj_3_4()) return true; + } + } } } } @@ -891,22 +813,24 @@ private boolean jj_3R_32() { } private boolean jj_3R_36() { - if (jj_scan_token(24)) - return true; - if (jj_3R_7()) - return true; + if (jj_scan_token(25)) return true; + if (jj_3R_7()) return true; return false; } - private boolean jj_3R_11() { - if (jj_3R_12()) - return true; + private boolean jj_3R_9() { + if (jj_scan_token(33)) return true; + if (jj_3R_7()) return true; + return false; + } + + private boolean jj_3R_27() { + if (jj_scan_token(STRING_LITERAL)) return true; return false; } private boolean jj_3R_18() { - if (jj_3R_25()) - return true; + if (jj_3R_25()) return true; Token xsp; while (true) { xsp = jjScanpos; @@ -918,55 +842,95 @@ private boolean jj_3R_18() { return false; } - private boolean jj_3_4() { - if (jj_scan_token(31)) - return true; - if (jj_3R_7()) - return true; + private boolean jj_3R_8() { + if (jj_scan_token(32)) return true; + if (jj_3R_7()) return true; return false; } - private boolean jj_3R_10() { - if (jj_scan_token(NOT)) - return true; - if (jj_3R_7()) - return true; + private boolean jj_3R_7() { + Token xsp; + xsp = jjScanpos; + if (jj_3R_8()) { + jjScanpos = xsp; + if (jj_3R_9()) { + jjScanpos = xsp; + if (jj_3R_10()) { + jjScanpos = xsp; + if (jj_3R_11()) return true; + } + } + } return false; } - private boolean jj_3R_9() { - if (jj_scan_token(32)) - return true; - if (jj_3R_7()) - return true; + private boolean jj_3R_44() { + if (jj_scan_token(30)) return true; + if (jj_3R_27()) return true; return false; } - private boolean jj_3R_27() { - if (jj_scan_token(STRING_LITERAL)) - return true; + private boolean jj_3R_30() { + if (jj_3R_7()) return true; + Token xsp; + while (true) { + xsp = jjScanpos; + if (jj_3R_32()) { + jjScanpos = xsp; + break; + } + } return false; } - private boolean jj_3R_30() { - if (jj_3R_7()) - return true; + private boolean jj_3R_24() { + if (jj_scan_token(NULL)) return true; + return false; + } + + private boolean jj_3R_23() { + if (jj_scan_token(FALSE)) return true; + return false; + } + + private boolean jj_3R_35() { + if (jj_scan_token(IS)) return true; + if (jj_scan_token(NOT)) return true; + if (jj_scan_token(NULL)) return true; + return false; + } + + private boolean jj_3R_22() { + if (jj_scan_token(TRUE)) return true; + return false; + } + + private boolean jj_3_4() { + if (jj_scan_token(NOT)) return true; + if (jj_scan_token(IN)) return true; + if (jj_scan_token(29)) return true; + if (jj_3R_27()) return true; Token xsp; while (true) { xsp = jjScanpos; - if (jj_3R_32()) { + if (jj_3R_44()) { jjScanpos = xsp; break; } } + if (jj_scan_token(31)) return true; return false; } - private boolean jj_3R_8() { - if (jj_scan_token(31)) - return true; - if (jj_3R_7()) - return true; + private boolean jj_3_1() { + if (jj_scan_token(IS)) return true; + if (jj_scan_token(NULL)) return true; + return false; + } + + private boolean jj_3R_43() { + if (jj_scan_token(30)) return true; + if (jj_3R_27()) return true; return false; } @@ -987,7 +951,7 @@ private boolean jj_3R_8() { private Token jjScanpos, jjLastpos; private int jjLa; private int jjGen; - final private int[] jjLa1 = new int[13]; + final private int[] jjLa1 = new int[14]; static private int[] jjLa10; static private int[] jjLa11; @@ -997,16 +961,14 @@ private boolean jj_3R_8() { } private static void jj_la1_init_0() { - jjLa10 = new int[] { - 0x400, 0x200, 0xc10000, 0xc00000, 0x10000, 0xf001900, 0x20000000, 0x20000000, 0xf000800, - 0x1000, 0x1036e100, 0x1036e000, 0x16e000}; + jjLa10 = new int[]{0x400, 0x200, 0x1810000, 0x1800000, 0x10000, 0x1e021900, 0x40000000, 0x40000000, 0x1e020000, 0x800, 0x1000, 0x206ce100, 0x206ce000, 0x2ce000,}; } private static void jj_la1_init_1() { - jjLa11 = new int[] {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0}; + jjLa11 = new int[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0,}; } - final private JJCalls[] jj2Rtns = new JJCalls[4]; + final private JJCalls[] jj2Rtns = new JJCalls[5]; private boolean jjRescan = false; private int jjGc = 0; @@ -1030,10 +992,8 @@ public SelectorParser(java.io.InputStream stream, String encoding) { token = new Token(); jjNtk = -1; jjGen = 0; - for (int i = 0; i < 13; i++) - jjLa1[i] = -1; - for (int i = 0; i < jj2Rtns.length; i++) - jj2Rtns[i] = new JJCalls(); + for (int i = 0; i < 14; i++) jjLa1[i] = -1; + for (int i = 0; i < jj2Rtns.length; i++) jj2Rtns[i] = new JJCalls(); } /** @@ -1056,10 +1016,8 @@ public void ReInit(java.io.InputStream stream, String encoding) { token = new Token(); jjNtk = -1; jjGen = 0; - for (int i = 0; i < 13; i++) - jjLa1[i] = -1; - for (int i = 0; i < jj2Rtns.length; i++) - jj2Rtns[i] = new JJCalls(); + for (int i = 0; i < 14; i++) jjLa1[i] = -1; + for (int i = 0; i < jj2Rtns.length; i++) jj2Rtns[i] = new JJCalls(); } /** @@ -1071,10 +1029,8 @@ public SelectorParser(java.io.Reader stream) { token = new Token(); jjNtk = -1; jjGen = 0; - for (int i = 0; i < 13; i++) - jjLa1[i] = -1; - for (int i = 0; i < jj2Rtns.length; i++) - jj2Rtns[i] = new JJCalls(); + for (int i = 0; i < 14; i++) jjLa1[i] = -1; + for (int i = 0; i < jj2Rtns.length; i++) jj2Rtns[i] = new JJCalls(); } /** @@ -1086,10 +1042,8 @@ public void ReInit(java.io.Reader stream) { token = new Token(); jjNtk = -1; jjGen = 0; - for (int i = 0; i < 13; i++) - jjLa1[i] = -1; - for (int i = 0; i < jj2Rtns.length; i++) - jj2Rtns[i] = new JJCalls(); + for (int i = 0; i < 14; i++) jjLa1[i] = -1; + for (int i = 0; i < jj2Rtns.length; i++) jj2Rtns[i] = new JJCalls(); } /** @@ -1100,10 +1054,8 @@ public SelectorParser(SelectorParserTokenManager tm) { token = new Token(); jjNtk = -1; jjGen = 0; - for (int i = 0; i < 13; i++) - jjLa1[i] = -1; - for (int i = 0; i < jj2Rtns.length; i++) - jj2Rtns[i] = new JJCalls(); + for (int i = 0; i < 14; i++) jjLa1[i] = -1; + for (int i = 0; i < jj2Rtns.length; i++) jj2Rtns[i] = new JJCalls(); } /** @@ -1114,18 +1066,14 @@ public void ReInit(SelectorParserTokenManager tm) { token = new Token(); jjNtk = -1; jjGen = 0; - for (int i = 0; i < 13; i++) - jjLa1[i] = -1; - for (int i = 0; i < jj2Rtns.length; i++) - jj2Rtns[i] = new JJCalls(); + for (int i = 0; i < 14; i++) jjLa1[i] = -1; + for (int i = 0; i < jj2Rtns.length; i++) jj2Rtns[i] = new JJCalls(); } private Token jj_consume_token(int kind) throws ParseException { Token oldToken; - if ((oldToken = token).next != null) - token = token.next; - else - token = token.next = tokenSource.getNextToken(); + if ((oldToken = token).next != null) token = token.next; + else token = token.next = tokenSource.getNextToken(); jjNtk = -1; if (token.kind == kind) { jjGen++; @@ -1134,8 +1082,7 @@ private Token jj_consume_token(int kind) throws ParseException { for (int i = 0; i < jj2Rtns.length; i++) { JJCalls c = jj2Rtns[i]; while (c != null) { - if (c.gen < jjGen) - c.first = null; + if (c.gen < jjGen) c.first = null; c = c.next; } } @@ -1170,24 +1117,20 @@ private boolean jj_scan_token(int kind) { i++; tok = tok.next; } - if (tok != null) - jj_add_error_token(kind, i); + if (tok != null) jj_add_error_token(kind, i); } - if (jjScanpos.kind != kind) - return true; - if (jjLa == 0 && jjScanpos == jjLastpos) - throw jjLs; + if (jjScanpos.kind != kind) return true; + if (jjLa == 0 && jjScanpos == jjLastpos) throw jjLs; return false; } + /** * Get the next Token. */ final public Token getNextToken() { - if (token.next != null) - token = token.next; - else - token = token.next = tokenSource.getNextToken(); + if (token.next != null) token = token.next; + else token = token.next = tokenSource.getNextToken(); jjNtk = -1; jjGen++; return token; @@ -1199,10 +1142,8 @@ final public Token getNextToken() { final public Token getToken(int index) { Token t = token; for (int i = 0; i < index; i++) { - if (t.next != null) - t = t.next; - else - t = t.next = tokenSource.getNextToken(); + if (t.next != null) t = t.next; + else t = t.next = tokenSource.getNextToken(); } return t; } @@ -1221,8 +1162,7 @@ private int jj_ntk() { private int jjEndpos; private void jj_add_error_token(int kind, int pos) { - if (pos >= 100) - return; + if (pos >= 100) return; if (pos == jjEndpos + 1) { jjLasttokens[jjEndpos++] = kind; } else if (jjEndpos != 0) { @@ -1243,8 +1183,7 @@ private void jj_add_error_token(int kind, int pos) { break jj_entries_loop; } } - if (pos != 0) - jjLasttokens[(jjEndpos = pos) - 1] = kind; + if (pos != 0) jjLasttokens[(jjEndpos = pos) - 1] = kind; } } @@ -1253,12 +1192,12 @@ private void jj_add_error_token(int kind, int pos) { */ public ParseException generateParseException() { jjExpentries.clear(); - boolean[] la1tokens = new boolean[33]; + boolean[] la1tokens = new boolean[34]; if (jjKind >= 0) { la1tokens[jjKind] = true; jjKind = -1; } - for (int i = 0; i < 13; i++) { + for (int i = 0; i < 14; i++) { if (jjLa1[i] == jjGen) { for (int j = 0; j < 32; j++) { if ((jjLa10[i] & (1 << j)) != 0) { @@ -1270,7 +1209,7 @@ public ParseException generateParseException() { } } } - for (int i = 0; i < 33; i++) { + for (int i = 0; i < 34; i++) { if (la1tokens[i]) { jjExpentry = new int[1]; jjExpentry[0] = i; @@ -1301,7 +1240,7 @@ final public void disable_tracing() { private void jj_rescan_token() { jjRescan = true; - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 5; i++) { try { JJCalls p = jj2Rtns[i]; do { @@ -1321,11 +1260,13 @@ private void jj_rescan_token() { case 3: jj_3_4(); break; + case 4: + jj_3_5(); + break; } } p = p.next; - } - while (p != null); + } while (p != null); } catch (LookaheadSuccess ls) { } } diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.jj b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.jj index adb485143ce..09e03d9bbc1 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.jj +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParser.jj @@ -53,7 +53,6 @@ import org.apache.rocketmq.filter.expression.LogicExpression; import org.apache.rocketmq.filter.expression.MQFilterException; import org.apache.rocketmq.filter.expression.PropertyExpression; import org.apache.rocketmq.filter.expression.UnaryExpression; -import org.apache.rocketmq.filter.util.LRUCache; import java.io.StringReader; import java.util.ArrayList; @@ -170,6 +169,7 @@ TOKEN [IGNORE_CASE] : | < FALSE : "FALSE" > | < NULL : "NULL" > | < IS : "IS" > + | < CONTAINS : "CONTAINS"> } /* Literals */ @@ -322,6 +322,17 @@ Expression comparisonExpression() : { left = ComparisonExpression.createLessThanEqual(left, right); } + | + t = stringLitteral() + { + left = ComparisonExpression.createContains(left, t); + } + | + LOOKAHEAD(2) + t = stringLitteral() + { + left = ComparisonExpression.createNotContains(left, t); + } | low = unaryExpr() high = unaryExpr() { diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java index 915658ca60b..8f849cb51ff 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserConstants.java @@ -75,23 +75,27 @@ public interface SelectorParserConstants { /** * RegularExpression Id. */ - int DECIMAL_LITERAL = 17; + int CONTAINS = 17; /** * RegularExpression Id. */ - int FLOATING_POINT_LITERAL = 18; + int DECIMAL_LITERAL = 18; /** * RegularExpression Id. */ - int EXPONENT = 19; + int FLOATING_POINT_LITERAL = 19; /** * RegularExpression Id. */ - int STRING_LITERAL = 20; + int EXPONENT = 20; /** * RegularExpression Id. */ - int ID = 21; + int STRING_LITERAL = 21; + /** + * RegularExpression Id. + */ + int ID = 22; /** * Lexical state. @@ -119,6 +123,7 @@ public interface SelectorParserConstants { "\"FALSE\"", "\"NULL\"", "\"IS\"", + "\"CONTAINS\"", "", "", "", diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java index b5bac982405..9d42eea7118 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SelectorParserTokenManager.java @@ -59,33 +59,35 @@ private int jjMoveStringLiteralDfa0_0() { jjmatchedKind = 1; return jjMoveNfa_0(5, 0); case 40: - jjmatchedKind = 28; + jjmatchedKind = 29; return jjMoveNfa_0(5, 0); case 41: - jjmatchedKind = 30; + jjmatchedKind = 31; return jjMoveNfa_0(5, 0); case 43: - jjmatchedKind = 31; + jjmatchedKind = 32; return jjMoveNfa_0(5, 0); case 44: - jjmatchedKind = 29; + jjmatchedKind = 30; return jjMoveNfa_0(5, 0); case 45: - jjmatchedKind = 32; + jjmatchedKind = 33; return jjMoveNfa_0(5, 0); case 60: - jjmatchedKind = 26; - return jjMoveStringLiteralDfa1_0(0x8800000L); + jjmatchedKind = 27; + return jjMoveStringLiteralDfa1_0(0x11000000L); case 61: - jjmatchedKind = 22; + jjmatchedKind = 23; return jjMoveNfa_0(5, 0); case 62: - jjmatchedKind = 24; - return jjMoveStringLiteralDfa1_0(0x2000000L); + jjmatchedKind = 25; + return jjMoveStringLiteralDfa1_0(0x4000000L); case 65: return jjMoveStringLiteralDfa1_0(0x200L); case 66: return jjMoveStringLiteralDfa1_0(0x800L); + case 67: + return jjMoveStringLiteralDfa1_0(0x20000L); case 70: return jjMoveStringLiteralDfa1_0(0x4000L); case 73: @@ -100,6 +102,8 @@ private int jjMoveStringLiteralDfa0_0() { return jjMoveStringLiteralDfa1_0(0x200L); case 98: return jjMoveStringLiteralDfa1_0(0x800L); + case 99: + return jjMoveStringLiteralDfa1_0(0x20000L); case 102: return jjMoveStringLiteralDfa1_0(0x4000L); case 105: @@ -123,17 +127,17 @@ private int jjMoveStringLiteralDfa1_0(long active0) { } switch (curChar) { case 61: - if ((active0 & 0x2000000L) != 0L) { - jjmatchedKind = 25; + if ((active0 & 0x4000000L) != 0L) { + jjmatchedKind = 26; jjmatchedPos = 1; - } else if ((active0 & 0x8000000L) != 0L) { - jjmatchedKind = 27; + } else if ((active0 & 0x10000000L) != 0L) { + jjmatchedKind = 28; jjmatchedPos = 1; } break; case 62: - if ((active0 & 0x800000L) != 0L) { - jjmatchedKind = 23; + if ((active0 & 0x1000000L) != 0L) { + jjmatchedKind = 24; jjmatchedPos = 1; } break; @@ -148,7 +152,7 @@ private int jjMoveStringLiteralDfa1_0(long active0) { } return jjMoveStringLiteralDfa2_0(active0, 0x200L); case 79: - return jjMoveStringLiteralDfa2_0(active0, 0x100L); + return jjMoveStringLiteralDfa2_0(active0, 0x20100L); case 82: if ((active0 & 0x400L) != 0L) { jjmatchedKind = 10; @@ -174,7 +178,7 @@ private int jjMoveStringLiteralDfa1_0(long active0) { } return jjMoveStringLiteralDfa2_0(active0, 0x200L); case 111: - return jjMoveStringLiteralDfa2_0(active0, 0x100L); + return jjMoveStringLiteralDfa2_0(active0, 0x20100L); case 114: if ((active0 & 0x400L) != 0L) { jjmatchedKind = 10; @@ -212,6 +216,8 @@ private int jjMoveStringLiteralDfa2_0(long old0, long active0) { break; case 76: return jjMoveStringLiteralDfa3_0(active0, 0xc000L); + case 78: + return jjMoveStringLiteralDfa3_0(active0, 0x20000L); case 84: if ((active0 & 0x100L) != 0L) { jjmatchedKind = 8; @@ -228,6 +234,8 @@ private int jjMoveStringLiteralDfa2_0(long old0, long active0) { break; case 108: return jjMoveStringLiteralDfa3_0(active0, 0xc000L); + case 110: + return jjMoveStringLiteralDfa3_0(active0, 0x20000L); case 116: if ((active0 & 0x100L) != 0L) { jjmatchedKind = 8; @@ -265,6 +273,8 @@ private int jjMoveStringLiteralDfa3_0(long old0, long active0) { break; case 83: return jjMoveStringLiteralDfa4_0(active0, 0x4000L); + case 84: + return jjMoveStringLiteralDfa4_0(active0, 0x20000L); case 87: return jjMoveStringLiteralDfa4_0(active0, 0x800L); case 101: @@ -281,6 +291,8 @@ private int jjMoveStringLiteralDfa3_0(long old0, long active0) { break; case 115: return jjMoveStringLiteralDfa4_0(active0, 0x4000L); + case 116: + return jjMoveStringLiteralDfa4_0(active0, 0x20000L); case 119: return jjMoveStringLiteralDfa4_0(active0, 0x800L); default: @@ -298,12 +310,16 @@ private int jjMoveStringLiteralDfa4_0(long old0, long active0) { return jjMoveNfa_0(5, 3); } switch (curChar) { + case 65: + return jjMoveStringLiteralDfa5_0(active0, 0x20000L); case 69: if ((active0 & 0x4000L) != 0L) { jjmatchedKind = 14; jjmatchedPos = 4; } return jjMoveStringLiteralDfa5_0(active0, 0x800L); + case 97: + return jjMoveStringLiteralDfa5_0(active0, 0x20000L); case 101: if ((active0 & 0x4000L) != 0L) { jjmatchedKind = 14; @@ -327,8 +343,12 @@ private int jjMoveStringLiteralDfa5_0(long old0, long active0) { switch (curChar) { case 69: return jjMoveStringLiteralDfa6_0(active0, 0x800L); + case 73: + return jjMoveStringLiteralDfa6_0(active0, 0x20000L); case 101: return jjMoveStringLiteralDfa6_0(active0, 0x800L); + case 105: + return jjMoveStringLiteralDfa6_0(active0, 0x20000L); default: break; } @@ -349,19 +369,46 @@ private int jjMoveStringLiteralDfa6_0(long old0, long active0) { jjmatchedKind = 11; jjmatchedPos = 6; } - break; + return jjMoveStringLiteralDfa7_0(active0, 0x20000L); case 110: if ((active0 & 0x800L) != 0L) { jjmatchedKind = 11; jjmatchedPos = 6; } - break; + return jjMoveStringLiteralDfa7_0(active0, 0x20000L); default: break; } return jjMoveNfa_0(5, 6); } + private int jjMoveStringLiteralDfa7_0(long old0, long active0) { + if (((active0 &= old0)) == 0L) + return jjMoveNfa_0(5, 6); + try { + curChar = inputStream.readChar(); + } catch (java.io.IOException e) { + return jjMoveNfa_0(5, 6); + } + switch (curChar) { + case 83: + if ((active0 & 0x20000L) != 0L) { + jjmatchedKind = 17; + jjmatchedPos = 7; + } + break; + case 115: + if ((active0 & 0x20000L) != 0L) { + jjmatchedKind = 17; + jjmatchedPos = 7; + } + break; + default: + break; + } + return jjMoveNfa_0(5, 7); + } + static final long[] JJ_BIT_VEC_0 = { 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL }; @@ -396,8 +443,8 @@ private int jjMoveNfa_0(int startState, int curPos) { if ((0x3ff000000000000L & l) != 0L) jjCheckNAddStates(0, 3); else if (curChar == 36) { - if (kind > 21) - kind = 21; + if (kind > 22) + kind = 22; jjCheckNAdd(28); } else if (curChar == 39) jjCheckNAddStates(4, 6); @@ -408,12 +455,12 @@ else if (curChar == 47) else if (curChar == 45) jjstateSet[jjnewStateCnt++] = 0; if ((0x3fe000000000000L & l) != 0L) { - if (kind > 17) - kind = 17; + if (kind > 18) + kind = 18; jjCheckNAddTwoStates(15, 16); } else if (curChar == 48) { - if (kind > 17) - kind = 17; + if (kind > 18) + kind = 18; } break; case 0: @@ -465,21 +512,21 @@ else if (curChar == 45) jjstateSet[jjnewStateCnt++] = 6; break; case 13: - if (curChar == 48 && kind > 17) - kind = 17; + if (curChar == 48 && kind > 18) + kind = 18; break; case 14: if ((0x3fe000000000000L & l) == 0L) break; - if (kind > 17) - kind = 17; + if (kind > 18) + kind = 18; jjCheckNAddTwoStates(15, 16); break; case 15: if ((0x3ff000000000000L & l) == 0L) break; - if (kind > 17) - kind = 17; + if (kind > 18) + kind = 18; jjCheckNAddTwoStates(15, 16); break; case 17: @@ -489,8 +536,8 @@ else if (curChar == 45) case 18: if ((0x3ff000000000000L & l) == 0L) break; - if (kind > 18) - kind = 18; + if (kind > 19) + kind = 19; jjCheckNAddTwoStates(18, 19); break; case 20: @@ -500,8 +547,8 @@ else if (curChar == 45) case 21: if ((0x3ff000000000000L & l) == 0L) break; - if (kind > 18) - kind = 18; + if (kind > 19) + kind = 19; jjCheckNAdd(21); break; case 22: @@ -518,21 +565,21 @@ else if (curChar == 45) jjCheckNAddStates(4, 6); break; case 26: - if (curChar == 39 && kind > 20) - kind = 20; + if (curChar == 39 && kind > 21) + kind = 21; break; case 27: if (curChar != 36) break; - if (kind > 21) - kind = 21; + if (kind > 22) + kind = 22; jjCheckNAdd(28); break; case 28: if ((0x3ff001000000000L & l) == 0L) break; - if (kind > 21) - kind = 21; + if (kind > 22) + kind = 22; jjCheckNAdd(28); break; case 29: @@ -546,15 +593,15 @@ else if (curChar == 45) case 31: if (curChar != 46) break; - if (kind > 18) - kind = 18; + if (kind > 19) + kind = 19; jjCheckNAddTwoStates(32, 33); break; case 32: if ((0x3ff000000000000L & l) == 0L) break; - if (kind > 18) - kind = 18; + if (kind > 19) + kind = 19; jjCheckNAddTwoStates(32, 33); break; case 34: @@ -564,8 +611,8 @@ else if (curChar == 45) case 35: if ((0x3ff000000000000L & l) == 0L) break; - if (kind > 18) - kind = 18; + if (kind > 19) + kind = 19; jjCheckNAdd(35); break; case 36: @@ -579,15 +626,14 @@ else if (curChar == 45) case 39: if ((0x3ff000000000000L & l) == 0L) break; - if (kind > 18) - kind = 18; + if (kind > 19) + kind = 19; jjCheckNAdd(39); break; default: break; } - } - while (i != startsAt); + } while (i != startsAt); } else if (curChar < 128) { long l = 1L << (curChar & 077); do { @@ -596,8 +642,8 @@ else if (curChar == 45) case 28: if ((0x7fffffe87fffffeL & l) == 0L) break; - if (kind > 21) - kind = 21; + if (kind > 22) + kind = 22; jjCheckNAdd(28); break; case 1: @@ -611,8 +657,8 @@ else if (curChar == 45) jjCheckNAddTwoStates(10, 8); break; case 16: - if ((0x100000001000L & l) != 0L && kind > 17) - kind = 17; + if ((0x100000001000L & l) != 0L && kind > 18) + kind = 18; break; case 19: if ((0x2000000020L & l) != 0L) @@ -632,8 +678,7 @@ else if (curChar == 45) default: break; } - } - while (i != startsAt); + } while (i != startsAt); } else { int hiByte = (int) (curChar >> 8); int i1 = hiByte >> 6; @@ -662,8 +707,7 @@ else if (curChar == 45) default: break; } - } - while (i != startsAt); + } while (i != startsAt); } if (kind != 0x7fffffff) { jjmatchedKind = kind; @@ -722,8 +766,8 @@ private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, lo */ public static final String[] JJ_STR_LITERAL_IMAGES = { "", null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null, "\75", "\74\76", "\76", - "\76\75", "\74", "\74\75", "\50", "\54", "\51", "\53", "\55"}; + null, null, null, null, null, null, null, null, null, null, "\75", "\74\76", "\76", + "\76\75", "\74", "\74\75", "\50", "\54", "\51", "\53", "\55",}; /** * Lexer state names. @@ -732,7 +776,7 @@ private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, lo "DEFAULT", }; static final long[] JJ_TO_TOKEN = { - 0x1fff7ff01L, + 0x3ffefff01L, }; static final long[] JJ_TO_SKIP = { 0xfeL, @@ -905,8 +949,7 @@ private void jjCheckNAdd(int state) { private void jjAddStates(int start, int end) { do { jjstateSet[jjnewStateCnt++] = JJ_NEXT_STATES[start]; - } - while (start++ != end); + } while (start++ != end); } private void jjCheckNAddTwoStates(int state1, int state2) { @@ -917,8 +960,7 @@ private void jjCheckNAddTwoStates(int state1, int state2) { private void jjCheckNAddStates(int start, int end) { do { jjCheckNAdd(JJ_NEXT_STATES[start]); - } - while (start++ != end); + } while (start++ != end); } } diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java index 42626f0f23c..b8e375e51cd 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/SimpleCharStream.java @@ -501,4 +501,4 @@ public void adjustBeginLineColumn(int newLine, int newCol) { } } -/* JavaCC - OriginalChecksum=af79bfe4b18b4b4ea9720ffeb7e52fc5 (do not edit this line) */ +/* JavaCC - OriginalChecksum=ea3493f692d4975c1ad70c4a750107d3 (do not edit this line) */ diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java index 8e6a48a0868..edb78800867 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/Token.java @@ -149,4 +149,4 @@ public static Token newToken(int ofKind) { } } -/* JavaCC - OriginalChecksum=6b0af88eb45a551d929d3cdd9582f827 (do not edit this line) */ +/* JavaCC - OriginalChecksum=20094f1ccfbf423c6d9e770d6a7a0188 (do not edit this line) */ diff --git a/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java b/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java index 0aeb27cf4ca..4a8f2c86a30 100644 --- a/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java +++ b/filter/src/main/java/org/apache/rocketmq/filter/parser/TokenMgrError.java @@ -172,4 +172,4 @@ public TokenMgrError(boolean eofSeen, int lexState, int errorLine, int errorColu this(LexicalError(eofSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); } } -/* JavaCC - OriginalChecksum=e960778c8dcd73e167ed5bfddd59f288 (do not edit this line) */ +/* JavaCC - OriginalChecksum=de79709675790dcbad2e0d728aa630d1 (do not edit this line) */ diff --git a/filter/src/test/java/org/apache/rocketmq/filter/ExpressionTest.java b/filter/src/test/java/org/apache/rocketmq/filter/ExpressionTest.java index 8b02a2627de..fa6b04af45a 100644 --- a/filter/src/test/java/org/apache/rocketmq/filter/ExpressionTest.java +++ b/filter/src/test/java/org/apache/rocketmq/filter/ExpressionTest.java @@ -46,6 +46,324 @@ public class ExpressionTest { private static String nullOrExpression = "a is null OR a='hello'"; private static String stringHasString = "TAGS is not null and TAGS='''''tag'''''"; + + @Test + public void testConstains_has() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.TRUE); + } + + @Test + public void test_notConstains_has() throws Exception { + Expression expr = genExp("value not contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_has_not() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", "abb") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_has_not() throws Exception { + Expression expr = genExp("value not contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", "abb") + ); + eval(expr, context, Boolean.TRUE); + } + + @Test + public void testConstains_hasEmpty() throws Exception { + Expression expr = genExp("value contains ''"); + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_hasEmpty() throws Exception { + Expression expr = genExp("value not contains ''"); + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_null_has_1() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", null) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_null_has_1() throws Exception { + Expression expr = genExp("value not contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", null) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_null_has_2() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( +// KeyValue.c("value", null) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_null_has_2() throws Exception { + Expression expr = genExp("value not contains 'x'"); + EvaluationContext context = genContext( +// KeyValue.c("value", null) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_number_has() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", 1.23) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_number_has() throws Exception { + Expression expr = genExp("value not contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", 1.23) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_boolean_has() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", Boolean.TRUE) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_boolean_has() throws Exception { + Expression expr = genExp("value not contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", Boolean.TRUE) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_object_has() throws Exception { + Expression expr = genExp("value contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("value", new Object()) + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_has_not_string_1() throws Exception { + try { + Expression expr = genExp("value contains x"); // will throw parse exception. + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } catch (Throwable e) { + } + } + + @Test + public void test_notConstains_has_not_string_1() throws Exception { + try { + Expression expr = genExp("value not contains x"); // will throw parse exception. + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } catch (Throwable e) { + } + } + + @Test + public void testConstains_has_not_string_2() throws Exception { + try { + Expression expr = genExp("value contains 123"); // will throw parse exception. + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } catch (Throwable e) { + } + } + + @Test + public void test_notConstains_has_not_string_2() throws Exception { + try { + Expression expr = genExp("value not contains 123"); // will throw parse exception. + EvaluationContext context = genContext( + KeyValue.c("value", "axb") + ); + eval(expr, context, Boolean.FALSE); + } catch (Throwable e) { + } + } + + @Test + public void testConstains_string_has_string() throws Exception { + Expression expr = genExp("'axb' contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.TRUE); + } + + @Test + public void test_notConstains_string_has_string() throws Exception { + Expression expr = genExp("'axb' not contains 'x'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_string_has_not_string() throws Exception { + Expression expr = genExp("'axb' contains 'u'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_string_has_not_string() throws Exception { + Expression expr = genExp("'axb' not contains 'u'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.TRUE); + } + + @Test + public void testConstains_string_has_empty() throws Exception { + Expression expr = genExp("'axb' contains ''"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_string_has_empty() throws Exception { + Expression expr = genExp("'axb' not contains ''"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_string_has_space() throws Exception { + Expression expr = genExp("' ' contains ' '"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.TRUE); + } + + @Test + public void test_notConstains_string_has_space() throws Exception { + Expression expr = genExp("' ' not contains ' '"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testConstains_string_has_nothing() throws Exception { + try { + Expression expr = genExp("'axb' contains "); // will throw parse exception. + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.TRUE); + } catch (Throwable e) { + } + } + + @Test + public void test_notConstains_string_has_nothing() throws Exception { + try { + Expression expr = genExp("'axb' not contains "); // will throw parse exception. + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.TRUE); + } catch (Throwable e) { + } + } + + @Test + public void testConstains_string_has_special_1() throws Exception { + Expression expr = genExp("'axb' contains '.'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void test_notConstains_string_has_special_1() throws Exception { + Expression expr = genExp("'axb' not contains '.'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.TRUE); + } + + @Test + public void testConstains_string_has_special_2() throws Exception { + Expression expr = genExp("'s' contains '\\'"); + EvaluationContext context = genContext( + KeyValue.c("whatever", "whatever") + ); + eval(expr, context, Boolean.FALSE); + } + + @Test + public void testContainsAllInOne() throws Exception { + Expression expr = genExp("a not in ('4', '4', '5') and b between 3 and 10 and c not contains 'axbc'"); + EvaluationContext context = genContext( + KeyValue.c("a", "3"), + KeyValue.c("b", 3), + KeyValue.c("c", "axbdc") + ); + eval(expr, context, Boolean.TRUE); + } + @Test public void testEvaluate_stringHasString() throws Exception { Expression expr = genExp(stringHasString); diff --git a/filter/src/test/java/org/apache/rocketmq/filter/ParserTest.java b/filter/src/test/java/org/apache/rocketmq/filter/ParserTest.java index 7dc2ab25468..9e6291ff10b 100644 --- a/filter/src/test/java/org/apache/rocketmq/filter/ParserTest.java +++ b/filter/src/test/java/org/apache/rocketmq/filter/ParserTest.java @@ -37,7 +37,7 @@ public class ParserTest { private static String equalNullExpression = "a is null"; private static String notEqualNullExpression = "a is not null"; private static String nowExpression = "a <= now"; - + private static String containsExpression = "a=3 and b contains 'xxx' and c not contains 'xxx'"; private static String invalidExpression = "a and between 2 and 10"; private static String illegalBetween = " a between 10 and 0"; @@ -45,7 +45,7 @@ public class ParserTest { public void testParse_valid() { for (String expr : Arrays.asList( andExpression, orExpression, inExpression, notInExpression, betweenExpression, - equalNullExpression, notEqualNullExpression, nowExpression + equalNullExpression, notEqualNullExpression, nowExpression, containsExpression )) { try {