Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hEWzv-0005NP-Am for pgsql-ru-general@arkaria.postgresql.org; Thu, 11 Apr 2019 10:32:00 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hEWzt-0002ql-Fq for pgsql-ru-general@arkaria.postgresql.org; Thu, 11 Apr 2019 10:31:57 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hEWzt-0002qe-4T for pgsql-ru-general@lists.postgresql.org; Thu, 11 Apr 2019 10:31:57 +0000 Received: from cyclops.postgrespro.ru ([93.174.131.138] helo=mail.postgrespro.ru) by magus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hEWzp-0001PN-Os for pgsql-ru-general@lists.postgresql.org; Thu, 11 Apr 2019 10:31:56 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.postgrespro.ru (Postfix) with ESMTP id 609A321C4050; Thu, 11 Apr 2019 13:31:52 +0300 (MSK) X-Virus-Scanned: Debian amavisd-new at postgrespro.ru X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=x tagged_above=-99 required=4 WHITELISTED tests=[] autolearn=unavailable Received: from [10.100.236.29] (unknown [195.82.154.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by mail.postgrespro.ru (Postfix) with ESMTPSA id 2521A21C4049; Thu, 11 Apr 2019 13:31:52 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1554978712; bh=YeGsK2TOyb7SsJwHD6melBounhGHyClS8wIOKXUbOok=; h=Subject:To:Cc:References:From:Date:In-Reply-To; b=gvxVy3xlylYiP0IsHuG2jXHXSOVi50dgE0JIvminxR/AfYEfzg01f++hTaoThcK5o pkrnstaM7jdjOsQ38498CaZMUgBkoVlnRH6zK/uMb+gi9dsklQxHsvBfRf/MEaf78s m/8OgHaOQ7zf6m0WX/bExOTrlGvVoM7vf4xRrTrU= Subject: Re: OPERATOR CLASS To: "Dmitry E. Oboukhov" Cc: "pgsql-ru-general@lists.postgresql.org" References: <10196171554829471@iva7-6548a8037c6d.qloud-c.yandex.net> <2084391554950401@myt2-cd7fa496c4f7.qloud-c.yandex.net> From: Nikita Glukhov Organization: Postgres Professional Message-ID: <3b78bd3f-f051-3ff0-97db-e2f4f9a7ab54@postgrespro.ru> Date: Thu, 11 Apr 2019 13:31:43 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <2084391554950401@myt2-cd7fa496c4f7.qloud-c.yandex.net> Content-Type: multipart/alternative; boundary="------------01F0255E6022EF8A8D457052" Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------01F0255E6022EF8A8D457052 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit On 11.04.2019 5:40, Dmitry E. Oboukhov wrote: > 11.04.2019, 01:58, "Nikita Glukhov" : >>  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 (на русском) > насколько я понимаю функция 1 - сравнивает именно то, что возвращает > функция 2 > функция 3 нужна за тем же зачем и функция 2, но она работает над запросом > то есть если у нас > WHERE json_field @> json_query > то реально получается следующее > json_field пропускается через функцию 2 при индексировании > json_query - пропускается через функцию 3 при самом запросе > функция 1 используется для сравнения двух элементов между собой > Да, все правильно. Хочу еще обратить внимание, что запрос может быть другого, не jsonb, типа, а функция extractQuery() различает разные типы запорсов по их номеру стратегии. >  а вот функции 4 и 6 - они для чего используются? В документации про это написано, но если будут вопросы, отвечу на них. Вот файл, в котором находится реализация этих функций для jsonb: https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/jsonb_gin.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) возвращает массив извлеченных элементов, а также необязательные массив флагов 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-опклассы в ядро. -- Nikita Glukhov Postgres Professional: http://www.postgrespro.com The Russian Postgres Company --------------01F0255E6022EF8A8D457052 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit

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 (на русском)

 
насколько я понимаю функция 1 - сравнивает именно то, что возвращает функция 2
функция 3 нужна за тем же зачем и функция 2, но она работает над запросом
 
то есть если у нас
 
WHERE json_field @> json_query
 
то реально получается следующее
 
json_field пропускается через функцию 2 при индексировании
json_query - пропускается через функцию 3 при самом запросе
функция 1 используется для сравнения двух элементов между собой

Да, все правильно. Хочу еще обратить внимание, что запрос может быть другого, не jsonb, типа, а функция extractQuery() различает разные типы запорсов по их номеру стратегии.

 а вот функции 4 и 6 - они для чего используются?

В документации про это написано, но если будут вопросы, отвечу на них.

Вот файл, в котором находится реализация этих функций для jsonb:
https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/jsonb_gin.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)

возвращает массив извлеченных элементов, а также необязательные массив флагов 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-опклассы в ядро.

--
Nikita Glukhov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

--------------01F0255E6022EF8A8D457052--