我的应用程序使用slick(v2.0.0)来管理postgresql(9.1)数据库。
我的一个表包含网络设备,因此包含mac-和ip地址。我使用postgres类型macaddr
和ine
,因为它们似乎是完成任务的完美工具。现在我想使用slick和提升的emebedding,但很难定义我的表。当我自动为我的表生成代码时,我注意到使用了String
而不是这些类型,但并不介意。
这适用于从DB读取,但当我尝试更新或插入一行时,它会导致
org.postgresql.util.PSQLException: ERROR:
column "mac" is of type macaddr but expression is of type character varying
Hint: You will need to rewrite or cast the expression.
维奇似乎很合乎逻辑。
现在的问题是我如何告诉滑头:
macaddr
/net
或
?
更新:
正如Craig所描述的,我使用macaddr_in
和inet_in
周围的包装函数创建了隐式强制转换
\dC macaddr
List of casts
Source type | Target type | Function | Implicit?
-------------+-------------+----------------+-----------
text | macaddr | macaddr_intext | yes
\dC inet
List of casts
Source type | Target type | Function | Implicit?
-------------+-------------------+--------------------+---------------
cidr | inet | (binary coercible) | yes
inet | character | text | in assignment
inet | character varying | text | in assignment
inet | cidr | cidr | in assignment
inet | text | text | in assignment
text | inet | inet_intext | yes
\df+ macaddr_intext
List of functions
Schema | Name | Result data type | Argument data types | Type | Volatility | Owner | Language | Source code | Description
--------+----------------+------------------+---------------------+--------+------------+----------+----------+---------------------------------+-------------
public | macaddr_intext | macaddr | text | normal | immutable | postgres | sql | |
: select macaddr_in($1::cstring);
:
\df+ inet_intext
List of functions
Schema | Name | Result data type | Argument data types | Type | Volatility | Owner | Language | Source code | Description
--------+-------------+------------------+---------------------+--------+------------+----------+----------+------------------------------+-------------
public | inet_intext | inet | text | normal | immutable | postgres | sql | |
: select inet_in($1::cstring);
:
错误消息仍然与上面显示的完全相同。
要复制的标题:
在psql
create or replace function macaddr_intext(text) returns macaddr as $$
select macaddr_in($1::cstring);
$$ language sql immutable;
create cast (text as macaddr) with function macaddr_intext(text) as implicit;
create or replace function inet_intext(text) returns inet as $$
select inet_in($1::cstring);
$$ language sql immutable;
create cast (text as inet) with function inet_intext(text) as implicit;
更新2:
我将其缩小到权限错误,因为如果我以用户postgres
身份运行:
mydb=# create table test(i inet, m macaddr)
CREATE TABLE
mydb=# insert into test values ('1.1.1.1'::text, '00:00:00:00:00:00'::text);
INSERT 0 1
但是如果我尝试以实际尝试插入的用户身份运行它
mydb=> insert into test values ('1.1.1.1'::text, '00:00:00:00:00:00'::text);
ERROR: permission denied for relation test
设置我运行的数据库时:
template1=# GRANT ALL PRIVILEGES ON DATABASE mydb to myuser;
更新3:
Update2被证明是唯一的问题,因为创建的表归postgres
所有,而不是myuser
这是许多人在json
或XML
中遇到的问题的变体,归结为PostgreSQL对数据类型之间的转换过于严格。
请参阅这个答案,它讨论了json
的类似问题。使用转换函数创建强制转换的相同方法在这里是合适的。
您的强制转换函数是macaddr_in
和inet_in
。由于一些恼人的类型问题,您需要编写包装SQL函数来接受text
参数。请参阅上面的链接。
另请参阅xml
类型的相关答案。
更新后,我测试了您的功能,发现它们按预期工作:
postgres=# CREATE TABLE inetmac (i inet, m macaddr);
CREATE TABLE
postgres=# PREPARE insinet(text) AS INSERT INTO inetmac(i) VALUES ($1);
PREPARE
postgres=# EXECUTE insinet('10.1.1.1');
INSERT 0 1
postgres=#
…但是,相当令人惊讶的是,Pg并没有隐式地从varchar
转换为text
以使用text
转换:
postgres=# PREPARE insinet(varchar) AS INSERT INTO inetmac(i) VALUES ($1);
ERROR: column "i" is of type inet but expression is of type character varying
LINE 1: ...PARE insinet(varchar) AS INSERT INTO inetmac(i) VALUES ($1);
^
HINT: You will need to rewrite or cast the expression.
如果您使用varchar
输入,您将需要另一组带有varchar
而不是text
输入的强制转换。
请注意,如果您只是:
INSERT INTO inetmac(i) VALUES ('10.1.1.1');
直接,因为这里'10.1.1.1
是伪类型未知
,并且被解释为net
,因为这是输入所需要的。它有点像一个可以隐式转换为任何输入函数的类型。相比之下,text
和varchar
是Pg必须参考转换规则的具体类型,所以如果不创建转换,这将无法工作:
INSERT INTO inetmac(i) VALUES ('10.1.1.1'::text);
我要在-hacker列表上对此提出一个大惊小怪的问题,人们从客户端接口使用PostgreSQL的扩展类型是多么困难,这只是令人痛苦。当然,所说的客户端接口应该公开一种方法来告诉JDBC驱动程序基本类型是什么,但是如果大多数事情都能处理像索引和复合键这样的极端基础知识,我们就很幸运了,更不用说类型处理的细节了。Pg真的需要对此少一点疯狂,或者提供一种方法来指定参数绑定中的'未知'
伪类型。
大惊小怪:
>
http://www.postgresql.org/message-id/CACTajFZ8 hg_kom6QiVBa94Kx9L3XUqZ99RdUsHBFkSb1MoCPQ@mail.gmail.com
http://www.postgresql.org/message-id/52E87EB0.7010504@2ndquadrant.com