Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void testWhereWithMultiLogicalExpr() throws IOException {
executeQuery(
String.format(
"source=%s "
+ "| where firstname='Amber' lastname='Duke' age=32 "
+ "| where firstname='Amber' and lastname='Duke' and age=32 "
+ "| fields firstname, lastname, age",
TEST_INDEX_ACCOUNT));
verifyDataRows(result, rows("Amber", "Duke", 32));
Expand Down
113 changes: 43 additions & 70 deletions ppl/src/main/antlr/OpenSearchPPLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ root

// statement
pplStatement
: dmlStatement
;

dmlStatement
: queryStatement
| explainStatement
: explainStatement
| queryStatement
;

queryStatement
Expand All @@ -43,9 +39,9 @@ subSearch

// commands
pplCommands
: searchCommand
| describeCommand
: describeCommand
| showDataSourcesCommand
| searchCommand
;

commands
Expand Down Expand Up @@ -106,9 +102,7 @@ commandName
;

searchCommand
: (SEARCH)? fromClause # searchFrom
| (SEARCH)? fromClause logicalExpression # searchFromFilter
| (SEARCH)? logicalExpression fromClause # searchFilterFrom
: (SEARCH)? (logicalExpression)* fromClause (logicalExpression)* # searchFrom
;

describeCommand
Expand Down Expand Up @@ -373,7 +367,7 @@ sortbyClause
;

evalClause
: fieldExpression EQUAL expression
: fieldExpression EQUAL logicalExpression
;

eventstatsAggTerm
Expand Down Expand Up @@ -447,68 +441,52 @@ numericLiteral
| floatLiteral
;

// expressions
expression
: logicalExpression
| comparisonExpression
| valueExpression
;

// predicates
logicalExpression
: LT_PRTHS logicalExpression RT_PRTHS # parentheticLogicalExpr
| NOT logicalExpression # logicalNot
| left = logicalExpression (AND)? right = logicalExpression # logicalAnd
: NOT logicalExpression # logicalNot
| left = logicalExpression AND right = logicalExpression # logicalAnd
Copy link
Member Author

@LantaoJin LantaoJin Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AND will be required in Where expression. But it is still optional in Search filter expression:

source=t a=1 b=c

source=t | where a=1 b=c

❌ (SPL cannot work either)

source=t | where a=1 and b=c

This limitation is because functionArgs could be ambiguous. For example:

source=t | eval f=position('substr' IN 'str')

can be parsed to an incorrect syntax tree:
Screenshot 2025-07-08 at 16 39 31

The correct syntax tree is

Screenshot 2025-07-08 at 16 41 02

| left = logicalExpression XOR right = logicalExpression # logicalXor
| left = logicalExpression OR right = logicalExpression # logicalOr
| comparisonExpression # comparsion
| booleanExpression # booleanExpr
| relevanceExpression # relevanceExpr
;

comparisonExpression
: left = valueExpression comparisonOperator right = valueExpression # compareExpr
| valueExpression NOT? IN valueList # inExpr
| valueExpression NOT? BETWEEN valueExpression AND valueExpression # between
| expression # logicalExpr
;

valueExpressionList
: valueExpression
| LT_PRTHS valueExpression (COMMA valueExpression)* RT_PRTHS
expression
: valueExpression # valueExpr
| relevanceExpression # relevanceExpr
| left = expression comparisonOperator right = expression # compareExpr
| expression NOT? IN valueList # inExpr
| expression NOT? BETWEEN expression AND expression # between
;

valueExpression
: left = valueExpression binaryOperator = (STAR | DIVIDE | MODULE) right = valueExpression # binaryArithmetic
| left = valueExpression binaryOperator = (PLUS | MINUS) right = valueExpression # binaryArithmetic
| primaryExpression # valueExpressionDefault
| positionFunction # positionFunctionCall
| caseFunction # caseExpr
| extractFunction # extractFunctionCall
| getFormatFunction # getFormatFunctionCall
| timestampFunction # timestampFunctionCall
| LT_PRTHS valueExpression RT_PRTHS # parentheticValueExpr
| LT_SQR_PRTHS subSearch RT_SQR_PRTHS # scalarSubqueryExpr
| lambda # lambdaExpr
;

primaryExpression
: left = valueExpression binaryOperator = (STAR | DIVIDE | MODULE) right = valueExpression # binaryArithmetic
| left = valueExpression binaryOperator = (PLUS | MINUS) right = valueExpression # binaryArithmetic
| literalValue # literalValueExpr
| functionCall # functionCallExpr
| lambda # lambdaExpr
| LT_SQR_PRTHS subSearch RT_SQR_PRTHS # scalarSubqueryExpr
| valueExpression NOT? IN LT_SQR_PRTHS subSearch RT_SQR_PRTHS # inSubqueryExpr
| LT_PRTHS valueExpression (COMMA valueExpression)* RT_PRTHS NOT? IN LT_SQR_PRTHS subSearch RT_SQR_PRTHS # inSubqueryExpr
| EXISTS LT_SQR_PRTHS subSearch RT_SQR_PRTHS # existsSubqueryExpr
| fieldExpression # fieldExpr
| LT_PRTHS logicalExpression RT_PRTHS # nestedValueExpr
;

functionCall
: evalFunctionCall
| dataTypeFunctionCall
| fieldExpression
| literalValue
| positionFunctionCall
| caseFunctionCall
| timestampFunctionCall
| extractFunctionCall
| getFormatFunctionCall
;

positionFunction
positionFunctionCall
: positionFunctionName LT_PRTHS functionArg IN functionArg RT_PRTHS
;

booleanExpression
: booleanFunctionCall # booleanFunctionCallExpr
| valueExpressionList NOT? IN LT_SQR_PRTHS subSearch RT_SQR_PRTHS # inSubqueryExpr
| EXISTS LT_SQR_PRTHS subSearch RT_SQR_PRTHS # existsSubqueryExpr
;

caseFunction
caseFunctionCall
: CASE LT_PRTHS logicalExpression COMMA valueExpression (COMMA logicalExpression COMMA valueExpression)* (ELSE valueExpression)? RT_PRTHS
;

Expand Down Expand Up @@ -573,12 +551,7 @@ evalFunctionCall

// cast function
dataTypeFunctionCall
: CAST LT_PRTHS expression AS convertedDataType RT_PRTHS
;

// boolean functions
booleanFunctionCall
: conditionFunctionName LT_PRTHS functionArgs RT_PRTHS
: CAST LT_PRTHS logicalExpression AS convertedDataType RT_PRTHS
;

convertedDataType
Expand Down Expand Up @@ -621,12 +594,12 @@ functionArg

functionArgExpression
: lambda
| expression
| logicalExpression
;

lambda
: ident ARROW expression
| LT_PRTHS ident (COMMA ident)+ RT_PRTHS ARROW expression
: ident ARROW logicalExpression
| LT_PRTHS ident (COMMA ident)+ RT_PRTHS ARROW logicalExpression
;

relevanceArg
Expand Down Expand Up @@ -837,7 +810,7 @@ dateTimeFunctionName
| YEARWEEK
;

getFormatFunction
getFormatFunctionCall
: GET_FORMAT LT_PRTHS getFormatType COMMA functionArg RT_PRTHS
;

Expand All @@ -848,7 +821,7 @@ getFormatType
| TIMESTAMP
;

extractFunction
extractFunctionCall
: EXTRACT LT_PRTHS datetimePart FROM functionArg RT_PRTHS
;

Expand Down Expand Up @@ -883,7 +856,7 @@ datetimePart
| complexDateTimePart
;

timestampFunction
timestampFunctionCall
: timestampFunctionName LT_PRTHS simpleDateTimePart COMMA firstArg = functionArg COMMA secondArg = functionArg RT_PRTHS
;

Expand Down
26 changes: 11 additions & 15 deletions ppl/src/main/java/org/opensearch/sql/ppl/parser/AstBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.FieldsCommandContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.HeadCommandContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.RenameCommandContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SearchFilterFromContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SearchFromContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SearchFromFilterContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.SortCommandContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.StatsCommandContext;
import static org.opensearch.sql.ppl.antlr.parser.OpenSearchPPLParser.TableFunctionContext;
Expand All @@ -42,6 +40,7 @@
import org.opensearch.sql.ast.dsl.AstDSL;
import org.opensearch.sql.ast.expression.Alias;
import org.opensearch.sql.ast.expression.AllFieldsExcludeMeta;
import org.opensearch.sql.ast.expression.And;
import org.opensearch.sql.ast.expression.EqualTo;
import org.opensearch.sql.ast.expression.Field;
import org.opensearch.sql.ast.expression.Let;
Expand Down Expand Up @@ -139,19 +138,16 @@ public UnresolvedPlan visitSubSearch(OpenSearchPPLParser.SubSearchContext ctx) {
/** Search command. */
@Override
public UnresolvedPlan visitSearchFrom(SearchFromContext ctx) {
return visitFromClause(ctx.fromClause());
}

@Override
public UnresolvedPlan visitSearchFromFilter(SearchFromFilterContext ctx) {
return new Filter(internalVisitExpression(ctx.logicalExpression()))
.attach(visit(ctx.fromClause()));
}

@Override
public UnresolvedPlan visitSearchFilterFrom(SearchFilterFromContext ctx) {
return new Filter(internalVisitExpression(ctx.logicalExpression()))
.attach(visit(ctx.fromClause()));
if (ctx.logicalExpression().isEmpty()) {
return visitFromClause(ctx.fromClause());
} else {
return new Filter(
ctx.logicalExpression().stream()
.map(this::internalVisitExpression)
.reduce(And::new)
.get())
.attach(visit(ctx.fromClause()));
}
}

/**
Expand Down
Loading
Loading