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

Commit

Permalink
Support cast function in SQL (#926)
Browse files Browse the repository at this point in the history
* init

* update

* update doc

* update doc

* update doc

* fix breaking IT
  • Loading branch information
penghuo authored Dec 15, 2020
1 parent 64c7bd6 commit 1675e2d
Show file tree
Hide file tree
Showing 20 changed files with 808 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.amazon.opendistroforelasticsearch.sql.ast.expression.AllFields;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.And;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Case;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Cast;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Compare;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.EqualTo;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Field;
Expand Down Expand Up @@ -67,6 +68,13 @@ public class ExpressionAnalyzer extends AbstractNodeVisitor<Expression, Analysis
private final BuiltinFunctionRepository repository;
private final DSL dsl;

@Override
public Expression visitCast(Cast node, AnalysisContext context) {
final Expression expression = node.getExpression().accept(this, context);
return (Expression) repository
.compile(node.convertFunctionName(), Collections.singletonList(expression));
}

public ExpressionAnalyzer(
BuiltinFunctionRepository repository) {
this.repository = repository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Argument;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.AttributeList;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Case;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Cast;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Compare;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.EqualTo;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Field;
Expand Down Expand Up @@ -226,6 +227,10 @@ public T visitWhen(When node, C context) {
return visitChildren(node, context);
}

public T visitCast(Cast node, C context) {
return visitChildren(node, context);
}

public T visitUnresolvedArgument(UnresolvedArgument node, C context) {
return visitChildren(node, context);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.amazon.opendistroforelasticsearch.sql.ast.expression.And;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Argument;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Case;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Cast;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.Compare;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.DataType;
import com.amazon.opendistroforelasticsearch.sql.ast.expression.EqualTo;
Expand Down Expand Up @@ -221,6 +222,10 @@ public UnresolvedExpression caseWhen(UnresolvedExpression caseValueExpr,
return new Case(caseValueExpr, Arrays.asList(whenClauses), elseClause);
}

public UnresolvedExpression cast(UnresolvedExpression expr, Literal type) {
return new Cast(expr, type);
}

public When when(UnresolvedExpression condition, UnresolvedExpression result) {
return new When(condition, result);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
*
* Copyright 2020 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.expression;

import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_BOOLEAN;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_DATE;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_DOUBLE;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_FLOAT;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_INT;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_LONG;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_STRING;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_TIME;
import static com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName.CAST_TO_TIMESTAMP;

import com.amazon.opendistroforelasticsearch.sql.ast.AbstractNodeVisitor;
import com.amazon.opendistroforelasticsearch.sql.ast.Node;
import com.amazon.opendistroforelasticsearch.sql.expression.function.FunctionName;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;

/**
* AST node that represents Cast clause.
*/
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Getter
@ToString
public class Cast extends UnresolvedExpression {

private static Map<String, FunctionName> CONVERTED_TYPE_FUNCTION_NAME_MAP =
new ImmutableMap.Builder<String, FunctionName>()
.put("string", CAST_TO_STRING.getName())
.put("int", CAST_TO_INT.getName())
.put("long", CAST_TO_LONG.getName())
.put("float", CAST_TO_FLOAT.getName())
.put("double", CAST_TO_DOUBLE.getName())
.put("boolean", CAST_TO_BOOLEAN.getName())
.put("date", CAST_TO_DATE.getName())
.put("time", CAST_TO_TIME.getName())
.put("timestamp", CAST_TO_TIMESTAMP.getName())
.build();

/**
* The source expression cast from.
*/
private final UnresolvedExpression expression;

/**
* Expression that represents ELSE statement result.
*/
private final UnresolvedExpression convertedType;

/**
* Get the converted type.
*
* @return converted type
*/
public FunctionName convertFunctionName() {
String type = convertedType.toString().toLowerCase(Locale.ROOT);
if (CONVERTED_TYPE_FUNCTION_NAME_MAP.containsKey(type)) {
return CONVERTED_TYPE_FUNCTION_NAME_MAP.get(type);
} else {
throw new IllegalStateException("unsupported cast type: " + type);
}
}

@Override
public List<? extends Node> getChild() {
return Collections.singletonList(expression);
}

@Override
public <T, C> T accept(AbstractNodeVisitor<T, C> nodeVisitor, C context) {
return nodeVisitor.visitCast(this, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -523,4 +523,49 @@ public FunctionExpression interval(Expression value, Expression unit) {
return (FunctionExpression) repository.compile(
BuiltinFunctionName.INTERVAL.getName(), Arrays.asList(value, unit));
}

public FunctionExpression castString(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_STRING.getName(), Arrays.asList(value));
}

public FunctionExpression castInt(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_INT.getName(), Arrays.asList(value));
}

public FunctionExpression castLong(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_LONG.getName(), Arrays.asList(value));
}

public FunctionExpression castFloat(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_FLOAT.getName(), Arrays.asList(value));
}

public FunctionExpression castDouble(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_DOUBLE.getName(), Arrays.asList(value));
}

public FunctionExpression castBoolean(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_BOOLEAN.getName(), Arrays.asList(value));
}

public FunctionExpression castDate(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_DATE.getName(), Arrays.asList(value));
}

public FunctionExpression castTime(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_TIME.getName(), Arrays.asList(value));
}

public FunctionExpression castTimestamp(Expression value) {
return (FunctionExpression) repository
.compile(BuiltinFunctionName.CAST_TO_TIMESTAMP.getName(), Arrays.asList(value));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionRepository;
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.ArithmeticFunction;
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.MathematicalFunction;
import com.amazon.opendistroforelasticsearch.sql.expression.operator.convert.TypeCastOperator;
import com.amazon.opendistroforelasticsearch.sql.expression.operator.predicate.BinaryPredicateOperator;
import com.amazon.opendistroforelasticsearch.sql.expression.operator.predicate.UnaryPredicateOperator;
import com.amazon.opendistroforelasticsearch.sql.expression.text.TextFunction;
Expand Down Expand Up @@ -51,6 +52,7 @@ public BuiltinFunctionRepository functionRepository() {
IntervalClause.register(builtinFunctionRepository);
WindowFunctions.register(builtinFunctionRepository);
TextFunction.register(builtinFunctionRepository);
TypeCastOperator.register(builtinFunctionRepository);
return builtinFunctionRepository;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,20 @@ public enum BuiltinFunctionName {
RANK(FunctionName.of("rank")),
DENSE_RANK(FunctionName.of("dense_rank")),

INTERVAL(FunctionName.of("interval"));
INTERVAL(FunctionName.of("interval")),

/**
* Data Type Convert Function.
*/
CAST_TO_STRING(FunctionName.of("cast_to_string")),
CAST_TO_INT(FunctionName.of("cast_to_int")),
CAST_TO_LONG(FunctionName.of("cast_to_long")),
CAST_TO_FLOAT(FunctionName.of("cast_to_float")),
CAST_TO_DOUBLE(FunctionName.of("cast_to_double")),
CAST_TO_BOOLEAN(FunctionName.of("cast_to_boolean")),
CAST_TO_DATE(FunctionName.of("cast_to_date")),
CAST_TO_TIME(FunctionName.of("cast_to_time")),
CAST_TO_TIMESTAMP(FunctionName.of("cast_to_timestamp"));

private final FunctionName name;

Expand Down
Loading

0 comments on commit 1675e2d

Please sign in to comment.