Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
ae038f3c
提交
ae038f3c
authored
6 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for java.time.Period
上级
8469b131
master
version-1.4.198
无相关合并请求
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
184 行增加
和
7 行删除
+184
-7
help.csv
h2/src/docsrc/help/help.csv
+3
-0
JdbcResultSet.java
h2/src/main/org/h2/jdbc/JdbcResultSet.java
+2
-0
LocalDateTimeUtils.java
h2/src/main/org/h2/util/LocalDateTimeUtils.java
+123
-1
DataType.java
h2/src/main/org/h2/value/DataType.java
+2
-0
Value.java
h2/src/main/org/h2/value/Value.java
+1
-1
TestPreparedStatement.java
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
+39
-0
TestResultSet.java
h2/src/test/org/h2/test/jdbc/TestResultSet.java
+14
-5
没有找到文件。
h2/src/docsrc/help/help.csv
浏览文件 @
ae038f3c
...
...
@@ -3260,6 +3260,7 @@ Interval data type.
If precision is specified it should be from 1 to 18, 2 is default.
Mapped to ""org.h2.api.Interval"".
""java.time.Period"" is also supported on Java 8 and later versions.
","
INTERVAL YEAR
"
...
...
@@ -3271,6 +3272,7 @@ Interval data type.
If precision is specified it should be from 1 to 18, 2 is default.
Mapped to ""org.h2.api.Interval"".
""java.time.Period"" is also supported on Java 8 and later versions.
","
INTERVAL MONTH
"
...
...
@@ -3331,6 +3333,7 @@ Interval data type.
If leading field precision is specified it should be from 1 to 18, 2 is default.
Mapped to ""org.h2.api.Interval"".
""java.time.Period"" is also supported on Java 8 and later versions.
","
INTERVAL YEAR TO MONTH
"
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/jdbc/JdbcResultSet.java
浏览文件 @
ae038f3c
...
...
@@ -3949,6 +3949,8 @@ public class JdbcResultSet extends TraceObject implements ResultSet, JdbcResultS
return
type
.
cast
(
LocalDateTimeUtils
.
valueToInstant
(
value
));
}
else
if
(
type
==
LocalDateTimeUtils
.
OFFSET_DATE_TIME
)
{
return
type
.
cast
(
LocalDateTimeUtils
.
valueToOffsetDateTime
(
value
));
}
else
if
(
type
==
LocalDateTimeUtils
.
PERIOD
)
{
return
type
.
cast
(
LocalDateTimeUtils
.
valueToPeriod
(
value
));
}
else
if
(
type
==
LocalDateTimeUtils
.
DURATION
)
{
return
type
.
cast
(
LocalDateTimeUtils
.
valueToDuration
(
value
));
}
else
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/util/LocalDateTimeUtils.java
浏览文件 @
ae038f3c
...
...
@@ -70,6 +70,11 @@ public class LocalDateTimeUtils {
*/
private
static
final
Class
<?>
ZONE_OFFSET
;
/**
* {@code Class<java.time.Period>} or {@code null}.
*/
public
static
final
Class
<?>
PERIOD
;
/**
* {@code Class<java.time.Duration>} or {@code null}.
*/
...
...
@@ -156,6 +161,26 @@ public class LocalDateTimeUtils {
*/
private
static
final
Method
ZONE_OFFSET_GET_TOTAL_SECONDS
;
/**
* {@code java.time.Period#of(int, int, int)} or {@code null}.
*/
private
static
final
Method
PERIOD_OF
;
/**
* {@code java.time.Period#getYears()} or {@code null}.
*/
private
static
final
Method
PERIOD_GET_YEARS
;
/**
* {@code java.time.Period#getMonths()} or {@code null}.
*/
private
static
final
Method
PERIOD_GET_MONTHS
;
/**
* {@code java.time.Period#getDays()} or {@code null}.
*/
private
static
final
Method
PERIOD_GET_DAYS
;
/**
* {@code java.time.Duration#ofSeconds(long, long)} or {@code null}.
*/
...
...
@@ -180,10 +205,11 @@ public class LocalDateTimeUtils {
INSTANT
=
tryGetClass
(
"java.time.Instant"
);
OFFSET_DATE_TIME
=
tryGetClass
(
"java.time.OffsetDateTime"
);
ZONE_OFFSET
=
tryGetClass
(
"java.time.ZoneOffset"
);
PERIOD
=
tryGetClass
(
"java.time.Period"
);
DURATION
=
tryGetClass
(
"java.time.Duration"
);
IS_JAVA8_DATE_API_PRESENT
=
LOCAL_DATE
!=
null
&&
LOCAL_TIME
!=
null
&&
LOCAL_DATE_TIME
!=
null
&&
INSTANT
!=
null
&&
OFFSET_DATE_TIME
!=
null
&&
ZONE_OFFSET
!=
null
&&
DURATION
!=
null
;
OFFSET_DATE_TIME
!=
null
&&
ZONE_OFFSET
!=
null
&&
PERIOD
!=
null
&&
DURATION
!=
null
;
if
(
IS_JAVA8_DATE_API_PRESENT
)
{
LOCAL_TIME_OF_NANO
=
getMethod
(
LOCAL_TIME
,
"ofNanoOfDay"
,
long
.
class
);
...
...
@@ -214,6 +240,11 @@ public class LocalDateTimeUtils {
ZONE_OFFSET_GET_TOTAL_SECONDS
=
getMethod
(
ZONE_OFFSET
,
"getTotalSeconds"
);
PERIOD_OF
=
getMethod
(
PERIOD
,
"of"
,
int
.
class
,
int
.
class
,
int
.
class
);
PERIOD_GET_YEARS
=
getMethod
(
PERIOD
,
"getYears"
);
PERIOD_GET_MONTHS
=
getMethod
(
PERIOD
,
"getMonths"
);
PERIOD_GET_DAYS
=
getMethod
(
PERIOD
,
"getDays"
);
DURATION_OF_SECONDS
=
getMethod
(
DURATION
,
"ofSeconds"
,
long
.
class
,
long
.
class
);
DURATION_GET_SECONDS
=
getMethod
(
DURATION
,
"getSeconds"
);
DURATION_GET_NANO
=
getMethod
(
DURATION
,
"getNano"
);
...
...
@@ -236,6 +267,10 @@ public class LocalDateTimeUtils {
OFFSET_DATE_TIME_GET_OFFSET
=
null
;
OFFSET_DATE_TIME_OF_LOCAL_DATE_TIME_ZONE_OFFSET
=
null
;
ZONE_OFFSET_GET_TOTAL_SECONDS
=
null
;
PERIOD_OF
=
null
;
PERIOD_GET_YEARS
=
null
;
PERIOD_GET_MONTHS
=
null
;
PERIOD_GET_DAYS
=
null
;
DURATION_OF_SECONDS
=
null
;
DURATION_GET_SECONDS
=
null
;
DURATION_GET_NANO
=
null
;
...
...
@@ -382,6 +417,37 @@ public class LocalDateTimeUtils {
}
}
/**
* Converts a value to a Period.
*
* <p>This method should only called from Java 8 or later.</p>
*
* @param value the value to convert
* @return the Period
*/
public
static
Object
valueToPeriod
(
Value
value
)
{
if
(!(
value
instanceof
ValueInterval
))
{
value
=
value
.
convertTo
(
Value
.
INTERVAL_YEAR_TO_MONTH
);
}
if
(!
DataType
.
isYearMonthIntervalType
(
value
.
getType
()))
{
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
(
Throwable
)
null
,
value
.
getString
());
}
ValueInterval
v
=
(
ValueInterval
)
value
;
IntervalQualifier
qualifier
=
v
.
getQualifier
();
boolean
negative
=
v
.
isNegative
();
long
leading
=
v
.
getLeading
();
long
remaining
=
v
.
getRemaining
();
int
y
=
Value
.
convertToInt
(
IntervalUtils
.
yearsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
),
null
);
int
m
=
Value
.
convertToInt
(
IntervalUtils
.
monthsFromInterval
(
qualifier
,
negative
,
leading
,
remaining
),
null
);
try
{
return
PERIOD_OF
.
invoke
(
null
,
y
,
m
,
0
);
}
catch
(
IllegalAccessException
e
)
{
throw
DbException
.
convert
(
e
);
}
catch
(
InvocationTargetException
e
)
{
throw
DbException
.
convertInvocation
(
e
,
"timestamp with time zone conversion failed"
);
}
}
/**
* Converts a value to a Duration.
*
...
...
@@ -552,6 +618,62 @@ public class LocalDateTimeUtils {
return
LOCAL_DATE_TIME_PLUS_NANOS
.
invoke
(
localDateTime
,
timeNanos
);
}
/**
* Converts a Period to a Value.
*
* @param period the Period to convert, not {@code null}
* @return the value
*/
public
static
ValueInterval
periodToValue
(
Object
period
)
{
try
{
int
days
=
(
int
)
PERIOD_GET_DAYS
.
invoke
(
period
);
if
(
days
!=
0
)
{
throw
DbException
.
getInvalidValueException
(
"Period.days"
,
days
);
}
int
years
=
(
int
)
PERIOD_GET_YEARS
.
invoke
(
period
);
int
months
=
(
int
)
PERIOD_GET_MONTHS
.
invoke
(
period
);
IntervalQualifier
qualifier
;
boolean
negative
=
false
;
long
leading
=
0L
,
remaining
=
0L
;
if
(
years
==
0
)
{
if
(
months
==
0L
)
{
// Use generic qualifier
qualifier
=
IntervalQualifier
.
YEAR_TO_MONTH
;
}
else
{
qualifier
=
IntervalQualifier
.
MONTH
;
leading
=
months
;
if
(
leading
<
0
)
{
leading
=
-
leading
;
negative
=
true
;
}
}
}
else
{
if
(
months
==
0L
)
{
qualifier
=
IntervalQualifier
.
YEAR
;
leading
=
years
;
if
(
leading
<
0
)
{
leading
=
-
leading
;
negative
=
true
;
}
}
else
{
qualifier
=
IntervalQualifier
.
YEAR_TO_MONTH
;
leading
=
years
*
12
+
months
;
if
(
leading
<
0
)
{
leading
=
-
leading
;
negative
=
true
;
}
remaining
=
leading
%
12
;
leading
/=
12
;
}
}
return
ValueInterval
.
from
(
qualifier
,
negative
,
leading
,
remaining
);
}
catch
(
IllegalAccessException
e
)
{
throw
DbException
.
convert
(
e
);
}
catch
(
InvocationTargetException
e
)
{
throw
DbException
.
convertInvocation
(
e
,
"interval conversion failed"
);
}
}
/**
* Converts a Duration to a Value.
*
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/DataType.java
浏览文件 @
ae038f3c
...
...
@@ -1285,6 +1285,8 @@ public class DataType {
}
else
if
(
x
instanceof
Interval
)
{
Interval
i
=
(
Interval
)
x
;
return
ValueInterval
.
from
(
i
.
getQualifier
(),
i
.
isNegative
(),
i
.
getLeading
(),
i
.
getRemaining
());
}
else
if
(
clazz
==
LocalDateTimeUtils
.
PERIOD
)
{
return
LocalDateTimeUtils
.
periodToValue
(
x
);
}
else
if
(
clazz
==
LocalDateTimeUtils
.
DURATION
)
{
return
LocalDateTimeUtils
.
durationToValue
(
x
);
}
else
{
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/value/Value.java
浏览文件 @
ae038f3c
...
...
@@ -1405,7 +1405,7 @@ public abstract class Value {
return
(
short
)
x
;
}
p
rivate
static
int
convertToInt
(
long
x
,
Object
column
)
{
p
ublic
static
int
convertToInt
(
long
x
,
Object
column
)
{
if
(
x
>
Integer
.
MAX_VALUE
||
x
<
Integer
.
MIN_VALUE
)
{
throw
DbException
.
get
(
ErrorCode
.
NUMERIC_VALUE_OUT_OF_RANGE_2
,
Long
.
toString
(
x
),
getColumnName
(
column
));
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/jdbc/TestPreparedStatement.java
浏览文件 @
ae038f3c
...
...
@@ -923,6 +923,23 @@ public class TestPreparedStatement extends TestDb {
return
;
}
PreparedStatement
prep
=
conn
.
prepareStatement
(
"SELECT ?"
);
testPeriod8
(
prep
,
1
,
2
,
"INTERVAL '1-2' YEAR TO MONTH"
);
testPeriod8
(
prep
,
-
1
,
-
2
,
"INTERVAL '-1-2' YEAR TO MONTH"
);
testPeriod8
(
prep
,
1
,
-
8
,
"INTERVAL '0-4' YEAR TO MONTH"
,
0
,
4
);
testPeriod8
(
prep
,
-
1
,
8
,
"INTERVAL '-0-4' YEAR TO MONTH"
,
0
,
-
4
);
testPeriod8
(
prep
,
0
,
0
,
"INTERVAL '0-0' YEAR TO MONTH"
);
testPeriod8
(
prep
,
100
,
0
,
"INTERVAL '100' YEAR"
);
testPeriod8
(
prep
,
-
100
,
0
,
"INTERVAL '-100' YEAR"
);
testPeriod8
(
prep
,
0
,
100
,
"INTERVAL '100' MONTH"
);
testPeriod8
(
prep
,
0
,
-
100
,
"INTERVAL '-100' MONTH"
);
Object
period
;
try
{
Method
method
=
LocalDateTimeUtils
.
PERIOD
.
getMethod
(
"of"
,
int
.
class
,
int
.
class
,
int
.
class
);
period
=
method
.
invoke
(
null
,
0
,
0
,
1
);
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
assertThrows
(
ErrorCode
.
INVALID_VALUE_2
,
prep
).
setObject
(
1
,
period
);
Object
duration
;
try
{
duration
=
LocalDateTimeUtils
.
DURATION
.
getMethod
(
"ofSeconds"
,
long
.
class
,
long
.
class
)
...
...
@@ -937,6 +954,28 @@ public class TestPreparedStatement extends TestDb {
assertEquals
(
duration
,
rs
.
getObject
(
1
,
LocalDateTimeUtils
.
DURATION
));
}
private
void
testPeriod8
(
PreparedStatement
prep
,
int
years
,
int
months
,
String
expectedString
)
throws
SQLException
{
testPeriod8
(
prep
,
years
,
months
,
expectedString
,
years
,
months
);
}
private
void
testPeriod8
(
PreparedStatement
prep
,
int
years
,
int
months
,
String
expectedString
,
int
expYears
,
int
expMonths
)
throws
SQLException
{
Object
period
,
expectedPeriod
;
try
{
Method
method
=
LocalDateTimeUtils
.
PERIOD
.
getMethod
(
"of"
,
int
.
class
,
int
.
class
,
int
.
class
);
period
=
method
.
invoke
(
null
,
years
,
months
,
0
);
expectedPeriod
=
method
.
invoke
(
null
,
expYears
,
expMonths
,
0
);
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
prep
.
setObject
(
1
,
period
);
ResultSet
rs
=
prep
.
executeQuery
();
rs
.
next
();
assertEquals
(
expectedString
,
rs
.
getString
(
1
));
assertEquals
(
expectedPeriod
,
rs
.
getObject
(
1
,
LocalDateTimeUtils
.
PERIOD
));
}
private
void
testPreparedSubquery
(
Connection
conn
)
throws
SQLException
{
Statement
s
=
conn
.
createStatement
();
s
.
executeUpdate
(
"CREATE TABLE TEST(ID IDENTITY, FLAG BIT)"
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/jdbc/TestResultSet.java
浏览文件 @
ae038f3c
...
...
@@ -1589,11 +1589,23 @@ public class TestResultSet extends TestDb {
}
trace
(
"Test INTERVAL 8"
);
ResultSet
rs
;
Object
expected
;
rs
=
stat
.
executeQuery
(
"CALL INTERVAL '1-2' YEAR TO MONTH"
);
rs
.
next
();
assertEquals
(
"INTERVAL '1-2' YEAR TO MONTH"
,
rs
.
getString
(
1
));
try
{
expected
=
LocalDateTimeUtils
.
PERIOD
.
getMethod
(
"of"
,
int
.
class
,
int
.
class
,
int
.
class
)
.
invoke
(
null
,
1
,
2
,
0
);
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
assertEquals
(
expected
,
rs
.
getObject
(
1
,
LocalDateTimeUtils
.
PERIOD
));
assertThrows
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
rs
).
getObject
(
1
,
LocalDateTimeUtils
.
DURATION
);
rs
=
stat
.
executeQuery
(
"CALL INTERVAL '-3.1' SECOND"
);
rs
.
next
();
assertEquals
(
"INTERVAL '-3.1' SECOND"
,
rs
.
getString
(
1
));
Object
expected
;
try
{
expected
=
LocalDateTimeUtils
.
DURATION
.
getMethod
(
"ofSeconds"
,
long
.
class
,
long
.
class
)
.
invoke
(
null
,
-
4
,
900_000_000
);
...
...
@@ -1601,10 +1613,7 @@ public class TestResultSet extends TestDb {
throw
new
RuntimeException
(
ex
);
}
assertEquals
(
expected
,
rs
.
getObject
(
1
,
LocalDateTimeUtils
.
DURATION
));
rs
=
stat
.
executeQuery
(
"CALL INTERVAL '1-2' YEAR TO MONTH"
);
rs
.
next
();
assertThrows
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
rs
).
getObject
(
1
,
LocalDateTimeUtils
.
DURATION
);
assertThrows
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
rs
).
getObject
(
1
,
LocalDateTimeUtils
.
PERIOD
);
}
private
void
testBlob
()
throws
SQLException
{
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论