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

Support cast function in SQL #926

Merged
merged 7 commits into from
Dec 15, 2020
Merged
Changes from all 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
@@ -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;
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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;
@@ -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);
}
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 {
penghuo marked this conversation as resolved.
Show resolved Hide resolved

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
@@ -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
@@ -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;
@@ -51,6 +52,7 @@ public BuiltinFunctionRepository functionRepository() {
IntervalClause.register(builtinFunctionRepository);
WindowFunctions.register(builtinFunctionRepository);
TextFunction.register(builtinFunctionRepository);
TypeCastOperator.register(builtinFunctionRepository);
return builtinFunctionRepository;
}

Original file line number Diff line number Diff line change
@@ -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;

Loading