更新:请参阅问题编辑,此答案适用于常见的 16 字节序列化 uuid;该问题已修改以反映java 序列化。
有趣的问题。我开始编写一个简单的 C 扩展来有效地完成它,但使用下面的 PL/Python 版本可能更明智。
因为uuid
是一个固定大小的类型,bytea
你varlena
不能仅仅create cast ... as implicit
对它们进行二进制强制,因为可变长度的字段标题会妨碍它们。
bytea 输入没有返回 uuid 的内置函数。拥有它会很方便,但我认为还没有人做过。
最简单的方法
更新:实际上有一种简单的方法可以做到这一点。bytea
十六进制形式实际上是一个有效的 uuid 文字,一旦\x
被剥离,因为接受没有or的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)
它涉及几个字符串副本和一个十六进制编码/解码周期,但它比我之前建议的任何 PL 答案都要快很多,尽管比 C 慢。
其他选项
我个人推荐使用 PL/Perl 或 pl/pythonu。我会跟进一个例子。
假设您的 uuid 是十六进制格式的 bytea 文字:
'\x0FCC6350118D11E4A5597DE5338EB025'
你可以把它变成一个uuid
类型:
PL/Perl
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');
PL/Python
它在 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');
在 C 中,只是为了踢球。丑陋的黑客。
您可以在此处查看 C 扩展模块。
但实际上,我的意思是它很丑。如果您希望它在 C 中正确完成,最好实际修补 PostgreSQL 而不是使用扩展。