Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Add where stats rename command #466

Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -16,16 +16,27 @@
package com.amazon.opendistroforelasticsearch.sql.analysis;

import com.amazon.opendistroforelasticsearch.sql.ast.AbstractNodeVisitor;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Field;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedExpression;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Aggregation;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Filter;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Relation;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Rename;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.UnresolvedPlan;
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
import com.amazon.opendistroforelasticsearch.sql.expression.DSL;
import com.amazon.opendistroforelasticsearch.sql.expression.Expression;
import com.amazon.opendistroforelasticsearch.sql.expression.ReferenceExpression;
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.Aggregator;
import com.amazon.opendistroforelasticsearch.sql.planner.logical.LogicalAggregation;
import com.amazon.opendistroforelasticsearch.sql.planner.logical.LogicalFilter;
import com.amazon.opendistroforelasticsearch.sql.planner.logical.LogicalPlan;
import com.amazon.opendistroforelasticsearch.sql.planner.logical.LogicalRelation;
import com.amazon.opendistroforelasticsearch.sql.planner.logical.LogicalRename;
import com.amazon.opendistroforelasticsearch.sql.storage.StorageEngine;
import com.amazon.opendistroforelasticsearch.sql.storage.Table;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import lombok.RequiredArgsConstructor;

/**
Expand Down Expand Up @@ -53,6 +64,48 @@ public LogicalPlan visitRelation(Relation node, AnalysisContext context) {
public LogicalPlan visitFilter(Filter node, AnalysisContext context) {
LogicalPlan child = node.getChild().get(0).accept(this, context);
Expression condition = expressionAnalyzer.analyze(node.getCondition(), context);
return new LogicalFilter(condition, child);
return new LogicalFilter(child, condition);
}

/**
* Build {@link LogicalRename}
*/
@Override
public LogicalPlan visitRename(Rename node, AnalysisContext context) {
LogicalPlan child = node.getChild().get(0).accept(this, context);
ImmutableMap.Builder<Expression, Expression> renameMapBuilder = new ImmutableMap.Builder<>();
for (com.amazon.opendistroforelasticsearch.sql.ast.expression.Map renameMap : node.getRenameList()) {
Expression origin = expressionAnalyzer.analyze(renameMap.getOrigin(), context);
// We should define the new target field in the context instead of analyze it.
if (renameMap.getTarget() instanceof Field) {
ReferenceExpression target =
new ReferenceExpression(((Field) renameMap.getTarget()).getField().toString());
context.peek().define(target, origin.type(context.peek()));
renameMapBuilder.put(target, DSL.ref(origin.toString()));
} else {
throw new SemanticCheckException(String.format("the target expected to be field, but is %s",
renameMap.getTarget()));
}
}

return new LogicalRename(child, renameMapBuilder.build());
}

/**
* Build {@link LogicalAggregation}
*/
@Override
public LogicalPlan visitAggregation(Aggregation node, AnalysisContext context) {
LogicalPlan child = node.getChild().get(0).accept(this, context);
ImmutableList.Builder<Aggregator> aggregatorBuilder = new ImmutableList.Builder<>();
for (UnresolvedExpression uExpr : node.getAggExprList()) {
aggregatorBuilder.add((Aggregator) expressionAnalyzer.analyze(uExpr, context));
}

ImmutableList.Builder<Expression> groupbyBuilder = new ImmutableList.Builder<>();
for (UnresolvedExpression uExpr : node.getGroupExprList()) {
groupbyBuilder.add(expressionAnalyzer.analyze(uExpr, context));
}
return new LogicalAggregation(child, aggregatorBuilder.build(), groupbyBuilder.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,33 @@
package com.amazon.opendistroforelasticsearch.sql.analysis;

import com.amazon.opendistroforelasticsearch.sql.ast.AbstractNodeVisitor;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.AggregateFunction;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.And;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.EqualTo;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Field;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Literal;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedAttribute;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedExpression;
import com.amazon.opendistroforelasticsearch.sql.data.model.ExprValueUtils;
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
import com.amazon.opendistroforelasticsearch.sql.expression.DSL;
import com.amazon.opendistroforelasticsearch.sql.expression.Expression;
import com.amazon.opendistroforelasticsearch.sql.expression.ReferenceExpression;
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.Aggregator;
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName;
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionRepository;
import lombok.RequiredArgsConstructor;

import java.util.Collections;
import java.util.Optional;

/**
* Analyze the {@link UnresolvedExpression} in the {@link AnalysisContext} to construct the {@link Expression}
*/
@RequiredArgsConstructor
public class ExpressionAnalyzer extends AbstractNodeVisitor<Expression, AnalysisContext> {
private final DSL dsl;
private final BuiltinFunctionRepository repository;

public Expression analyze(UnresolvedExpression unresolved, AnalysisContext context) {
return unresolved.accept(this, context);
Expand Down Expand Up @@ -66,4 +76,26 @@ public Expression visitAnd(And node, AnalysisContext context) {

return dsl.and(context.peek(), left, right);
}

@Override
public Expression visitAggregateFunction(AggregateFunction node, AnalysisContext context) {
Optional<BuiltinFunctionName> builtinFunctionName = BuiltinFunctionName.of(node.getFuncName());
if (builtinFunctionName.isPresent()) {
Expression arg = node.getField().accept(this, context);
return (Aggregator) repository.compile(builtinFunctionName.get().getName(),
Collections.singletonList(arg),
context.peek());
} else {
throw new SemanticCheckException("Unsupported aggregation function " + node.getFuncName());
}
}

@Override
public Expression visitField(Field node, AnalysisContext context) {
String attr = node.getField().toString();
TypeEnvironment typeEnv = context.peek();
ReferenceExpression ref = DSL.ref(attr);
typeEnv.resolve(ref);
return ref;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Filter;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Project;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Relation;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Rename;

/**
* AST nodes visitor
Expand Down Expand Up @@ -138,5 +139,9 @@ public T visitField(Field node, C context) {
public T visitQualifiedName(QualifiedName node, C context) {
return visitChildren(node, context);
}

public T visitRename(Rename node, C context) {
return visitChildren(node, context);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.amazon.opendistroforelasticsearch.sql.ast.expression.UnresolvedAttribute;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Aggregation;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Filter;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Rename;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.UnresolvedPlan;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Project;
import com.amazon.opendistroforelasticsearch.sql.ast.tree.Relation;
Expand Down Expand Up @@ -65,6 +66,10 @@ public static UnresolvedPlan agg(UnresolvedPlan input, List<UnresolvedExpression
return new Aggregation(aggList, sortList, groupList, argList).attach(input);
}

public static UnresolvedPlan rename(UnresolvedPlan input, Map... maps) {
return new Rename(Arrays.asList(maps), input);
}

public static UnresolvedExpression qualifiedName(String... parts) {
return new QualifiedName(Arrays.asList(parts));
}
Expand Down Expand Up @@ -105,7 +110,7 @@ public static UnresolvedExpression map(String origin, String target) {
return new Map(new Field(origin), new Field(target));
}

public static UnresolvedExpression map(UnresolvedExpression origin, UnresolvedExpression target) {
public static Map map(UnresolvedExpression origin, UnresolvedExpression target) {
return new Map(origin, target);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,17 @@
package com.amazon.opendistroforelasticsearch.sql.ast.expression;

import com.amazon.opendistroforelasticsearch.sql.ast.AbstractNodeVisitor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

/**
* Expression node of aggregate functions
* Params include aggregate function name (AVG, SUM, MAX etc.) and the field to aggregate
*/
@Getter
@ToString
@EqualsAndHashCode(callSuper = false)
@RequiredArgsConstructor
public class AggregateFunction extends UnresolvedExpression {
Expand All @@ -45,11 +42,16 @@ public AggregateFunction(String funcName, UnresolvedExpression field) {

@Override
public List<UnresolvedExpression> getChild() {
return Arrays.asList(field);
return Collections.singletonList(field);
}

@Override
public <R, C> R accept(AbstractNodeVisitor<R, C> nodeVisitor, C context) {
return nodeVisitor.visitAggregateFunction(this, context);
}

@Override
public String toString() {
return String.format("%s(%s)", funcName, field);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package com.amazon.opendistroforelasticsearch.sql.ast.tree;

import com.amazon.opendistroforelasticsearch.sql.ast.AbstractNodeVisitor;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Map;
import com.google.common.collect.ImmutableList;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;

import java.util.List;

@ToString
@EqualsAndHashCode(callSuper = false)
@Getter
public class Rename extends UnresolvedPlan {
private final List<Map> renameList;
private UnresolvedPlan child;

public Rename(List<Map> renameList, UnresolvedPlan child) {
this.renameList = renameList;
this.child = child;
}

@Override
public Rename attach(UnresolvedPlan child) {
if (null == this.child) {
this.child = child;
} else {
this.child.attach(child);
}
return this;
}

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

@Override
public <T, C> T accept(AbstractNodeVisitor<T, C> nodeVisitor, C context) {
return nodeVisitor.visitRename(this, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ public static ExprValue nullValue() {
}

public static ExprValue fromObjectValue(Object o) {
if ( null == o) {
return LITERAL_NULL;
}
if (o instanceof Map) {
return tupleValue((Map) o);
} else if (o instanceof List) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import com.amazon.opendistroforelasticsearch.sql.data.model.ExprType;
import com.amazon.opendistroforelasticsearch.sql.data.model.ExprValue;
import com.amazon.opendistroforelasticsearch.sql.data.model.ExprValueUtils;
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.Aggregator;
import com.amazon.opendistroforelasticsearch.sql.expression.env.Environment;
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName;
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionRepository;
Expand All @@ -28,6 +30,10 @@
public class DSL {
private final BuiltinFunctionRepository repository;

public static LiteralExpression literal(Integer value) {
return new LiteralExpression(ExprValueUtils.integerValue(value));
}

public static LiteralExpression literal(ExprValue value) {
return new LiteralExpression(value);
}
Expand All @@ -37,42 +43,50 @@ public static ReferenceExpression ref(String ref) {
}

public FunctionExpression add(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.ADD.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.ADD.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression subtract(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.SUBTRACT.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.SUBTRACT.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression multiply(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.MULTIPLY.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.MULTIPLY.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression divide(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.DIVIDE.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.DIVIDE.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression module(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.MODULES.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.MODULES.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression and(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.AND.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.AND.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression or(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.OR.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.OR.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression xor(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.XOR.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.XOR.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression not(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.NOT.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.NOT.getName(), Arrays.asList(expressions), env);
}

public FunctionExpression equal(Environment<Expression, ExprType> env, Expression... expressions) {
return repository.compile(BuiltinFunctionName.EQUAL.getName(), Arrays.asList(expressions), env);
return (FunctionExpression) repository.compile(BuiltinFunctionName.EQUAL.getName(), Arrays.asList(expressions), env);
}

public Aggregator avg(Environment<Expression, ExprType> env, Expression... expressions) {
return (Aggregator) repository.compile(BuiltinFunctionName.AVG.getName(), Arrays.asList(expressions), env);
}

public Aggregator sum(Environment<Expression, ExprType> env, Expression... expressions) {
return (Aggregator) repository.compile(BuiltinFunctionName.SUM.getName(), Arrays.asList(expressions), env);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.amazon.opendistroforelasticsearch.sql.expression;

import com.amazon.opendistroforelasticsearch.sql.expression.function.FunctionImplementation;
import com.amazon.opendistroforelasticsearch.sql.expression.function.FunctionName;
import lombok.EqualsAndHashCode;
import lombok.Getter;
Expand All @@ -27,7 +28,7 @@
*/
@EqualsAndHashCode
@RequiredArgsConstructor
public abstract class FunctionExpression implements Expression {
public abstract class FunctionExpression implements Expression, FunctionImplementation {
@Getter
private final FunctionName functionName;

Expand Down
Loading