升级 JDBC 驱动程序后,Postgres 中到整数的隐式类型转换失败
Posted
技术标签:
【中文标题】升级 JDBC 驱动程序后,Postgres 中到整数的隐式类型转换失败【英文标题】:Implicit type conversions to integers in Postgres fail after upgrading JDBC driver 【发布时间】:2012-12-11 19:19:42 【问题描述】:我的应用程序当前使用 Postgres 8.2 JDBC 驱动程序(带有 Postgres 8.2 数据库),但我们正在升级到 Java 7 和 JDBC 4 驱动程序,目前是 9.2-1002 版本。最终配置将是带有 Postgres 8.2 数据库的 JDBC 9.2 驱动程序。
在我们的一个触发器函数中抛出了一个异常,它只在使用 9.2 驱动程序运行时发生。这是另一个表上的ON UPDATE
触发器。触发器有效地:
DECLARE
mytime bigint;
BEGIN
SELECT INTO mytime EXTRACT(EPOCH FROM current_timestamp(3))*1000;
UPDATE resource SET lastmodified=mytime WHERE id=NEW.resource_id;
END
resource.lastmodified
列定义为 BIGINT 类型。
发生的SQL错误是:
ERROR: invalid input syntax for integer: "1355248911435.9998"
Where: PL/pgSQL function "f_modify_resource" line 4 at SQL statement;
显然错误在SELECT INTO
行;这里应该有一个 BIGINT 的演员表。但是,我想知道为什么该语句使用 8.2 JDBC 驱动程序成功,但在没有其他任何更改的情况下使用 9.2 驱动程序失败?既然触发代码在数据库内部运行,这对 JDBC 驱动程序不应该是透明的吗?我以为 PostgreSQL 会继续在这里进行隐式转换,但它似乎已经停止了。
我尝试在 JDBC 连接 URL 上设置 compatible=8.2
也没有效果。
编辑 以下是使用 9.2-1002.jdbc4 驱动程序运行时语句日志中的输出(我可以确认这至少发生在 9.0 驱动程序之前,可能更早):
STATEMENT: UPDATE message SET hastext='true' WHERE rid='2-1355323570239' AND mid='1-1355329102968'
ERROR: 22P02: invalid input syntax for integer: "1355329102985.0002"
CONTEXT: PL/pgSQL function "f_modify_resource" line 4 at SQL statement
LOCATION: scanint8, int8.c:137
f_modify_resource
函数由ON UPDATE
触发器在message
表上运行,其主体与上面给出的完全相同。第 4 行对应于SELECT INTO
语句。我可以确认EXTRACT(EPOCH...)
确实返回了double precision
,而且确实应该返回。
使用 8.2(jdbc4 和 jdbc3)驱动程序,不会出现此错误,并且语句可以正确处理。
【问题讨论】:
PostgreSQL 8.2 不再受支持(而且真的非常老了)。你真的应该尽快升级。如果这样做,您会遇到隐式类型转换的问题,但越早处理越好。 这在路线图上,但不幸的是不在范围内。 您确定唯一改变的是 JDBC 驱动程序吗?请在postgresql.conf
中启用log_statement = 'all'
,然后使用8.2 和9.2 驱动程序运行您的测试。发布日志。
另外,您确定这是正确的触发器并且 9.2 和 8.2 测试都在完全相同的数据库上吗?并且触发源一模一样?我根本不明白如何从EXTRACT (epoch FROM ...)
获得浮点结果。
测试在完全相同的机器、相同的 Postgres 数据库、相同的软件上运行。我停止它,交换驱动程序 JAR,然后重新启动它。
【参考方案1】:
检查 JDBC 驱动程序是否设置了 *extra_float_digits*。发行说明说,从 8.3-dev602 开始,它在连接时设置为“2”,而通常默认为零。我无法重现您的行为(我只有 9.1 和 9.2 可供测试)。但是,我可以这样做:
postgres=# set extra_float_digits = 2;
SET
postgres=# select extract(epoch from current_timestamp(3));
date_part
--------------------
1355346251.7550001
(1 row)
postgres=# select extract(epoch from current_timestamp(3));
date_part
--------------------
1355346253.1619999
(1 row)
当乘以 1000 并分配给 BIGINT 时,我不能让它失败,但这可能是特定于 8.2 的东西,因此您必须使用 9.2 驱动程序并显式运行语句 SET 进行测试extra_float_digits = 0 在您完成连接之后,但在运行失败的查询之前。
【讨论】:
可能是。这个问题只是间歇性的,因为问题在于浮点精度。我设法得到了1355347361873.0002
和extra_float_digits=2
的结果
我最终通过向函数添加显式强制转换解决了这个问题,但这看起来是问题首先发生的主要候选者。谢谢!以上是关于升级 JDBC 驱动程序后,Postgres 中到整数的隐式类型转换失败的主要内容,如果未能解决你的问题,请参考以下文章
Kafka JDBC Sink 连接器与 PostgreSQL 12 兼容吗?
启动 SpringBoot 应用程序时使用 JDBC 驱动程序创建 Postgres 数据库?