数值超出范围减去 jOOQ 中的日期
Numeric value out of range subtracting dates in jOOQ
我正在尝试使用 H2 数据库 (v1.4.185) 比较 jOOQ (v3.5.0) 中的日期,但如果比较太大,我会得到 "Numeric value out of range"。
例如,使用以下 table
CREATE TABLE example (
id INT AUTO_INCREMENT,
deadline TIMESTAMP,
PRIMARY KEY (id)
);
并使用以下示例代码(未显示 jOOQ 的代码生成步骤)
DSLContext dsl = DSL.using(getDataSource(dbUrl), SQLDialect.H2);
ExampleRecord exampleRecord = dsl.newRecord(EXAMPLE);
exampleRecord.setDeadline(Timestamp.valueOf("2001-01-10 12:15:30"));
exampleRecord.store();
dsl.selectFrom(EXAMPLE)
.where(EXAMPLE.DEADLINE.sub(
DayToSecond.valueOf(Duration.ofDays(30).toMillis()))
.le(currentTimestamp()))
.fetch().forEach(record -> System.out.println(record.getDeadline()));
产生以下错误
Exception in thread "main" org.jooq.exception.DataAccessException:
SQL [select "EXAMPLE"."ID", "EXAMPLE"."DEADLINE" from "EXAMPLE"
where dateadd('ms', cast(? as bigint), "EXAMPLE"."DEADLINE")
<= current_timestamp()];
Numeric value out of range: "-2592000000";
SQL statement:
select "EXAMPLE"."ID", "EXAMPLE"."DEADLINE" from "EXAMPLE"
where dateadd('ms', cast(? as bigint), "EXAMPLE"."DEADLINE")
<= current_timestamp() [22003-185]
这个错误对我来说没有意义。生成的 SQL (bigint
) 表明 jOOQ 知道参数是 long
并且 -2592000000
完全在限制范围内。
我想知道错误消息是否添加了引号,或者如果 DayToSecond.toMillis()
可能 returns 是 String
而不是 long
。除了我会期待一个不同的错误消息(加上一个编译错误)。
为了安全起见,尝试用常量替换代码来降低表达式的复杂性:
dsl.selectFrom(EXAMPLE)
.where(EXAMPLE.DEADLINE.sub(-2592000000L))
...
只是为了看看这对错误有何影响。
在我看来,这像是 H2 中的一个缺陷。 H2 的DATEADD()
function expects the number of units added to be of type int
. That doesn't make sense when operating with milliseconds, of course. I've reported it on the H2 user group。让我们看看他们怎么说。如果这不能在 H2 中得到纠正,我们将在 jOOQ 中解决它,就像我们对 Sybase 和其他数据库所做的那样。
解决方法:
Field.sub(Number)
方法在用于日期时间算术时已经从时间戳中减去天数(如 Oracle)。因此,您 可以 编写与以下相同的表达式:
EXAMPLE.DEADLINE.sub(30)
另一种选择是使用 DSL.timestampAdd()
代替:
timestampAdd(EXAMPLE.DEADLINE, -30, DatePart.DAY);
第三种选择是使用普通的 SQL:
public static Field<Timestamp> mySub(Field<Timestamp> field, Number days) {
return DSL.field("dateadd('day', {0}, {1})", Timestamp.class, val(-days), field);
}
我正在尝试使用 H2 数据库 (v1.4.185) 比较 jOOQ (v3.5.0) 中的日期,但如果比较太大,我会得到 "Numeric value out of range"。
例如,使用以下 table
CREATE TABLE example (
id INT AUTO_INCREMENT,
deadline TIMESTAMP,
PRIMARY KEY (id)
);
并使用以下示例代码(未显示 jOOQ 的代码生成步骤)
DSLContext dsl = DSL.using(getDataSource(dbUrl), SQLDialect.H2);
ExampleRecord exampleRecord = dsl.newRecord(EXAMPLE);
exampleRecord.setDeadline(Timestamp.valueOf("2001-01-10 12:15:30"));
exampleRecord.store();
dsl.selectFrom(EXAMPLE)
.where(EXAMPLE.DEADLINE.sub(
DayToSecond.valueOf(Duration.ofDays(30).toMillis()))
.le(currentTimestamp()))
.fetch().forEach(record -> System.out.println(record.getDeadline()));
产生以下错误
Exception in thread "main" org.jooq.exception.DataAccessException:
SQL [select "EXAMPLE"."ID", "EXAMPLE"."DEADLINE" from "EXAMPLE"
where dateadd('ms', cast(? as bigint), "EXAMPLE"."DEADLINE")
<= current_timestamp()];
Numeric value out of range: "-2592000000";
SQL statement:
select "EXAMPLE"."ID", "EXAMPLE"."DEADLINE" from "EXAMPLE"
where dateadd('ms', cast(? as bigint), "EXAMPLE"."DEADLINE")
<= current_timestamp() [22003-185]
这个错误对我来说没有意义。生成的 SQL (bigint
) 表明 jOOQ 知道参数是 long
并且 -2592000000
完全在限制范围内。
我想知道错误消息是否添加了引号,或者如果 DayToSecond.toMillis()
可能 returns 是 String
而不是 long
。除了我会期待一个不同的错误消息(加上一个编译错误)。
为了安全起见,尝试用常量替换代码来降低表达式的复杂性:
dsl.selectFrom(EXAMPLE)
.where(EXAMPLE.DEADLINE.sub(-2592000000L))
...
只是为了看看这对错误有何影响。
在我看来,这像是 H2 中的一个缺陷。 H2 的DATEADD()
function expects the number of units added to be of type int
. That doesn't make sense when operating with milliseconds, of course. I've reported it on the H2 user group。让我们看看他们怎么说。如果这不能在 H2 中得到纠正,我们将在 jOOQ 中解决它,就像我们对 Sybase 和其他数据库所做的那样。
解决方法:
Field.sub(Number)
方法在用于日期时间算术时已经从时间戳中减去天数(如 Oracle)。因此,您 可以 编写与以下相同的表达式:
EXAMPLE.DEADLINE.sub(30)
另一种选择是使用 DSL.timestampAdd()
代替:
timestampAdd(EXAMPLE.DEADLINE, -30, DatePart.DAY);
第三种选择是使用普通的 SQL:
public static Field<Timestamp> mySub(Field<Timestamp> field, Number days) {
return DSL.field("dateadd('day', {0}, {1})", Timestamp.class, val(-days), field);
}