如何在不更改客户端代码的情况下将 varchar 转换为 macaddr

Den*_*lte 2 postgresql jdbc cast

我有一个带有 Debian Jessie 和 Postgresql 9.4 的专用数据库服务器

客户端:A 是一个 Tomcat Java 应用程序,它使用扭矩与连接到数据库服务器的 JDBC 驱动程序。

问题:在使用新值更新行时,更新失败,因为应用程序传输了错误的数据类型。

错误信息:

列“device_macaddr”的类型是 macaddr,但表达式的类型是在字符 159 处变化的字符

Torque 生成的更新语句:

UPDATE device SET device_last_change = $1, device_macaddr = $2 WHERE device_ID = $3
Run Code Online (Sandbox Code Playgroud)

postgresql 中数据类型的定义:

last_change is timestamp (0) without time zone NOT NULL
device_macaddr is macaddr NOT NULL
device_id is bigint NOT NULL
Run Code Online (Sandbox Code Playgroud)

我们最近确实将 DB 和 jdbc 驱动程序从 8.4 更新到 9.4

我能够查明对 jdbc 驱动程序的更改,但无法找到准确显示此行为更改的更改日志。

从那以后,上面的语句似乎不再起作用,而尽管当时可能是错误的数据类型,但它以前仍然起作用。

有没有办法“减轻”来自 Postgres 9.4 DB Server 的针对特定情况的严格检测?

我确实阅读了 jdbc 驱动程序的增强以包含那些额外的数据类型,但是这对我来说还没有用,所以我尝试在我拥有的选项的另一端找到解决方法。

dez*_*zso 6

无耻地从克雷格的回答中窃取了 SO

您需要创建一个强制转换以使varchar->macaddr强制自动工作。这有点棘手,因为没有函数可以做到这一点,所以我们必须将内部函数包装成我们可以使用的东西:

CREATE TABLE mac (addr macaddr);

INSERT INTO mac VALUES ('11:11:11:11:11:11'::varchar);
=> ERROR:  column "addr" is of type macaddr but expression is of type character varying

CREATE OR REPLACE FUNCTION macaddr_invarchar(varchar) 
RETURNS macaddr LANGUAGE SQL AS $$
    SELECT macaddr_in($1::cstring);
$$ IMMUTABLE;

CREATE CAST (varchar AS macaddr) WITH FUNCTION macaddr_invarchar(varchar) AS IMPLICIT;

INSERT INTO mac VALUES ('11:11:11:11:11:11'::varchar);
=> INSERT 0 1
Run Code Online (Sandbox Code Playgroud)