sql - 了解从 bytea 到 oid 的转换

标签 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 将如何使用它?

最佳答案

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

Per documentation:

All large objects are stored in a single system table named pg_largeobject. Each large object also has an entry in the system table pg_largeobject_metadata. Large objects can be created, modified, and deleted using a read/write API that is similar to standard operations on files.

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

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:

The module also provides a data type lo, which is really just a domain of the oid type. This is useful for differentiating database columns that hold large object references from those that are OIDs of other things.

函数decode()返回 byteaINSERT 语句将 bytea 值分配给 largeObj 列,这会触发对其类型 lo 的赋值转换,这就是上述 Actor 的用武之地。

警告/纠正/更新

博客条目草率且过时。

  • 懒得提那个 ( per documentation ):

    To be able to create a cast, you must own the source or the target data type and have USAGE privilege on the other type.

    实际上,您必须是 super 用户。

  • 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.

有一个built-in function为此,在 Postgres 9.4 中。改用它:

lo_from_bytea(loid oid, string bytea)

来自release notes :

对于 CREATE CAST ( per documentation ):

The first argument type must be identical to or binary-coercible from the cast's source type.

我建议使用一个只有 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 转换。我可能会从仅显式开始:

关于sql - 了解从 bytea 到 oid 的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29433041/

相关文章:

ruby-on-rails - 了解事件记录查询

postgresql - Postgresql - 使用动态列名触发

sql - CoffeeScript,寻找类似 SQL 的模块

sql - 修改元组值的 MYSQL Select 语句

sql - 是否可以在 Sql Server Management Studio Express 中自动缩进查询?

类型参数中的Scala类型级标识函数

c++ - C++ 中的类型安全类型定义

sql - Oracle - 从 XMLType 中的 XML 序言中提取 XML 版本和编码

regex - 在字符串列中查找非整数值

python - 我如何知道要使用什么类型的浮子?