F.47. pgpro_bfile — составной тип для доступа к внешнему файлу #
Расширение pgpro_bfile добавляет составной тип bfile, который реализует метод Oracle для доступа к внешнему файлу.
F.47.1. Структуры данных #
Тип bfile содержит два поля:
dir_id— идентификатор каталога в таблицеbfile_directoriesfile_name— имя внешнего файла
Информация о каталогах хранится в таблице bfile_directories, которая состоит из следующих столбцов:
dir_id— уникальный идентификатор каталога типаint32.dir_alias— уникальный псевдоним каталога.dir_path— путь к каталогу.
Хотя наличие двух уникальных идентификаторов dir_id и dir_alias является избыточным, работа с dir_alias удобнее для пользователя, мигрирующего с Oracle, особенно для понимания семантики команд, а для хранения dir_id лучше использовать тип bfile, поскольку для него требуется меньше места в хранилище и он обеспечивает более быстрый поиск.
Информация о правах доступа к каталогам хранится в таблице bfile_directory_roles, которая состоит из следующих столбцов:
dr_dir_id— идентификатор каталога типаint32, то есть внешняя ссылка на столбецdir_idв таблицеbfile_directories.dr_role_id— идентификатор пользователя или роли, имеющей права доступа к каталогу.dr_rights— битовый массив прав доступа к каталогу (1 означает доступ для чтения, 2 — доступ для записи). Выбор битового массива предусматривает возможность предоставления новых прав доступа, например необходимость в отдельном праве на удаление.
F.47.2. Функции #
Функции для работы с каталогами и управления правами доступа к каталогам реализованы на языке PL/PgSQL, а функции для работы со значениями bfile реализованы на языке C для повышения эффективности.
Таблица F.31. Функции для работы с каталогами
Функция Описание |
|---|
Создаёт каталог для заданных псевдонима и пути и возвращает идентификатор созданного каталога. Для вызова этой функции требуются права суперпользователя. |
Удаляет каталог с заданным псевдонимом. Для вызова этой функции требуются права суперпользователя. |
Изменяет псевдоним каталога. Для вызова этой функции требуются права суперпользователя. |
Изменяет путь к каталогу с заданным псевдонимом. Для вызова этой функции требуются права суперпользователя. |
Возвращает путь к каталогу с заданным псевдонимом. |
Возвращает путь к каталогу с заданным идентификатором. |
Возвращает псевдоним каталога с заданным идентификатором. |
Возвращает идентификатор каталога с заданным псевдонимом. |
Таблица F.32. Функции предоставления и отзыва прав доступа к каталогам
Функция Описание |
|---|
Предоставляет права доступа к каталогу |
Отзывает права доступа к каталогу |
Удаляет из таблицы |
Таблица F.33. Функции для работы со значениями bfile
Функция Описание |
|---|
Возвращает структуру |
Возвращает структуру |
Открывает файл для заданного |
Закрывает файл для заданного дескриптора, возвращаемого функцией |
Закрывает все файлы, которые были открыты ранее функцией |
Возвращает длину открытого файла с заданным дескриптором. |
Считывает |
Записывает буфер, заданный в |
Возвращает |
Возвращает длину файла для заданного значения |
Для заданного значения |
Для заданного значения |
Удаляет файл для заданного значения |
Когда аргументы |
Вычисляет MD5-хеш для указанного объекта |
F.47.3. Пример #
В следующем примере показано использование типа bfile.
Скрипт будет запускаться в файловой системе сервера. Но сначала создайте каталог для хранения данных bfile:
mkdir "/tmp/bfiles"
Теперь для запуска следующего скрипта будет использоваться psql:
-- Создание расширения pgpro_bfile:
CREATE EXTENSION pgpro_bfile;
-- Создание каталога в базе данных для хранения bfile:
SELECT bfile_directory_create('BFILE_DATA', '/tmp/bfiles');
-- Создание файла bfile.data в файловой системе и добавление в него значения '0123456789':
SELECT bfile_write_direct(bfile_make('BFILE_DATA', 'bfile.data'), '0123456789');
-- Создание таблицы bfile и добавление в неё одной записи, ссылающейся на этот файл:
CREATE TABLE bfile_table(id int, bf bfile);
INSERT INTO bfile_table VALUES (1, bfile_make('BFILE_DATA', 'bfile.data'));
-- Создание пользователя для запуска скрипта:
CREATE USER bf_test_user;
-- Предоставление пользователю bf_test_user права чтения и записи в файл BFILE_DATA:
SELECT bfile_grant_directory('BFILE_DATA', 'bf_test_user', 3);
-- Предоставление пользователю bf_test_user прав на таблицу bfile_table:
GRANT ALL ON bfile_table TO bf_test_user;
-- Авторизация bf_test_user:
SET SESSION AUTHORIZATION bf_test_user;
DO $$
DECLARE
v_bfile bfile;
v_buffer bytea;
v_length bigint;
v_handler int;
BEGIN
-- Открытие файла для чтения и записи:
SELECT bfile_open(bf, 3) INTO v_handler FROM bfile_table WHERE id = 1;
-- Эта строка символов будет записана в конец файла:
PERFORM bfile_write(v_handler, '_suffix');
-- Эта строка символов будет записана с позиции 0 и заменит '0123456':
PERFORM bfile_write(v_handler, 'prefix_', 0);
-- Считывание строки символов из файла в буфер и вывод её длины и содержимого:
v_buffer = bfile_read(v_handler);
RAISE NOTICE 'Buffer length: %', length(v_buffer);
RAISE NOTICE 'Buffer content: %', encode(v_buffer, 'escape');
-- Получение и вывод длины файла:
v_length = bfile_length(v_handler);
RAISE NOTICE 'BFILE length: %', v_length;
-- Закрытие bfile:
PERFORM bfile_close(v_handler);
END $$;
-- Проверка содержимого таблицы:
SELECT encode(b, 'escape'), length(b) from (SELECT bfile_read_direct(bf) b FROM bfile_table) x;
-- Удаление таблицы, пользователя и расширения pgpro_bfile:
RESET SESSION AUTHORIZATION;
DROP TABLE bfile_table;
DROP USER bf_test_user;
DROP EXTENSION pgpro_bfile;Скрипт выдаёт следующий результат:
CREATE EXTENSION
bfile_directory_create
------------------------
1
(1 row)
bfile_write_direct
--------------------
(1 row)
CREATE TABLE
INSERT 0 1
CREATE ROLE
bfile_grant_directory
-----------------------
(1 row)
GRANT
SET
NOTICE: Buffer length: 17
NOTICE: Buffer content: prefix_789_suffix
NOTICE: BFILE length: 17
DO
encode | length
-------------------+--------
prefix_789_suffix | 17
(1 row)
RESET
DROP TABLE
DROP ROLE
DROP EXTENSION