提交 09a3e807 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Merge branch 'master' into generated_keys

...@@ -10,6 +10,7 @@ import java.io.IOException; ...@@ -10,6 +10,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Connection; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
...@@ -61,6 +62,7 @@ import org.h2.value.ValueArray; ...@@ -61,6 +62,7 @@ import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean; import org.h2.value.ValueBoolean;
import org.h2.value.ValueBytes; import org.h2.value.ValueBytes;
import org.h2.value.ValueDate; import org.h2.value.ValueDate;
import org.h2.value.ValueDecimal;
import org.h2.value.ValueDouble; import org.h2.value.ValueDouble;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueLong; import org.h2.value.ValueLong;
...@@ -69,6 +71,7 @@ import org.h2.value.ValueResultSet; ...@@ -69,6 +71,7 @@ import org.h2.value.ValueResultSet;
import org.h2.value.ValueString; import org.h2.value.ValueString;
import org.h2.value.ValueTime; import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp; import org.h2.value.ValueTimestamp;
import org.h2.value.ValueTimestampTimeZone;
import org.h2.value.ValueUuid; import org.h2.value.ValueUuid;
/** /**
...@@ -112,6 +115,11 @@ public class Function extends Expression implements FunctionCall { ...@@ -112,6 +115,11 @@ public class Function extends Expression implements FunctionCall {
*/ */
public static final int MILLISECOND = 126; public static final int MILLISECOND = 126;
/**
* 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,
READONLY = 156, DATABASE_PATH = 157, LOCK_TIMEOUT = 158, READONLY = 156, DATABASE_PATH = 157, LOCK_TIMEOUT = 158,
...@@ -197,6 +205,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -197,6 +205,7 @@ public class Function extends Expression implements FunctionCall {
DATE_PART.put("S", SECOND); DATE_PART.put("S", SECOND);
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);
// SOUNDEX_INDEX // SOUNDEX_INDEX
String index = "7AEIOUY8HW1BFPV2CGJKQSXZ3DT4L5MN6R"; String index = "7AEIOUY8HW1BFPV2CGJKQSXZ3DT4L5MN6R";
...@@ -1493,7 +1502,57 @@ public class Function extends Expression implements FunctionCall { ...@@ -1493,7 +1502,57 @@ public class Function extends Expression implements FunctionCall {
break; break;
case EXTRACT: { case EXTRACT: {
int field = getDatePart(v0.getString()); int field = getDatePart(v0.getString());
// Normal case when we don't retrieve the EPOCH time
if (field != EPOCH) {
result = ValueInt.get(getDatePart(v1, field)); result = ValueInt.get(getDatePart(v1, field));
} else {
// Case where we retrieve the EPOCH time.
// First we retrieve the dateValue and his time in nanoseconds.
long[] a = DateTimeUtils.dateAndTimeFromValue(v1);
long dateValue = a[0];
long timeNanos = a[1];
// We compute the time in nanoseconds and the total number of days.
BigDecimal timeNanosBigDecimal = new BigDecimal(timeNanos);
BigDecimal numberOfDays = new BigDecimal(DateTimeUtils.absoluteDayFromDateValue(dateValue));
BigDecimal nanosSeconds = new BigDecimal(1_000_000_000);
BigDecimal secondsPerDay = new BigDecimal(DateTimeUtils.SECONDS_PER_DAY);
// Case where the value is of type time e.g. '10:00:00'
if (v1 instanceof ValueTime) {
// In order to retrieve the EPOCH time we only have to convert the time
// in nanoseconds (previously retrieved) in seconds.
result = ValueDecimal.get(timeNanosBigDecimal.divide(nanosSeconds));
} else if (v1 instanceof ValueDate) {
// Case where the value is of type date '2000:01:01', we have to retrieve the total
// number of days and multiply it by the number of seconds in a day.
result = ValueDecimal.get(numberOfDays.multiply(secondsPerDay));
} else if (v1 instanceof ValueTimestampTimeZone) {
// Case where the value is a of type ValueTimestampTimeZone ('2000:01:01 10:00:00+05).
// We retrieve the time zone offset in minute
ValueTimestampTimeZone v = (ValueTimestampTimeZone) v1;
BigDecimal timeZoneOffsetSeconds = new BigDecimal(v.getTimeZoneOffsetMins() * 60);
// Sum the time in nanoseconds and the total number of days in seconds
// and adding the timeZone offset in seconds.
result = ValueDecimal.get(timeNanosBigDecimal.divide(nanosSeconds)
.add(numberOfDays.multiply(secondsPerDay))
.subtract(timeZoneOffsetSeconds));
} else {
// By default, we have the date and the time ('2000:01:01 10:00:00) if no type is given.
// We just have to sum the time in nanoseconds and the total number of days in seconds.
result = ValueDecimal.get(timeNanosBigDecimal.divide(nanosSeconds).add(numberOfDays.multiply(secondsPerDay)));
}
}
break; break;
} }
case FORMATDATETIME: { case FORMATDATETIME: {
......
...@@ -37,6 +37,11 @@ public class DateTimeUtils { ...@@ -37,6 +37,11 @@ public class DateTimeUtils {
*/ */
public static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L; public static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
/**
* The number of seconds per day.
*/
public static final long SECONDS_PER_DAY = 24 * 60 * 60;
/** /**
* UTC time zone. * UTC time zone.
*/ */
......
...@@ -92,6 +92,7 @@ public class TestScript extends TestBase { ...@@ -92,6 +92,7 @@ public class TestScript extends TestBase {
} else { } else {
decimal2 = "decimal_numeric"; decimal2 = "decimal_numeric";
} }
for (String s : new String[] { "array", "bigint", "binary", "blob", for (String s : new String[] { "array", "bigint", "binary", "blob",
"boolean", "char", "clob", "date", "decimal", decimal2, "double", "enum", "boolean", "char", "clob", "date", "decimal", decimal2, "double", "enum",
"geometry", "identity", "int", "other", "real", "smallint", "geometry", "identity", "int", "other", "real", "smallint",
......
...@@ -2,3 +2,42 @@ ...@@ -2,3 +2,42 @@
-- and the EPL 1.0 (http://h2database.com/html/license.html). -- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group -- Initial Developer: H2 Group
-- --
select EXTRACT (EPOCH from time '00:00:00');
> 0
select EXTRACT (EPOCH from time '10:00:00');
> 36000
select EXTRACT (EPOCH from time '10:00:00.123456');
> 36000.123456
select EXTRACT (EPOCH from date '1970-01-01');
> 0
select EXTRACT (EPOCH from date '2000-01-03');
> 946857600
select EXTRACT (EPOCH from timestamp '1970-01-01 00:00:00');
> 0
select EXTRACT (EPOCH from timestamp '1970-01-03 12:00:00.123456');
> 216000.123456
select EXTRACT (EPOCH from timestamp '2000-01-03 12:00:00.123456');
> 946900800.123456
select EXTRACT (EPOCH from timestamp '2500-01-03 12:00:00.654321');
> 16725441600.654321
select EXTRACT (EPOCH from timestamp with time zone '1970-01-01 00:00:00+05');
> -18000
select EXTRACT (EPOCH from timestamp with time zone '1970-01-03 12:00:00.123456+05');
> 198000.123456
select EXTRACT (EPOCH from timestamp with time zone '2000-01-03 12:00:00.123456+05');
> 946882800.123456
select extract(EPOCH from '2001-02-03 14:15:16');
> 981209716
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论