From a27540581814eaa197f68fd66526d97d30f8468c Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 07:57:50 -0700 Subject: [PATCH 01/10] Add where in grammar and UT --- sql/src/main/antlr/OpenDistroSQLParser.g4 | 4 ++++ .../sql/sql/parser/AstBuilder.java | 13 ++++++++++++- .../sql/sql/antlr/SQLSyntaxParserTest.java | 7 ++++++- .../sql/sql/parser/AstBuilderTest.java | 18 ++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/sql/src/main/antlr/OpenDistroSQLParser.g4 b/sql/src/main/antlr/OpenDistroSQLParser.g4 index ac72d0b233..0d37f50823 100644 --- a/sql/src/main/antlr/OpenDistroSQLParser.g4 +++ b/sql/src/main/antlr/OpenDistroSQLParser.g4 @@ -77,8 +77,12 @@ selectElement fromClause : FROM tableName + (whereClause)? ; +whereClause + : WHERE expression + ; // Literals diff --git a/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilder.java b/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilder.java index 2d00909967..b404062261 100644 --- a/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilder.java +++ b/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilder.java @@ -20,10 +20,12 @@ import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.SelectClauseContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.SelectElementContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.SimpleSelectContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.WhereClauseContext; import com.amazon.opendistroforelasticsearch.sql.ast.expression.Alias; import com.amazon.opendistroforelasticsearch.sql.ast.expression.AllFields; import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedExpression; +import com.amazon.opendistroforelasticsearch.sql.ast.tree.Filter; import com.amazon.opendistroforelasticsearch.sql.ast.tree.Project; import com.amazon.opendistroforelasticsearch.sql.ast.tree.Relation; import com.amazon.opendistroforelasticsearch.sql.ast.tree.UnresolvedPlan; @@ -90,7 +92,16 @@ public UnresolvedPlan visitSelectClause(SelectClauseContext ctx) { @Override public UnresolvedPlan visitFromClause(FromClauseContext ctx) { - return new Relation(visitAstExpression(ctx.tableName().qualifiedName())); + UnresolvedPlan result = new Relation(visitAstExpression(ctx.tableName().qualifiedName())); + if (ctx.whereClause() != null) { + result = visit(ctx.whereClause()).attach(result); + } + return result; + } + + @Override + public UnresolvedPlan visitWhereClause(WhereClauseContext ctx) { + return new Filter(visitAstExpression(ctx.expression())); } @Override diff --git a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java index f8f9df9875..f9b77305bf 100644 --- a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java +++ b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java @@ -91,10 +91,15 @@ public void canNotParseIndexNameSingleQuoted() { () -> parser.parse("SELECT * FROM 'test'")); } + @Test + public void canParseWhereClause() { + assertNotNull(parser.parse("SELECT name FROM test WHERE age = 10")); + } + @Test public void canNotParseInvalidSelect() { assertThrows(SyntaxCheckException.class, - () -> parser.parse("SELECT * FROM test WHERE age = 10")); + () -> parser.parse("SELECT * FROM test WHERE age = 10 GROUP BY name")); } } \ No newline at end of file diff --git a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilderTest.java b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilderTest.java index 3de6b9920b..dafb74e9c9 100644 --- a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilderTest.java +++ b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstBuilderTest.java @@ -19,6 +19,7 @@ import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.alias; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.booleanLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.doubleLiteral; +import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.filter; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.function; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.intLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.project; @@ -145,6 +146,23 @@ public void can_build_select_fields_with_alias_quoted() { ); } + @Test + public void can_build_where_clause() { + assertEquals( + project( + filter( + relation("test"), + function( + "=", + qualifiedName("name"), + stringLiteral("John")) + ), + alias("name", qualifiedName("name")) + ), + buildAST("SELECT name FROM test WHERE name = 'John'") + ); + } + private UnresolvedPlan buildAST(String query) { ParseTree parseTree = parser.parse(query); return parseTree.accept(new AstBuilder(query)); From 5df73989af893e23cae18571babf7a59cda3d0d9 Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 08:28:54 -0700 Subject: [PATCH 02/10] Skip old semantic analysis IT --- integ-test/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integ-test/build.gradle b/integ-test/build.gradle index 974973fe49..0ef74b6cd0 100644 --- a/integ-test/build.gradle +++ b/integ-test/build.gradle @@ -114,6 +114,9 @@ task integTestWithNewEngine(type: RestIntegTestTask) { exclude 'com/amazon/opendistroforelasticsearch/sql/doctest/**/*IT.class' exclude 'com/amazon/opendistroforelasticsearch/sql/correctness/**' + + // Skip old semantic analyzer IT + exclude 'com/amazon/opendistroforelasticsearch/sql/legacy/QueryAnalysisIT.class' } } From e54308a3764b5fee494ea094c7851071a7642a48 Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 09:44:02 -0700 Subject: [PATCH 03/10] Change unsupported query UT --- .../sql/legacy/plugin/RestSQLQueryActionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/legacy/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/plugin/RestSQLQueryActionTest.java b/legacy/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/plugin/RestSQLQueryActionTest.java index dac792ef06..31e4b8845b 100644 --- a/legacy/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/plugin/RestSQLQueryActionTest.java +++ b/legacy/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/plugin/RestSQLQueryActionTest.java @@ -71,8 +71,8 @@ public void skipExplainThatNotSupport() { @Test public void skipQueryThatNotSupport() { SQLQueryRequest request = new SQLQueryRequest( - new JSONObject("{\"query\": \"SELECT * FROM test WHERE age = 10\"}"), - "SELECT * FROM test WHERE age = 10", + new JSONObject("{\"query\": \"SELECT * FROM test WHERE age = 10 GROUP BY age\"}"), + "SELECT * FROM test WHERE age = 10 GROUP BY age", QUERY_API_ENDPOINT, ""); From 4bc960314b461f3912dd7a319bbd150b00b073b0 Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 10:42:08 -0700 Subject: [PATCH 04/10] Add logical operator to grammar and UT --- sql/src/main/antlr/OpenDistroSQLParser.g4 | 12 +++++++++++- .../sql/sql/parser/AstExpressionBuilder.java | 14 ++++++++++++++ .../sql/sql/antlr/SQLSyntaxParserTest.java | 6 ++++++ .../sql/sql/parser/AstExpressionBuilderTest.java | 15 +++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/sql/src/main/antlr/OpenDistroSQLParser.g4 b/sql/src/main/antlr/OpenDistroSQLParser.g4 index 0d37f50823..03d761088c 100644 --- a/sql/src/main/antlr/OpenDistroSQLParser.g4 +++ b/sql/src/main/antlr/OpenDistroSQLParser.g4 @@ -146,7 +146,9 @@ timestampLiteral // Simplified approach for expression expression - : predicate #predicateExpression + : left=expression AND right=expression #andExpression + | left=expression OR right=expression #orExpression + | predicate #predicateExpression ; predicate @@ -164,6 +166,14 @@ expressionAtom | left=expressionAtom mathOperator right=expressionAtom #mathExpressionAtom ; +/* +logicalExpression + : left=logicalExpression AND right=logicalExpression #andExpression + | left=logicalExpression OR right=logicalExpression #orExpression + | NOT logicalExpression #notExpression + ; +*/ + mathOperator : PLUS | MINUS | STAR | DIVIDE | MODULE ; diff --git a/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java b/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java index 1dadde63ff..7eb327aa3a 100644 --- a/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java +++ b/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java @@ -28,14 +28,18 @@ import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.StringContext; import com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL; +import com.amazon.opendistroforelasticsearch.sql.ast.expression.And; import com.amazon.opendistroforelasticsearch.sql.ast.expression.Function; +import com.amazon.opendistroforelasticsearch.sql.ast.expression.Or; import com.amazon.opendistroforelasticsearch.sql.ast.expression.QualifiedName; import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedExpression; import com.amazon.opendistroforelasticsearch.sql.common.utils.StringUtils; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser; +import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.AndExpressionContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.ColumnNameContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.IdentContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.NestedExpressionAtomContext; +import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.OrExpressionContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.QualifiedNameContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.TableNameContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParserBaseVisitor; @@ -111,6 +115,16 @@ public UnresolvedExpression visitLikePredicate(OpenDistroSQLParser.LikePredicate Arrays.asList(visit(ctx.left), visit(ctx.right))); } + @Override + public UnresolvedExpression visitAndExpression(AndExpressionContext ctx) { + return new And(visit(ctx.left), visit(ctx.right)); + } + + @Override + public UnresolvedExpression visitOrExpression(OrExpressionContext ctx) { + return new Or(visit(ctx.left), visit(ctx.right)); + } + @Override public UnresolvedExpression visitString(StringContext ctx) { return AstDSL.stringLiteral(StringUtils.unquoteText(ctx.getText())); diff --git a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java index f9b77305bf..3921ef3f67 100644 --- a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java +++ b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java @@ -96,6 +96,12 @@ public void canParseWhereClause() { assertNotNull(parser.parse("SELECT name FROM test WHERE age = 10")); } + @Test + public void canParseWhereClauseWithLogicalOperator() { + assertNotNull(parser.parse("SELECT name FROM test " + + "WHERE age = 10 AND name = 'John' OR balance > 1000")); + } + @Test public void canNotParseInvalidSelect() { assertThrows(SyntaxCheckException.class, diff --git a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java index cde9340313..79c5090083 100644 --- a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java +++ b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java @@ -16,12 +16,14 @@ package com.amazon.opendistroforelasticsearch.sql.sql.parser; +import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.and; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.booleanLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.dateLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.doubleLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.function; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.intLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.nullLiteral; +import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.or; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.stringLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.timeLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.timestampLiteral; @@ -195,6 +197,19 @@ public void canBuildLikeExpression() { ); } + @Test + public void canBuildLogicalExpression() { + assertEquals( + and(booleanLiteral(true), booleanLiteral(false)), + buildExprAst("true AND false") + ); + + assertEquals( + or(booleanLiteral(true), booleanLiteral(false)), + buildExprAst("true OR false") + ); + } + private Node buildExprAst(String expr) { OpenDistroSQLLexer lexer = new OpenDistroSQLLexer(new CaseInsensitiveCharStream(expr)); OpenDistroSQLParser parser = new OpenDistroSQLParser(new CommonTokenStream(lexer)); From 5af18e7fe565ec17a7a77dc99fa7a6423f9111b1 Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 13:55:15 -0700 Subject: [PATCH 05/10] Add not expression and comparison test --- .../correctness/expressions/predicates.txt | 7 +++++ .../resources/correctness/queries/select.txt | 2 ++ sql/src/main/antlr/OpenDistroSQLParser.g4 | 3 +- .../sql/sql/parser/AstExpressionBuilder.java | 29 ++++++++++++++----- .../sql/parser/AstExpressionBuilderTest.java | 6 ++++ 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/integ-test/src/test/resources/correctness/expressions/predicates.txt b/integ-test/src/test/resources/correctness/expressions/predicates.txt index e69de29bb2..9bc00c0be9 100644 --- a/integ-test/src/test/resources/correctness/expressions/predicates.txt +++ b/integ-test/src/test/resources/correctness/expressions/predicates.txt @@ -0,0 +1,7 @@ +true AND true AS bool +false AND true AS bool +false OR false AS bool +true or false AS bool +NOT true AS bool +NOT false AS bool +NOT (true AND false) AS bool \ No newline at end of file diff --git a/integ-test/src/test/resources/correctness/queries/select.txt b/integ-test/src/test/resources/correctness/queries/select.txt index 298e0f22a1..24f0b8a0e5 100644 --- a/integ-test/src/test/resources/correctness/queries/select.txt +++ b/integ-test/src/test/resources/correctness/queries/select.txt @@ -6,3 +6,5 @@ SELECT abs(DistanceMiles), Abs(FlightDelayMin) FROM kibana_sample_data_flights SELECT Cancelled AS Cancel, AvgTicketPrice AS ATP FROM kibana_sample_data_flights SELECT Cancelled AS `Cancel`, AvgTicketPrice AS "ATP" FROM kibana_sample_data_flights SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice <= 500 +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice <= 500 AND FlightDelayMin = 0 +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice <= 500 OR FlightDelayMin = 0 diff --git a/sql/src/main/antlr/OpenDistroSQLParser.g4 b/sql/src/main/antlr/OpenDistroSQLParser.g4 index 03d761088c..315238ff79 100644 --- a/sql/src/main/antlr/OpenDistroSQLParser.g4 +++ b/sql/src/main/antlr/OpenDistroSQLParser.g4 @@ -146,7 +146,8 @@ timestampLiteral // Simplified approach for expression expression - : left=expression AND right=expression #andExpression + : NOT expression #notExpression + | left=expression AND right=expression #andExpression | left=expression OR right=expression #orExpression | predicate #predicateExpression ; diff --git a/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java b/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java index 7eb327aa3a..11018fe9d3 100644 --- a/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java +++ b/sql/src/main/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilder.java @@ -20,21 +20,29 @@ import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.IS_NULL; import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.LIKE; import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.NOT_LIKE; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.BinaryComparisonPredicateContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.BooleanContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.DateLiteralContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.IsNullPredicateContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.LikePredicateContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.MathExpressionAtomContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.NotExpressionContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.NullLiteralContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.ScalarFunctionCallContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.SignedDecimalContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.SignedRealContext; import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.StringContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.TimeLiteralContext; +import static com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.TimestampLiteralContext; import com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL; import com.amazon.opendistroforelasticsearch.sql.ast.expression.And; import com.amazon.opendistroforelasticsearch.sql.ast.expression.Function; +import com.amazon.opendistroforelasticsearch.sql.ast.expression.Not; import com.amazon.opendistroforelasticsearch.sql.ast.expression.Or; import com.amazon.opendistroforelasticsearch.sql.ast.expression.QualifiedName; import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedExpression; import com.amazon.opendistroforelasticsearch.sql.common.utils.StringUtils; -import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.AndExpressionContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.ColumnNameContext; import com.amazon.opendistroforelasticsearch.sql.sql.antlr.parser.OpenDistroSQLParser.IdentContext; @@ -100,7 +108,7 @@ public UnresolvedExpression visitScalarFunctionCall(ScalarFunctionCallContext ct } @Override - public UnresolvedExpression visitIsNullPredicate(OpenDistroSQLParser.IsNullPredicateContext ctx) { + public UnresolvedExpression visitIsNullPredicate(IsNullPredicateContext ctx) { return new Function( ctx.nullNotnull().NOT() == null ? IS_NULL.getName().getFunctionName() : IS_NOT_NULL.getName().getFunctionName(), @@ -108,7 +116,7 @@ public UnresolvedExpression visitIsNullPredicate(OpenDistroSQLParser.IsNullPredi } @Override - public UnresolvedExpression visitLikePredicate(OpenDistroSQLParser.LikePredicateContext ctx) { + public UnresolvedExpression visitLikePredicate(LikePredicateContext ctx) { return new Function( ctx.NOT() == null ? LIKE.getName().getFunctionName() : NOT_LIKE.getName().getFunctionName(), @@ -125,6 +133,11 @@ public UnresolvedExpression visitOrExpression(OrExpressionContext ctx) { return new Or(visit(ctx.left), visit(ctx.right)); } + @Override + public UnresolvedExpression visitNotExpression(NotExpressionContext ctx) { + return new Not(visit(ctx.expression())); + } + @Override public UnresolvedExpression visitString(StringContext ctx) { return AstDSL.stringLiteral(StringUtils.unquoteText(ctx.getText())); @@ -146,29 +159,29 @@ public UnresolvedExpression visitBoolean(BooleanContext ctx) { } @Override - public UnresolvedExpression visitNullLiteral(OpenDistroSQLParser.NullLiteralContext ctx) { + public UnresolvedExpression visitNullLiteral(NullLiteralContext ctx) { return AstDSL.nullLiteral(); } @Override - public UnresolvedExpression visitDateLiteral(OpenDistroSQLParser.DateLiteralContext ctx) { + public UnresolvedExpression visitDateLiteral(DateLiteralContext ctx) { return AstDSL.dateLiteral(StringUtils.unquoteText(ctx.date.getText())); } @Override - public UnresolvedExpression visitTimeLiteral(OpenDistroSQLParser.TimeLiteralContext ctx) { + public UnresolvedExpression visitTimeLiteral(TimeLiteralContext ctx) { return AstDSL.timeLiteral(StringUtils.unquoteText(ctx.time.getText())); } @Override public UnresolvedExpression visitTimestampLiteral( - OpenDistroSQLParser.TimestampLiteralContext ctx) { + TimestampLiteralContext ctx) { return AstDSL.timestampLiteral(StringUtils.unquoteText(ctx.timestamp.getText())); } @Override public UnresolvedExpression visitBinaryComparisonPredicate( - OpenDistroSQLParser.BinaryComparisonPredicateContext ctx) { + BinaryComparisonPredicateContext ctx) { String functionName = ctx.comparisonOperator().getText(); return new Function( functionName.equals("<>") ? "!=" : functionName, diff --git a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java index 79c5090083..a6e5d6f798 100644 --- a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java +++ b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/parser/AstExpressionBuilderTest.java @@ -22,6 +22,7 @@ import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.doubleLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.function; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.intLiteral; +import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.not; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.nullLiteral; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.or; import static com.amazon.opendistroforelasticsearch.sql.ast.dsl.AstDSL.stringLiteral; @@ -208,6 +209,11 @@ public void canBuildLogicalExpression() { or(booleanLiteral(true), booleanLiteral(false)), buildExprAst("true OR false") ); + + assertEquals( + not(booleanLiteral(false)), + buildExprAst("NOT false") + ); } private Node buildExprAst(String expr) { From 81822caf6d06bab3b382d0177bcede42f8c964ab Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 16:01:57 -0700 Subject: [PATCH 06/10] Add comparison test for bug fixes --- .../sql/sql/SQLCorrectnessIT.java | 2 +- .../test/resources/correctness/bugfixes/234.txt | 1 + .../test/resources/correctness/bugfixes/237.txt | 2 ++ .../test/resources/correctness/bugfixes/368.txt | 1 + .../test/resources/correctness/bugfixes/521.txt | 2 +- .../correctness/kibana_sample_data_flights.json | 16 ++++++++++++++-- 6 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 integ-test/src/test/resources/correctness/bugfixes/234.txt create mode 100644 integ-test/src/test/resources/correctness/bugfixes/237.txt create mode 100644 integ-test/src/test/resources/correctness/bugfixes/368.txt diff --git a/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java b/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java index 58c10073a1..8a1379a8fc 100644 --- a/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java +++ b/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java @@ -32,7 +32,7 @@ public class SQLCorrectnessIT extends CorrectnessTestBase { private static final String ROOT_DIR = "correctness/"; private static final String[] EXPR_TEST_DIR = { "expressions" }; - private static final String[] QUERY_TEST_DIR = { "queries"/*, "bugfixes"*/ }; //TODO: skip bugfixes folder for now since it fails + private static final String[] QUERY_TEST_DIR = { "queries", "bugfixes" }; @Override protected void init() throws Exception { diff --git a/integ-test/src/test/resources/correctness/bugfixes/234.txt b/integ-test/src/test/resources/correctness/bugfixes/234.txt new file mode 100644 index 0000000000..e0c108546d --- /dev/null +++ b/integ-test/src/test/resources/correctness/bugfixes/234.txt @@ -0,0 +1 @@ +SELECT FlightNum FROM kibana_sample_data_flights where (AvgTicketPrice + 100) <= 1000 \ No newline at end of file diff --git a/integ-test/src/test/resources/correctness/bugfixes/237.txt b/integ-test/src/test/resources/correctness/bugfixes/237.txt new file mode 100644 index 0000000000..5fd9878b0b --- /dev/null +++ b/integ-test/src/test/resources/correctness/bugfixes/237.txt @@ -0,0 +1,2 @@ +SELECT ((Origin = 'Munich Airport') and (Dest = 'Venice Marco Polo Airport')) AS Calculation_462181953506873347 FROM kibana_sample_data_flights +SELECT ((Origin = 'Munich Airport') or (Dest = 'Venice Marco Polo Airport')) AS Calculation_462181953506873347 FROM kibana_sample_data_flights diff --git a/integ-test/src/test/resources/correctness/bugfixes/368.txt b/integ-test/src/test/resources/correctness/bugfixes/368.txt new file mode 100644 index 0000000000..a9faaca95c --- /dev/null +++ b/integ-test/src/test/resources/correctness/bugfixes/368.txt @@ -0,0 +1 @@ +SELECT Origin FROM kibana_sample_data_flights WHERE Origin LIKE 'London%' \ No newline at end of file diff --git a/integ-test/src/test/resources/correctness/bugfixes/521.txt b/integ-test/src/test/resources/correctness/bugfixes/521.txt index 72a27b01d7..f0ef35d198 100644 --- a/integ-test/src/test/resources/correctness/bugfixes/521.txt +++ b/integ-test/src/test/resources/correctness/bugfixes/521.txt @@ -1 +1 @@ -SELECT timestamp, COUNT(*) FROM kibana_sample_data_flights GROUP BY timestamp \ No newline at end of file +SELECT timestamp FROM kibana_sample_data_flights GROUP BY timestamp \ No newline at end of file diff --git a/integ-test/src/test/resources/correctness/kibana_sample_data_flights.json b/integ-test/src/test/resources/correctness/kibana_sample_data_flights.json index d180b6283c..4ad67e88a6 100644 --- a/integ-test/src/test/resources/correctness/kibana_sample_data_flights.json +++ b/integ-test/src/test/resources/correctness/kibana_sample_data_flights.json @@ -11,7 +11,13 @@ "type": "keyword" }, "Dest": { - "type": "keyword" + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } }, "DestAirportID": { "type": "keyword" @@ -53,7 +59,13 @@ "type": "float" }, "Origin": { - "type": "keyword" + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } }, "OriginAirportID": { "type": "keyword" From 0b2c435bb003c20604d832a9e6b342faf6ea2d1c Mon Sep 17 00:00:00 2001 From: Dai Date: Thu, 13 Aug 2020 16:35:38 -0700 Subject: [PATCH 07/10] Handle multi field in wildcard query too --- .../script/filter/lucene/LuceneQuery.java | 9 +++++ .../script/filter/lucene/TermQuery.java | 6 +--- .../script/filter/lucene/WildcardQuery.java | 1 + .../script/filter/FilterQueryBuilderTest.java | 36 +++++++++++++++++-- .../resources/correctness/bugfixes/368.txt | 2 +- 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java index d97a2517e2..b50c741318 100644 --- a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java +++ b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java @@ -16,6 +16,8 @@ package com.amazon.opendistroforelasticsearch.sql.elasticsearch.storage.script.filter.lucene; +import static com.amazon.opendistroforelasticsearch.sql.elasticsearch.data.type.ElasticsearchDataType.ES_TEXT_KEYWORD; + import com.amazon.opendistroforelasticsearch.sql.data.model.ExprValue; import com.amazon.opendistroforelasticsearch.sql.data.type.ExprType; import com.amazon.opendistroforelasticsearch.sql.expression.FunctionExpression; @@ -69,4 +71,11 @@ protected QueryBuilder doBuild(String fieldName, ExprType fieldType, ExprValue l "Subclass doesn't implement this and build method either"); } + protected String convertTextToKeyword(String fieldName, ExprType fieldType) { + if (fieldType == ES_TEXT_KEYWORD) { // Assume inner field name is always "keyword" + return fieldName + ".keyword"; + } + return fieldName; + } + } diff --git a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/TermQuery.java b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/TermQuery.java index 01e3c4d9f0..db07116a25 100644 --- a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/TermQuery.java +++ b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/TermQuery.java @@ -16,8 +16,6 @@ package com.amazon.opendistroforelasticsearch.sql.elasticsearch.storage.script.filter.lucene; -import static com.amazon.opendistroforelasticsearch.sql.elasticsearch.data.type.ElasticsearchDataType.ES_TEXT_KEYWORD; - import com.amazon.opendistroforelasticsearch.sql.data.model.ExprValue; import com.amazon.opendistroforelasticsearch.sql.data.type.ExprType; import org.elasticsearch.index.query.QueryBuilder; @@ -30,9 +28,7 @@ public class TermQuery extends LuceneQuery { @Override protected QueryBuilder doBuild(String fieldName, ExprType fieldType, ExprValue literal) { - if (fieldType == ES_TEXT_KEYWORD) { // Assume inner field name is always "keyword" - fieldName += ".keyword"; - } + fieldName = convertTextToKeyword(fieldName, fieldType); return QueryBuilders.termQuery(fieldName, literal.value()); } diff --git a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/WildcardQuery.java b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/WildcardQuery.java index 1f20663a9d..7b5c109924 100644 --- a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/WildcardQuery.java +++ b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/WildcardQuery.java @@ -28,6 +28,7 @@ public class WildcardQuery extends LuceneQuery { @Override protected QueryBuilder doBuild(String fieldName, ExprType fieldType, ExprValue literal) { + fieldName = convertTextToKeyword(fieldName, fieldType); String matchText = convertSqlWildcardToLucene(literal.stringValue()); return QueryBuilders.wildcardQuery(fieldName, matchText); } diff --git a/elasticsearch/src/test/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/FilterQueryBuilderTest.java b/elasticsearch/src/test/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/FilterQueryBuilderTest.java index 5a7d93ec6b..aabbd857dc 100644 --- a/elasticsearch/src/test/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/FilterQueryBuilderTest.java +++ b/elasticsearch/src/test/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/FilterQueryBuilderTest.java @@ -171,7 +171,7 @@ void should_build_script_query_for_comparison_between_fields() { @Test void should_build_bool_query_for_and_or_expression() { String[] names = { "filter", "should" }; - FunctionExpression expr1 = dsl.equal(ref("name", ES_TEXT_KEYWORD), literal("John")); + FunctionExpression expr1 = dsl.equal(ref("name", STRING), literal("John")); FunctionExpression expr2 = dsl.equal(ref("age", INTEGER), literal(30)); Expression[] exprs = { dsl.and(expr1, expr2), @@ -185,7 +185,7 @@ void should_build_bool_query_for_and_or_expression() { + " \"" + names[i] + "\" : [\n" + " {\n" + " \"term\" : {\n" - + " \"name.keyword\" : {\n" + + " \"name\" : {\n" + " \"value\" : \"John\",\n" + " \"boost\" : 1.0\n" + " }\n" @@ -233,6 +233,38 @@ void should_build_bool_query_for_not_expression() { ref("age", INTEGER), literal(30))))); } + @Test + void should_use_keyword_for_multi_field_in_equality_expression() { + assertEquals( + "{\n" + + " \"term\" : {\n" + + " \"name.keyword\" : {\n" + + " \"value\" : \"John\",\n" + + " \"boost\" : 1.0\n" + + " }\n" + + " }\n" + + "}", + buildQuery( + dsl.equal( + ref("name", ES_TEXT_KEYWORD), literal("John")))); + } + + @Test + void should_use_keyword_for_multi_field_in_like_expression() { + assertEquals( + "{\n" + + " \"wildcard\" : {\n" + + " \"name.keyword\" : {\n" + + " \"wildcard\" : \"John*\",\n" + + " \"boost\" : 1.0\n" + + " }\n" + + " }\n" + + "}", + buildQuery( + dsl.like( + ref("name", ES_TEXT_KEYWORD), literal("John%")))); + } + private String buildQuery(Expression expr) { return filterQueryBuilder.build(expr).toString(); } diff --git a/integ-test/src/test/resources/correctness/bugfixes/368.txt b/integ-test/src/test/resources/correctness/bugfixes/368.txt index a9faaca95c..13796605cb 100644 --- a/integ-test/src/test/resources/correctness/bugfixes/368.txt +++ b/integ-test/src/test/resources/correctness/bugfixes/368.txt @@ -1 +1 @@ -SELECT Origin FROM kibana_sample_data_flights WHERE Origin LIKE 'London%' \ No newline at end of file +SELECT Origin FROM kibana_sample_data_flights WHERE Origin LIKE 'London Hea%' \ No newline at end of file From bcac73f44fa564265ba61bbb9821339d055fd74b Mon Sep 17 00:00:00 2001 From: Dai Date: Tue, 18 Aug 2020 10:04:48 -0700 Subject: [PATCH 08/10] Prepare for PR --- .../storage/script/filter/lucene/LuceneQuery.java | 14 +++++++++++--- integ-test/build.gradle | 2 +- .../sql/sql/SQLCorrectnessIT.java | 2 -- .../test/resources/correctness/bugfixes/234.txt | 3 ++- .../test/resources/correctness/bugfixes/237.txt | 5 +++-- .../test/resources/correctness/bugfixes/368.txt | 3 ++- sql/src/main/antlr/OpenDistroSQLParser.g4 | 8 -------- .../sql/sql/antlr/SQLSyntaxParserTest.java | 8 +++++++- 8 files changed, 26 insertions(+), 19 deletions(-) diff --git a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java index b50c741318..379995ce5c 100644 --- a/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java +++ b/elasticsearch/src/main/java/com/amazon/opendistroforelasticsearch/sql/elasticsearch/storage/script/filter/lucene/LuceneQuery.java @@ -62,8 +62,8 @@ public QueryBuilder build(FunctionExpression func) { * from reference and literal in function arguments. * * @param fieldName field name - * @param fieldType expr fieldType - * @param literal expr literal + * @param fieldType field type + * @param literal field value literal * @return query */ protected QueryBuilder doBuild(String fieldName, ExprType fieldType, ExprValue literal) { @@ -71,8 +71,16 @@ protected QueryBuilder doBuild(String fieldName, ExprType fieldType, ExprValue l "Subclass doesn't implement this and build method either"); } + /** + * Convert multi-field text field name to its inner keyword field. The limitation and assumption + * is that the keyword field name is always "keyword" which is true by default. + * + * @param fieldName field name + * @param fieldType field type + * @return keyword field name for multi-field, otherwise original field name returned + */ protected String convertTextToKeyword(String fieldName, ExprType fieldType) { - if (fieldType == ES_TEXT_KEYWORD) { // Assume inner field name is always "keyword" + if (fieldType == ES_TEXT_KEYWORD) { return fieldName + ".keyword"; } return fieldName; diff --git a/integ-test/build.gradle b/integ-test/build.gradle index 0ef74b6cd0..622497dcf2 100644 --- a/integ-test/build.gradle +++ b/integ-test/build.gradle @@ -115,7 +115,7 @@ task integTestWithNewEngine(type: RestIntegTestTask) { exclude 'com/amazon/opendistroforelasticsearch/sql/doctest/**/*IT.class' exclude 'com/amazon/opendistroforelasticsearch/sql/correctness/**' - // Skip old semantic analyzer IT + // Skip old semantic analyzer IT because analyzer in new engine has different behavior exclude 'com/amazon/opendistroforelasticsearch/sql/legacy/QueryAnalysisIT.class' } } diff --git a/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java b/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java index 8a1379a8fc..e069141d4b 100644 --- a/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java +++ b/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/SQLCorrectnessIT.java @@ -71,6 +71,4 @@ private void verifyQueries(Path file, Function converter) { } } - - } diff --git a/integ-test/src/test/resources/correctness/bugfixes/234.txt b/integ-test/src/test/resources/correctness/bugfixes/234.txt index e0c108546d..3056acb199 100644 --- a/integ-test/src/test/resources/correctness/bugfixes/234.txt +++ b/integ-test/src/test/resources/correctness/bugfixes/234.txt @@ -1 +1,2 @@ -SELECT FlightNum FROM kibana_sample_data_flights where (AvgTicketPrice + 100) <= 1000 \ No newline at end of file +SELECT FlightNum FROM kibana_sample_data_flights where (AvgTicketPrice + 100) <= 1000 +SELECT FlightNum FROM kibana_sample_data_flights where ROUND(FlightTimeMin) > ABS(FlightDelayMin) \ No newline at end of file diff --git a/integ-test/src/test/resources/correctness/bugfixes/237.txt b/integ-test/src/test/resources/correctness/bugfixes/237.txt index 5fd9878b0b..5ffd41287c 100644 --- a/integ-test/src/test/resources/correctness/bugfixes/237.txt +++ b/integ-test/src/test/resources/correctness/bugfixes/237.txt @@ -1,2 +1,3 @@ -SELECT ((Origin = 'Munich Airport') and (Dest = 'Venice Marco Polo Airport')) AS Calculation_462181953506873347 FROM kibana_sample_data_flights -SELECT ((Origin = 'Munich Airport') or (Dest = 'Venice Marco Polo Airport')) AS Calculation_462181953506873347 FROM kibana_sample_data_flights +SELECT ((Origin = 'Munich Airport') AND (Dest = 'Venice Marco Polo Airport')) AS Calculation_462181953506873347 FROM kibana_sample_data_flights +SELECT ((Origin = 'Munich Airport') OR (Origin = 'Itami Airport')) AS Calculation_462181953506873347 FROM kibana_sample_data_flights +SELECT NOT (Origin = 'Munich Airport') AS Calculation_462181953506873347 FROM kibana_sample_data_flights \ No newline at end of file diff --git a/integ-test/src/test/resources/correctness/bugfixes/368.txt b/integ-test/src/test/resources/correctness/bugfixes/368.txt index 13796605cb..a81edeec97 100644 --- a/integ-test/src/test/resources/correctness/bugfixes/368.txt +++ b/integ-test/src/test/resources/correctness/bugfixes/368.txt @@ -1 +1,2 @@ -SELECT Origin FROM kibana_sample_data_flights WHERE Origin LIKE 'London Hea%' \ No newline at end of file +SELECT Origin FROM kibana_sample_data_flights WHERE Origin LIKE 'London Hea%' +SELECT Origin FROM kibana_sample_data_flights WHERE Origin LIKE '%International%' \ No newline at end of file diff --git a/sql/src/main/antlr/OpenDistroSQLParser.g4 b/sql/src/main/antlr/OpenDistroSQLParser.g4 index 315238ff79..3bc728ad03 100644 --- a/sql/src/main/antlr/OpenDistroSQLParser.g4 +++ b/sql/src/main/antlr/OpenDistroSQLParser.g4 @@ -167,14 +167,6 @@ expressionAtom | left=expressionAtom mathOperator right=expressionAtom #mathExpressionAtom ; -/* -logicalExpression - : left=logicalExpression AND right=logicalExpression #andExpression - | left=logicalExpression OR right=logicalExpression #orExpression - | NOT logicalExpression #notExpression - ; -*/ - mathOperator : PLUS | MINUS | STAR | DIVIDE | MODULE ; diff --git a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java index 3921ef3f67..0f516de40d 100644 --- a/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java +++ b/sql/src/test/java/com/amazon/opendistroforelasticsearch/sql/sql/antlr/SQLSyntaxParserTest.java @@ -96,10 +96,16 @@ public void canParseWhereClause() { assertNotNull(parser.parse("SELECT name FROM test WHERE age = 10")); } + @Test + public void canParseSelectClauseWithLogicalOperator() { + assertNotNull(parser.parse( + "SELECT age = 10 AND name = 'John' OR NOT (balance > 1000) FROM test")); + } + @Test public void canParseWhereClauseWithLogicalOperator() { assertNotNull(parser.parse("SELECT name FROM test " - + "WHERE age = 10 AND name = 'John' OR balance > 1000")); + + "WHERE age = 10 AND name = 'John' OR NOT (balance > 1000)")); } @Test From 121f3801e50140a021e4671effa6f2add6b2ba3b Mon Sep 17 00:00:00 2001 From: Dai Date: Tue, 18 Aug 2020 10:44:37 -0700 Subject: [PATCH 09/10] Add more test --- integ-test/src/test/resources/correctness/queries/select.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/integ-test/src/test/resources/correctness/queries/select.txt b/integ-test/src/test/resources/correctness/queries/select.txt index 24f0b8a0e5..50372e4ff2 100644 --- a/integ-test/src/test/resources/correctness/queries/select.txt +++ b/integ-test/src/test/resources/correctness/queries/select.txt @@ -6,5 +6,10 @@ SELECT abs(DistanceMiles), Abs(FlightDelayMin) FROM kibana_sample_data_flights SELECT Cancelled AS Cancel, AvgTicketPrice AS ATP FROM kibana_sample_data_flights SELECT Cancelled AS `Cancel`, AvgTicketPrice AS "ATP" FROM kibana_sample_data_flights SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice <= 500 +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE NOT AvgTicketPrice <= 500 SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice <= 500 AND FlightDelayMin = 0 SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice <= 500 OR FlightDelayMin = 0 +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE AvgTicketPrice + 100 <= 500 +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE ABS(AvgTicketPrice * -2) > 1000 +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE Carrier LIKE 'JetBeat_' +SELECT AvgTicketPrice, Carrier FROM kibana_sample_data_flights WHERE Carrier LIKE '%Air%' From 5a54c22340cd97b809a1dc778f9e3cf28cdb5036 Mon Sep 17 00:00:00 2001 From: Dai Date: Tue, 18 Aug 2020 10:55:08 -0700 Subject: [PATCH 10/10] Add test for issue 690 --- integ-test/src/test/resources/correctness/bugfixes/690.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 integ-test/src/test/resources/correctness/bugfixes/690.txt diff --git a/integ-test/src/test/resources/correctness/bugfixes/690.txt b/integ-test/src/test/resources/correctness/bugfixes/690.txt new file mode 100644 index 0000000000..940087e79e --- /dev/null +++ b/integ-test/src/test/resources/correctness/bugfixes/690.txt @@ -0,0 +1,4 @@ +SELECT FlightNum, Origin FROM kibana_sample_data_flights WHERE NULL IS NULL +SELECT FlightNum, Origin FROM kibana_sample_data_flights WHERE NULL IS NOT NULL +SELECT FlightNum, Origin FROM kibana_sample_data_flights WHERE NULL IS NULL AND NULL IS NULL +SELECT FlightNum, Origin FROM kibana_sample_data_flights WHERE NULL IS NULL OR NULL IS NULL