我正在使用 PostgreSQL 9.2
。
This blog entry by Grace Batumbya提供从 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
将如何使用它?
最佳答案
Actor 不是真正的 Actor 。它只是(ab)使用方便的语法。 large object (LO)在后台创建,单独存储并返回引用它的 OID。
All large objects are stored in a single system table named
pg_largeobject
. Each large object also has an entry in the system tablepg_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 theoid
type. This is useful for differentiating database columns that hold large object references from those that are OIDs of other things.
函数decode()
返回 bytea
。 INSERT
语句将 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;
有一个built-in function为此,在 Postgres 9.4 中。改用它:
lo_from_bytea(loid oid, string bytea)
来自release notes :
- Add SQL functions to allow large object reads/writes at arbitrary offsets (Pavel Stehule)
对于 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/