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

Commit 4b33a2f

Browse files
authored
add date and time support (#560)
* add date and time support * update doc * update doc
1 parent 923c96d commit 4b33a2f

File tree

19 files changed

+706
-16
lines changed

19 files changed

+706
-16
lines changed

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/analysis/ExpressionAnalyzer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ public Expression visitEqualTo(EqualTo node, AnalysisContext context) {
7878

7979
@Override
8080
public Expression visitLiteral(Literal node, AnalysisContext context) {
81-
return DSL.literal(ExprValueUtils.fromObjectValue(node.getValue()));
81+
return DSL
82+
.literal(ExprValueUtils.fromObjectValue(node.getValue(), node.getType().getCoreType()));
8283
}
8384

8485
@Override

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/ast/dsl/AstDSL.java

+12
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ public static Literal intLiteral(Integer value) {
123123
return literal(value, DataType.INTEGER);
124124
}
125125

126+
public static Literal dateLiteral(String value) {
127+
return literal(value, DataType.DATE);
128+
}
129+
130+
public static Literal timeLiteral(String value) {
131+
return literal(value, DataType.TIME);
132+
}
133+
134+
public static Literal timestampLiteral(String value) {
135+
return literal(value, DataType.TIMESTAMP);
136+
}
137+
126138
public static Literal doubleLiteral(Double value) {
127139
return literal(value, DataType.DOUBLE);
128140
}

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/ast/expression/DataType.java

+22-6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,28 @@
1515

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

18+
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
19+
import lombok.Getter;
20+
import lombok.RequiredArgsConstructor;
21+
22+
/**
23+
* The DataType defintion in AST.
24+
* Question, could we use {@link ExprCoreType} directly in AST?
25+
*/
26+
@RequiredArgsConstructor
1827
public enum DataType {
19-
TYPE_ERROR,
20-
NULL,
28+
TYPE_ERROR(ExprCoreType.UNKNOWN),
29+
NULL(ExprCoreType.UNKNOWN),
30+
31+
INTEGER(ExprCoreType.INTEGER),
32+
DOUBLE(ExprCoreType.DOUBLE),
33+
STRING(ExprCoreType.STRING),
34+
BOOLEAN(ExprCoreType.BOOLEAN),
35+
36+
DATE(ExprCoreType.DATE),
37+
TIME(ExprCoreType.TIME),
38+
TIMESTAMP(ExprCoreType.TIMESTAMP);
2139

22-
INTEGER,
23-
DOUBLE,
24-
STRING,
25-
BOOLEAN
40+
@Getter
41+
private final ExprCoreType coreType;
2642
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
*
3+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License").
6+
* You may not use this file except in compliance with the License.
7+
* A copy of the License is located at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* or in the "license" file accompanying this file. This file is distributed
12+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13+
* express or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*
16+
*/
17+
18+
package com.amazon.opendistroforelasticsearch.sql.data.model;
19+
20+
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
21+
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
22+
import java.time.Instant;
23+
import java.time.LocalDate;
24+
import java.time.ZoneId;
25+
import java.time.ZonedDateTime;
26+
import java.time.format.DateTimeFormatter;
27+
import java.time.format.DateTimeParseException;
28+
import lombok.EqualsAndHashCode;
29+
import lombok.RequiredArgsConstructor;
30+
31+
/**
32+
* Date Value.
33+
*/
34+
@EqualsAndHashCode
35+
@RequiredArgsConstructor
36+
public class ExprDateValue implements ExprValue {
37+
/**
38+
* todo. only support UTC now.
39+
*/
40+
private static final ZoneId ZONE = ZoneId.of("UTC");
41+
private final Instant date;
42+
43+
/**
44+
* Constructor of ExprDateValue.
45+
*/
46+
public ExprDateValue(String date) {
47+
try {
48+
LocalDate localDate = LocalDate.parse(date);
49+
this.date = localDate.atStartOfDay(ZONE).toInstant();
50+
} catch (DateTimeParseException e) {
51+
throw new SemanticCheckException(String.format("date:%s in unsupported format, please use "
52+
+ "yyyy-MM-dd", date));
53+
}
54+
}
55+
56+
@Override
57+
public String value() {
58+
return DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZONE).format(date);
59+
}
60+
61+
@Override
62+
public ExprCoreType type() {
63+
return ExprCoreType.DATE;
64+
}
65+
66+
@Override
67+
public String toString() {
68+
return String.format("DATE '%s'", value());
69+
}
70+
71+
public ZonedDateTime getDate() {
72+
return date.atZone(ZONE);
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
*
3+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License").
6+
* You may not use this file except in compliance with the License.
7+
* A copy of the License is located at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* or in the "license" file accompanying this file. This file is distributed
12+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13+
* express or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*
16+
*/
17+
18+
package com.amazon.opendistroforelasticsearch.sql.data.model;
19+
20+
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
21+
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
22+
import java.time.LocalTime;
23+
import java.time.ZoneId;
24+
import java.time.format.DateTimeFormatter;
25+
import java.time.format.DateTimeParseException;
26+
import lombok.EqualsAndHashCode;
27+
import lombok.RequiredArgsConstructor;
28+
29+
/**
30+
* Time Value.
31+
*/
32+
@EqualsAndHashCode
33+
@RequiredArgsConstructor
34+
public class ExprTimeValue implements ExprValue {
35+
/**
36+
* todo. only support UTC now.
37+
*/
38+
private static final ZoneId ZONE = ZoneId.of("UTC");
39+
private final LocalTime time;
40+
41+
/**
42+
* Constructor.
43+
*/
44+
public ExprTimeValue(String time) {
45+
try {
46+
this.time = LocalTime.parse(time);
47+
} catch (DateTimeParseException e) {
48+
throw new SemanticCheckException(String.format("time:%s in unsupported format, please use "
49+
+ "HH:mm:ss", time));
50+
}
51+
}
52+
53+
@Override
54+
public String value() {
55+
return DateTimeFormatter.ISO_LOCAL_TIME.withZone(ZONE).format(time);
56+
}
57+
58+
@Override
59+
public ExprCoreType type() {
60+
return ExprCoreType.TIME;
61+
}
62+
63+
@Override
64+
public String toString() {
65+
return String.format("TIME '%s'", value());
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
*
3+
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License").
6+
* You may not use this file except in compliance with the License.
7+
* A copy of the License is located at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* or in the "license" file accompanying this file. This file is distributed
12+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13+
* express or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*
16+
*/
17+
18+
package com.amazon.opendistroforelasticsearch.sql.data.model;
19+
20+
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
21+
import com.amazon.opendistroforelasticsearch.sql.exception.SemanticCheckException;
22+
import java.time.Instant;
23+
import java.time.LocalDateTime;
24+
import java.time.ZoneId;
25+
import java.time.format.DateTimeFormatter;
26+
import java.time.format.DateTimeParseException;
27+
import java.time.temporal.ChronoUnit;
28+
import lombok.EqualsAndHashCode;
29+
import lombok.RequiredArgsConstructor;
30+
31+
/**
32+
* Timestamp Value.
33+
*/
34+
@EqualsAndHashCode
35+
@RequiredArgsConstructor
36+
public class ExprTimestampValue implements ExprValue {
37+
/**
38+
* todo. only support UTC now.
39+
*/
40+
private static final ZoneId ZONE = ZoneId.of("UTC");
41+
/**
42+
* todo. only support timestamp in format yyyy-MM-dd HH:mm:ss.
43+
*/
44+
private static final DateTimeFormatter FORMATTER = DateTimeFormatter
45+
.ofPattern("yyyy-MM-dd HH:mm:ss");
46+
private final Instant timestamp;
47+
48+
/**
49+
* Constructor.
50+
*/
51+
public ExprTimestampValue(String timestamp) {
52+
try {
53+
this.timestamp = LocalDateTime.parse(timestamp, FORMATTER).atZone(ZONE).toInstant();
54+
} catch (DateTimeParseException e) {
55+
throw new SemanticCheckException(String.format("timestamp:%s in unsupported format, please "
56+
+ "use yyyy-MM-dd HH:mm:ss", timestamp));
57+
}
58+
59+
}
60+
61+
@Override
62+
public String value() {
63+
return FORMATTER.withZone(ZONE).format(timestamp.truncatedTo(ChronoUnit.SECONDS));
64+
}
65+
66+
@Override
67+
public ExprCoreType type() {
68+
return ExprCoreType.TIMESTAMP;
69+
}
70+
71+
@Override
72+
public String toString() {
73+
return String.format("TIMESTAMP '%s'", value());
74+
}
75+
}

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/data/model/ExprValueUtils.java

+30
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprCoreType;
2424
import com.amazon.opendistroforelasticsearch.sql.exception.ExpressionEvaluationException;
2525
import com.google.common.annotations.VisibleForTesting;
26+
import java.time.ZonedDateTime;
2627
import java.util.ArrayList;
2728
import java.util.LinkedHashMap;
2829
import java.util.List;
@@ -117,6 +118,22 @@ public static ExprValue fromObjectValue(Object o) {
117118
}
118119
}
119120

121+
/**
122+
* Construct ExprValue from Object with ExprCoreType.
123+
*/
124+
public static ExprValue fromObjectValue(Object o, ExprCoreType type) {
125+
switch (type) {
126+
case TIMESTAMP:
127+
return new ExprTimestampValue((String)o);
128+
case DATE:
129+
return new ExprDateValue((String)o);
130+
case TIME:
131+
return new ExprTimeValue((String)o);
132+
default:
133+
return fromObjectValue(o);
134+
}
135+
}
136+
120137
public static Integer getIntegerValue(ExprValue exprValue) {
121138
return getNumberValue(exprValue).intValue();
122139
}
@@ -149,6 +166,19 @@ public static Boolean getBooleanValue(ExprValue exprValue) {
149166
return convert(exprValue, BOOLEAN);
150167
}
151168

169+
/**
170+
* Get {@link ZonedDateTime} from ExprValue of Date type.
171+
*/
172+
public static ZonedDateTime getDateValue(ExprValue exprValue) {
173+
if (ExprCoreType.DATE == exprValue.type()) {
174+
return ((ExprDateValue) exprValue).getDate();
175+
} else {
176+
throw new ExpressionEvaluationException(
177+
String.format("invalid to convert expression with type:%s to type:%s", exprValue.type(),
178+
ExprCoreType.DATE));
179+
}
180+
}
181+
152182
/**
153183
* Get Number Value from {@link ExprValue}.
154184
*/

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/DSL.java

+5
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public FunctionExpression multiply(Expression... expressions) {
8181
repository.compile(BuiltinFunctionName.MULTIPLY.getName(), Arrays.asList(expressions));
8282
}
8383

84+
public FunctionExpression dayofmonth(Expression... expressions) {
85+
return (FunctionExpression)
86+
repository.compile(BuiltinFunctionName.DAYOFMONTH.getName(), Arrays.asList(expressions));
87+
}
88+
8489
public FunctionExpression divide(Expression... expressions) {
8590
return (FunctionExpression)
8691
repository.compile(BuiltinFunctionName.DIVIDE.getName(), Arrays.asList(expressions));

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/config/ExpressionConfig.java

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import com.amazon.opendistroforelasticsearch.sql.expression.DSL;
1919
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.AggregatorFunction;
20+
import com.amazon.opendistroforelasticsearch.sql.expression.datetime.DateTimeFunction;
2021
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionRepository;
2122
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.ArithmeticFunction;
2223
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.UnaryFunction;
@@ -43,6 +44,7 @@ public BuiltinFunctionRepository functionRepository() {
4344
UnaryFunction.register(builtinFunctionRepository);
4445
UnaryPredicateOperator.register(builtinFunctionRepository);
4546
AggregatorFunction.register(builtinFunctionRepository);
47+
DateTimeFunction.register(builtinFunctionRepository);
4648
return builtinFunctionRepository;
4749
}
4850

0 commit comments

Comments
 (0)