- PVSM.RU - https://www.pvsm.ru -
Эх, давно я не брал в руки шашечек. Но делать нечего, я заперт в чужом городе до вечера и единственным утешением мне служит безалкогольное пиво в местной пиццерии. А потому, чтобы слегка умерщвлить время, напишу статейку о том, как я решал несложную задачу наших переднеконечников (фронтэндеров).
Они в данный момент создают некий интерфейс, в коем, помимо всего прочего, будет редактор фильтров на возвращаемые данные. Потому меня и спросили:
достаточно ли будет в качестве операторов сравнения использовать стандартные
"<,>,!=,="
? Или есть какие-то операторы, которые стоит добавить?
— Нет, не достаточно, — отвечал я им. — Мало того, что PostgreSQL из коробки поддерживает тьму-тьмущую операторов [1], так их еще можно определять [2] самому, и вдобавок каждое расширение норовит дополнить систему еще дюжиной.
Мой ответ их озадачил. А когда кто-то озадачен, он с удовольствием озадачит ближнего своего. И меня попросили (как непререкаемого авторитета, само собой) составить список операторов, хотя бы для случая голой и свежей системы.
Но я не первый раз женат, и знаю, что система системе рознь, начиная c различий между версиями ванильного слона, и заканчивая форками, например PostgresPro, CitusDB… тысячи их. Ну, а во-вторых, эти же ребята завтра захотят получать список доступных операторов для отображения, и таки мне все равно придется решать эту задачу. Потому данный текст представляет собой ход моих мыслей.
boolean
Моим первым желанием было полезть в мануал [1] и надергать по-быстрому оттуда список основных операторов. Лениво и не спортивно.
Потом посетила мысль прошерстить на этот предмет исходники. Лежит это добро в /src/include/catalog/pg_operator.h [3]. Естественно, мысль тоже пошла лесом. Раз уж мы будем копаться в системных каталогах сервера, то удобнее это делать с помощью SQL.
В пиццерии не оказалось поднятого Postgres сервера, но у меня с собой, как говорится, было. Если же у вас с собой нет, то вы можете провести со мной эти эксперименты на замечательном сервисе SQL Fiddle [4].
Итак, информация об операторах хранится в системном каталоге pg_operator
, потому первой итерацией логично предположить
SELECT * FROM pg_operator;
На моем голом PostgreSQL 9.6 я получил 772 строки, а на том же SQL Fiddle (PostgreSQL 9.3) запрос вернул 823 строки. Такой разброс не должен вас удивлять. Выяснилось, что во втором случае «из коробки» установлено дополнительно 8 расширений:
SELECT extname FROM pg_extension;
| extname |
|---------------|
| plpgsql |
| fuzzystrmatch |
| hstore |
| intagg |
| intarray |
| ltree |
| pg_trgm |
| uuid-ossp |
| xml2 |
Теперь ограничим выдачу только операторами, которые результатом возвращают boolean
.
SELECT * FROM pg_operator WHERE oprresult = 'boolean'::regtype;
---------------
Record Count: 513; (local 9.6)
Record Count: 552; (SQL Fiddle 9.3)
Разберем эту особую уличную магию. Поле oprresult
имеет тип oid, что изнутре представляет собой беззнаковый целочисленный тип в 4-байта. По-хорошему надо было бы и сравнивать с числом, но не все такие ботаны как я, чтобы помнить, что oid типа boolean равен 16. Потому тут мы воспользовались псевдотипом regtype
и приведением типов. Очень удобная штучка. Советую взять на вооружение.
Как вы, наверное, заметили один и тот же оператор может использоваться для разных типов аргументов. Нам не нужны дубли по итогу, поэтому попробуем убрать дубли и сделать вывод более осмысленным.
SELECT oprname,
count(1),
array_agg(DISTINCT oprleft::regtype) AS left_args,
array_agg(DISTINCT oprright::regtype) AS right_args,
array_agg(DISTINCT obj_description(oid, 'pg_operator')) AS comments
FROM pg_operator
WHERE oprresult = 'boolean'::regtype
GROUP BY oprname
ORDER BY count(1) DESC;
---------------
Record Count: 58; (local 9.6)
Record Count: 62; (SQL Fiddle 9.3)
Автор: Павел Голубь
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/postgresql/252655
Ссылки в тексте:
[1] операторов: https://www.postgresql.org/docs/current/static/functions.html
[2] определять: https://www.postgresql.org/docs/current/static/sql-createoperator.html
[3] /src/include/catalog/pg_operator.h: https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/include/catalog/pg_operator.h;hb=HEAD
[4] SQL Fiddle: http://sqlfiddle.com/
[5] Источник: https://habrahabr.ru/post/324264/
Нажмите здесь для печати.