From 83c16ad1c61c4e9b32483816df3787e9deb31a1e Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Wed, 13 Jul 2016 10:12:15 +1200 Subject: [PATCH] EQL - parsing IN expressions with named parameters --- .../server/grammer/EqlAdapter.java | 31 ++- .../server/grammer/antlr/EQLParser.java | 253 +++++++++--------- .../server/expression/InExpressionTest.java | 16 +- .../server/grammer/EqlParserTest.java | 22 ++ .../server/querydefn/DefaultOrmQueryTest.java | 8 + src/test/resources/EQL.g4 | 1 - 6 files changed, 186 insertions(+), 145 deletions(-) diff --git a/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java b/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java index ddfc5a20b..3a64d6d53 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java +++ b/src/main/java/com/avaje/ebeaninternal/server/grammer/EqlAdapter.java @@ -103,18 +103,18 @@ class EqlAdapter extends EQLBaseListener { if (op != EqlOperator.BETWEEN) { throw new IllegalStateException("Expecting BETWEEN operator but got "+op); } - helper.addBetween(path, ctx.getChild(2).getText(), ctx.getChild(4).getText()); + helper.addBetween(path, child(ctx,2), child(ctx,4)); } @Override public void enterPropertyBetween_expression(EQLParser.PropertyBetween_expressionContext ctx) { checkChildren(ctx, 5); - String rawValue = ctx.getChild(0).getText(); + String rawValue = child(ctx,0); EqlOperator op = getOperator(ctx); if (op != EqlOperator.BETWEEN) { throw new IllegalStateException("Expecting BETWEEN operator but got "+op); } - helper.addBetweenProperty(rawValue, ctx.getChild(2).getText(), ctx.getChild(4).getText()); + helper.addBetweenProperty(rawValue, child(ctx,2), child(ctx,4)); } @Override @@ -127,14 +127,25 @@ class EqlAdapter extends EQLBaseListener { public void enterIn_value(EQLParser.In_valueContext ctx) { int childCount = ctx.getChildCount(); for (int i = 0; i < childCount; i++) { - ParseTree child = ctx.getChild(i); - String text = child.getText(); - if (!text.equals("(") && !text.equals(")")) { + String text = child(ctx, i); + if (isInValue(text)) { inValues.add(helper.bind(text)); } } } + private String child(ParserRuleContext ctx, int position) { + ParseTree child = ctx.getChild(position); + return child.getText(); + } + + private boolean isInValue(String text) { + if (text.length() == 1 && (text.equals("(") || text.equals(")") || text.equals(","))) { + return false; + } + return true; + } + @Override public void exitIn_expression(EQLParser.In_expressionContext ctx) { helper.addIn(inPropertyName, inValues); @@ -180,15 +191,14 @@ class EqlAdapter extends EQLBaseListener { throw new IllegalStateException("expecting 3 children for comparison? " + ctx); } String path = getLeftHandSidePath(ctx); - String operator = ctx.getChild(1).getText(); + String operator = child(ctx, 1); EqlOperator op = operatorMapping.get(operator); if (op == null) { throw new IllegalStateException("No operator found for " + operator); } // RHS is Path, Literal or Named input parameter - ParseTree rhs = ctx.getChild(2); - helper.addExpression(path, op, rhs.getText()); + helper.addExpression(path, op, child(ctx, 2)); } @@ -236,8 +246,7 @@ class EqlAdapter extends EQLBaseListener { } private EqlOperator getOperator(ParserRuleContext ctx) { - // the operator text which may be a variation - String operator = ctx.getChild(1).getText(); + String operator = child(ctx,1); EqlOperator op = operatorMapping.get(operator); if (op == null) { throw new IllegalStateException("No operator found for " + operator); diff --git a/src/main/java/com/avaje/ebeaninternal/server/grammer/antlr/EQLParser.java b/src/main/java/com/avaje/ebeaninternal/server/grammer/antlr/EQLParser.java index b68dd3905..8e87e7047 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/grammer/antlr/EQLParser.java +++ b/src/main/java/com/avaje/ebeaninternal/server/grammer/antlr/EQLParser.java @@ -891,54 +891,44 @@ public class EQLParser extends Parser { enterRule(_localctx, 26, RULE_in_value); int _la; try { - setState(149); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { - case 1: + setState(146); + switch (_input.LA(1)) { + case INPUT_VARIABLE: enterOuterAlt(_localctx, 1); { setState(134); match(INPUT_VARIABLE); } break; - case 2: + case T__1: enterOuterAlt(_localctx, 2); { setState(135); match(T__1); setState(136); - match(INPUT_VARIABLE); - setState(137); - match(T__2); - } - break; - case 3: - enterOuterAlt(_localctx, 3); - { - setState(138); - match(T__1); - setState(139); value_expression(); - setState(144); + setState(141); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__5) { { { - setState(140); + setState(137); match(T__5); - setState(141); + setState(138); value_expression(); } } - setState(146); + setState(143); _errHandler.sync(this); _la = _input.LA(1); } - setState(147); + setState(144); match(T__2); } break; + default: + throw new NoViableAltException(this); } } catch (RecognitionException re) { @@ -980,15 +970,15 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(151); + setState(148); match(PATH_VARIABLE); - setState(152); + setState(149); match(T__10); - setState(153); + setState(150); value_expression(); - setState(154); + setState(151); match(T__7); - setState(155); + setState(152); value_expression(); } } @@ -1031,15 +1021,15 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(157); + setState(154); value_expression(); - setState(158); + setState(155); match(T__10); - setState(159); + setState(156); match(PATH_VARIABLE); - setState(160); + setState(157); match(T__7); - setState(161); + setState(158); match(PATH_VARIABLE); } } @@ -1074,26 +1064,26 @@ public class EQLParser extends Parser { IsNull_expressionContext _localctx = new IsNull_expressionContext(_ctx, getState()); enterRule(_localctx, 32, RULE_isNull_expression); try { - setState(168); + setState(165); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(163); + setState(160); match(PATH_VARIABLE); - setState(164); + setState(161); match(T__11); - setState(165); + setState(162); match(T__12); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(166); + setState(163); match(PATH_VARIABLE); - setState(167); + setState(164); match(T__13); } break; @@ -1130,37 +1120,37 @@ public class EQLParser extends Parser { IsNotNull_expressionContext _localctx = new IsNotNull_expressionContext(_ctx, getState()); enterRule(_localctx, 34, RULE_isNotNull_expression); try { - setState(178); + setState(175); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,12,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(170); + setState(167); match(PATH_VARIABLE); - setState(171); + setState(168); match(T__11); - setState(172); + setState(169); match(T__8); - setState(173); + setState(170); match(T__12); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(174); + setState(171); match(PATH_VARIABLE); - setState(175); + setState(172); match(T__14); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(176); + setState(173); match(PATH_VARIABLE); - setState(177); + setState(174); match(T__15); } break; @@ -1197,26 +1187,26 @@ public class EQLParser extends Parser { IsEmpty_expressionContext _localctx = new IsEmpty_expressionContext(_ctx, getState()); enterRule(_localctx, 36, RULE_isEmpty_expression); try { - setState(185); + setState(182); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(180); + setState(177); match(PATH_VARIABLE); - setState(181); + setState(178); match(T__11); - setState(182); + setState(179); match(T__16); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(183); + setState(180); match(PATH_VARIABLE); - setState(184); + setState(181); match(T__17); } break; @@ -1253,37 +1243,37 @@ public class EQLParser extends Parser { IsNotEmpty_expressionContext _localctx = new IsNotEmpty_expressionContext(_ctx, getState()); enterRule(_localctx, 38, RULE_isNotEmpty_expression); try { - setState(195); + setState(192); _errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) { case 1: enterOuterAlt(_localctx, 1); { - setState(187); + setState(184); match(PATH_VARIABLE); - setState(188); + setState(185); match(T__11); - setState(189); + setState(186); match(T__8); - setState(190); + setState(187); match(T__16); } break; case 2: enterOuterAlt(_localctx, 2); { - setState(191); + setState(188); match(PATH_VARIABLE); - setState(192); + setState(189); match(T__18); } break; case 3: enterOuterAlt(_localctx, 3); { - setState(193); + setState(190); match(PATH_VARIABLE); - setState(194); + setState(191); match(T__19); } break; @@ -1328,11 +1318,11 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(197); + setState(194); match(PATH_VARIABLE); - setState(198); + setState(195); like_op(); - setState(199); + setState(196); value_expression(); } } @@ -1369,7 +1359,7 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(201); + setState(198); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23) | (1L << T__24) | (1L << T__25) | (1L << T__26) | (1L << T__27))) != 0)) ) { _errHandler.recoverInline(this); @@ -1417,11 +1407,11 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(203); + setState(200); match(PATH_VARIABLE); - setState(204); + setState(201); comparison_operator(); - setState(205); + setState(202); value_expression(); } } @@ -1458,7 +1448,7 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(207); + setState(204); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__28) | (1L << T__29) | (1L << T__30) | (1L << T__31) | (1L << T__32) | (1L << T__33) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43))) != 0)) ) { _errHandler.recoverInline(this); @@ -1501,21 +1491,21 @@ public class EQLParser extends Parser { Value_expressionContext _localctx = new Value_expressionContext(_ctx, getState()); enterRule(_localctx, 48, RULE_value_expression); try { - setState(211); + setState(208); switch (_input.LA(1)) { case BOOLEAN_LITERAL: case NUMBER_LITERAL: case STRING_LITERAL: enterOuterAlt(_localctx, 1); { - setState(209); + setState(206); literal(); } break; case INPUT_VARIABLE: enterOuterAlt(_localctx, 2); { - setState(210); + setState(207); match(INPUT_VARIABLE); } break; @@ -1559,7 +1549,7 @@ public class EQLParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(213); + setState(210); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << BOOLEAN_LITERAL) | (1L << NUMBER_LITERAL) | (1L << STRING_LITERAL))) != 0)) ) { _errHandler.recoverInline(this); @@ -1580,7 +1570,7 @@ public class EQLParser extends Parser { } public static final String _serializedATN = - "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\64\u00da\4\2\t\2"+ + "\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\64\u00d7\4\2\t\2"+ "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ @@ -1589,64 +1579,63 @@ public class EQLParser extends Parser { "S\n\7\f\7\16\7V\13\7\3\b\3\b\3\t\3\t\3\t\7\t]\n\t\f\t\16\t`\13\t\3\n\3"+ "\n\3\n\7\ne\n\n\f\n\16\nh\13\n\3\13\5\13k\n\13\3\13\3\13\3\f\3\f\3\f\3"+ "\f\3\f\5\ft\n\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\5"+ - "\r\u0083\n\r\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\17\3"+ - "\17\7\17\u0091\n\17\f\17\16\17\u0094\13\17\3\17\3\17\5\17\u0098\n\17\3"+ - "\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3"+ - "\22\3\22\3\22\5\22\u00ab\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23"+ - "\5\23\u00b5\n\23\3\24\3\24\3\24\3\24\3\24\5\24\u00bc\n\24\3\25\3\25\3"+ - "\25\3\25\3\25\3\25\3\25\3\25\5\25\u00c6\n\25\3\26\3\26\3\26\3\26\3\27"+ - "\3\27\3\30\3\30\3\30\3\30\3\31\3\31\3\32\3\32\5\32\u00d6\n\32\3\33\3\33"+ - "\3\33\2\2\34\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64"+ - "\2\5\3\2\27\36\3\2\37.\3\2\61\63\u00da\2\67\3\2\2\2\4?\3\2\2\2\6D\3\2"+ - "\2\2\bF\3\2\2\2\nI\3\2\2\2\fO\3\2\2\2\16W\3\2\2\2\20Y\3\2\2\2\22a\3\2"+ - "\2\2\24j\3\2\2\2\26s\3\2\2\2\30\u0082\3\2\2\2\32\u0084\3\2\2\2\34\u0097"+ - "\3\2\2\2\36\u0099\3\2\2\2 \u009f\3\2\2\2\"\u00aa\3\2\2\2$\u00b4\3\2\2"+ - "\2&\u00bb\3\2\2\2(\u00c5\3\2\2\2*\u00c7\3\2\2\2,\u00cb\3\2\2\2.\u00cd"+ - "\3\2\2\2\60\u00d1\3\2\2\2\62\u00d5\3\2\2\2\64\u00d7\3\2\2\2\668\5\4\3"+ - "\2\67\66\3\2\2\2\678\3\2\2\28:\3\2\2\29;\5\6\4\2:9\3\2\2\2:;\3\2\2\2;"+ - "=\3\2\2\2<>\5\b\5\2=<\3\2\2\2=>\3\2\2\2>\3\3\2\2\2?@\7\3\2\2@A\7\4\2\2"+ - "AB\5\f\7\2BC\7\5\2\2C\5\3\2\2\2DE\5\n\6\2E\7\3\2\2\2FG\7\6\2\2GH\5\20"+ - "\t\2H\t\3\2\2\2IJ\7\7\2\2JK\7\60\2\2KL\7\4\2\2LM\5\f\7\2MN\7\5\2\2N\13"+ - "\3\2\2\2OT\5\16\b\2PQ\7\b\2\2QS\5\16\b\2RP\3\2\2\2SV\3\2\2\2TR\3\2\2\2"+ - "TU\3\2\2\2U\r\3\2\2\2VT\3\2\2\2WX\7\60\2\2X\17\3\2\2\2Y^\5\22\n\2Z[\7"+ - "\t\2\2[]\5\22\n\2\\Z\3\2\2\2]`\3\2\2\2^\\\3\2\2\2^_\3\2\2\2_\21\3\2\2"+ - "\2`^\3\2\2\2af\5\24\13\2bc\7\n\2\2ce\5\24\13\2db\3\2\2\2eh\3\2\2\2fd\3"+ - "\2\2\2fg\3\2\2\2g\23\3\2\2\2hf\3\2\2\2ik\7\13\2\2ji\3\2\2\2jk\3\2\2\2"+ - "kl\3\2\2\2lm\5\26\f\2m\25\3\2\2\2nt\5\30\r\2op\7\4\2\2pq\5\20\t\2qr\7"+ - "\5\2\2rt\3\2\2\2sn\3\2\2\2so\3\2\2\2t\27\3\2\2\2u\u0083\5.\30\2v\u0083"+ - "\5*\26\2w\u0083\5\36\20\2x\u0083\5 \21\2y\u0083\5\32\16\2z\u0083\5\"\22"+ - "\2{\u0083\5$\23\2|\u0083\5&\24\2}\u0083\5(\25\2~\177\7\4\2\2\177\u0080"+ - "\5\30\r\2\u0080\u0081\7\5\2\2\u0081\u0083\3\2\2\2\u0082u\3\2\2\2\u0082"+ - "v\3\2\2\2\u0082w\3\2\2\2\u0082x\3\2\2\2\u0082y\3\2\2\2\u0082z\3\2\2\2"+ - "\u0082{\3\2\2\2\u0082|\3\2\2\2\u0082}\3\2\2\2\u0082~\3\2\2\2\u0083\31"+ - "\3\2\2\2\u0084\u0085\7\60\2\2\u0085\u0086\7\f\2\2\u0086\u0087\5\34\17"+ - "\2\u0087\33\3\2\2\2\u0088\u0098\7/\2\2\u0089\u008a\7\4\2\2\u008a\u008b"+ - "\7/\2\2\u008b\u0098\7\5\2\2\u008c\u008d\7\4\2\2\u008d\u0092\5\62\32\2"+ - "\u008e\u008f\7\b\2\2\u008f\u0091\5\62\32\2\u0090\u008e\3\2\2\2\u0091\u0094"+ - "\3\2\2\2\u0092\u0090\3\2\2\2\u0092\u0093\3\2\2\2\u0093\u0095\3\2\2\2\u0094"+ - "\u0092\3\2\2\2\u0095\u0096\7\5\2\2\u0096\u0098\3\2\2\2\u0097\u0088\3\2"+ - "\2\2\u0097\u0089\3\2\2\2\u0097\u008c\3\2\2\2\u0098\35\3\2\2\2\u0099\u009a"+ - "\7\60\2\2\u009a\u009b\7\r\2\2\u009b\u009c\5\62\32\2\u009c\u009d\7\n\2"+ - "\2\u009d\u009e\5\62\32\2\u009e\37\3\2\2\2\u009f\u00a0\5\62\32\2\u00a0"+ - "\u00a1\7\r\2\2\u00a1\u00a2\7\60\2\2\u00a2\u00a3\7\n\2\2\u00a3\u00a4\7"+ - "\60\2\2\u00a4!\3\2\2\2\u00a5\u00a6\7\60\2\2\u00a6\u00a7\7\16\2\2\u00a7"+ - "\u00ab\7\17\2\2\u00a8\u00a9\7\60\2\2\u00a9\u00ab\7\20\2\2\u00aa\u00a5"+ - "\3\2\2\2\u00aa\u00a8\3\2\2\2\u00ab#\3\2\2\2\u00ac\u00ad\7\60\2\2\u00ad"+ - "\u00ae\7\16\2\2\u00ae\u00af\7\13\2\2\u00af\u00b5\7\17\2\2\u00b0\u00b1"+ - "\7\60\2\2\u00b1\u00b5\7\21\2\2\u00b2\u00b3\7\60\2\2\u00b3\u00b5\7\22\2"+ - "\2\u00b4\u00ac\3\2\2\2\u00b4\u00b0\3\2\2\2\u00b4\u00b2\3\2\2\2\u00b5%"+ - "\3\2\2\2\u00b6\u00b7\7\60\2\2\u00b7\u00b8\7\16\2\2\u00b8\u00bc\7\23\2"+ - "\2\u00b9\u00ba\7\60\2\2\u00ba\u00bc\7\24\2\2\u00bb\u00b6\3\2\2\2\u00bb"+ - "\u00b9\3\2\2\2\u00bc\'\3\2\2\2\u00bd\u00be\7\60\2\2\u00be\u00bf\7\16\2"+ - "\2\u00bf\u00c0\7\13\2\2\u00c0\u00c6\7\23\2\2\u00c1\u00c2\7\60\2\2\u00c2"+ - "\u00c6\7\25\2\2\u00c3\u00c4\7\60\2\2\u00c4\u00c6\7\26\2\2\u00c5\u00bd"+ - "\3\2\2\2\u00c5\u00c1\3\2\2\2\u00c5\u00c3\3\2\2\2\u00c6)\3\2\2\2\u00c7"+ - "\u00c8\7\60\2\2\u00c8\u00c9\5,\27\2\u00c9\u00ca\5\62\32\2\u00ca+\3\2\2"+ - "\2\u00cb\u00cc\t\2\2\2\u00cc-\3\2\2\2\u00cd\u00ce\7\60\2\2\u00ce\u00cf"+ - "\5\60\31\2\u00cf\u00d0\5\62\32\2\u00d0/\3\2\2\2\u00d1\u00d2\t\3\2\2\u00d2"+ - "\61\3\2\2\2\u00d3\u00d6\5\64\33\2\u00d4\u00d6\7/\2\2\u00d5\u00d3\3\2\2"+ - "\2\u00d5\u00d4\3\2\2\2\u00d6\63\3\2\2\2\u00d7\u00d8\t\4\2\2\u00d8\65\3"+ - "\2\2\2\22\67:=T^fjs\u0082\u0092\u0097\u00aa\u00b4\u00bb\u00c5\u00d5"; + "\r\u0083\n\r\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\7\17\u008e\n"+ + "\17\f\17\16\17\u0091\13\17\3\17\3\17\5\17\u0095\n\17\3\20\3\20\3\20\3"+ + "\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\5"+ + "\22\u00a8\n\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\5\23\u00b2\n\23"+ + "\3\24\3\24\3\24\3\24\3\24\5\24\u00b9\n\24\3\25\3\25\3\25\3\25\3\25\3\25"+ + "\3\25\3\25\5\25\u00c3\n\25\3\26\3\26\3\26\3\26\3\27\3\27\3\30\3\30\3\30"+ + "\3\30\3\31\3\31\3\32\3\32\5\32\u00d3\n\32\3\33\3\33\3\33\2\2\34\2\4\6"+ + "\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64\2\5\3\2\27\36\3\2"+ + "\37.\3\2\61\63\u00d6\2\67\3\2\2\2\4?\3\2\2\2\6D\3\2\2\2\bF\3\2\2\2\nI"+ + "\3\2\2\2\fO\3\2\2\2\16W\3\2\2\2\20Y\3\2\2\2\22a\3\2\2\2\24j\3\2\2\2\26"+ + "s\3\2\2\2\30\u0082\3\2\2\2\32\u0084\3\2\2\2\34\u0094\3\2\2\2\36\u0096"+ + "\3\2\2\2 \u009c\3\2\2\2\"\u00a7\3\2\2\2$\u00b1\3\2\2\2&\u00b8\3\2\2\2"+ + "(\u00c2\3\2\2\2*\u00c4\3\2\2\2,\u00c8\3\2\2\2.\u00ca\3\2\2\2\60\u00ce"+ + "\3\2\2\2\62\u00d2\3\2\2\2\64\u00d4\3\2\2\2\668\5\4\3\2\67\66\3\2\2\2\67"+ + "8\3\2\2\28:\3\2\2\29;\5\6\4\2:9\3\2\2\2:;\3\2\2\2;=\3\2\2\2<>\5\b\5\2"+ + "=<\3\2\2\2=>\3\2\2\2>\3\3\2\2\2?@\7\3\2\2@A\7\4\2\2AB\5\f\7\2BC\7\5\2"+ + "\2C\5\3\2\2\2DE\5\n\6\2E\7\3\2\2\2FG\7\6\2\2GH\5\20\t\2H\t\3\2\2\2IJ\7"+ + "\7\2\2JK\7\60\2\2KL\7\4\2\2LM\5\f\7\2MN\7\5\2\2N\13\3\2\2\2OT\5\16\b\2"+ + "PQ\7\b\2\2QS\5\16\b\2RP\3\2\2\2SV\3\2\2\2TR\3\2\2\2TU\3\2\2\2U\r\3\2\2"+ + "\2VT\3\2\2\2WX\7\60\2\2X\17\3\2\2\2Y^\5\22\n\2Z[\7\t\2\2[]\5\22\n\2\\"+ + "Z\3\2\2\2]`\3\2\2\2^\\\3\2\2\2^_\3\2\2\2_\21\3\2\2\2`^\3\2\2\2af\5\24"+ + "\13\2bc\7\n\2\2ce\5\24\13\2db\3\2\2\2eh\3\2\2\2fd\3\2\2\2fg\3\2\2\2g\23"+ + "\3\2\2\2hf\3\2\2\2ik\7\13\2\2ji\3\2\2\2jk\3\2\2\2kl\3\2\2\2lm\5\26\f\2"+ + "m\25\3\2\2\2nt\5\30\r\2op\7\4\2\2pq\5\20\t\2qr\7\5\2\2rt\3\2\2\2sn\3\2"+ + "\2\2so\3\2\2\2t\27\3\2\2\2u\u0083\5.\30\2v\u0083\5*\26\2w\u0083\5\36\20"+ + "\2x\u0083\5 \21\2y\u0083\5\32\16\2z\u0083\5\"\22\2{\u0083\5$\23\2|\u0083"+ + "\5&\24\2}\u0083\5(\25\2~\177\7\4\2\2\177\u0080\5\30\r\2\u0080\u0081\7"+ + "\5\2\2\u0081\u0083\3\2\2\2\u0082u\3\2\2\2\u0082v\3\2\2\2\u0082w\3\2\2"+ + "\2\u0082x\3\2\2\2\u0082y\3\2\2\2\u0082z\3\2\2\2\u0082{\3\2\2\2\u0082|"+ + "\3\2\2\2\u0082}\3\2\2\2\u0082~\3\2\2\2\u0083\31\3\2\2\2\u0084\u0085\7"+ + "\60\2\2\u0085\u0086\7\f\2\2\u0086\u0087\5\34\17\2\u0087\33\3\2\2\2\u0088"+ + "\u0095\7/\2\2\u0089\u008a\7\4\2\2\u008a\u008f\5\62\32\2\u008b\u008c\7"+ + "\b\2\2\u008c\u008e\5\62\32\2\u008d\u008b\3\2\2\2\u008e\u0091\3\2\2\2\u008f"+ + "\u008d\3\2\2\2\u008f\u0090\3\2\2\2\u0090\u0092\3\2\2\2\u0091\u008f\3\2"+ + "\2\2\u0092\u0093\7\5\2\2\u0093\u0095\3\2\2\2\u0094\u0088\3\2\2\2\u0094"+ + "\u0089\3\2\2\2\u0095\35\3\2\2\2\u0096\u0097\7\60\2\2\u0097\u0098\7\r\2"+ + "\2\u0098\u0099\5\62\32\2\u0099\u009a\7\n\2\2\u009a\u009b\5\62\32\2\u009b"+ + "\37\3\2\2\2\u009c\u009d\5\62\32\2\u009d\u009e\7\r\2\2\u009e\u009f\7\60"+ + "\2\2\u009f\u00a0\7\n\2\2\u00a0\u00a1\7\60\2\2\u00a1!\3\2\2\2\u00a2\u00a3"+ + "\7\60\2\2\u00a3\u00a4\7\16\2\2\u00a4\u00a8\7\17\2\2\u00a5\u00a6\7\60\2"+ + "\2\u00a6\u00a8\7\20\2\2\u00a7\u00a2\3\2\2\2\u00a7\u00a5\3\2\2\2\u00a8"+ + "#\3\2\2\2\u00a9\u00aa\7\60\2\2\u00aa\u00ab\7\16\2\2\u00ab\u00ac\7\13\2"+ + "\2\u00ac\u00b2\7\17\2\2\u00ad\u00ae\7\60\2\2\u00ae\u00b2\7\21\2\2\u00af"+ + "\u00b0\7\60\2\2\u00b0\u00b2\7\22\2\2\u00b1\u00a9\3\2\2\2\u00b1\u00ad\3"+ + "\2\2\2\u00b1\u00af\3\2\2\2\u00b2%\3\2\2\2\u00b3\u00b4\7\60\2\2\u00b4\u00b5"+ + "\7\16\2\2\u00b5\u00b9\7\23\2\2\u00b6\u00b7\7\60\2\2\u00b7\u00b9\7\24\2"+ + "\2\u00b8\u00b3\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b9\'\3\2\2\2\u00ba\u00bb"+ + "\7\60\2\2\u00bb\u00bc\7\16\2\2\u00bc\u00bd\7\13\2\2\u00bd\u00c3\7\23\2"+ + "\2\u00be\u00bf\7\60\2\2\u00bf\u00c3\7\25\2\2\u00c0\u00c1\7\60\2\2\u00c1"+ + "\u00c3\7\26\2\2\u00c2\u00ba\3\2\2\2\u00c2\u00be\3\2\2\2\u00c2\u00c0\3"+ + "\2\2\2\u00c3)\3\2\2\2\u00c4\u00c5\7\60\2\2\u00c5\u00c6\5,\27\2\u00c6\u00c7"+ + "\5\62\32\2\u00c7+\3\2\2\2\u00c8\u00c9\t\2\2\2\u00c9-\3\2\2\2\u00ca\u00cb"+ + "\7\60\2\2\u00cb\u00cc\5\60\31\2\u00cc\u00cd\5\62\32\2\u00cd/\3\2\2\2\u00ce"+ + "\u00cf\t\3\2\2\u00cf\61\3\2\2\2\u00d0\u00d3\5\64\33\2\u00d1\u00d3\7/\2"+ + "\2\u00d2\u00d0\3\2\2\2\u00d2\u00d1\3\2\2\2\u00d3\63\3\2\2\2\u00d4\u00d5"+ + "\t\4\2\2\u00d5\65\3\2\2\2\22\67:=T^fjs\u0082\u008f\u0094\u00a7\u00b1\u00b8"+ + "\u00c2\u00d2"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/test/java/com/avaje/ebeaninternal/server/expression/InExpressionTest.java b/src/test/java/com/avaje/ebeaninternal/server/expression/InExpressionTest.java index b26b09917..e52824f92 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/expression/InExpressionTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/expression/InExpressionTest.java @@ -23,6 +23,9 @@ public class InExpressionTest { InExpression ex1 = new InExpression("foo", values, false); InExpression ex2 = new InExpression("bar", values, false); + ex1.prepareExpression(null); + ex2.prepareExpression(null); + HashQueryPlanBuilder b1 = new HashQueryPlanBuilder(); ex1.queryPlanHash(b1); @@ -41,6 +44,9 @@ public class InExpressionTest { InExpression ex1 = new InExpression("foo", values1, false); InExpression ex2 = new InExpression("foo", values2, false); + ex1.prepareExpression(null); + ex2.prepareExpression(null); + HashQueryPlanBuilder b1 = new HashQueryPlanBuilder(); ex1.queryPlanHash(b1); @@ -58,6 +64,9 @@ public class InExpressionTest { InExpression ex1 = new InExpression("foo", values, true); InExpression ex2 = new InExpression("foo", values, false); + ex1.prepareExpression(null); + ex2.prepareExpression(null); + HashQueryPlanBuilder b1 = new HashQueryPlanBuilder(); ex1.queryPlanHash(b1); @@ -75,6 +84,9 @@ public class InExpressionTest { InExpression ex1 = new InExpression("foo", values, true); InExpression ex2 = new InExpression("foo", values, true); + ex1.prepareExpression(null); + ex2.prepareExpression(null); + HashQueryPlanBuilder b1 = new HashQueryPlanBuilder(); ex1.queryPlanHash(b1); @@ -94,7 +106,9 @@ public class InExpressionTest { @NotNull private InExpression exp(String propName, boolean not, Object... values) { - return new InExpression(propName, Arrays.asList(values), not); + InExpression ex = new InExpression(propName, Arrays.asList(values), not); + ex.prepareExpression(null); + return ex; } @Test diff --git a/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java b/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java index ab8d084bd..0344dea96 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/grammer/EqlParserTest.java @@ -114,6 +114,28 @@ public class EqlParserTest { assertThat(query.getGeneratedSql()).contains("where t0.name in (?, ? )"); } + @Test + public void where_in_when_namedParams_withWhitespace() throws Exception { + + Query query = parse("where name in (:one, :two)"); + query.setParameter("one", "Foo"); + query.setParameter("two", "Bar"); + query.findList(); + + assertThat(query.getGeneratedSql()).contains("where t0.name in (?, ? )"); + } + + @Test + public void where_in_when_namedParams_withNoWhitespace() throws Exception { + + Query query = parse("where name in (:one,:two)"); + query.setParameter("one", "Foo"); + query.setParameter("two", "Bar"); + query.findList(); + + assertThat(query.getGeneratedSql()).contains("where t0.name in (?, ? )"); + } + @Test public void where_in_when_namedParamAsList() throws Exception { diff --git a/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryTest.java b/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryTest.java index 43c8770e8..ced5d21d7 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQueryTest.java @@ -37,6 +37,7 @@ public class DefaultOrmQueryTest { DefaultOrmQuery q1 = (DefaultOrmQuery)Ebean.find(Order.class).where().in("name", "a","b","c").query(); DefaultOrmQuery q2 = (DefaultOrmQuery)Ebean.find(Order.class).where().in("id", 2,2,3).query(); + prepare(q1, q2); assertThat(q1.createQueryPlanKey()).isNotEqualTo(q2.createQueryPlanKey()); assertThat(q1.queryBindHash()).isNotEqualTo(q2.queryBindHash()); } @@ -47,6 +48,7 @@ public class DefaultOrmQueryTest { DefaultOrmQuery q1 = (DefaultOrmQuery)Ebean.find(Order.class).where().in("id", 1,2,3).query(); DefaultOrmQuery q2 = (DefaultOrmQuery)Ebean.find(Order.class).where().in("id", 2,2,3).query(); + prepare(q1, q2); assertThat(q1.createQueryPlanKey()).isEqualTo(q2.createQueryPlanKey()); assertThat(q1.queryBindHash()).isNotEqualTo(q2.queryBindHash()); } @@ -57,6 +59,7 @@ public class DefaultOrmQueryTest { DefaultOrmQuery q1 = (DefaultOrmQuery)Ebean.find(Order.class).where().in("id", 1,2,3).query(); DefaultOrmQuery q2 = (DefaultOrmQuery)Ebean.find(Order.class).where().in("id", 1,2,3).query(); + prepare(q1, q2); assertThat(q1.createQueryPlanKey()).isEqualTo(q2.createQueryPlanKey()); assertThat(q1.queryBindHash()).isEqualTo(q2.queryBindHash()); } @@ -72,7 +75,12 @@ public class DefaultOrmQueryTest { .setFirstRow(1) .setMaxRows(0); + prepare(query1, query2); assertThat(query1.createQueryPlanKey()).isNotEqualTo(query2.createQueryPlanKey()); } + private void prepare(DefaultOrmQuery q1, DefaultOrmQuery q2) { + q1.prepare(null); + q2.prepare(null); + } } \ No newline at end of file diff --git a/src/test/resources/EQL.g4 b/src/test/resources/EQL.g4 index 4085f17bc..d7a8c68e8 100644 --- a/src/test/resources/EQL.g4 +++ b/src/test/resources/EQL.g4 @@ -65,7 +65,6 @@ in_expression in_value : INPUT_VARIABLE - | '(' INPUT_VARIABLE ')' | '(' value_expression (',' value_expression)* ')' ;