Пару-тройку раз у меня уже встречалась потребность посмотреть код, который выполняет PostgreSQL чтобы выполнить метакоманды psql. Это можно сделать очень просто, но времени много проходит между использованиями этого метода, и я некоторые детали забываю.
Так что решил опубликовать ответ, чтобы можно было его очень быстро найти. Ниже как раз он и приведен.
Итак, метакоманды psql — очень удобная штука. Например, чтобы вывести список доступных баз данных можно выполнить вот такую команду:
\l;
В ответ можно получить примерно такое:
postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges -----------+----------+----------+-------------+-------------+------------+-----------------+----------------------- postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres + | | | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres + | | | | | | | postgres=CTc/postgres (3 rows)
Но мы выполнили только крошечную команду, ясное дело что PostgreSQL «разворачивает» её в запрос. Но какой?
Узнать это можно «включив» переменную ECHO_HIDDEN, то есть присвоить ей значение on. Давайте попробуем:
\set ECHO_HIDDEN on
И снова выполним команду \l:
postgres=# \l ********* QUERY ********** SELECT d.datname as "Name", pg_catalog.pg_get_userbyid(d.datdba) as "Owner", pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding", d.datcollate as "Collate", d.datctype as "Ctype", d.daticulocale as "ICU Locale", CASE d.datlocprovider WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS "Locale Provider", pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" FROM pg_catalog.pg_database d ORDER BY 1; ************************** List of databases Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges -----------+----------+----------+-------------+-------------+------------+-----------------+----------------------- postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres + | | | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | libc | =c/postgres + | | | | | | | postgres=CTc/postgres (3 rows)
Теперь можно увидеть запрос (в частности, здесь идет обращение к таблице системного каталога pg_database).
Точно так же можно смотреть запросы для других метакоманд.
Узнать текущее значение переменной ECHO_HIDDEN (и других) можно с помощью команды:
\echo :ECHO_HIDDEN off
Но мы видим не только запрос, но и результат его работы. А что делать если нам нужно только текст запроса посмотреть? То есть, нам не нужно его выполнять? Для этого можно переменной ECHO_HIDDEN присвоить значение noexec — тогда мы увидим только текст без его выполнения:
postgres=# \set ECHO_HIDDEN noexec postgres=# \l ********* QUERY ********** SELECT d.datname as "Name", pg_catalog.pg_get_userbyid(d.datdba) as "Owner", pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding", d.datcollate as "Collate", d.datctype as "Ctype", d.daticulocale as "ICU Locale", CASE d.datlocprovider WHEN 'c' THEN 'libc' WHEN 'i' THEN 'icu' END AS "Locale Provider", pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" FROM pg_catalog.pg_database d ORDER BY 1; **************************
А если уже не хотите смотреть тексты запросов метакоманд — установите значение этой переменной в off.
Leave a Reply