11.04.2019, 13:32, "Nikita Glukhov" <n.gluhov@postgrespro.ru>:

On 11.04.2019 5:40, Dmitry E. Oboukhov wrote:

11.04.2019, 01:58, "Nikita Glukhov" <n.gluhov@postgrespro.ru>:
 
 FUNCTION 1 btint4cmp, 
 FUNCTION 2 gin_extract_jsonb_path, 
 FUNCTION 3 gin_extract_jsonb_query_path, 
 FUNCTION 4 gin_consistent_jsonb_path,
 FUNCTION 6 gin_triconsistent_jsonb_path,
STORAGE integer;
 
А вот по этим функциям где-то можно почитать разъяснения?

В официальной документации вроде бы все достаточно подробно описано:

https://www.postgresql.org/docs/11/gin-extensibility.html (на английском)
https://postgrespro.ru/docs/postgresql/11/gin-extensibility (на русском)

 
интересно - можно ли писать эти функции на SQL (plpgsql)?
 
если смотреть на функцию gin_triconsistent_jsonb, например, то
 
 
Тип данных результата  | "char"
Типы данных аргументов | internal, smallint, jsonb, integer, internal, internal, internal
 
если посмотреть на неё со стороны документации, то
 
bool consistent(bool check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool nullFlags[])
 
 
я хочу (хотел, пока Ваш ответ не прочитал) написать скетч индекса на plpgsql. пусть он медленно работает в области сплита данных на индексируемые массивы итп, но если он заработает - появится смысл сесть это и на C написать.
 

 

и вот еще вопрос. Некоторые из этих функций принимают internal в виде аргументов, соответственно вызвать их и посмотреть их поведение прямо из SELECT - непонятно как.
 
соответственно непонятно - как полностью с нуля написать свой OPERATOR CLASS не используя программирование на C (допустим хотим сделать скетч на SQL, возможно ли это сделать?)


Да, все GIN-функции, за исключением первой compare(), можно написать сейчас только на C, и вызывать их из SQL нельзя. Но можно попробовать сделать один раз специальный обобщенный OPERATOR CLASS, в котором из функциий 2-6, написанных на C, будут вызываться другие функции с соответствующими номерами (например, 12-16), в которых уже будут использоваться только SQL-типы. Но полностью перенести всю функциональность C-функций на уровень SQL будет не так просто, потому что многие функции могут возвращать несколько значений сразу, а внутри Postgres, по-моему, нет такого удобного способа вызова для функций с OUT-параметрами, который есть для обычных функций. Например,

  Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)

спасибо, помедитирую над этим всем.
 
я сишечную реализацию не смотрел вовсе, думал со стороны SQL до скетча добраться можно.
 

возвращает массив извлеченных элементов, а также необязательные массив флагов pmatch, массив произвольных С-указателй extra_data, массив null-флагов nullFlags, и режим поиска searchMode. Если оставить только обязательный массив элементов, то сигнатрура SQL-функции extract_query будет совсем простой:
 
   extract_query (query anyelement, strategy int2) RETURNS storage_type[]

но я не уверен, что с anyelement не возникнет каких-либо проблем.
 

И еще хочу на всякий случай напомнить, что у нас есть еще расширение JsQuery (https://github.com/postgrespro/jsquery), которое содержит опклассы, позволяющие выполнять по GIN-индексам более широкий ряд jsonb-запросов (например, range-запросов, которые реализованы с использования partialMatch). Возможно даже, что JsQuery решит Вашу задачу. Сейчас мы работает в JsQuery на поддержкой jsonpath, который выйдет в PostgreSQL12, а в будущем планируем даже перенести эти JsQuery-опклассы в ядро.

 
 
цитата оттуда:
 
int compare(Datum a, Datum b)

Сравнивает два ключа (не индексированные объекты!) и возвращает целое меньше нуля, ноль или целое больше нуля, показывающее, что первый ключ меньше, равен или больше второго. Ключи NULL никогда не передаются этой функции.

Если же класс операторов не определяет метод compare, GIN попытается найти класс операторов B-дерева по умолчанию для типа данных ключа индекса и воспользоваться его функцией сравнения. Если класс операторов GIN предназначен только для одного типа данных, рекомендуется задавать функцию сравнения в этом классе операторов, так как поиск класса операторов B-дерева занимает несколько циклов. Однако для полиморфных классов операторов GIN (например, array_ops) задать одну функцию сравнения обычно не представляется возможным.

 
для полиморфных типов (например массивы) a и b - это ключи возвращённые extractValue или это массивы ключей извлечённые из записей? (я еще не разобрался с API низкого уровня, сорри если вопрос глупый: пытаюсь понять как индекс работает).
 
то есть extractValue вернул например:
 
1. для записи 1 - массив "a", "b", "c"
2. для записи 2 - массив "c", "d", "e"
3. для записи 3 - массив "x", "y", "z"
 
потом пользователь ищет
 
"ary" @> [ "c" ]
 
compare что с чем сравнивает при этом? я хочу своей функцией compare иметь возможность поднять или опустить ввверх-низ списка записи в зависимости от своих критериев.