forked from opensearch-project/sql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pulled out analyzers to opensearch module
Signed-off-by: Guian Gumpac <guian.gumpac@improving.com>
- Loading branch information
Showing
9 changed files
with
219 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
opensearch/src/main/java/org/opensearch/sql/opensearch/analysis/OpenSearchAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package org.opensearch.sql.opensearch.analysis; | ||
|
||
import org.opensearch.sql.analysis.Analyzer; | ||
import org.opensearch.sql.analysis.ExpressionAnalyzer; | ||
import org.opensearch.sql.analysis.NamedExpressionAnalyzer; | ||
import org.opensearch.sql.datasource.DataSourceService; | ||
import org.opensearch.sql.expression.function.BuiltinFunctionRepository; | ||
|
||
public class OpenSearchAnalyzer extends Analyzer { | ||
/** | ||
* Constructor. | ||
* | ||
* @param dataSourceService | ||
* @param repository | ||
*/ | ||
public OpenSearchAnalyzer(DataSourceService dataSourceService, | ||
BuiltinFunctionRepository repository) { | ||
super( | ||
new OpenSearchExpressionAnalyzer(repository), | ||
new OpenSearchSelectExpressionAnalyzer(new OpenSearchExpressionAnalyzer(repository)), | ||
new NamedExpressionAnalyzer(new OpenSearchExpressionAnalyzer(repository)), | ||
dataSourceService, | ||
repository); | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
...ch/src/main/java/org/opensearch/sql/opensearch/analysis/OpenSearchExpressionAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package org.opensearch.sql.opensearch.analysis; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import org.opensearch.sql.analysis.AnalysisContext; | ||
import org.opensearch.sql.analysis.ExpressionAnalyzer; | ||
import org.opensearch.sql.ast.expression.DataType; | ||
import org.opensearch.sql.ast.expression.Function; | ||
import org.opensearch.sql.ast.expression.Literal; | ||
import org.opensearch.sql.ast.expression.RelevanceFieldList; | ||
import org.opensearch.sql.ast.expression.ScoreFunction; | ||
import org.opensearch.sql.ast.expression.UnresolvedArgument; | ||
import org.opensearch.sql.ast.expression.UnresolvedExpression; | ||
import org.opensearch.sql.data.model.ExprValueUtils; | ||
import org.opensearch.sql.exception.SemanticCheckException; | ||
import org.opensearch.sql.expression.Expression; | ||
import org.opensearch.sql.expression.LiteralExpression; | ||
import org.opensearch.sql.expression.function.BuiltinFunctionRepository; | ||
import org.opensearch.sql.expression.function.OpenSearchFunctions; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class OpenSearchExpressionAnalyzer extends ExpressionAnalyzer { | ||
public OpenSearchExpressionAnalyzer(BuiltinFunctionRepository repository) { | ||
super(repository); | ||
} | ||
|
||
/** | ||
* visitScoreFunction removes the score function from the AST and replaces it with the child | ||
* relevance function node. If the optional boost variable is provided, the boost argument of the | ||
* relevance function is combined. | ||
* | ||
* @param node score function node | ||
* @param context analysis context for the query | ||
* @return resolved relevance function | ||
*/ | ||
public Expression visitScoreFunction(ScoreFunction node, AnalysisContext context) { | ||
Literal boostArg = node.getRelevanceFieldWeight(); | ||
if (!boostArg.getType().equals(DataType.DOUBLE)) { | ||
throw new SemanticCheckException( | ||
String.format( | ||
"Expected boost type '%s' but got '%s'", | ||
DataType.DOUBLE.name(), boostArg.getType().name())); | ||
} | ||
Double thisBoostValue = ((Double) boostArg.getValue()); | ||
|
||
// update the existing unresolved expression to add a boost argument if it doesn't exist | ||
// OR multiply the existing boost argument | ||
Function relevanceQueryUnresolvedExpr = (Function) node.getRelevanceQuery(); | ||
List<UnresolvedExpression> relevanceFuncArgs = relevanceQueryUnresolvedExpr.getFuncArgs(); | ||
|
||
boolean doesFunctionContainBoostArgument = false; | ||
List<UnresolvedExpression> updatedFuncArgs = new ArrayList<>(); | ||
for (UnresolvedExpression expr : relevanceFuncArgs) { | ||
String argumentName = ((UnresolvedArgument) expr).getArgName(); | ||
if (argumentName.equalsIgnoreCase("boost")) { | ||
doesFunctionContainBoostArgument = true; | ||
Literal boostArgLiteral = (Literal) ((UnresolvedArgument) expr).getValue(); | ||
Double boostValue = | ||
Double.parseDouble((String) boostArgLiteral.getValue()) * thisBoostValue; | ||
UnresolvedArgument newBoostArg = | ||
new UnresolvedArgument( | ||
argumentName, new Literal(boostValue.toString(), DataType.STRING)); | ||
updatedFuncArgs.add(newBoostArg); | ||
} else { | ||
updatedFuncArgs.add(expr); | ||
} | ||
} | ||
|
||
// since nothing was found, add an argument | ||
if (!doesFunctionContainBoostArgument) { | ||
UnresolvedArgument newBoostArg = | ||
new UnresolvedArgument( | ||
"boost", new Literal(Double.toString(thisBoostValue), DataType.STRING)); | ||
updatedFuncArgs.add(newBoostArg); | ||
} | ||
|
||
// create a new function expression with boost argument and resolve it | ||
Function updatedRelevanceQueryUnresolvedExpr = | ||
new Function(relevanceQueryUnresolvedExpr.getFuncName(), updatedFuncArgs); | ||
OpenSearchFunctions.OpenSearchFunction relevanceQueryExpr = | ||
(OpenSearchFunctions.OpenSearchFunction) | ||
updatedRelevanceQueryUnresolvedExpr.accept(this, context); | ||
relevanceQueryExpr.setScoreTracked(true); | ||
return relevanceQueryExpr; | ||
} | ||
|
||
@Override | ||
public Expression visitRelevanceFieldList(RelevanceFieldList node, AnalysisContext context) { | ||
return new LiteralExpression( | ||
ExprValueUtils.tupleValue(ImmutableMap.copyOf(node.getFieldList()))); | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
.../main/java/org/opensearch/sql/opensearch/analysis/OpenSearchSelectExpressionAnalyzer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package org.opensearch.sql.opensearch.analysis; | ||
|
||
import org.opensearch.sql.analysis.AnalysisContext; | ||
import org.opensearch.sql.analysis.ExpressionAnalyzer; | ||
import org.opensearch.sql.analysis.SelectExpressionAnalyzer; | ||
import org.opensearch.sql.analysis.TypeEnvironment; | ||
import org.opensearch.sql.analysis.symbol.Namespace; | ||
import org.opensearch.sql.analysis.symbol.Symbol; | ||
import org.opensearch.sql.ast.expression.Alias; | ||
import org.opensearch.sql.ast.expression.Function; | ||
import org.opensearch.sql.ast.expression.NestedAllTupleFields; | ||
import org.opensearch.sql.ast.expression.QualifiedName; | ||
import org.opensearch.sql.data.type.ExprType; | ||
import org.opensearch.sql.expression.DSL; | ||
import org.opensearch.sql.expression.Expression; | ||
import org.opensearch.sql.expression.NamedExpression; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
|
||
public class OpenSearchSelectExpressionAnalyzer extends SelectExpressionAnalyzer { | ||
public OpenSearchSelectExpressionAnalyzer(ExpressionAnalyzer expressionAnalyzer) { | ||
super(expressionAnalyzer); | ||
} | ||
|
||
@Override | ||
public List<NamedExpression> visitAlias(Alias node, AnalysisContext context) { | ||
// Expand all nested fields if used in SELECT clause | ||
if (node.getDelegated() instanceof NestedAllTupleFields) { | ||
return node.getDelegated().accept(this, context); | ||
} | ||
|
||
Expression expr = referenceIfSymbolDefined(node, context); | ||
return Collections.singletonList( | ||
DSL.named(unqualifiedNameIfFieldOnly(node, context), expr, node.getAlias())); | ||
} | ||
|
||
|
||
@Override | ||
public List<NamedExpression> visitNestedAllTupleFields( | ||
NestedAllTupleFields node, AnalysisContext context) { | ||
TypeEnvironment environment = context.peek(); | ||
Map<String, ExprType> lookupAllTupleFields = | ||
environment.lookupAllTupleFields(Namespace.FIELD_NAME); | ||
environment.resolve(new Symbol(Namespace.FIELD_NAME, node.getPath())); | ||
|
||
// Match all fields with same path as used in nested function. | ||
Pattern p = Pattern.compile(node.getPath() + "\\.[^\\.]+$"); | ||
return lookupAllTupleFields.entrySet().stream() | ||
.filter(field -> p.matcher(field.getKey()).find()) | ||
.map( | ||
entry -> { | ||
Expression nestedFunc = | ||
new Function( | ||
"nested", | ||
List.of(new QualifiedName(List.of(entry.getKey().split("\\."))))) | ||
.accept(expressionAnalyzer, context); | ||
return DSL.named("nested(" + entry.getKey() + ")", nestedFunc); | ||
}) | ||
.collect(Collectors.toList()); | ||
} | ||
} |
Oops, something went wrong.