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

Add support for MILLISECOND and NANOSECOND units

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