如何使用 JOOQ 将 Postgres "infinity" 插入时间戳字段?
How do I insert Postgres "infinity" into a Timestamp field with JOOQ?
我有一个这样定义的列:
expiry timestamp(0) without time zone not null
使用 Postgres,我可以发出 SQL 比如:
insert into my_table(expiry) values ('infinity')
我一直在研究 JOOQ doco,但找不到任何处理此问题的示例。
我可以用 JOOQ 做到这一点吗?它会是什么样子?
此外,是否可以使用 UpdatableRecord
?我可以使用 Timestamp
的某种无限 "flag" 实例吗?
好的,找到了直接执行的方法。
MyRecord r = db.insertInto(
MY_RECORD,
MY_RECORD.ID,
MY_RECORD.CREATED,
MY_RECORD.EXPIRY
).values(
val(id),
currentTimestamp(),
val("infinity").cast(Timestamp.class)
).returning().fetchOne();
但这感觉更像是一种解决方法,而不是正确的方法。将字符串转换为 timestamp
对我来说似乎有点迂回,所以我写了一个 CustomField
来简化使用和查询:
public class TimestampLiteral extends CustomField<Timestamp> {
public static final TimestampLiteral INFINITY =
new TimestampLiteral("'infinity'");
public static final TimestampLiteral NEGATIVE_INFINITY =
new TimestampLiteral("'-infinity'");
public static final TimestampLiteral TODAY =
new TimestampLiteral("'today'");
private String literalValue;
public TimestampLiteral(String literalValue){
super("timestamp_literal", SQLDataType.TIMESTAMP);
this.literalValue = literalValue;
}
@Override
public void accept(Context<?> context){
context.visit(delegate(context.configuration()));
}
private QueryPart delegate(Configuration configuration){
switch( configuration.dialect().family() ){
case POSTGRES:
return DSL.field(literalValue);
default:
throw new UnsupportedOperationException(
"Dialect not supported because I don't know how/if this works in other databases.");
}
}
}
则查询为:
MyRecord r = db.insertInto(
MY_RECORD,
MY_RECORD.ID,
MY_RECORD.CREATED,
MY_RECORD.EXPIRY
).values(
val(id),
TimestampLiteral.TODAY,
TimestampLiteral.INFINITY
).returning().fetchOne();
不知道这是否一定是 "right" 的方法,但目前看来可行。
仍然有兴趣听听是否有办法用 UpdatableRecord
来做到这一点。
我创建了一个 java.sql.Timestamp
将 org.postgresql.PGStatement.DATE_POSITIVE_INFINITY
传递给它的构造函数。
create.insertInto(
MY_RECORD,
MY_RECORD.ID,
MY_RECORD.CREATED,
MY_RECORD.EXPIRY
).values(
1,
new Timestamp(System.currentTimeMillis()),
new Timestamp(PGStatement.DATE_POSITIVE_INFINITY)
).execute();
我有一个这样定义的列:
expiry timestamp(0) without time zone not null
使用 Postgres,我可以发出 SQL 比如:
insert into my_table(expiry) values ('infinity')
我一直在研究 JOOQ doco,但找不到任何处理此问题的示例。 我可以用 JOOQ 做到这一点吗?它会是什么样子?
此外,是否可以使用 UpdatableRecord
?我可以使用 Timestamp
的某种无限 "flag" 实例吗?
好的,找到了直接执行的方法。
MyRecord r = db.insertInto(
MY_RECORD,
MY_RECORD.ID,
MY_RECORD.CREATED,
MY_RECORD.EXPIRY
).values(
val(id),
currentTimestamp(),
val("infinity").cast(Timestamp.class)
).returning().fetchOne();
但这感觉更像是一种解决方法,而不是正确的方法。将字符串转换为 timestamp
对我来说似乎有点迂回,所以我写了一个 CustomField
来简化使用和查询:
public class TimestampLiteral extends CustomField<Timestamp> {
public static final TimestampLiteral INFINITY =
new TimestampLiteral("'infinity'");
public static final TimestampLiteral NEGATIVE_INFINITY =
new TimestampLiteral("'-infinity'");
public static final TimestampLiteral TODAY =
new TimestampLiteral("'today'");
private String literalValue;
public TimestampLiteral(String literalValue){
super("timestamp_literal", SQLDataType.TIMESTAMP);
this.literalValue = literalValue;
}
@Override
public void accept(Context<?> context){
context.visit(delegate(context.configuration()));
}
private QueryPart delegate(Configuration configuration){
switch( configuration.dialect().family() ){
case POSTGRES:
return DSL.field(literalValue);
default:
throw new UnsupportedOperationException(
"Dialect not supported because I don't know how/if this works in other databases.");
}
}
}
则查询为:
MyRecord r = db.insertInto(
MY_RECORD,
MY_RECORD.ID,
MY_RECORD.CREATED,
MY_RECORD.EXPIRY
).values(
val(id),
TimestampLiteral.TODAY,
TimestampLiteral.INFINITY
).returning().fetchOne();
不知道这是否一定是 "right" 的方法,但目前看来可行。
仍然有兴趣听听是否有办法用 UpdatableRecord
来做到这一点。
我创建了一个 java.sql.Timestamp
将 org.postgresql.PGStatement.DATE_POSITIVE_INFINITY
传递给它的构造函数。
create.insertInto(
MY_RECORD,
MY_RECORD.ID,
MY_RECORD.CREATED,
MY_RECORD.EXPIRY
).values(
1,
new Timestamp(System.currentTimeMillis()),
new Timestamp(PGStatement.DATE_POSITIVE_INFINITY)
).execute();