Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
59f45c1
Migrate peng's branch
joshuali925 Dec 13, 2021
0320ac7
Fix checkstyle errors
joshuali925 Dec 14, 2021
f322301
Remove putevent
joshuali925 Dec 16, 2021
fc50120
Revert unnecessary changes
joshuali925 Dec 29, 2021
a80ee02
Define regex fields as string
joshuali925 Jan 3, 2022
4d90cae
WIP debug
joshuali925 Jan 3, 2022
fb05061
Add explicit type cast for integers and strings
joshuali925 Jan 4, 2022
44ede64
Fix checkstyle errors
joshuali925 Jan 5, 2022
0e2d030
Revert to jdbc response format
joshuali925 Jan 7, 2022
fd2107f
Refactor and fix results being null
joshuali925 Jan 7, 2022
18144ac
Rename regex command to parse
joshuali925 Jan 7, 2022
d96f4d2
Remove unused
joshuali925 Jan 10, 2022
c3ee246
Fix checkstyle
joshuali925 Jan 10, 2022
6aa701a
Add error message to type casting
joshuali925 Jan 10, 2022
44500f5
Add logical parse unit tests
joshuali925 Jan 10, 2022
166e61e
WIP parse operator tests
joshuali925 Jan 11, 2022
78c2b9d
WIP regex function implementation
joshuali925 Jan 12, 2022
73e38be
WIP add grok lib
joshuali925 Jan 13, 2022
b218fbe
Revert "WIP add grok lib"
joshuali925 Jan 27, 2022
4635716
Revert "WIP regex function implementation"
joshuali925 Jan 27, 2022
7f0aa7c
Add more tests
joshuali925 Jan 27, 2022
a52d765
Add parse docs
joshuali925 Feb 3, 2022
9f74f23
Add license headers
joshuali925 Feb 3, 2022
76960f0
Revert "Revert "WIP regex function implementation""
joshuali925 Feb 4, 2022
ce399f1
Revert "Revert "WIP add grok lib""
joshuali925 Feb 4, 2022
e9fd34b
Analyze parse command as expression
joshuali925 Feb 9, 2022
68fd302
Combine ParseOperator with ProjectOperator
joshuali925 Feb 15, 2022
dc91d09
Support aggregations with parse
joshuali925 Feb 15, 2022
00ef294
Add parse utils class
joshuali925 Feb 15, 2022
e5ad7b7
Add cast function for PPL
joshuali925 Feb 16, 2022
e04b813
WIP remove unused files
joshuali925 Feb 16, 2022
d3acbd3
Revert "Revert "Revert "WIP add grok lib"""
joshuali925 Feb 16, 2022
cc82bb2
Revert "Revert "Revert "WIP regex function implementation"""
joshuali925 Feb 16, 2022
87ad208
Revert unnecessary changes, fix bugs
joshuali925 Feb 16, 2022
6407920
Merge branch 'main' into ppl-cast-regex
joshuali925 Feb 16, 2022
7894ea2
Fix bugs and refactor
joshuali925 Feb 17, 2022
80d6369
Add java docs
joshuali925 Feb 21, 2022
7a79d18
Add parse utils tests
joshuali925 Feb 21, 2022
d0c4f1d
WIP add parse expression tests
joshuali925 Feb 21, 2022
10e30fe
Add parse expression and project operator tests
joshuali925 Feb 23, 2022
906b372
Fix parse in named expression when using fields command
joshuali925 Feb 23, 2022
b74ebfd
Update parse command docs
joshuali925 Feb 23, 2022
0670799
Add agg builder tests
joshuali925 Feb 23, 2022
1c77c5f
Update docs format
joshuali925 Feb 23, 2022
c06d6c3
Update docs with examples
joshuali925 Feb 25, 2022
13f155c
Address comments
joshuali925 Mar 2, 2022
98beb66
Use valueOf in ProjectOperator
joshuali925 Mar 2, 2022
42d237b
Change parse expression map to list of named expressions
joshuali925 Mar 2, 2022
27e9ec3
Return parsed instead of named when visiting identifiers
joshuali925 Mar 2, 2022
7033552
Rename parsedList to namedParseExpressions
joshuali925 Mar 2, 2022
89494f3
Update unit tests
joshuali925 Mar 2, 2022
f9cbbe5
Rename variables for consistency
joshuali925 Mar 3, 2022
578c6b2
Enable and update parse doctest
joshuali925 Mar 3, 2022
2d12b8d
Link to TODO issue for better implementation of parse command
joshuali925 Mar 3, 2022
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 @@ -6,7 +6,11 @@

package org.opensearch.sql.analysis;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import lombok.Getter;
import org.opensearch.sql.expression.NamedExpression;

/**
* The context used for Analyzer.
Expand All @@ -16,13 +20,16 @@ public class AnalysisContext {
* Environment stack for symbol scope management.
*/
private TypeEnvironment environment;
@Getter
private final List<NamedExpression> namedParseExpressions;

public AnalysisContext() {
this.environment = new TypeEnvironment(null);
this(new TypeEnvironment(null));
}

public AnalysisContext(TypeEnvironment environment) {
this.environment = environment;
this.namedParseExpressions = new ArrayList<>();
}

/**
Expand Down
26 changes: 25 additions & 1 deletion core/src/main/java/org/opensearch/sql/analysis/Analyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.opensearch.sql.ast.tree.Filter;
import org.opensearch.sql.ast.tree.Head;
import org.opensearch.sql.ast.tree.Limit;
import org.opensearch.sql.ast.tree.Parse;
import org.opensearch.sql.ast.tree.Project;
import org.opensearch.sql.ast.tree.RareTopN;
import org.opensearch.sql.ast.tree.Relation;
Expand All @@ -47,11 +48,13 @@
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.ast.tree.Values;
import org.opensearch.sql.data.model.ExprMissingValue;
import org.opensearch.sql.data.type.ExprCoreType;
import org.opensearch.sql.exception.SemanticCheckException;
import org.opensearch.sql.expression.DSL;
import org.opensearch.sql.expression.Expression;
import org.opensearch.sql.expression.LiteralExpression;
import org.opensearch.sql.expression.NamedExpression;
import org.opensearch.sql.expression.ParseExpression;
import org.opensearch.sql.expression.ReferenceExpression;
import org.opensearch.sql.expression.aggregation.Aggregator;
import org.opensearch.sql.expression.aggregation.NamedAggregator;
Expand All @@ -70,6 +73,7 @@
import org.opensearch.sql.planner.logical.LogicalValues;
import org.opensearch.sql.storage.StorageEngine;
import org.opensearch.sql.storage.Table;
import org.opensearch.sql.utils.ParseUtils;

/**
* Analyze the {@link UnresolvedPlan} in the {@link AnalysisContext} to construct the {@link
Expand Down Expand Up @@ -286,7 +290,8 @@ public LogicalPlan visitProject(Project node, AnalysisContext context) {
TypeEnvironment newEnv = context.peek();
namedExpressions.forEach(expr -> newEnv.define(new Symbol(Namespace.FIELD_NAME,
expr.getNameOrAlias()), expr.type()));
return new LogicalProject(child, namedExpressions);
List<NamedExpression> namedParseExpressions = context.getNamedParseExpressions();
return new LogicalProject(child, namedExpressions, namedParseExpressions);
}

/**
Expand All @@ -308,6 +313,25 @@ public LogicalPlan visitEval(Eval node, AnalysisContext context) {
return new LogicalEval(child, expressionsBuilder.build());
}

/**
* Build {@link ParseExpression} to context and skip to child nodes.
*/
@Override
public LogicalPlan visitParse(Parse node, AnalysisContext context) {
LogicalPlan child = node.getChild().get(0).accept(this, context);
Expression expression = expressionAnalyzer.analyze(node.getExpression(), context);
String pattern = (String) node.getPattern().getValue();
Expression patternExpression = DSL.literal(pattern);

TypeEnvironment curEnv = context.peek();
ParseUtils.getNamedGroupCandidates(pattern).forEach(group -> {
curEnv.define(new Symbol(Namespace.FIELD_NAME, group), ExprCoreType.STRING);
context.getNamedParseExpressions().add(new NamedExpression(group,
new ParseExpression(expression, patternExpression, DSL.literal(group))));
});
return child;
}

/**
* Build {@link LogicalSort}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.opensearch.sql.expression.Expression;
import org.opensearch.sql.expression.NamedArgumentExpression;
import org.opensearch.sql.expression.NamedExpression;
import org.opensearch.sql.expression.ParseExpression;
import org.opensearch.sql.expression.ReferenceExpression;
import org.opensearch.sql.expression.aggregation.AggregationState;
import org.opensearch.sql.expression.aggregation.Aggregator;
Expand Down Expand Up @@ -276,6 +277,13 @@ public Expression visitUnresolvedArgument(UnresolvedArgument node, AnalysisConte
}

private Expression visitIdentifier(String ident, AnalysisContext context) {
// ParseExpression will always override ReferenceExpression when ident conflicts
for (NamedExpression expr : context.getNamedParseExpressions()) {
if (expr.getNameOrAlias().equals(ident) && expr.getDelegated() instanceof ParseExpression) {
return expr.getDelegated();
}
}

TypeEnvironment typeEnv = context.peek();
ReferenceExpression ref = DSL.ref(ident,
typeEnv.resolve(new Symbol(Namespace.FIELD_NAME, ident)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.opensearch.sql.ast.tree.Filter;
import org.opensearch.sql.ast.tree.Head;
import org.opensearch.sql.ast.tree.Limit;
import org.opensearch.sql.ast.tree.Parse;
import org.opensearch.sql.ast.tree.Project;
import org.opensearch.sql.ast.tree.RareTopN;
import org.opensearch.sql.ast.tree.Relation;
Expand Down Expand Up @@ -175,6 +176,10 @@ public T visitEval(Eval node, C context) {
return visitChildren(node, context);
}

public T visitParse(Parse node, C context) {
return visitChildren(node, context);
}

public T visitLet(Let node, C context) {
return visitChildren(node, context);
}
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/org/opensearch/sql/ast/dsl/AstDSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.opensearch.sql.ast.tree.Filter;
import org.opensearch.sql.ast.tree.Head;
import org.opensearch.sql.ast.tree.Limit;
import org.opensearch.sql.ast.tree.Parse;
import org.opensearch.sql.ast.tree.Project;
import org.opensearch.sql.ast.tree.RareTopN;
import org.opensearch.sql.ast.tree.RareTopN.CommandType;
Expand Down Expand Up @@ -407,4 +408,9 @@ public static RareTopN rareTopN(UnresolvedPlan input, CommandType commandType,
public static Limit limit(UnresolvedPlan input, Integer limit, Integer offset) {
return new Limit(limit, offset).attach(input);
}

public static Parse parse(UnresolvedPlan input, UnresolvedExpression expression,
Literal pattern) {
return new Parse(expression, pattern, input);
}
}
61 changes: 61 additions & 0 deletions core/src/main/java/org/opensearch/sql/ast/tree/Parse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/


package org.opensearch.sql.ast.tree;

import com.google.common.collect.ImmutableList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.opensearch.sql.ast.AbstractNodeVisitor;
import org.opensearch.sql.ast.expression.Literal;
import org.opensearch.sql.ast.expression.UnresolvedExpression;

/**
* AST node represent Parse operation.
*/
@Getter
@Setter
@ToString
@EqualsAndHashCode(callSuper = false)
@RequiredArgsConstructor
@AllArgsConstructor
public class Parse extends UnresolvedPlan {
/**
* Field.
*/
private final UnresolvedExpression expression;

/**
* Pattern.
*/
private final Literal pattern;

/**
* Child Plan.
*/
private UnresolvedPlan child;

@Override
public Parse attach(UnresolvedPlan child) {
this.child = child;
return this;
}

@Override
public List<UnresolvedPlan> getChild() {
return ImmutableList.of(this.child);
}

@Override
public <T, C> T accept(AbstractNodeVisitor<T, C> nodeVisitor, C context) {
return nodeVisitor.visitParse(this, context);
}
}
13 changes: 11 additions & 2 deletions core/src/main/java/org/opensearch/sql/expression/DSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public static NamedExpression named(Expression expression) {
if (expression instanceof NamedExpression) {
return (NamedExpression) expression;
}
if (expression instanceof ParseExpression) {
return named(((ParseExpression) expression).getIdentifier().valueOf(null).stringValue(),
expression);
}
return named(expression.toString(), expression);
}

Expand All @@ -115,6 +119,11 @@ public NamedArgumentExpression namedArgument(String argName, Expression value) {
return new NamedArgumentExpression(argName, value);
}

public static ParseExpression parsed(Expression expression, Expression pattern,
Expression identifier) {
return new ParseExpression(expression, pattern, identifier);
}

public static SpanExpression span(Expression field, Expression value, String unit) {
return new SpanExpression(field, value, SpanUnit.of(unit));
}
Expand Down Expand Up @@ -254,7 +263,7 @@ public FunctionExpression subtract(Expression... expressions) {
public FunctionExpression multiply(Expression... expressions) {
return function(BuiltinFunctionName.MULTIPLY, expressions);
}

public FunctionExpression adddate(Expression... expressions) {
return function(BuiltinFunctionName.ADDDATE, expressions);
}
Expand Down Expand Up @@ -366,7 +375,7 @@ public FunctionExpression module(Expression... expressions) {
public FunctionExpression substr(Expression... expressions) {
return function(BuiltinFunctionName.SUBSTR, expressions);
}

public FunctionExpression substring(Expression... expressions) {
return function(BuiltinFunctionName.SUBSTR, expressions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ public T visitReference(ReferenceExpression node, C context) {
return visitNode(node, context);
}

public T visitParse(ParseExpression node, C context) {
return visitNode(node, context);
}

public T visitFunction(FunctionExpression node, C context) {
return visitChildren(node, context);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.expression;

import com.google.common.collect.ImmutableList;
import java.util.regex.Pattern;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.data.type.ExprCoreType;
import org.opensearch.sql.data.type.ExprType;
import org.opensearch.sql.exception.ExpressionEvaluationException;
import org.opensearch.sql.exception.SemanticCheckException;
import org.opensearch.sql.expression.env.Environment;
import org.opensearch.sql.expression.function.FunctionName;
import org.opensearch.sql.utils.ParseUtils;

/**
* ParseExpression with regex and named capture group.
*/
@EqualsAndHashCode
@ToString
public class ParseExpression extends FunctionExpression {
@Getter
private final Expression expression;
private final Expression rawPattern;
@Getter
private final Expression identifier;
@Getter
@EqualsAndHashCode.Exclude
private final Pattern pattern;

/**
* ParseExpression.
*
* @param expression text field
* @param rawPattern regex
* @param identifier named capture group to extract
*/
public ParseExpression(Expression expression, Expression rawPattern, Expression identifier) {
super(FunctionName.of("parse"), ImmutableList.of(expression, rawPattern, identifier));
this.expression = expression;
this.rawPattern = rawPattern;
this.identifier = identifier;
this.pattern = Pattern.compile(rawPattern.valueOf(null).stringValue());
}

@Override
public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) {
ExprValue value = valueEnv.resolve(expression);
try {
return ParseUtils.parseValue(value, pattern, identifier.valueOf(null).stringValue());
} catch (ExpressionEvaluationException e) {
throw new SemanticCheckException(
String.format("failed to parse field \"%s\" with type [%s]", expression, value.type()));
}
}

@Override
public ExprType type() {
return ExprCoreType.STRING;
}

@Override
public <T, C> T accept(ExpressionNodeVisitor<T, C> visitor, C context) {
return visitor.visitParse(this, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public PhysicalPlan visitDedupe(LogicalDedupe node, C context) {

@Override
public PhysicalPlan visitProject(LogicalProject node, C context) {
return new ProjectOperator(visitChild(node, context), node.getProjectList());
return new ProjectOperator(visitChild(node, context), node.getProjectList(),
node.getNamedParseExpressions());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

package org.opensearch.sql.planner.logical;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.util.Arrays;
import java.util.List;
Expand All @@ -17,6 +18,7 @@
import org.opensearch.sql.expression.Expression;
import org.opensearch.sql.expression.LiteralExpression;
import org.opensearch.sql.expression.NamedExpression;
import org.opensearch.sql.expression.ParseExpression;
import org.opensearch.sql.expression.ReferenceExpression;
import org.opensearch.sql.expression.aggregation.NamedAggregator;
import org.opensearch.sql.expression.window.WindowDefinition;
Expand Down Expand Up @@ -46,7 +48,12 @@ public static LogicalPlan rename(
}

public static LogicalPlan project(LogicalPlan input, NamedExpression... fields) {
return new LogicalProject(input, Arrays.asList(fields));
return new LogicalProject(input, Arrays.asList(fields), ImmutableList.of());
}

public static LogicalPlan project(LogicalPlan input, List<NamedExpression> fields,
List<NamedExpression> namedParseExpressions) {
return new LogicalProject(input, fields, namedParseExpressions);
}

public LogicalPlan window(LogicalPlan input,
Expand Down Expand Up @@ -81,14 +88,14 @@ public static LogicalPlan dedupe(
return new LogicalDedupe(
input, Arrays.asList(fields), allowedDuplication, keepEmpty, consecutive);
}

public static LogicalPlan rareTopN(LogicalPlan input, CommandType commandType,
List<Expression> groupByList, Expression... fields) {
List<Expression> groupByList, Expression... fields) {
return rareTopN(input, commandType, 10, groupByList, fields);
}

public static LogicalPlan rareTopN(LogicalPlan input, CommandType commandType, int noOfResults,
List<Expression> groupByList, Expression... fields) {
List<Expression> groupByList, Expression... fields) {
return new LogicalRareTopN(input, commandType, noOfResults, Arrays.asList(fields), groupByList);
}

Expand Down
Loading