mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-14 08:55:19 +00:00
SQL: Fix constant folding of datetime functions (elastic/x-pack-elasticsearch#3637)
I went to write some docs for datetime functions that look like: ``` SELECT YEAR(CAST('2018-01-19T10:23:27Z' AS TIMESTAMP)) as year; year 2018 ``` because I figured they'd be pretty easy to read because they didn't require any knowledge of a data set. But it turns out that constant folding doesn't work properly for date time functions because they don't actually apply the extraction. Original commit: elastic/x-pack-elasticsearch@aa9c66b2c7
This commit is contained in:
parent
f69a09ce83
commit
b165f1c71e
@ -251,8 +251,16 @@ include-tagged::{sql-specs}/math.sql-spec[sinh]
|
||||
include-tagged::{sql-specs}/math.sql-spec[cosh]
|
||||
--------------------------------------------------
|
||||
|
||||
// conversion
|
||||
// date time
|
||||
|
||||
=== Date and Time Functions
|
||||
|
||||
* Extract the year from a date (`YEAR`)
|
||||
|
||||
["source","sql",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{sql-specs}/datetime.csv-spec[year]
|
||||
--------------------------------------------------
|
||||
|
||||
// aggregate
|
||||
|
||||
// geospatial
|
||||
|
@ -22,6 +22,9 @@ import org.elasticsearch.xpack.sql.type.DataType;
|
||||
import org.elasticsearch.xpack.sql.type.DataTypes;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -61,7 +64,13 @@ public abstract class DateTimeFunction extends UnaryScalarFunction {
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return field().fold();
|
||||
Long folded = (Long) field().fold();
|
||||
if (folded == null) {
|
||||
return null;
|
||||
}
|
||||
ZonedDateTime time = ZonedDateTime.ofInstant(
|
||||
Instant.ofEpochMilli(folded), ZoneId.of(timeZone.getID()));
|
||||
return time.get(chronoField());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,7 +15,13 @@ import org.elasticsearch.xpack.sql.expression.Order;
|
||||
import org.elasticsearch.xpack.sql.expression.Order.OrderDirection;
|
||||
import org.elasticsearch.xpack.sql.expression.function.aggregate.AggregateFunction;
|
||||
import org.elasticsearch.xpack.sql.expression.function.aggregate.Count;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.Cast;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.arithmetic.Add;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DayOfMonth;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DayOfYear;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.MonthOfYear;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.WeekOfWeekYear;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.Year;
|
||||
import org.elasticsearch.xpack.sql.expression.predicate.And;
|
||||
import org.elasticsearch.xpack.sql.expression.predicate.Equals;
|
||||
import org.elasticsearch.xpack.sql.expression.predicate.GreaterThan;
|
||||
@ -49,7 +55,7 @@ import org.elasticsearch.xpack.sql.tree.Location;
|
||||
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
||||
import org.elasticsearch.xpack.sql.type.DataType;
|
||||
import org.elasticsearch.xpack.sql.type.DataTypes;
|
||||
|
||||
import org.joda.time.DateTimeZone;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -257,6 +263,23 @@ public class OptimizerTests extends ESTestCase {
|
||||
new ConstantFolding().rule(new RLike(EMPTY, Literal.of(EMPTY, "test_emp"), Literal.of(EMPTY, "test.emp"))));
|
||||
}
|
||||
|
||||
public void testConstantFoldingDatetime() {
|
||||
Expression cast = new Cast(EMPTY, Literal.of(EMPTY, "2018-01-19T10:23:27Z"), DataTypes.DATE);
|
||||
assertEquals(2018, unwrapAlias(new ConstantFolding().rule(new Year(EMPTY, cast, DateTimeZone.UTC))));
|
||||
assertEquals(1, unwrapAlias(new ConstantFolding().rule(new MonthOfYear(EMPTY, cast, DateTimeZone.UTC))));
|
||||
assertEquals(19, unwrapAlias(new ConstantFolding().rule(new DayOfMonth(EMPTY, cast, DateTimeZone.UTC))));
|
||||
assertEquals(19, unwrapAlias(new ConstantFolding().rule(new DayOfYear(EMPTY, cast, DateTimeZone.UTC))));
|
||||
assertEquals(3, unwrapAlias(new ConstantFolding().rule(new WeekOfWeekYear(EMPTY, cast, DateTimeZone.UTC))));
|
||||
assertNull(unwrapAlias(new ConstantFolding().rule(
|
||||
new WeekOfWeekYear(EMPTY, new Literal(EMPTY, null, DataTypes.NULL), DateTimeZone.UTC))));
|
||||
}
|
||||
|
||||
private Object unwrapAlias(Expression e) {
|
||||
Alias a = (Alias) e;
|
||||
Literal l = (Literal) a.child();
|
||||
return l.value();
|
||||
}
|
||||
|
||||
public void testBinaryComparisonSimplification() {
|
||||
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new Equals(EMPTY, L(5), L(5))));
|
||||
assertEquals(Literal.TRUE, new BinaryComparisonSimplification().rule(new GreaterThanOrEqual(EMPTY, L(5), L(5))));
|
||||
|
@ -10,53 +10,53 @@
|
||||
dateTimeSecond
|
||||
SELECT SECOND(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
||||
|
||||
d:i | l:s
|
||||
0 | Facello
|
||||
0 | Simmel
|
||||
0 | Bamford
|
||||
0 | Koblick
|
||||
0 | Maliniak
|
||||
0 | Preusig
|
||||
0 | Zielinski
|
||||
0 | Kalloufi
|
||||
0 | Peac
|
||||
d:i | l:s
|
||||
0 | Facello
|
||||
0 | Simmel
|
||||
0 | Bamford
|
||||
0 | Koblick
|
||||
0 | Maliniak
|
||||
0 | Preusig
|
||||
0 | Zielinski
|
||||
0 | Kalloufi
|
||||
0 | Peac
|
||||
;
|
||||
|
||||
dateTimeMinute
|
||||
SELECT MINUTE(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
||||
|
||||
d:i | l:s
|
||||
0 | Facello
|
||||
0 | Simmel
|
||||
0 | Bamford
|
||||
0 | Koblick
|
||||
0 | Maliniak
|
||||
0 | Preusig
|
||||
0 | Zielinski
|
||||
0 | Kalloufi
|
||||
0 | Peac
|
||||
d:i | l:s
|
||||
0 | Facello
|
||||
0 | Simmel
|
||||
0 | Bamford
|
||||
0 | Koblick
|
||||
0 | Maliniak
|
||||
0 | Preusig
|
||||
0 | Zielinski
|
||||
0 | Kalloufi
|
||||
0 | Peac
|
||||
;
|
||||
|
||||
dateTimeHour
|
||||
SELECT HOUR(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
||||
|
||||
d:i | l:s
|
||||
0 | Facello
|
||||
0 | Simmel
|
||||
0 | Bamford
|
||||
0 | Koblick
|
||||
0 | Maliniak
|
||||
0 | Preusig
|
||||
0 | Zielinski
|
||||
0 | Kalloufi
|
||||
0 | Peac
|
||||
d:i | l:s
|
||||
0 | Facello
|
||||
0 | Simmel
|
||||
0 | Bamford
|
||||
0 | Koblick
|
||||
0 | Maliniak
|
||||
0 | Preusig
|
||||
0 | Zielinski
|
||||
0 | Kalloufi
|
||||
0 | Peac
|
||||
|
||||
;
|
||||
|
||||
//
|
||||
// Date (in H2 these start at 0 instead of 1...)
|
||||
//
|
||||
dateTimeDayOfWeek
|
||||
dateTimeDayOfWeek
|
||||
SELECT DAY_OF_WEEK(birth_date) d, last_name l FROM "test_emp" WHERE emp_no < 10010 ORDER BY DAY_OF_WEEK(birth_date);
|
||||
|
||||
d:i | l:s
|
||||
@ -163,3 +163,12 @@ d:i | c:l | s:i
|
||||
2 | 4 | 40081
|
||||
1 | 5 | 50167
|
||||
;
|
||||
|
||||
constantYear
|
||||
// tag::year
|
||||
SELECT YEAR(CAST('2018-01-19T10:23:27Z' AS TIMESTAMP)) as year;
|
||||
|
||||
year
|
||||
2018
|
||||
// end::year
|
||||
;
|
||||
|
Loading…
x
Reference in New Issue
Block a user