FvH*_*ell 8 java postgresql uuid serialization bytea
我们的一个软件项目使用PostgreSQL表,其中列为'guid',类型为bytea.
这与hibernate 3.3.2.GA和PostgreSQL 8.4一起使用,它使用java对象序列化来序列化java UUID类型.结果是一个类似于以下escape格式的字节bytea文字:
'\254\355\000\005sr\000\016java.util.UUID\274\231\003\367\230m\205/\002\000\002??J\000\014leastSigBitsJ\000\013mostSigBitsxp\273\222)\360*r\322\262u\274\310\020\3??42\004M '
Run Code Online (Sandbox Code Playgroud)
...我们不能轻易地在查询中使用select或条件来检索相关行.
有没有人有办法在查询的select-或where-parts中读取或使用bytea-column(例如通过psql或pgadmin3),而无需设置一些hibernate-query?
更新:请参阅编辑问题,此答案适用于uuid的常见16字节序列化; 问题被修改以反映java序列化.
有趣的问题.我开始编写一个简单的C扩展来高效地完成它,但是使用下面的PL/Python版本可能更为明智.
由于uuid是固定大小的类型,bytea是varlena你不能只create cast ... as implicit以二进制强迫他们,因为可变长度字段标题会碍事.
bytea输入没有内置函数来返回uuid.这是一个方便的事情,但我认为没有人做过.
更新:实际上有一种简单的方法可以做到这一点.bytea十六进制形式实际上是一个有效的uuid文字一旦\x被剥离,因为uuid_in接受普通的未修饰的十六进制没有-或{}.所以就:
regress=> SET bytea_output = 'hex';
SET
regress=> SELECT CAST( substring(CAST (BYTEA '\x0FCC6350118D11E4A5597DE5338EB025' AS text) from 3) AS uuid);
substring
--------------------------------------
0fcc6350-118d-11e4-a559-7de5338eb025
(1 row)
Run Code Online (Sandbox Code Playgroud)
它涉及几个字符串副本和一个十六进制编码/解码周期,但它比我之前建议的任何PL答案快得多,尽管比C慢.
我个人建议使用PL/Perl或pl/pythonu.我会跟进一个例子.
假设你的uuid是十六进制格式的bytea文字:
'\x0FCC6350118D11E4A5597DE5338EB025'
Run Code Online (Sandbox Code Playgroud)
你可以把它变成一个uuid类型:
create language plperlu;
create or replace function to_uuid(bytea) returns uuid language plperlu immutable as $$
use Data::UUID;
my $ug = new Data::UUID;
my $uuid = $ug->from_hexstring(substr($_[0],2));
return $ug->to_string($uuid);
$$
SET bytea_output = hex;
SELECT to_uuid(BYTEA '\x0FCC6350118D11E4A5597DE5338EB025');
Run Code Online (Sandbox Code Playgroud)
它在Python中可能更快更干净,因为PL/Python接口bytea作为原始字节而不是十六进制字符串传递:
CREATE LANGUAGE plpythonu;
CREATE or replace function to_uuid(uuidbytes bytea)
RETURNS uuid LANGUAGE plpythonu IMMUTABLE
AS $$
import uuid
return uuid.UUID(bytes=uuidbytes)
$$;
SELECT to_uuid(BYTEA '\x0FCC6350118D11E4A5597DE5338EB025');
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看C扩展模块.
但实际上,我的意思是说它很难看.如果你想在C中正确完成它,最好实际修补PostgreSQL而不是使用扩展.
经过一番尝试和错误后,我创建了以下函数来提取 postgresql-UUID 值:
CREATE OR REPLACE FUNCTION bytea2uuid (x bytea) RETURNS uuid as $$ SELECT encode(substring(x, 73, 8) || substring(x, 65, 8), 'hex')::uuid $$ language sql;
这是通过提取 java long-values 中使用的 bytes 来实现的,这些字节以相反的顺序存储,而不是编码为十六进制并转换为类型“uuid”。
使用方法如下:
select bytea2uuid(guid) as guid from documents limit 1;
"75bcc810-e204-4d20-bb92-29f02a72d2b2"
| 归档时间: |
|
| 查看次数: |
5352 次 |
| 最近记录: |