提交 2f63fe27 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add support for MILLISECOND and NANOSECOND units

上级 98afcf54
......@@ -3727,7 +3727,8 @@ DAY_OF_YEAR(CREATED)
"Functions (Time and Date)","EXTRACT","
EXTRACT ( { YEAR | YY | MONTH | MM | QUARTER | WEEK | ISO_WEEK
| DAY | DD | DAY_OF_YEAR | DOY
| HOUR | HH | MINUTE | MI | SECOND | SS | MILLISECOND | MS }
| HOUR | HH | MINUTE | MI | SECOND | SS | EPOCH
| MILLISECOND | MS | MICROSECOND | MCS | NANOSECOND | NS }
FROM timestamp )
","
Returns a specific value from a timestamps.
......
......@@ -111,14 +111,9 @@ public class Function extends Expression implements FunctionCall {
ISO_WEEK = 124, ISO_DAY_OF_WEEK = 125;
/**
* Pseudo function for {@code EXTRACT(MILLISECOND FROM ...)}.
* Pseudo functions for DATEADD, DATEDIFF, and EXTRACT.
*/
public static final int MILLISECOND = 126;
/**
* Pseudo function for {@code EXTRACT(EPOCH FROM ...)}.
*/
public static final int EPOCH = 127;
public static final int MILLISECOND = 126, EPOCH = 127, MICROSECOND = 128, NANOSECOND = 129;
public static final int DATABASE = 150, USER = 151, CURRENT_USER = 152,
IDENTITY = 153, SCOPE_IDENTITY = 154, AUTOCOMMIT = 155,
......@@ -206,6 +201,10 @@ public class Function extends Expression implements FunctionCall {
DATE_PART.put("MILLISECOND", MILLISECOND);
DATE_PART.put("MS", MILLISECOND);
DATE_PART.put("EPOCH", EPOCH);
DATE_PART.put("MICROSECOND", MICROSECOND);
DATE_PART.put("MCS", MICROSECOND);
DATE_PART.put("NANOSECOND", NANOSECOND);
DATE_PART.put("NS", NANOSECOND);
// SOUNDEX_INDEX
String index = "7AEIOUY8HW1BFPV2CGJKQSXZ3DT4L5MN6R";
......@@ -864,7 +863,7 @@ public class Function extends Expression implements FunctionCall {
case SECOND:
case WEEK:
case YEAR:
result = ValueInt.get(getDatePart(v0, info.type));
result = ValueInt.get(getIntDatePart(v0, info.type));
break;
case MONTH_NAME: {
SimpleDateFormat monthName = new SimpleDateFormat("MMMM",
......@@ -1502,13 +1501,17 @@ public class Function extends Expression implements FunctionCall {
break;
case EXTRACT: {
int field = getDatePart(v0.getString());
// Normal case when we don't retrieve the EPOCH time
if (field != EPOCH) {
result = ValueInt.get(getDatePart(v1, field));
} else {
switch (field) {
default:
result = ValueInt.get(getIntDatePart(v1, field));
break;
case Function.MICROSECOND:
result = ValueLong.get(DateTimeUtils.dateAndTimeFromValue(v1)[1] / 1_000 % 1_000_000);
break;
case Function.NANOSECOND:
result = ValueLong.get(DateTimeUtils.dateAndTimeFromValue(v1)[1] % 1_000_000_000);
break;
case EPOCH: {
// Case where we retrieve the EPOCH time.
// First we retrieve the dateValue and his time in nanoseconds.
......@@ -1553,6 +1556,7 @@ public class Function extends Expression implements FunctionCall {
result = ValueDecimal.get(timeNanosBigDecimal.divide(nanosSeconds).add(numberOfDays.multiply(secondsPerDay)));
}
}
}
break;
}
case FORMATDATETIME: {
......@@ -1866,8 +1870,7 @@ public class Function extends Expression implements FunctionCall {
private static Value dateadd(String part, long count, Value v) {
int field = getDatePart(part);
//v = v.convertTo(Value.TIMESTAMP);
if (field != MILLISECOND &&
if (field != MILLISECOND && field != MICROSECOND && field != NANOSECOND &&
(count > Integer.MAX_VALUE || count < Integer.MIN_VALUE)) {
throw DbException.getInvalidValueException("DATEADD count", count);
}
......@@ -1923,6 +1926,11 @@ public class Function extends Expression implements FunctionCall {
case MILLISECOND:
count *= 1_000_000;
break;
case MICROSECOND:
count *= 1_000;
break;
case NANOSECOND:
break;
default:
throw DbException.getUnsupportedException("DATEADD " + part);
}
......@@ -1967,6 +1975,8 @@ public class Function extends Expression implements FunctionCall {
long dateValue2 = a2[0];
long absolute2 = DateTimeUtils.absoluteDayFromDateValue(dateValue2);
switch (field) {
case NANOSECOND:
case MICROSECOND:
case MILLISECOND:
case SECOND:
case EPOCH:
......@@ -1975,6 +1985,12 @@ public class Function extends Expression implements FunctionCall {
long timeNanos1 = a1[1];
long timeNanos2 = a2[1];
switch (field) {
case NANOSECOND:
return (absolute2 - absolute1) * DateTimeUtils.NANOS_PER_DAY
+ (timeNanos2 - timeNanos1);
case MICROSECOND:
return (absolute2 - absolute1) * (DateTimeUtils.MILLIS_PER_DAY * 1_000)
+ (timeNanos2 / 1_000 - timeNanos1 / 1_000);
case MILLISECOND:
return (absolute2 - absolute1) * DateTimeUtils.MILLIS_PER_DAY
+ (timeNanos2 / 1_000_000 - timeNanos1 / 1_000_000);
......@@ -2862,7 +2878,7 @@ public class Function extends Expression implements FunctionCall {
* @param field the field type, see {@link Function} for constants
* @return the value
*/
public static int getDatePart(Value date, int field) {
public static int getIntDatePart(Value date, int field) {
long[] a = DateTimeUtils.dateAndTimeFromValue(date);
long dateValue = a[0];
long timeNanos = a[1];
......
......@@ -105,6 +105,18 @@ call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
> 2001-02-03 04:05:06.790001
> rows: 1
SELECT DATEADD('MICROSECOND', 1, TIME '10:00:01'), DATEADD('MCS', 1, TIMESTAMP '2010-10-20 10:00:01.1');
> TIME '10:00:01.000001' TIMESTAMP '2010-10-20 10:00:01.100001'
> ---------------------- --------------------------------------
> 10:00:01.000001 2010-10-20 10:00:01.100001
> rows: 1
SELECT DATEADD('NANOSECOND', 1, TIME '10:00:01'), DATEADD('NS', 1, TIMESTAMP '2010-10-20 10:00:01.1');
> TIME '10:00:01.000000001' TIMESTAMP '2010-10-20 10:00:01.100000001'
> ------------------------- -----------------------------------------
> 10:00:01.000000001 2010-10-20 10:00:01.100000001
> rows: 1
SELECT DATEADD('HOUR', 1, DATE '2010-01-20');
> TIMESTAMP '2010-01-20 01:00:00.0'
> ---------------------------------
......
......@@ -159,6 +159,22 @@ call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 0
> 3408134399000
> rows: 1
SELECT DATEDIFF('MICROSECOND', '2006-01-01 00:00:00.0000000', '2006-01-01 00:00:00.123456789'),
DATEDIFF('MCS', '2006-01-01 00:00:00.0000000', '2006-01-01 00:00:00.123456789'),
DATEDIFF('MCS', '2006-01-01 00:00:00.0000000', '2006-01-02 00:00:00.123456789');
> 123456 123456 86400123456
> ------ ------ -----------
> 123456 123456 86400123456
> rows: 1
SELECT DATEDIFF('NANOSECOND', '2006-01-01 00:00:00.0000000', '2006-01-01 00:00:00.123456789'),
DATEDIFF('NS', '2006-01-01 00:00:00.0000000', '2006-01-01 00:00:00.123456789'),
DATEDIFF('NS', '2006-01-01 00:00:00.0000000', '2006-01-02 00:00:00.123456789');
> 123456789 123456789 86400123456789
> --------- --------- --------------
> 123456789 123456789 86400123456789
> rows: 1
SELECT DATEDIFF('WEEK', DATE '2018-02-02', DATE '2018-02-03'), DATEDIFF('ISO_WEEK', DATE '2018-02-02', DATE '2018-02-03');
> 0 0
> - -
......
......@@ -3,6 +3,20 @@
-- Initial Developer: H2 Group
--
SELECT EXTRACT (MICROSECOND FROM TIME '10:00:00.123456789'),
EXTRACT (MCS FROM TIMESTAMP '2015-01-01 11:22:33.987654321');
> 123456 987654
> ------ ------
> 123456 987654
> rows: 1
SELECT EXTRACT (NANOSECOND FROM TIME '10:00:00.123456789'),
EXTRACT (NS FROM TIMESTAMP '2015-01-01 11:22:33.987654321');
> 123456789 987654321
> --------- ---------
> 123456789 987654321
> rows: 1
select EXTRACT (EPOCH from time '00:00:00');
> 0
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论