了解从bytea到oid的强制转换

时间:2015-04-03 13:22:22

标签: sql postgresql types casting blob

我正在使用PostgreSQL 9.2 This blog entry by Grace Batumbya提供了从byteaoid的演员表。

create or replace function blob_write(lbytea bytea)
   returns oid
   volatile
   language plpgsql as
$f$
   declare
      loid oid;
      lfd integer;
      lsize integer;
begin
   if(lbytea is null) then
      return null;
   end if;

   loid := lo_create(0);
   lfd := lo_open(loid,131072);
   lsize := lowrite(lfd,lbytea);
   perform lo_close(lfd);
   return loid;
end;
$f$;
CREATE CAST (bytea AS oid) WITH FUNCTION blob_write(bytea) AS ASSIGNMENT;

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

我不明白我们为什么要创建bytea_to_lo表?如何PostgreSQL使用它?

1 个答案:

答案 0 :(得分:1)

演员不是真正的演员。它只是(ab)使用方便的语法。在后台创建large object (LO),单独存储,并返回引用它的OID。

Per documentation:

  

所有大对象都存储在一个名为的系统表中   pg_largeobject。每个大对象在系统中也有一个条目   表格1}}。可以创建,修改大对象,   并使用类似于标准的读/写API删除   对文件的操作。

返回的OID基本上是系统表pg_largeobject的PK的FK。

pg_largeobject_metadata完全独立于函数和伪转换。

CREATE TABLE

这只是上面创建的赋值转换的典型用例,从您忘记引用的以下行中可以看出这一点:

CREATE TABLE bytea_to_lo (
   largeObj lo 
);

这里发生了什么?

数据类型INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex')); 是基本类型lo上的域,由附加模块lo创建(在blog enty of Grace Batumbya中错误地称为“lo_manage包”) 。 Per documentation:

  

该模块还提供了一种数据类型oid,它实际上只是一个域   lo类型的。这对于区分数据库列很有用   持有来自其他东西的OID的大对象引用。

函数decode()返回oidbytea语句将INSERT值分配给列bytea,这会触发转换为其类型largeObj的赋值,这就是上面的转换所在的位置。

警告/纠正/更新

博客条目现在已经过时了,过时了。

  • 无需提及(per documentation):

      

    要创建演员表,您必须拥有源或目标   数据类型,对另一种类型具有lo权限。

    实际上,您必须是超级用户。

  • USAGE中的错字:列名称和类型已反转。

  • 功能定义冗长且效率低下。这样会更好(对于Postgres 9.3 或更早):

    CREATE TABLE

    SQL Fiddle.

Postgres 9.4 中有built-in function。请改用:

CREATE OR REPLACE FUNCTION blob_write(bytea)
  RETURNS oid AS
$func$
DECLARE
   loid oid := lo_create(0);
   lfd  int := lo_open(loid,131072);  -- = 2^17 = x2000
   -- symbolic constant defined in the header file libpq/libpq-fs.h
   -- #define   INV_WRITE   0x00020000
BEGIN
   PERFORM lowrite(lfd, $1);
   PERFORM lo_close(lfd);
   RETURN loid;
END
$func$  LANGUAGE plpgsql VOLATILE STRICT;

来自release notes

  

lo_from_bytea(loid oid, string bytea) per documentation):

  

第一个参数类型必须与cast的源类型相同或二元可强制化。

我建议使用只有CREATE CAST参数的重载变体:

bytea

由于伪演员具有相当大的副作用,我不相信会成为CREATE OR REPLACE FUNCTION lo_from_bytea(bytea) RETURNS oid LANGUAGE sql AS 'SELECT lo_from_bytea(0, $1)'; CREATE CAST (bytea AS oid) WITH FUNCTION lo_from_bytea(bytea) AS ASSIGNMENT; 演员。我可能会从仅显式开始:

相关问题