【问题标题】:Understanding cast from bytea to oid了解从 bytea 到 oid 的转换
【发布时间】:2015-06-08 14:15:17
【问题描述】:

我正在使用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将如何使用它?

【问题讨论】:

  • 所以你“找到”了?你能链接到源吗?
  • @ErwinBrandstetter 当然,我是从 there 那里得到的。
  • 这是一个非常糟糕的 IMO 主意,应该使用显式函数调用来代替。

标签: sql postgresql types casting blob


【解决方案1】:

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

Per documentation:

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

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

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() 返回byteaINSERT 语句将 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 CAST (per 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 演员。我可能会从仅显式开始:

【讨论】:

    猜你喜欢
    • 2011-06-29
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    相关资源
    最近更新 更多