Skip to content

Commit b98c7f6

Browse files
authored
Support full expression in WHERE clauses (opensearch-project#3849) (opensearch-project#3904)
* Support full expression in WHERE clauses * add unit tests * revert typo * Fix IT * Fix IT * Address comment --------- (cherry picked from commit 988ab2e) Signed-off-by: Lantao Jin <ltjin@amazon.com>
1 parent cc0b66d commit b98c7f6

7 files changed

Lines changed: 271 additions & 152 deletions

File tree

integ-test/src/test/java/org/opensearch/sql/ppl/WhereCommandIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void testWhereWithMultiLogicalExpr() throws IOException {
4444
executeQuery(
4545
String.format(
4646
"source=%s "
47-
+ "| where firstname='Amber' lastname='Duke' age=32 "
47+
+ "| where firstname='Amber' and lastname='Duke' and age=32 "
4848
+ "| fields firstname, lastname, age",
4949
TEST_INDEX_ACCOUNT));
5050
verifyDataRows(result, rows("Amber", "Duke", 32));

ppl/src/main/antlr/OpenSearchPPLParser.g4

Lines changed: 43 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ root
1414

1515
// statement
1616
pplStatement
17-
: dmlStatement
18-
;
19-
20-
dmlStatement
21-
: queryStatement
22-
| explainStatement
17+
: explainStatement
18+
| queryStatement
2319
;
2420

2521
queryStatement
@@ -43,9 +39,9 @@ subSearch
4339

4440
// commands
4541
pplCommands
46-
: searchCommand
47-
| describeCommand
42+
: describeCommand
4843
| showDataSourcesCommand
44+
| searchCommand
4945
;
5046

5147
commands
@@ -110,9 +106,7 @@ commandName
110106
;
111107

112108
searchCommand
113-
: (SEARCH)? fromClause # searchFrom
114-
| (SEARCH)? fromClause logicalExpression # searchFromFilter
115-
| (SEARCH)? logicalExpression fromClause # searchFilterFrom
109+
: (SEARCH)? (logicalExpression)* fromClause (logicalExpression)* # searchFrom
116110
;
117111

118112
describeCommand
@@ -377,7 +371,7 @@ sortbyClause
377371
;
378372

379373
evalClause
380-
: fieldExpression EQUAL expression
374+
: fieldExpression EQUAL logicalExpression
381375
;
382376

383377
eventstatsAggTerm
@@ -451,68 +445,52 @@ numericLiteral
451445
| floatLiteral
452446
;
453447

454-
// expressions
455-
expression
456-
: logicalExpression
457-
| comparisonExpression
458-
| valueExpression
459-
;
460-
461448
// predicates
462449
logicalExpression
463-
: LT_PRTHS logicalExpression RT_PRTHS # parentheticLogicalExpr
464-
| NOT logicalExpression # logicalNot
465-
| left = logicalExpression (AND)? right = logicalExpression # logicalAnd
450+
: NOT logicalExpression # logicalNot
451+
| left = logicalExpression AND right = logicalExpression # logicalAnd
466452
| left = logicalExpression XOR right = logicalExpression # logicalXor
467453
| left = logicalExpression OR right = logicalExpression # logicalOr
468-
| comparisonExpression # comparsion
469-
| booleanExpression # booleanExpr
470-
| relevanceExpression # relevanceExpr
471-
;
472-
473-
comparisonExpression
474-
: left = valueExpression comparisonOperator right = valueExpression # compareExpr
475-
| valueExpression NOT? IN valueList # inExpr
476-
| valueExpression NOT? BETWEEN valueExpression AND valueExpression # between
454+
| expression # logicalExpr
477455
;
478456

479-
valueExpressionList
480-
: valueExpression
481-
| LT_PRTHS valueExpression (COMMA valueExpression)* RT_PRTHS
457+
expression
458+
: valueExpression # valueExpr
459+
| relevanceExpression # relevanceExpr
460+
| left = expression comparisonOperator right = expression # compareExpr
461+
| expression NOT? IN valueList # inExpr
462+
| expression NOT? BETWEEN expression AND expression # between
482463
;
483464

484465
valueExpression
485-
: left = valueExpression binaryOperator = (STAR | DIVIDE | MODULE) right = valueExpression # binaryArithmetic
486-
| left = valueExpression binaryOperator = (PLUS | MINUS) right = valueExpression # binaryArithmetic
487-
| primaryExpression # valueExpressionDefault
488-
| positionFunction # positionFunctionCall
489-
| caseFunction # caseExpr
490-
| extractFunction # extractFunctionCall
491-
| getFormatFunction # getFormatFunctionCall
492-
| timestampFunction # timestampFunctionCall
493-
| LT_PRTHS valueExpression RT_PRTHS # parentheticValueExpr
494-
| LT_SQR_PRTHS subSearch RT_SQR_PRTHS # scalarSubqueryExpr
495-
| lambda # lambdaExpr
496-
;
497-
498-
primaryExpression
466+
: left = valueExpression binaryOperator = (STAR | DIVIDE | MODULE) right = valueExpression # binaryArithmetic
467+
| left = valueExpression binaryOperator = (PLUS | MINUS) right = valueExpression # binaryArithmetic
468+
| literalValue # literalValueExpr
469+
| functionCall # functionCallExpr
470+
| lambda # lambdaExpr
471+
| LT_SQR_PRTHS subSearch RT_SQR_PRTHS # scalarSubqueryExpr
472+
| valueExpression NOT? IN LT_SQR_PRTHS subSearch RT_SQR_PRTHS # inSubqueryExpr
473+
| LT_PRTHS valueExpression (COMMA valueExpression)* RT_PRTHS NOT? IN LT_SQR_PRTHS subSearch RT_SQR_PRTHS # inSubqueryExpr
474+
| EXISTS LT_SQR_PRTHS subSearch RT_SQR_PRTHS # existsSubqueryExpr
475+
| fieldExpression # fieldExpr
476+
| LT_PRTHS logicalExpression RT_PRTHS # nestedValueExpr
477+
;
478+
479+
functionCall
499480
: evalFunctionCall
500481
| dataTypeFunctionCall
501-
| fieldExpression
502-
| literalValue
482+
| positionFunctionCall
483+
| caseFunctionCall
484+
| timestampFunctionCall
485+
| extractFunctionCall
486+
| getFormatFunctionCall
503487
;
504488

505-
positionFunction
489+
positionFunctionCall
506490
: positionFunctionName LT_PRTHS functionArg IN functionArg RT_PRTHS
507491
;
508492

509-
booleanExpression
510-
: booleanFunctionCall # booleanFunctionCallExpr
511-
| valueExpressionList NOT? IN LT_SQR_PRTHS subSearch RT_SQR_PRTHS # inSubqueryExpr
512-
| EXISTS LT_SQR_PRTHS subSearch RT_SQR_PRTHS # existsSubqueryExpr
513-
;
514-
515-
caseFunction
493+
caseFunctionCall
516494
: CASE LT_PRTHS logicalExpression COMMA valueExpression (COMMA logicalExpression COMMA valueExpression)* (ELSE valueExpression)? RT_PRTHS
517495
;
518496

@@ -577,12 +555,7 @@ evalFunctionCall
577555

578556
// cast function
579557
dataTypeFunctionCall
580-
: CAST LT_PRTHS expression AS convertedDataType RT_PRTHS
581-
;
582-
583-
// boolean functions
584-
booleanFunctionCall
585-
: conditionFunctionName LT_PRTHS functionArgs RT_PRTHS
558+
: CAST LT_PRTHS logicalExpression AS convertedDataType RT_PRTHS
586559
;
587560

588561
convertedDataType
@@ -625,12 +598,12 @@ functionArg
625598

626599
functionArgExpression
627600
: lambda
628-
| expression
601+
| logicalExpression
629602
;
630603

631604
lambda
632-
: ident ARROW expression
633-
| LT_PRTHS ident (COMMA ident)+ RT_PRTHS ARROW expression
605+
: ident ARROW logicalExpression
606+
| LT_PRTHS ident (COMMA ident)+ RT_PRTHS ARROW logicalExpression
634607
;
635608

636609
relevanceArg
@@ -841,7 +814,7 @@ dateTimeFunctionName
841814
| YEARWEEK
842815
;
843816

844-
getFormatFunction
817+
getFormatFunctionCall
845818
: GET_FORMAT LT_PRTHS getFormatType COMMA functionArg RT_PRTHS
846819
;
847820

@@ -852,7 +825,7 @@ getFormatType
852825
| TIMESTAMP
853826
;
854827

855-
extractFunction
828+
extractFunctionCall
856829
: EXTRACT LT_PRTHS datetimePart FROM functionArg RT_PRTHS
857830
;
858831

@@ -887,7 +860,7 @@ datetimePart
887860
| complexDateTimePart
888861
;
889862

890-
timestampFunction
863+
timestampFunctionCall
891864
: timestampFunctionName LT_PRTHS simpleDateTimePart COMMA firstArg = functionArg COMMA secondArg = functionArg RT_PRTHS
892865
;
893866

ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.FieldsCommandContext;
1616
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.HeadCommandContext;
1717
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.RenameCommandContext;
18-
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SearchFilterFromContext;
1918
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SearchFromContext;
20-
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SearchFromFilterContext;
2119
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SortCommandContext;
2220
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.StatsCommandContext;
2321
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.TableFunctionContext;
@@ -42,6 +40,7 @@
4240
import org.opensearch.sql.ast.dsl.AstDSL;
4341
import org.opensearch.sql.ast.expression.Alias;
4442
import org.opensearch.sql.ast.expression.AllFieldsExcludeMeta;
43+
import org.opensearch.sql.ast.expression.And;
4544
import org.opensearch.sql.ast.expression.EqualTo;
4645
import org.opensearch.sql.ast.expression.Field;
4746
import org.opensearch.sql.ast.expression.Let;
@@ -139,19 +138,16 @@ public UnresolvedPlan visitSubSearch(OpenSearchPPLParser.SubSearchContext ctx) {
139138
/** Search command. */
140139
@Override
141140
public UnresolvedPlan visitSearchFrom(SearchFromContext ctx) {
142-
return visitFromClause(ctx.fromClause());
143-
}
144-
145-
@Override
146-
public UnresolvedPlan visitSearchFromFilter(SearchFromFilterContext ctx) {
147-
return new Filter(internalVisitExpression(ctx.logicalExpression()))
148-
.attach(visit(ctx.fromClause()));
149-
}
150-
151-
@Override
152-
public UnresolvedPlan visitSearchFilterFrom(SearchFilterFromContext ctx) {
153-
return new Filter(internalVisitExpression(ctx.logicalExpression()))
154-
.attach(visit(ctx.fromClause()));
141+
if (ctx.logicalExpression().isEmpty()) {
142+
return visitFromClause(ctx.fromClause());
143+
} else {
144+
return new Filter(
145+
ctx.logicalExpression().stream()
146+
.map(this::internalVisitExpression)
147+
.reduce(And::new)
148+
.get())
149+
.attach(visit(ctx.fromClause()));
150+
}
155151
}
156152

157153
/**

0 commit comments

Comments
 (0)