Skip to content

Commit 9c80c9f

Browse files
authored
Merge branch 'main' into feature/headtop-limit
Signed-off-by: Simeon Widdis <[email protected]>
2 parents 098b45c + 0af7429 commit 9c80c9f

File tree

199 files changed

+9662
-1392
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

199 files changed

+9662
-1392
lines changed

common/src/main/java/org/opensearch/sql/common/setting/Settings.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public enum Key {
3030
PATTERN_MAX_SAMPLE_COUNT("plugins.ppl.pattern.max.sample.count"),
3131
PATTERN_BUFFER_LIMIT("plugins.ppl.pattern.buffer.limit"),
3232
PPL_REX_MAX_MATCH_LIMIT("plugins.ppl.rex.max_match.limit"),
33+
PPL_SYNTAX_LEGACY_PREFERRED("plugins.ppl.syntax.legacy.preferred"),
3334

3435
/** Enable Calcite as execution engine */
3536
CALCITE_ENGINE_ENABLED("plugins.calcite.enabled"),

core/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ dependencies {
5454
api "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
5555
api "com.fasterxml.jackson.core:jackson-databind:${versions.jackson_databind}"
5656
api "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}"
57+
api "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${versions.jackson}"
5758
api group: 'com.google.code.gson', name: 'gson', version: '2.8.9'
5859
api group: 'com.tdunning', name: 't-digest', version: '3.3'
5960
api "net.minidev:json-smart:${versions.json_smart}"

core/src/main/java/org/opensearch/sql/analysis/Analyzer.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import org.opensearch.sql.ast.tree.Rename;
8787
import org.opensearch.sql.ast.tree.Reverse;
8888
import org.opensearch.sql.ast.tree.Rex;
89+
import org.opensearch.sql.ast.tree.Search;
8990
import org.opensearch.sql.ast.tree.Sort;
9091
import org.opensearch.sql.ast.tree.Sort.SortOption;
9192
import org.opensearch.sql.ast.tree.SubqueryAlias;
@@ -278,6 +279,18 @@ public LogicalPlan visitLimit(Limit node, AnalysisContext context) {
278279
return new LogicalLimit(child, node.getLimit(), node.getOffset());
279280
}
280281

282+
@Override
283+
public LogicalPlan visitSearch(Search node, AnalysisContext context) {
284+
LogicalPlan child = node.getChild().get(0).accept(this, context);
285+
Function queryStringFunc =
286+
AstDSL.function(
287+
"query_string",
288+
AstDSL.unresolvedArg("query", AstDSL.stringLiteral(node.getQueryString())));
289+
290+
Expression analyzed = expressionAnalyzer.analyze(queryStringFunc, context);
291+
return new LogicalFilter(child, analyzed);
292+
}
293+
281294
@Override
282295
public LogicalPlan visitFilter(Filter node, AnalysisContext context) {
283296
LogicalPlan child = node.getChild().get(0).accept(this, context);
@@ -880,7 +893,11 @@ private LogicalAggregation analyzeAggregation(
880893
groupBys.forEach(
881894
group ->
882895
newEnv.define(new Symbol(Namespace.FIELD_NAME, group.getNameOrAlias()), group.type()));
883-
return new LogicalAggregation(child, aggregators, groupBys);
896+
897+
Argument.ArgumentMap statsArgs = Argument.ArgumentMap.of(node.getArgExprList());
898+
boolean bucketNullable =
899+
(Boolean) statsArgs.getOrDefault(Argument.BUCKET_NULLABLE, Literal.TRUE).getValue();
900+
return new LogicalAggregation(child, aggregators, groupBys, bucketNullable);
884901
}
885902

886903
private Aggregation analyzePatternsAgg(Patterns node) {

core/src/main/java/org/opensearch/sql/analysis/ExpressionAnalyzer.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Collections;
1818
import java.util.List;
1919
import java.util.Optional;
20+
import java.util.Set;
2021
import java.util.stream.Collectors;
2122
import lombok.Getter;
2223
import org.opensearch.sql.analysis.symbol.Namespace;
@@ -53,6 +54,7 @@
5354
import org.opensearch.sql.ast.expression.subquery.ExistsSubquery;
5455
import org.opensearch.sql.ast.expression.subquery.InSubquery;
5556
import org.opensearch.sql.ast.expression.subquery.ScalarSubquery;
57+
import org.opensearch.sql.calcite.utils.CalciteUtils;
5658
import org.opensearch.sql.data.model.ExprValueUtils;
5759
import org.opensearch.sql.data.type.ExprCoreType;
5860
import org.opensearch.sql.data.type.ExprType;
@@ -191,6 +193,7 @@ public Expression visitRelevanceFieldList(RelevanceFieldList node, AnalysisConte
191193
@Override
192194
public Expression visitFunction(Function node, AnalysisContext context) {
193195
FunctionName functionName = FunctionName.of(node.getFuncName());
196+
validateCalciteOnlyFunction(functionName);
194197
List<Expression> arguments =
195198
node.getFuncArgs().stream()
196199
.map(
@@ -208,6 +211,34 @@ public Expression visitFunction(Function node, AnalysisContext context) {
208211
repository.compile(context.getFunctionProperties(), functionName, arguments);
209212
}
210213

214+
/**
215+
* Validates that functions requiring Calcite engine are not used without it.
216+
*
217+
* @param functionName The function name to validate
218+
*/
219+
private void validateCalciteOnlyFunction(FunctionName functionName) {
220+
if (isCalciteOnlyFunction(functionName)) {
221+
throw CalciteUtils.getOnlyForCalciteException(functionName.getFunctionName().toUpperCase());
222+
}
223+
}
224+
225+
/**
226+
* Checks if a function requires Calcite engine to be enabled.
227+
*
228+
* @param functionName The function name to check
229+
* @return true if the function requires Calcite, false otherwise
230+
*/
231+
private boolean isCalciteOnlyFunction(FunctionName functionName) {
232+
// Set of functions that are only supported with Calcite engine
233+
Set<String> calciteOnlyFunctions =
234+
ImmutableSet.of(
235+
BuiltinFunctionName.REGEX_MATCH.getName().getFunctionName(),
236+
BuiltinFunctionName.STRFTIME.getName().getFunctionName());
237+
238+
return calciteOnlyFunctions.stream()
239+
.anyMatch(f -> f.equalsIgnoreCase(functionName.getFunctionName()));
240+
}
241+
211242
@SuppressWarnings("unchecked")
212243
@Override
213244
public Expression visitWindowFunction(WindowFunction node, AnalysisContext context) {

core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import org.opensearch.sql.ast.tree.Reverse;
7676
import org.opensearch.sql.ast.tree.Rex;
7777
import org.opensearch.sql.ast.tree.SPath;
78+
import org.opensearch.sql.ast.tree.Search;
7879
import org.opensearch.sql.ast.tree.Sort;
7980
import org.opensearch.sql.ast.tree.SubqueryAlias;
8081
import org.opensearch.sql.ast.tree.TableFunction;
@@ -131,6 +132,10 @@ public T visitTableFunction(TableFunction node, C context) {
131132
return visitChildren(node, context);
132133
}
133134

135+
public T visitSearch(Search node, C context) {
136+
return visitChildren(node, context);
137+
}
138+
134139
public T visitFilter(Filter node, C context) {
135140
return visitChildren(node, context);
136141
}

core/src/main/java/org/opensearch/sql/ast/dsl/AstDSL.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.opensearch.sql.ast.tree.RelationSubquery;
7272
import org.opensearch.sql.ast.tree.Rename;
7373
import org.opensearch.sql.ast.tree.SPath;
74+
import org.opensearch.sql.ast.tree.Search;
7475
import org.opensearch.sql.ast.tree.Sort;
7576
import org.opensearch.sql.ast.tree.Sort.SortOption;
7677
import org.opensearch.sql.ast.tree.SpanBin;
@@ -109,6 +110,10 @@ public UnresolvedPlan describe(String tableName) {
109110
return new DescribeRelation(qualifiedName(tableName));
110111
}
111112

113+
public static UnresolvedPlan search(UnresolvedPlan input, String queryString) {
114+
return new Search(input, queryString);
115+
}
116+
112117
public UnresolvedPlan subqueryAlias(UnresolvedPlan child, String alias) {
113118
return new SubqueryAlias(child, alias);
114119
}
@@ -449,6 +454,7 @@ public static List<Argument> defaultStatsArgs() {
449454
argument("partitions", intLiteral(1)),
450455
argument("allnum", booleanLiteral(false)),
451456
argument("delim", stringLiteral(" ")),
457+
argument(Argument.BUCKET_NULLABLE, booleanLiteral(true)),
452458
argument("dedupsplit", booleanLiteral(false)));
453459
}
454460

core/src/main/java/org/opensearch/sql/ast/expression/Argument.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
@RequiredArgsConstructor
2121
@EqualsAndHashCode(callSuper = false)
2222
public class Argument extends UnresolvedExpression {
23+
public static final String BUCKET_NULLABLE = "bucket_nullable";
24+
2325
private final String argName;
2426
private final Literal value;
2527

@@ -66,5 +68,9 @@ public static ArgumentMap empty() {
6668
public Literal get(String name) {
6769
return map.get(name);
6870
}
71+
72+
public Literal getOrDefault(String name, Literal literal) {
73+
return map.getOrDefault(name, literal);
74+
}
6975
}
7076
}

core/src/main/java/org/opensearch/sql/ast/expression/Literal.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ public String toString() {
4949

5050
public static Literal TRUE = new Literal(true, DataType.BOOLEAN);
5151
public static Literal FALSE = new Literal(false, DataType.BOOLEAN);
52-
public static Literal ZERO = new Literal(Integer.valueOf("0"), DataType.INTEGER);
52+
public static Literal ZERO = new Literal(0, DataType.INTEGER);
53+
public static Literal ONE = new Literal(1, DataType.INTEGER);
5354
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.ast.expression;
7+
8+
import java.util.Arrays;
9+
import java.util.List;
10+
import lombok.EqualsAndHashCode;
11+
import lombok.Getter;
12+
import lombok.RequiredArgsConstructor;
13+
import lombok.ToString;
14+
15+
/** Search expression for AND operator. */
16+
@Getter
17+
@RequiredArgsConstructor
18+
@EqualsAndHashCode(callSuper = false)
19+
@ToString
20+
public class SearchAnd extends SearchExpression {
21+
22+
private final SearchExpression left;
23+
private final SearchExpression right;
24+
25+
@Override
26+
public String toQueryString() {
27+
return left.toQueryString() + " AND " + right.toQueryString();
28+
}
29+
30+
@Override
31+
public List<? extends UnresolvedExpression> getChild() {
32+
return Arrays.asList(left, right);
33+
}
34+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.ast.expression;
7+
8+
import java.util.Arrays;
9+
import java.util.List;
10+
import lombok.EqualsAndHashCode;
11+
import lombok.Getter;
12+
import lombok.RequiredArgsConstructor;
13+
import lombok.ToString;
14+
import org.opensearch.sql.utils.QueryStringUtils;
15+
16+
/** Search expression for field comparisons. */
17+
@Getter
18+
@RequiredArgsConstructor
19+
@EqualsAndHashCode(callSuper = false)
20+
@ToString
21+
public class SearchComparison extends SearchExpression {
22+
23+
public enum Operator {
24+
EQUALS("="),
25+
NOT_EQUALS("!="),
26+
LESS_THAN("<"),
27+
LESS_OR_EQUAL("<="),
28+
GREATER_THAN(">"),
29+
GREATER_OR_EQUAL(">=");
30+
31+
private final String symbol;
32+
33+
Operator(String symbol) {
34+
this.symbol = symbol;
35+
}
36+
37+
public String getSymbol() {
38+
return symbol;
39+
}
40+
}
41+
42+
private final Field field;
43+
private final Operator operator;
44+
private final SearchLiteral value;
45+
46+
@Override
47+
public String toQueryString() {
48+
String fieldName = QueryStringUtils.escapeFieldName(field.getField().toString());
49+
String valueStr = value.toQueryString();
50+
switch (operator) {
51+
case NOT_EQUALS:
52+
return "( _exists_:" + fieldName + " AND NOT " + fieldName + ":" + valueStr + " )";
53+
case GREATER_THAN:
54+
return fieldName + ":>" + valueStr;
55+
case GREATER_OR_EQUAL:
56+
return fieldName + ":>=" + valueStr;
57+
case LESS_THAN:
58+
return fieldName + ":<" + valueStr;
59+
case LESS_OR_EQUAL:
60+
return fieldName + ":<=" + valueStr;
61+
default:
62+
return fieldName + ":" + valueStr;
63+
}
64+
}
65+
66+
@Override
67+
public List<? extends UnresolvedExpression> getChild() {
68+
return Arrays.asList(field, value);
69+
}
70+
}

0 commit comments

Comments
 (0)