2015-04-03 55 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演員。我可能會用顯式纔開始: