F.16. dbms_lob — работа с большими объектами #
dbms_lob — это расширение Postgres Pro, позволяющее работать с большими объектами (LOB): BLOB
, CLOB
, BFILE
и временными LOB. Расширение можно использовать для обращения к определённым частям больших объектов или большим объектам целиком и управления ими. Функциональность, предоставляемая этим модулем, во многом пересекается с функциональностью пакета DBMS_LOB
в Oracle.
Примечание
Обратите внимание, что расширение dbms_lob зависит от расширения pgpro_sfile, поэтому pgpro_sfile устанавливается первым. Более подробная информация описана в документации самого расширения pgpro_sfile.
F.16.1. Установка #
Расширение dbms_lob
включено в состав Postgres Pro Enterprise как стандартное расширение. Чтобы задействовать dbms_lob
, создайте расширение с помощью следующего запроса:
CREATE EXTENSION dbms_lob;
F.16.2. Типы данных #
Расширение dbms_lob
работает с несколькими типами данных:
Тип
bfile
предоставляется расширением pgpro_bfile.CREATE TYPE BFILE AS ( dir_id int, file_name text );
Таблица F.12. Параметры
bfile
Параметр Описание dir_id
Идентификатор каталога, в котором хранится bfile
.file_name
Имя файла, из которого нужно прочитать bfile
.Тип
blob
хранит двоичные данные и имеет тот же интерфейс, что иBLOB
в Oracle. Предоставляется расширением pgpro_sfile.CREATE TYPE dbms_lob.blob AS ( temp_data bytea, mime text, sf @extschema:pgpro_sfile@.sfile );
Таблица F.13. Параметры
blob
Параметр Описание sf
Объект типа sfile
на диске, в котором хранятся объекты BLOB.temp_data
Временные данные BLOB, хранящиеся в памяти. mime
Вспомогательные данные, которые определяют тип данных, хранящихся в BLOB. Тип
clob
является эквивалентомCLOB
иNCLOB
в Oracle. Поддерживается только кодировка UTF-8.CREATE TYPE CLOB AS ( t text, istemp bool, mime text );
Таблица F.14. Параметры
clob
Параметр Описание t
Объект типа text
на диске, в котором хранятся данные.istemp
Определяет, является ли объект временным. mime
Вспомогательные данные, которые определяют тип данных, хранящихся в CLOB.
F.16.3. Вспомогательные функции #
-
bfilename(
#dirname
text
,filename
text
) returnsbfile
Создаёт объект
bfile
, связанный с физическим файлом в файловой системе. Здесьdirname
— это имя объекта каталога, созданного функциейbfile_directory_create()
, где находится файлfilename
.-
empty_blob() returns
#blob
Создаёт пустой объект
blob
, содержащий объект типаsfile
без данных. Его можно заполнить данными с помощью функций записи.-
empty_clob() returns
#clob
Создаёт пустой объект
clob
, содержащий пустую строку. Его можно заполнить данными с помощью функций записи.-
to_blob(
b
bytea
) returnsblob
to_blob(
#f
bfile
,mime_type
text
) returnsblob
Преобразует объекты типа
bytea
в объекты типаblob
. Если исходным файлом являетсяbfile
, можно указать тип данныхmime
.-
to_clob(
t
text
) returnsclob
to_clob(
t
varchar
) returnsclob
to_clob(
#b
bfile
,int
csid
,mime
text
) returnsclob
Преобразует текстовые объекты в объекты типа
clob
. Если исходным файлом являетсяbfile
, его данные считываются и преобразуются в типclob
. Поддерживается только кодировка UTF-8.-
to_raw(
b
blob
) returnsclob
to_raw(
#b
bfile
) returnsclob
Копирует данные из файла типа
blob
илиbfile
в файл типаbytea
. Обрабатывается только первый ГБ данных.
F.16.4. Функции и процедуры dbms_lob #
F.16.4.1. Открытие и закрытие больших объектов #
-
open(
file_loc
IN OUTbfile
,open_mode
INint
)
open(
lob_loc
IN OUTblob
,open_mode
INint
)
open(
#lob_loc
IN OUTclob
,open_mode
INint
) Открывает объект типа
bfile
. Параметрopen_mode
указывает, в каком режиме будет открыт файл: чтения/записи или только для чтения. Для типаbfile
поддерживается исключительно режим только для чтения (0). Функцииopen(
иblob
)open(
не выполняют никаких действий и необходимы только для обеспечения совместимости синтаксиса.clob
)-
isopen(
file_loc
INbfile
)
isopen(
lob_loc
INblob
)
isopen(
#lob_loc
INclob
) Проверяет, открыт ли объект типа
bfile
. Возвращает 1, если LOB открыт, и 0 в противном случае. Функцииisopen(
иblob
)isopen(
всегда возвращают 1 и необходимы только для обеспечения совместимости синтаксиса.clob
)-
close(
file_loc
IN OUTbfile
)
close(
lob_loc
IN OUTblob
)
close(
#lob_loc
IN OUTclob
) Проверяет, открыт ли объект
bfile
, и если да, то закрывает его. Функцииclose(
иblob
)close(
не выполняют никаких действий и необходимы только для совместимости синтаксиса.clob
)-
createtemporary(
lob_loc
IN OUTblob
,cache
INbool
,dur
INint
default 10)
createtemporary(
#lob_loc
IN OUTclob
,cache
INbool
,dur
INint
default 10) Создаёт временный объект LOB, в котором данные типа
blob
хранятся как данные типаbytea
, а данные типаclob
— как данные типаtext
.-
freetemporary(
lob_loc
IN OUTblob
)
freetemporary(
#lob_loc
IN OUTclob
) Освобождает ресурсы, связанные с временным большим объектом.
F.16.4.2. Чтение LOB #
-
getlength(
file_loc
INbfile
)
getlength(
lob_loc
INblob
)
getlength(
#lob_loc
INclob
) Возвращает длину
blob
илиbfile
в байтах илиclob
в символах.-
read(
file_loc
INbfile
,amount
IN OUTint
,offset
INint
,buffer
OUTbytea
)
read(
lob_loc
INblob
,amount
IN OUTint
,offset
INint
,buffer
OUTbytea
)
read(
#lob_loc
INclob
,amount
IN OUTint
,offset
INint
,buffer
OUTtext
) Считывает часть LOB и записывает указанное количество байтов (для
blob
/bfile
) или символов (дляclob
) в буфер (buffer
), начиная с абсолютного смещения (offset
) от начала LOB. Обратите внимание, что для чтения с начала файла необходимо указать для параметраoffset
значение 1.-
get_storage_limit(
lob_loc
INblob
)
get_storage_limit(
#lob_loc
INclob
) Возвращает размер хранилища LOB для указанного LOB.
-
substr(
file_loc
INbfile
,amount
INint
,offset
INint
)
substr(
lob_loc
INblob
,amount
INint
,offset
INint
)
substr(
#lob_loc
INclob
,amount
INint
,offset
INint
) Возвращает количество (
amount
) байтов (дляblob
/bfile
) или символов (дляclob
) LOB, начиная с абсолютного смещения (offset
) от начала LOB.-
instr(
file_loc
INbfile
,pattern
INint
,offset
INbigint
default 1,nth
INbigint
default 1)
instr(
lob_loc
INblob
,pattern
INint
,offset
INbigint
default 1,nth
INbigint
default 1)
instr(
#lob_loc
INclob
,pattern
INint
,offset
INbigint
default 1,nth
INbigint
default 1) Возвращает соответствующую позицию n-ого (
nth
) вхождения шаблона (pattern
) в LOB, начиная с указанного смещения (offset
). Возвращает 0, если шаблонpattern
не найден. Поиск осуществляется только в первом ГБ данных.
F.16.4.3. Изменение LOB #
-
write(
lob_loc
IN OUTblob
,amount
INint
,offset
INbigint
,buffer
INbytea
)
write(
#lob_loc
IN OUTclob
,amount
INint
,offset
INint
,buffer
INtext
) Записывает указанный объём (
amount
) данных во внутренний большой объект, начиная с абсолютного смещения (offset
) от начала большого объекта. Данные записываются из буфера, указанного в параметреbuffer
. Если указанное смещение (offset
) выходит за пределы данных, находящихся в данный момент в LOB, то вставляются нулевые заполнители (дляblob
) или пробелы (дляclob
).-
writeappend(
lob_loc
IN OUTblob
,amount
INint
,buffer
INbytea
)
writeappend(
#lob_loc
IN OUTclob
,amount
INint
,buffer
INtext
) Записывает указанный объём (
amount
) данных в конец внутреннего LOB. Данные записываются из буфера, указанного в параметреbuffer
.-
erase(
lob_loc
IN OUTblob
,amount
IN OUTint
,offset
INbigint
default 1)
erase(
#lob_loc
IN OUTclob
,amount
IN OUTint
,offset
INint
default 1) Удаляет весь внутренний LOB или часть внутреннего LOB. Когда данные стираются из середины LOB, записываются нулевые байтовые заполнители (для временных
blob
) или пробелы (дляclob
). Постоянные объекты типаblob
могут быть удалены только целиком.-
trim(
lob_loc
IN OUTblob
,newlen
INbigint
)
trim(
#lob_loc
IN OUTclob
,newlen
INint
) Обрезает значение внутреннего LOB до длины, указанной в параметре
newlen
. Необходимо указать длину в байтах для временногоblob
и длину в символах дляclob
. Применимо для постоянногоblob
, только если новая длина равна нулю, что означает удаление объекта.
F.16.4.4. Операции с несколькими LOB #
-
compare(
lob_1
INbfile
,lob_2
INbfile
,amount
INbigint
,offset_1
INbigint
default 1,offset_2
INbigint
default 1) returns int
compare(
lob_1
INblob
,lob_2
INblob
,amount
INint
default 1024*1024*1024-8,offset_1
INbigint
default 1,offset_2
INbigint
default 1) returns int
compare(
#lob_1
INclob
,lob_2
INclob
,amount
INint
default (1024*1024*1024-8)/2,offset_1
INint
default 1,offset_2
INint
default 1) returns int Сравнивает два полных LOB или части двух LOB. Можно сравнивать только LOB, имеющие одинаковые типы данных. Для
bfile
иblob
выполняется двоичное сравнение. Дляclob
файлы сравниваются в соответствии с текущим правилом сортировки базы данных.-
append(
lob_1
IN OUTblob
,lob_2
INblob
)
append(
#lob_1
IN OUTclob
,lob_2
INclob
) Добавляет содержимое исходного внутреннего LOB в целевой LOB. Исходный LOB добавляется полностью.
-
copy(
dest_lob
IN OUTblob
,src_lob
INblob
,amount
INbigint
,dest_offset
INbigint
default 1,src_offset
INbigint
default 1) returnsint
copy(
#dest_lob
IN OUTclob
,src_lob
INclob
,amount
INint
,dest_offset
INint
default 1,src_offset
INint
default 1) returnsint
Копирует весь или часть исходного внутреннего LOB в целевой внутренний LOB. Можно указать смещение как для исходного, так и для целевого LOB, а также количество байтов или символов для копирования.
-
converttoblob(
#dest_lob
IN OUTblob
,src_clob
INclob
,amount
INint
,dest_offset
IN OUTbigint
,src_offset
IN OUTint
,blob_csid
INint
,lang_context
IN OUTint
,warning
OUTint
) Считывает символьные данные из исходного
clob
, преобразует эти данные в указанный набор символов, записывает преобразованные данные в целевойblob
в двоичном формате и возвращает новые смещения. Поддерживается только кодировка UTF-8.-
converttoclob(
#dest_lob
IN OUTclob
,src_blob
INblob
,amount
INint
,dest_offset
IN OUTint
,src_offset
IN OUTbigint
,blob_csid
INint
,lang_context
IN OUTint
,warning
OUTint
) Считывает двоичные данные из исходного
blob
, преобразует их в кодировку UTF-8 и записывает преобразованные символьные данные в целевойclob
.
F.16.4.5. Устаревшие API #
-
fileexists(
#file_loc
INbfile
) returnsint
Проверяет, действительно ли существует в файловой системе файл, на который указывает заданный указатель
bfile
. Реализовано какbfile_fileexists
.-
fileopen(
#file_loc
IN OUTbfile
,open_mode
INint
) returnsint
Открывает указанный
bfile
в режиме только для чтения. Реализовано как функцияbfile_open
.-
fileisopen(
#file_loc
INbfile
) returnsint
Проверяет, открыт ли указанный
bfile
.-
loadfromfile(
#dest_lob
IN OUTblob
,src_bfile
INbfile
,amount
INint
default 1024*1024*1024-8,dest_offset
INbigint
default 1,src_offset
INbigint
default 1) Преобразует данные из указанного
bfile
вblob
.-
fileclose(
#file_loc
IN OUTbfile
) Закрывает ранее открытый
bfile
. Реализовано как функцияbfile_close
.-
filecloseall()
# Закрывает все файлы
bfile
, открытые в сеансе. Реализовано какbfile_close_all
.-
filegetname(
#file_loc
INbfile
,dir_alias
OUTtext
,filename
OUTtext
) Определяет объект каталога и имя файла. Эта функция показывает только имя объекта каталога и имя файла, назначенные указателю, а не подтверждает факт существования физического файла или каталога. Реализовано как функция
bfile_directory_get_alias_by_id
.
F.16.4.6. Прочие параметры #
-
loadblobfromfile(
#dest_lob
IN OUTblob
,src_bfile
INbfile
,amount
INint
default 1024*1024*1024-8,dest_offset
INbigint
default 1,src_offset
INbigint
default 1) returnsint
Синоним для
loadfromfile()
.-
loadclobfromfile(
#dest_lob
IN OUTclob
,src_bfile
INbfile
,amount
INint
,dest_offset
IN OUTint
,src_offset
IN OUTbigint
,bfile_csid
INint
,lang_context
IN OUTint
,warning
OUTint
) Загружает данные из
bfile
во внутреннийclob
.-
setcontenttype(
lob_loc
IN OUTblob
,contenttype
INtext
)
setcontenttype(
#lob_loc
IN OUTclob
,contenttype
INtext
) Устанавливает строку типа содержимого, связанную с LOB.
-
getcontenttype(
lob_loc
INblob
) returnstext
getcontenttype(
#lob_loc
INclob
) returnstext
Возвращает строку типа содержимого, связанную с LOB.
-
getchunksize(
lob_loc
INblob
) returnstext
getchunksize(
#lob_loc
INclob
) returnstext
Возвращает объём пространства, используемого в порции LOB для хранения значения LOB.
F.16.5. Пример #
Ниже приведён пример работы расширения dbms_lob.
DO $$ DECLARE cur_clob dbms_lob.clob; buffer text; amount int := 3000; BEGIN cur_clob := dbms_lob.empty_clob(); cur_clob.t := 'just some sample text'; raise notice 'clob length: %', dbms_lob.getlength(cur_clob); call dbms_lob.read(cur_clob, amount, 1, buffer); raise notice 'all clob read: %', buffer; amount := 6; call dbms_lob.read(cur_clob, amount, 4, buffer); raise notice 'clob read from 4 position for 6 symbols: %', buffer; raise notice 'storage limit: %', dbms_lob.get_storage_limit(cur_clob); raise notice 'clob substr from 6 position for 8 symbols: %', dbms_lob.substr(cur_clob, 8, 6); raise notice 'third postion of letter s in clob: %', dbms_lob.instr(cur_clob, 's', 1, 3); call dbms_lob.write(cur_clob, 6, 4, 'foobar'); raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.write(cur_clob, 3, 25, 'baz'); raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.writeappend(cur_clob, 4, 'test'); raise notice 'new clob contents: %', cur_clob.t; amount := 3; call dbms_lob.erase(cur_clob, amount, 2); raise notice 'amount of symbols deleted: %', amount; raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.erase(cur_clob, amount, 30); raise notice 'amount of symbols deleted: %', amount; raise notice 'new clob contents: %', cur_clob.t; call dbms_lob.trim_(cur_clob, 22); raise notice 'new clob contents: %', cur_clob.t; END; $$; --output NOTICE: clob length: 21 NOTICE: all clob read: just some sample text NOTICE: clob read from 4 position for 6 symbols: t some NOTICE: storage limit: 536870908 NOTICE: clob substr from 6 position for 8 symbols: some sam NOTICE: third postion of letter s in clob: 11 NOTICE: new clob contents: jusfoobar sample text NOTICE: new clob contents: jusfoobar sample text baz NOTICE: new clob contents: jusfoobar sample text baztest NOTICE: amount of symbols deleted: 3 NOTICE: new clob contents: j oobar sample text baztest NOTICE: amount of symbols deleted: 2 NOTICE: new clob contents: j oobar sample text bazte NOTICE: new clob contents: j oobar sample text
А вот так может выглядеть работа с LOB, находящимися в базе данных:
-- Создание таблицы и добавление данных CREATE TABLE dbms_lob_test (id INTEGER GENERATED ALWAYS AS IDENTITY, blob_col DBMS_LOB.BLOB); INSERT INTO dbms_lob_test (blob_col) VALUES (dbms_lob.to_blob(decode('d6b7a686ab4d4e9c5d2cbf49db6bc0f1', 'hex'))); DO $$ DECLARE v_lob_loc DBMS_LOB.BLOB; v_buffer BYTEA; v_amount INTEGER := 32700; v_offset BIGINT := 1; v_length BIGINT; BEGIN SELECT (blob_col).* INTO v_lob_loc FROM dbms_lob_test WHERE id=1; CALL dbms_lob.open(v_lob_loc, 0); -- Для DBMS_LOB.BLOB не обязательно SELECT DBMS_LOB.getlength(v_lob_loc) into v_length; RAISE NOTICE 'BLOB len=%', v_length; CALL dbms_lob.read(v_lob_loc, v_amount, v_offset, v_buffer); RAISE NOTICE 'Read % bytes', v_amount; RAISE NOTICE 'Buffer: %', encode(v_buffer, 'hex'); CALL dbms_lob.close(v_lob_loc); -- Для DBMS_LOB.BLOB не обязательно END $$;
Вывод будет выглядеть вот так:
BLOB len=16 Read 16 bytes Buffer: d6b7a686ab4d4e9c5d2cbf49db6bc0f1