Главная » Хабрахабр » Что нового в PostgreSQL 11: JSONB-трансформы

Что нового в PostgreSQL 11: JSONB-трансформы

Эти фичи появятся в PostgreSQL 11, релиз которого, напомню, планируется в октябре. В предыдущих постах вы могли прочитать про INCLUDE-индексы и встроенный веб-поиск. Оба патча написаны Антоном Быковым.
Как вам может быть известно, PostgreSQL позволяет писать хранимые процедуры на разных языках, в том числе на C, PL/pgSQL, PL/Perl, PL/Python и других. Сегодня мне хотелось бы продолжить обзор новых фичей грядущего релиза, рассказав про JSONB-трансформы для языков PL/Python (3f44e3db) и PL/Perl (341e1661). Для хранения документов есть два встроенных типа: JSON, являющийся по сути обычной строкой, и JSONB, реализующий более эффективное бинарное представление. Также PostgreSQL позволяет хранить JSON, строить по нему индексы и производить различные манипуляции с документами.

Проще всего объяснить его на примере: Однако на границе этих механизмов есть небольшой косяк.

-- Важно! Синтаксис `create language` задепрекейчен с 9.1
create extension plpython3u; CREATE OR REPLACE FUNCTION foo(val jsonb) RETURNS int
LANGUAGE plpython3u
AS $$
assert(isinstance(val, str))
return len(val)
$$; select foo('' :: jsonb);

В результате код выполнится без ошибок и вернет результат 24. То есть, при передаче в хранимую процедуру JSONB был в закодирован в строку, от которой мы вычислили длину.

Как ни странно, никакого бага здесь нет, как можно было бы предположить. Fun fact! На самом деле, длина исходного документа — 22 символа, а у нас почему-то получилось 24. Попробуйте в качестве домашнего задания выяснить, чем вызвано такое несоответствие.

Само собой разумеется, строку можно декодировать обратно: Так вот, но ведь мы хотели передать документ, а не строку.

CREATE OR REPLACE FUNCTION bar(val_str jsonb) RETURNS int
LANGUAGE plpython3u
AS $$
import json
val = json.loads(val_str)
assert(isinstance(val, dict))
plpy.info(sorted(val.items()))
return len(val)
$$; select bar('{"aaa": 123, "ййй": 456}' :: jsonb);

Результат:

INFO: [('aaa', 123), ('ййй', 456)]bar
-----
2
(1 row)

Но если подумать, мы тут делаем много бесполезной работы — сначала кодируем документ, а затем тут же декодируем. Вроде, похоже на правду. Если документ большой, а хранимая процедура вызывается часто, накладные расходы на это кодирование-декодирование могут быть довольно большими.

Оказывается, что можно, и названные патчи делают именно это. Спрашивается, а нельзя ли просто передать JSONB в Python или Perl в виде понятных им объектов (массивов, словарей/хэшей, и так далее)? Вот как этим примерно пользоваться:

create extension jsonb_plpython3u; CREATE OR REPLACE FUNCTION baz(val jsonb) RETURNS int
LANGUAGE plpython3u
TRANSFORM FOR TYPE jsonb
AS $$
assert isinstance(val, dict)
plpy.info(sorted(val.items()))
return len(val)
$$;

Кстати, в обратную сторону, то есть, кодировать возвращаемые документы, тоже можно:

CREATE OR REPLACE FUNCTION qux(val int) RETURNS jsonb
LANGUAGE plpython3u
TRANSFORM FOR TYPE jsonb
AS $$
obj = { "val": val }
return obj
$$;

Для Perl и Python 2 все делается аналогично, поэтому соответствующий код я не привожу. Кроме того, не стану грузить вас тонкостями работы кода в различных граничных случаях, например, что происходит, если в возвращаемом документе встретятся комплесные числа, NaN, ±Inf, и вот это вот все. Заинтересованных читателей я призываю ознакомиться с кодом патчей. Они обильно обмазаны тестами, как раз проверяющими подобные граничные случаи.

Конечно, ситуации, в которых она оказывается полезна, возникают не часто. Такая вот интересная фича. Но знать про существование JSONB-трансформов, все же, не повредит.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

В России приступили к тестированию отечественного нейроинтерфейса «Нейрочат»

Эта система предназначена для пациентов с ограниченными физическими способностями. В конце прошлого года компания Neurotrand разработала вместе с партнерами программно-аппаратный комплекс с нейрогарнитурой. Это могут быть пациенты клиник, перенесшие инсульт, военные с тяжелыми ранениями, люди, получившие травму на производстве. Она ...

Зрители не могут отличить нативную картинку 4K от интерполяции

Такие выводы можно сделать из результатов российского исследования, проведённого холдингом «Ромир». Человеческого зрения недостаточно, чтобы отличить настоящее видео 4K от картинки, которую получили из изображения HDTV с помощью интерполяции. Опрошенным показывали на телеэкране фрагменты двух видеороликов и спрашивали о восприятии ...