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

Commit

Permalink
add date and time support (#560)
Browse files Browse the repository at this point in the history
* add date and time support

* update doc

* update doc
  • Loading branch information
penghuo authored Jul 13, 2020
1 parent 923c96d commit 4b33a2f
Show file tree
Hide file tree
Showing 19 changed files with 706 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ public Expression visitEqualTo(EqualTo node, AnalysisContext context) {

@Override
public Expression visitLiteral(Literal node, AnalysisContext context) {
return DSL.literal(ExprValueUtils.fromObjectValue(node.getValue()));
return DSL
.literal(ExprValueUtils.fromObjectValue(node.getValue(), node.getType().getCoreType()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,18 @@ public static Literal intLiteral(Integer value) {
return literal(value, DataType.INTEGER);
}

public static Literal dateLiteral(String value) {
return literal(value, DataType.DATE);
}

public static Literal timeLiteral(String value) {
return literal(value, DataType.TIME);
}

public static Literal timestampLiteral(String value) {
return literal(value, DataType.TIMESTAMP);
}

public static Literal doubleLiteral(Double value) {
return literal(value, DataType.DOUBLE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,28 @@

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

import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
* The DataType defintion in AST.
* Question, could we use {@link ExprCoreType} directly in AST?
*/
@RequiredArgsConstructor
public enum DataType {
TYPE_ERROR,
NULL,
TYPE_ERROR(ExprCoreType.UNKNOWN),
NULL(ExprCoreType.UNKNOWN),

INTEGER(ExprCoreType.INTEGER),
DOUBLE(ExprCoreType.DOUBLE),
STRING(ExprCoreType.STRING),
BOOLEAN(ExprCoreType.BOOLEAN),

DATE(ExprCoreType.DATE),
TIME(ExprCoreType.TIME),
TIMESTAMP(ExprCoreType.TIMESTAMP);

INTEGER,
DOUBLE,
STRING,
BOOLEAN
@Getter
private final ExprCoreType coreType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
*
* 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.data.model;

import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;

/**
* Date Value.
*/
@EqualsAndHashCode
@RequiredArgsConstructor
public class ExprDateValue implements ExprValue {
/**
* todo. only support UTC now.
*/
private static final ZoneId ZONE = ZoneId.of("UTC");
private final Instant date;

/**
* Constructor of ExprDateValue.
*/
public ExprDateValue(String date) {
try {
LocalDate localDate = LocalDate.parse(date);
this.date = localDate.atStartOfDay(ZONE).toInstant();
} catch (DateTimeParseException e) {
throw new SemanticCheckException(String.format("date:%s in unsupported format, please use "
+ "yyyy-MM-dd", date));
}
}

@Override
public String value() {
return DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZONE).format(date);
}

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

@Override
public String toString() {
return String.format("DATE '%s'", value());
}

public ZonedDateTime getDate() {
return date.atZone(ZONE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
*
* 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.data.model;

import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;

/**
* Time Value.
*/
@EqualsAndHashCode
@RequiredArgsConstructor
public class ExprTimeValue implements ExprValue {
/**
* todo. only support UTC now.
*/
private static final ZoneId ZONE = ZoneId.of("UTC");
private final LocalTime time;

/**
* Constructor.
*/
public ExprTimeValue(String time) {
try {
this.time = LocalTime.parse(time);
} catch (DateTimeParseException e) {
throw new SemanticCheckException(String.format("time:%s in unsupported format, please use "
+ "HH:mm:ss", time));
}
}

@Override
public String value() {
return DateTimeFormatter.ISO_LOCAL_TIME.withZone(ZONE).format(time);
}

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

@Override
public String toString() {
return String.format("TIME '%s'", value());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
*
* 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.data.model;

import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;

/**
* Timestamp Value.
*/
@EqualsAndHashCode
@RequiredArgsConstructor
public class ExprTimestampValue implements ExprValue {
/**
* todo. only support UTC now.
*/
private static final ZoneId ZONE = ZoneId.of("UTC");
/**
* todo. only support timestamp in format yyyy-MM-dd HH:mm:ss.
*/
private static final DateTimeFormatter FORMATTER = DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss");
private final Instant timestamp;

/**
* Constructor.
*/
public ExprTimestampValue(String timestamp) {
try {
this.timestamp = LocalDateTime.parse(timestamp, FORMATTER).atZone(ZONE).toInstant();
} catch (DateTimeParseException e) {
throw new SemanticCheckException(String.format("timestamp:%s in unsupported format, please "
+ "use yyyy-MM-dd HH:mm:ss", timestamp));
}

}

@Override
public String value() {
return FORMATTER.withZone(ZONE).format(timestamp.truncatedTo(ChronoUnit.SECONDS));
}

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

@Override
public String toString() {
return String.format("TIMESTAMP '%s'", value());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
import com.amazon.opendistroforelasticsearch.sql.exception.ExpressionEvaluationException;
import com.google.common.annotations.VisibleForTesting;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -117,6 +118,22 @@ public static ExprValue fromObjectValue(Object o) {
}
}

/**
* Construct ExprValue from Object with ExprCoreType.
*/
public static ExprValue fromObjectValue(Object o, ExprCoreType type) {
switch (type) {
case TIMESTAMP:
return new ExprTimestampValue((String)o);
case DATE:
return new ExprDateValue((String)o);
case TIME:
return new ExprTimeValue((String)o);
default:
return fromObjectValue(o);
}
}

public static Integer getIntegerValue(ExprValue exprValue) {
return getNumberValue(exprValue).intValue();
}
Expand Down Expand Up @@ -149,6 +166,19 @@ public static Boolean getBooleanValue(ExprValue exprValue) {
return convert(exprValue, BOOLEAN);
}

/**
* Get {@link ZonedDateTime} from ExprValue of Date type.
*/
public static ZonedDateTime getDateValue(ExprValue exprValue) {
if (ExprCoreType.DATE == exprValue.type()) {
return ((ExprDateValue) exprValue).getDate();
} else {
throw new ExpressionEvaluationException(
String.format("invalid to convert expression with type:%s to type:%s", exprValue.type(),
ExprCoreType.DATE));
}
}

/**
* Get Number Value from {@link ExprValue}.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ public FunctionExpression multiply(Expression... expressions) {
repository.compile(BuiltinFunctionName.MULTIPLY.getName(), Arrays.asList(expressions));
}

public FunctionExpression dayofmonth(Expression... expressions) {
return (FunctionExpression)
repository.compile(BuiltinFunctionName.DAYOFMONTH.getName(), Arrays.asList(expressions));
}

public FunctionExpression divide(Expression... expressions) {
return (FunctionExpression)
repository.compile(BuiltinFunctionName.DIVIDE.getName(), Arrays.asList(expressions));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.amazon.opendistroforelasticsearch.sql.expression.DSL;
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.AggregatorFunction;
import com.amazon.opendistroforelasticsearch.sql.expression.datetime.DateTimeFunction;
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.UnaryFunction;
Expand All @@ -43,6 +44,7 @@ public BuiltinFunctionRepository functionRepository() {
UnaryFunction.register(builtinFunctionRepository);
UnaryPredicateOperator.register(builtinFunctionRepository);
AggregatorFunction.register(builtinFunctionRepository);
DateTimeFunction.register(builtinFunctionRepository);
return builtinFunctionRepository;
}

Expand Down
Loading

0 comments on commit 4b33a2f

Please sign in to comment.