Введение

В примерах ниже предполагается, что среда настроена так, что при запуске psql Вы получали доступ к PostgreSQL с достаточными правами. Тогда Вы можете пользоваться pgoblin без указания параметров соединения с базой. Можно параметрами задавать другую СУБД, например, pgoblin -Bsqlite3 будет по умолчанию работать с sqlite3.

Запросы можно указывать прямо в параметрах, например:

pgoblin -Bpgsql -s'SELECT * FROM pg_group'
Сразу видим, что оформление за нас придумывать некому :-). Пробуем сделать запрос с оформленным выводом:
pgoblin -Bpgsql -s"SELECT groname,'[',grosysid,']=',grolist,'
' FROM pg_group"
Уже интереснее. Но такое выражение не всяким шеллом выдать можно, по крайней мере с клавиатуры. Делаем файлик $TMPDIR/t:
#!/usr/local/bin/pgoblin -Bpgsql
#select
SELECT groname,'[',grosysid,']=',grolist,'
' FROM pg_group
делаем его исполняемым и исполняем.

Угу. Уже неплохо.

Теперь для примера скрипт, который создает и заполняет временную таблицу именами файлов в текущем каталоге. Заодно и выведем ее:

#!/usr/local/bin/pgoblin -Bpgsql
#file N
/dev/null
#exec    20N
/bin/ls
#getstr  302
#perform
CREATE TEMP TABLE t(i int, t text);
#copyin  003
COPY t FROM stdin;
#strselect
SELECT '[',i,']=',t,'~
' FROM t
Здесь первоисточником служит /bin/ls, который запускается оператором #exec, и этот оператор направляет stdout запускаемой команды в регистр ввода/вывода 2. Следующая команда, #getstr, берет поток из регистра ввода/вывода 2, преобразует его в вид, пригодный для скармливания команде COPY и направляет преобразованный поток в регистр ввода/вывода 3. Следующая команда, #copyin, берет поток из регистра ввода/вывода 3 для COPY в заполняемую таблицу. Как видно, в литерале к команде #copyin перед SQL оператором COPY при работе с СУБД PostgreSQL можно задавать другие операторы, в данном случае SQL оператор для создания таблицы, которая и будет заполняться. Не все СУБД позволяют это, потому для универсальности так лучше не делать.

При выполнении #exec надо задавать выполняемой программе stdin и stdout независимор от того, использует ли программа их. Если не задать из явно, то они будут взяты из 0го регистра ввода-вывода. В начале выплнения pgoblin там обычно stdin и stdout самого pgoblinа, но гарантии, что всегда в момент вызова #exec они там будут, нет, потому об этом надо заботиться специально.

Последний оператор - #strselect, он выводит получившуюся таблицу. #strselect отличается от #select тем, что он работает в потоке, и при неограниченном размере выводимого в памяти будет присутствовать только небольшая часть потока в процессе передачи. Оператор #select размещает весь результат целиком в памяти, что удобно для небольших результатов, но опасно для неограниченных.

Еще один пример. В нем мы вводим строки из stdin, считаем каждую строку названием файла и проверяем, есть ли названный файл в текущем каталоге:

#!/usr/local/bin/pgoblin -Bpgsql
#file N
/dev/null
#perform
CREATE TEMP TABLE f(i int, t text);
#getstr 3
#copyin 003
COPY f FROM stdin
#exec 20N
/bin/ls
#
-a
#
-A
#getstr 302
#copyin 003
CREATE TEMP TABLE t(i int, t text);
COPY t FROM stdin
#strselect
SELECT CASE WHEN t.t IS NULL THEN 'None=' ELSE 'Exists=' END,f.t,'~
' FROM f LEFT JOIN t USING(t)
Какие особенности видим тут? В начале не стали совмещать в одном литерале создание и заполнение таблицы а использовали команду #perform для выполнения SQL команды без ввода/вывода. Так тоже можно. Даже лучше так. Для того, что бы получить все файлы текущего каталога, в том числе с точкой вначале, /bin/ls запущен с флагами -aA. Таким образом можно задавать любое количество параметров запускаемой программе.

Поскольку pgoblin предназначен для написания скриптов, а не для работы в диалоге, ввод/вывод как правило буферизуется, и потому, скорее всего, результата Вы не увидите, пока не закончите файл ввода. Если вводите названия вручную, то в стандартных настройках конец файла надо выдать с клавиатуры несколько раз (обычно 3), что бы программа ввода поверила, что вводу конец. Этим заведует библиотека mife, в документации к ней можно узнать подробности.

Теперь нарисуем скрипт, который запускается с 2мя параметрами, именем каталога и количеством файлов, которые оттуда надо изобразить:

#!/usr/local/bin/pgoblin -Bpgsql
#file N
/dev/null
#getarg 2
#copyin 002
CREATE TEMP TABLE a(i int, a text);
COPY a FROM stdin
#perform
CREATE TEMP TABLE x(d text, l int);
INSERT INTO x(d, l)
 SELECT (SELECT a FROM a WHERE i = 1 LIMIT 1)
      , (SELECT a::int4 FROM a WHERE i = 2 AND a ~ '^[0-9]+$' LIMIT 1)
;
DELETE FROM x WHERE d IS NULL OR l IS NULL;
#select 4
SELECT '/bin/ls','-aA',d
 FROM x
#exec 34N
#getstr 203
#perform
CREATE TEMP TABLE t(i int, t text);
#copyin 002
COPY t FROM stdin
#select 4
SELECT 'SELECT ''['',i,'']='',t,''~
'' FROM t LIMIT ' || l
 FROM x
#strselect 04
Второй оператор скрипта, #getarg, помещает в регистр ввода/вывода 2 поток параметров скрипта, которые и вводятся в третьем операторе. 4й оператор, #perform, готовит временную таблицу x, в которой дешифрованы все параметры скрипта. Далее, 5ым оператором (#select) в 4ом регистре ввода/вывода создаются строки (в данном случае только одна) для 6го оператора - #exec для запуска внешних программ (в данном случае /bin/ls с соответствующими параметрами. stdout запущенной команды направляется в регистр 3, откуда он берется командой #getstr и отправляется команде #copyin через 2й регистр, как ранее было уже рассмотрено. Далее нечто новенькое: команда #select создает во 2ом регистре команду SQL, которая и выполняется последней командой скрипта - #strselect. В этом примере показано, как выполняются не статические, а тут же построенные SQL команды.

На всякий случай запомните, что /bin/ls тут используется для примера работы с потомками и потоками, для получения каталога у pgoblin имеется команда #getdir, которая аккуратно обращается с, в частности, непечатными символами в названии файла.


А.А.Бабайлов (C)2003..2022