Страницы

Поиск по вопросам

вторник, 9 июля 2019 г.

Как вставить файл из папки в postgresql?

Как из папки на компьютере ( не из корневой папки бд ) вставить файл в одно из полей таблицы. Нужно что-то типа
insert into test(idserial, contenttext) values (4, нужнаяфункция('D:\html\ex02.xml'));
Знаю, что можно использовать copy, pg_read_file, но не понимаю как. P.S. Просто вставить текст из файла xml я могу, нужно именно вставлять файл из папки.


Ответ

insert into test(idserial, contenttext) values (4, pg_read_file('ex02.xml'));
Два момента: pg_read_file разрешено использовать только суперпользователю по соображениям безопасности. Если вы понимаете, что делаете, то обойти это ограничение возможно, например, созданием новой функции от имени суперпользователи и помеченной как security definer. От суперпользователя объявление функции:
CREATE OR REPLACE FUNCTION get_text_document(p_filename CHARACTER VARYING) RETURNS TEXT AS $$ SELECT pg_read_file($1); $$ LANGUAGE sql VOLATILE SECURITY DEFINER;
Затем можно её использовать от обычного пользователя
insert into test(idserial, contenttext) values (4, get_text_document('ex02.xml'));
Второй момент более проблемный: читать так можно только из директории, где лежит сама база или логи. Относительный путь выше по иерархии так же запрещён. Поэтому необходимо либо файл перебросить в нужное место, либо использовать симлинк на директорию (хотя надо бы проверить, вдруг и по симлинку ходить откажется) либо использовать другой способ.
Есть вариант через large object, опять же хранимка от суперпользователя:
create or replace function bytea_import(p_path text, p_result out bytea) language plpgsql as $$ declare l_oid oid; r record; begin p_result := ''; select lo_import(p_path) into l_oid; for r in ( select data from pg_largeobject where loid = l_oid order by pageno ) loop p_result = p_result || r.data; end loop; perform lo_unlink(l_oid); end;$$;
Оригинальная функция возвращает bytea, не стал это изменять в самой функции. Перекодировать можно вот так:
insert into test(idserial, contenttext) values (4, convert_from(bytea_import('/etc/fstab'), 'utf8'));
Можно использовать отдельное расширение с базовыми функциями ввода-вывода.
Или можно обратиться опять же к хранимым языкам, но помеченным как небезопасные: pl/perlu или pl/pythonu. Небезопасные они как раз потому, что могут обращаться в том числе к файловой системе беспрепятственно от имени пользователя базы данных. Например
CREATE FUNCTION gettext(url TEXT) RETURNS TEXT AS $$ import urllib2 try: f = urllib2.urlopen(url) return ''.join(f.readlines()) except Exception: return "" $$ LANGUAGE plpythonu;
insert into test(idserial, contenttext) values (4, gettext('file://D:\html\ex02.xml'));

Комментариев нет:

Отправить комментарий