gms_lob使用

创建Extension

创建gms_lob Extension可直接使用CREATE Extension命令进行创建:

openGauss=# CREATE Extension gms_lob;

使用Extension

包常量

ConstantTypeValueDescription
CALLINTEGER12创建生命周期为当前调用的临时LOB
FILE_READONLYBINARY_INTEGER0用只读方式打开BFILE
LOB_READONLYBINARY_INTEGER0用只读方式打开LOB
LOB_READWRITEBINARY_INTEGER1用读-写方式打开LOB
LOBMAXSIZENUMERIC18446744073709551615LOB的最大字节数
SESSIONINTEGER10创建生命周期为当前session的临时LOB

函数声明

gms_lob.getlength

getlength获取LOB值的长度

GMS_LOB.GETLENGTH (
   lob_loc    IN  BLOB/CLOB) 
  RETURN INTEGER;

getlength获取bfile对象关联的文件大小

GMS_LOB.GETLENGTH (
   bfileobj     IN  bfile) 
  RETURN INTEGER;

gms_lob.read

从LOB中指定偏移量开始 读取数据

GMS_LOB.READ (
   lob_loc   IN             BLOB,
   amount    INOUT          INTEGER, // 读取长度
   offset    IN             INTEGER, // 偏移量
   buffer    OUT            RAW);

GMS_LOB.READ (
   lob_loc   IN             CLOB,
   amount    INOUT          INTEGER,
   offset    IN             INTEGER,
   buffer    OUT            VARCHAR2); 

从BFILE关联文件的指定偏移量开始 读取数据

GMS_LOB.READ (
   bfileobj  IN             bfile,
   amount    INOUT          INTEGER, // 读取长度
   offset    IN             INTEGER, // 偏移量
   buffer    OUT            RAW);

gms_lob.bfileread

从BFILE关联文件的指定偏移量开始 读取数据

GMS_LOB.BFILEREAD (
   bfileobj  IN             bfile,
   amount    INOUT          INTEGER, // 读取长度
   offset    IN             INTEGER) // 偏移量
  RETURNS RAW;

gms_lob.write

将数据写入LOB中指定的偏移量

GMS_LOB.WRITE (
   lob_loc  INOUT          BLOB,
   amount   IN             NUMERIC,//读取长度,向下取整
   offset   IN             NUMERIC,//偏移量,向下取整
   buffer   IN             RAW);

GMS_LOB.WRITE (
   lob_loc  INOUT          CHARACTER,
   amount   IN             NUMERIC,
   offset   IN             NUMERIC,
   buffer   IN             VARCHAR2); 

gms_lob.append

将源 LOB 的内容追加到目标 LOB

GMS_LOB.APPEND (
   dest_lob INOUT          BLOB, 
   src_lob  IN             BLOB); 

GMS_LOB.APPEND (
   dest_lob INOUT          CLOB, 
   src_lob  IN             CLOB);

gms_lob.createtemporary

在用户的默认临时表空间中创建临时 BLOB 或 CLOB 及其相应的索引,将lob_loc置为varlena指针

GMS_LOB.CREATETEMPORARY (
   lob_loc INOUT         BLOB/CLOB,
   cache   IN            BOOLEAN, --指定是否将LOB读取到缓冲区(不生效)
   dur     IN            PLS_INTEGER := GMS_LOB.SESSION);--指定何时清除临时LOB(10/ SESSION:会话结束时;12/ CALL:调用结束时)(不生效)

gms_lob.freetemporary

释放默认临时表空间中的临时 BLOB 或 CLOB,将lob_loc置为空值varlena

GMS_LOB.FREETEMPORARY (
   lob_loc  INOUT     BLOB/CLOB); 

gms_lob.open

OPEN函数用于以指定的模式打开LOB,有效模式包括只读和读/写。

GMS_LOB.OPEN (
   lob_loc   INOUT BLOB/CLOB,
   open_mode IN            BINARY_INTEGER); --取整0 / 1 只读/读写 gms_lob.LOB_READONLY/gms_lob.LOB_READWRITE

gms_lob.bfileopen

BFILEOPEN函数用于以指定的模式打开BFILE对象关联文件,目前只允许读文件。

GMS_LOB.BFILEOPEN (
   bfileobj  IN             bfile,
   mode      IN             INTEGER) --目前取值只有 0 只读,其他值报错。
  RETURNS pg_catalog.bfile;

gms_lob.fileopen

FILEOPEN存储过程用于以指定的模式打开BFILE对象关联文件,目前只允许读文件。

GMS_LOB.FILEOPEN (
   bfileobj  INOUT          bfile,
   mode      IN             INTEGER); --目前取值只有 0 只读,其他值报错。

gms_lob.close

CLOSE 函数用于关闭先前打开的 LOB。

GMS_LOB.CLOSE (
    lob_loc    INOUT  BLOB/CLOB); 

gms_lob.bfileclose

BFILECLOSE函数用于关闭BFILE对象关联文件。

GMS_LOB.BFILECLOSE (
   bfileobj  IN             bfile);

gms_lob.fileclose

FILECLOSE存储过程用于关闭BFILE对象关联文件。

GMS_LOB.FILEOPEN (
   bfileobj  IN             bfile);

gms_lob.isopen

isopen函数用于判断LOB是否打开

GMS_LOB.ISOPEN (
   lob_loc IN BLOB/CLOB) 
  RETURN INTEGER; -- 1 is open/ 0 is close

函数使用

Gms_lob包中函数同时使用

create table tbl_testlob(id int, c_lob clob, b_lob blob);
insert into tbl_testlob values(1, 'clob', cast_to_raw('blob'));
insert into tbl_testlob values(2, '中文clobobject测试', cast_to_raw('中文blobobject测试'));
create or replace function func_clob() returns void 
AS $$
DECLARE
    v_clob1 clob;
    v_clob2 clob;
    v_clob3 clob;
    len1 int;
    len3 int;
BEGIN
    select c_lob into v_clob1 from tbl_testlob where id = 1;
    gms_lob.open(v_clob1, gms_lob.LOB_READWRITE);
    gms_lob.append(v_clob1, ' test');
    len1 := gms_lob.getlength(v_clob1);
    gms_output.put_line('clob2:' || v_clob2);
    gms_lob.read(v_clob1, len1, 1, v_clob2);
    gms_output.put_line('clob1:' || v_clob1);
    gms_output.put_line('clob2:' || v_clob2);

    select c_lob into v_clob3 from tbl_testlob where id = 2;
    len3 := gms_lob.getlength(v_clob3);

    gms_output.put_line('clob3:' || v_clob3);
    --不调用open函数。默认权限为读写
    gms_lob.write(v_clob3, len1, len3, v_clob1);
    gms_output.put_line('clob3:' || v_clob3);
    
    gms_lob.close(v_clob1);
    gms_lob.freetemporary(v_clob2);
END;
$$LANGUAGE plpgsql;
create or replace function func_blob() returns void 
AS $$
DECLARE
    v_blob1 blob;
    v_blob2 blob;
    v_blob3 blob;
    len1 int;
    len3 int;
BEGIN
    select b_lob into v_blob1 from tbl_testlob where id = 1;
    gms_lob.open(v_blob1, gms_lob.LOB_READWRITE);

    len1 := gms_lob.getlength(v_blob1);
    gms_output.put_line('blob1:' || v_blob1::text);
    gms_output.put_line('blob2:' || v_blob2::text);
    gms_lob.read(v_blob1, len1, 1, v_blob2);
    gms_output.put_line('blob1:' || v_blob1::text);
    gms_output.put_line('blob2:' || v_blob2::text);

    select b_lob into v_blob3 from tbl_testlob where id = 2;
    len3 := gms_lob.getlength(v_blob3);
    --不调用open函数。默认权限为读写
    gms_output.put_line('blob3:' || v_blob3::text);
    gms_lob.write(v_blob3, len1, len3, v_blob1);
    gms_output.put_line('blob3:' || v_blob3::text);
    
    gms_lob.close(v_blob1);
    gms_lob.freetemporary(v_blob2);
END;
$$LANGUAGE plpgsql;
select func_clob();
clob2:
clob1:clob test
clob2:clob test
clob3:中文clobobject测试
clob3:中文clobobject测clob test
 func_clob 
-----------
 
(1 row)

select func_blob();
blob1:626C6F62
blob2:
blob1:626C6F62
blob2:626C6F62
blob3:E4B8ADE69687626C6F626F626A656374E6B58BE8AF95
blob3:E4B8ADE69687626C6F626F626A656374E6B58BE8AF626C6F62
 func_blob 
-----------
 
(1 row)

测试Open/close/createtemporary/freetemporary/isopen函数

--(1)打开无效的lob
DECLARE
    v_clob clob;
BEGIN
    gms_lob.open(v_clob, gms_lob.LOB_READWRITE);
    
    gms_lob.close(v_clob);
END;
/
ERROR:  invalid LOB object specified
CONTEXT:  SQL statement "CALL gms_lob.open(v_clob,gms_lob.LOB_READWRITE)"
PL/pgSQL function inline_code_block line 3 at SQL statement
DECLARE
    v_clob clob;
BEGIN
    gms_lob.createtemporary(v_clob, false);
    gms_lob.open(v_clob, gms_lob.LOB_READWRITE);
    gms_output.put_line('isopen: ' || gms_lob.isopen(v_clob));
    gms_lob.close(v_clob);
    gms_output.put_line('isopen: ' || gms_lob.isopen(v_clob));
    gms_lob.freetemporary(v_clob);
END;
/
isopen: 1
isopen: 0

DECLARE
    v_clob CLOB;
    v_char VARCHAR2(100);
BEGIN
    v_char := 'Chinese中国人';
    gms_lob.createtemporary(v_clob,TRUE,12);
    gms_lob.append(v_clob,v_char);
    gms_output.put_line(v_clob||' 字符长度:'||gms_lob.getlength(v_clob));
    gms_lob.freetemporary(v_clob);
    gms_output.put_line(' 释放后再输出:'||v_clob);
END;
/
Chinese中国人 字符长度:10
 释放后再输出:

测试read/write/append函数

declare
c1 clob :='abcdefgh';
amount INTEGER :=3;
off_set INTEGER :=1;
var_buf varchar2(10);
begin
gms_lob.read(c1, amount, off_set, var_buf);
gms_output.put_line('clob read: ' || var_buf::text);
end;
/
clob read: abc

declare
c1 clob :='11111111';
amount INTEGER :=3;
off_set INTEGER :=1;
c2 clob :='222';
begin
gms_lob.write(c1, amount, off_set, c2);
gms_output.put_line(c1::text);
end;
/
22211111

declare
c1 clob :='11111111';
c2 clob :='222';
begin
gms_lob.append(c1, c2);
gms_output.put_line(c1::text);
end;
/
11111111222

测试bfileopen/bfileclose/bfileread函数

create extension gms_lob;
create extension gms_output;
CREATE or REPLACE DIRECTORY bfile_test_dir AS '/tmp';
create table falt_bfile (id number, bfile_name bfile);
insert into falt_bfile values(1, bfilename('bfile_test_dir','regress_bfile.txt'));
copy (select * from falt_bfile) to '/tmp/regress_bfile.txt';
select gms_output.enable;
 enable 
--------
 
(1 row)

DECLARE
    buff raw(2000);
    my_bfile bfile;
    amount integer;
    f_offset integer := 1;
BEGIN
    my_bfile := bfilename('bfile_test_dir','regress_bfile.txt');
    my_bfile = gms_lob.bfileopen(my_bfile, 0);
    amount := gms_lob.getlength(my_bfile);
    buff = gms_lob.bfileread(my_bfile, amount, f_offset);
    gms_lob.bfileclose(my_bfile);
    gms_output.put_line(CONVERT_FROM(decode(buff,'hex'), 'SQL_ASCII'));
END;
/
1	bfilename('bfile_test_dir', 'regress_bfile.txt')

测试fileopen/fileclose/read函数

DECLARE
    buff raw(2000);
    my_bfile bfile;
    amount integer;
    f_offset integer := 1;
BEGIN
    my_bfile := bfilename('bfile_test_dir','regress_bfile.txt');
    gms_lob.fileopen(my_bfile, 0);
    amount := gms_lob.getlength(my_bfile);
    gms_lob.read(my_bfile, amount, f_offset, buff);
    gms_lob.fileclose(my_bfile);
    gms_output.put_line(CONVERT_FROM(decode(buff,'hex'), 'SQL_ASCII'));
END;
/
1	bfilename('bfile_test_dir', 'regress_bfile.txt')

删除Extension

在openGauss中删除gms_output Extension的方法如下所示:

openGauss=# DROP Extension gms_lob [CASCADE];

说明:

如果Extension被其它对象依赖,需要加入CASCADE(级联)关键字,删除所有依赖对象。

意见反馈
编组 3备份
    openGauss 2025-04-20 07:42:35
    取消