2015-04-03 52 views
1

我正在使用PostgreSQL 9.2
This blog entry by Grace Batumbya提供了从byteaoid的演员阵容。了解从bytea投射到oid

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

+0

所以你 “发现” 了吗?你愿意链接到源代码吗? – 2015-04-03 14:51:22

+0

@ErwinBrandstetter当然,我从[那里](https://gbatumbya.wordpress.com/2011/06/15/create-a-large-object-lo-from-binary-data-bytea-on-server -侧/)。 – user3663882 2015-04-03 15:07:43

+0

相关:http://stackoverflow.com/questions/10139077/convert-a-bytea-column-to-oid-column-with-retained-values-postgresql – 2015-04-03 16:48:35

回答

1

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

Per documentation:

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

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

CREATE TABLE是完全独立于函数和伪演员。

CREATE TABLE bytea_to_lo (
    largeObj lo 
); 

这只是一个典型的用例投上面创建的任务,然后从下面的行,你忘了引用变得很明显:

INSERT INTO bytea_to_lo VALUES (DECODE('00AB','hex')); 

这里会发生什么?

数据类型lo是在基底类型oid,通过附加模块lo(错误引用作为blog enty of Grace Batumbya“lo_manage包”)创建了一个域。 Per documentation:

该模块还提供了一种数据类型lo,这是真正的oid类型的只是一个域 。这对于区分容纳大对象引用的数据库列和其他事物的OID数据库列是很有用的。

功能decode()返回bytea。该INSERT语句将bytea值列largeObj,这将触发一个赋值转换其类型lo,而这也正是上面铸用武之地。

警告/纠正/更新

博客条目是草率和现在过时了。

  • 不打扰一提的是(per documentation):

    为了能够创造一个演员,你必须拥有源或目标 数据类型和对其他类型的USAGE特权。

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

  • 错字CREATE TABLE:列名和类型颠倒过来。

  • 函数定义是冗长而低效的。这将是更好的(Postgres的9.3或以上):

    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; 
    

    SQL Fiddle.

有Postgres里9.4这一个built-in function。就用它来:

lo_from_bytea(loid oid, string bytea) 

release notes

对于CREATE CASTper documentation):

第一个参数类型必须与演员的源类型相同或二进制强制。

我建议过载的变种,只有一个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; 

由于伪铸有相当大的副作用,我不相信做,一个ASSIGNMENT演员。我可能会用显式才开始: