null

Расширение функциональности СУБД с помощью внешних скриптов

Тема вызова внешних скриптов из СУБД не так уж нова, но часто остаётся за рамками технических решений, несмотря на свою простоту и изящность. Рассмотрим СУБД PostgreSQL (аналогичной функциональностью обладают OracleDB и MySQL). Иногда в процессе работы приложения может потребоваться обращаться к утилитам операционной системы, например, чтобы управлять подсистемами. Скажем, управлять записями в таблицах пакетного фильтра при изменении содержимого в БД. Также может потребоваться результаты выборки обрабатывать сложным образом, что не всегда удобно описывать в приложениях, работающих с базой (особенно, когда таких приложений несколько). Поэтому расскажу о стандартной возможности расширения языковых возможностей в PostgreSQL. Внимательный администратор обращал внимание на каталог databases/postgresql96-plperl в портах (ну или на наличие аналогичного пакета во всяких GNU/Linux-ах). Этот пакет позволяет нам создавать в БД дополнительные языки написания процедур, помимо PL/SQL, на котором описывать более-менее сложную логику -- не самое приятное занятие.

Давайте рассмотрим на примере двух кейсов. В первом кейсе БД является хранилищем системы тестирования и в ней есть табличка, в которой хранятся математические формулки, вводимые туда пользователями в ходе прохождения электронного тестирования. Задача состоит в том, чтобы найти в таблице все записи с некорректно расставленными скобками (для примера; в реальной системе там присутствует ещё несколько строк и одним запросом к БД можно получать все некорректные/корректные ответы. Ниже я привожу код, в котором создается БД с именем "test", создаётся в ней процедурный язык plperl, создаётся таблица для хранения математических выражений, заполняется тремя тестовыми выражениями. Далее создаётся функция, которая принимает текстовое поле и с помощью простого регулярного выражения проверяет корректность расстановки скобок в полученном текстовом поле. И приведён пример запроса, который из таблицы выбирает строки с некорректно расставленными скобками. 

postgres=# create database test;
CREATE DATABASE
postgres=# \c test;
psql (9.3.15, server 9.3.5)
You are now connected to database "test" as user "pgsql".
test=# create language plperl;
CREATE LANGUAGE
test=# create table math (id integer, math text, primary key(id));
CREATE TABLE
test=# insert into math values(1, '((a + b) * c) / 2 = y');
INSERT 0 1
test=# insert into math values(2, 'z = sum[ lg(e + 2 ^ e) + (a / b) ^ 4 ]');
INSERT 0 1
test=# insert into math values(3, 'x = q + (w + z_ ^ e + t ^ 2');
INSERT 0 1
test=# create function brcheck (text) returns integer as $$
test$#  return 0+($_[1] =~ /^[^][{}()]*(([({[])((?:[^][{}()]*+|(?1)))*(??{($0=$2)=~y|([{|)]}|;"\\$0"}))/);
test$# $$ language plperl;
CREATE FUNCTION
test=# select id, math from math where brcheck(math) = 0;
 id |            math
----+-----------------------------
  3 | x = q + (w + z_ ^ e + t ^ 2
(1 row)

test=#

Во втором кейсе требуется уже менее безобидная задачка -- управление внешними утилитами. Это не так безопасно, поэтому необходимо создать другой язык: PL/PerlU, буква "U" -- от слова Unsafe. В примере я вызываю 'ls -la /', но можно вызвать и более суровые вещи, типа 'rm -rf /'. Также сразу рассмотрим, как можно получить из подобной функции возвращаемые значения. 

test=# create function ls() returns setof text as $$
 chomp(my@a = `ls -la /`);
 return \@a;
$$ language plperlu;
CREATE FUNCTION
test=# select * from ls();
                                ls
------------------------------------------------------------------
 total 59
 drwxr-xr-x  20 root  wheel    26 May 19 09:22 .
 drwxr-xr-x  20 root  wheel    26 May 19 09:22 ..
 -r--r--r--   1 root  wheel  6195 Jan 25  2016 COPYRIGHT
...

Таким образом, мы покрыли практически все необходимые функциональные возможности программирования внутри БД, которые часто рационально использовать вместо огорода костылей на PHP. 

korg

 

Коротко о себе

Работаю в компании Tune-IT, администрирую инфраструктуру компании и вычислительную сеть кафедры Вычислительной ТехникиСПбНИУ ИТМО.

Интересы: администрирование UNIX и UNIX-like систем и активного сетевого оборудования, написание shell- и perl-скриптов, изучение технологий глобальных сетей.
Люблю собирать GNU/Linux и FreeBSD, использовать тайлинговые оконные менеджеры и писать системный софт.