PostgreSQL UDF
YQL предоставляет возможность доступа к функциям и типам данных PostgreSQL.
Имена PostgreSQL типов в YQL получаются добавлением префикса Pg
к исходному имени типа.
Например PgVarchar
, PgInt4
, PgText
. Имена pg типов (как и вообще всех типов) в YQL являются case-insensitive. На данный момент поддерживаются все простые типы данных из PostgreSQL, а также массивы.
Если исходный тип является типом массива (в PostgreSQL такие типы начинаются с подчеркивания: _int4
- массив 32-битных целых), то имя типа в YQL тоже начинается с подчеркивания – _PgInt4
.
Литералы
Строковые и числовые литералы Pg типов можно создавать с помощью специальных суффиксов (аналогично простым строковым и числовым литералам).
Целочисленные литералы
Суффикс | Тип | Комментарий |
---|---|---|
p |
PgInt4 |
32-битное знаковое целое (в PostgreSQL нет беззнаковых типов) |
ps |
PgInt2 |
16-битное знаковое целое |
pi |
PgInt4 |
|
pb |
PgInt8 |
64-битное знаковое цело |
pn |
PgNumeric |
знаковое целое произвольной точности (до 131072 цифр) |
Литералы с плавающей точкой
Суффикс | Тип | Комментарий |
---|---|---|
p |
PgFloat8 |
число с плавающей точкой (64 бит double) |
pf4 |
PgFloat4 |
число с плавающей точкой (32 бит float) |
pf8 |
PgFloat8 |
|
pn |
PgNumeric |
число с плавающей точкой произвольной точности (до 131072 цифр перед запятой, до 16383 цифр после запятой) |
Строковые литералы
Суффикс | Тип | Комментарий |
---|---|---|
p |
PgText |
текстовая строка |
pt |
PgText |
|
pv |
PgVarchar |
текстовая строка |
pb |
PgBytea |
бинарная строка |
Внимание
Значения строковых/числовых литералов (т.е. то что идет перед суффиксом) должны быть валидной строкой/числом с точки зрения YQL.
В частности, должны соблюдаться правила эскейпинга YQL, а не PostgreSQL.
Пример:
SELECT
1234p, -- pgint4
0x123pb, -- pgint8
"тест"pt, -- pgtext
123e-1000pn; -- pgnumeric
;
Литерал массива
Для построения литерала массива используется функция PgArray
:
SELECT
PgArray(1p, NULL ,2p) -- {1,NULL,2}, тип _int4
;
Конструктор литералов произвольного типа
Литералы всех типов (в том числе и Pg типов) могут создаваться с помощью конструктора литералов со следующей сигнатурой:
Имя_типа(<строковая константа>)
.
Напрмер:
DECLARE $foo AS String;
SELECT
PgInt4("1234"), -- то же что и 1234p
PgInt4(1234), -- в качестве аргумента можно использовать литеральные константы
PgInt4($foo), -- и declare параметры
PgBool(true),
PgInt8(1234),
PgDate("1932-01-07"),
;
Также поддерживается встроенная функция PgConst
со следующей сигнатурой: PgConst(<строковое значение>, <тип>)
.
Такой способ более удобен для кодогенерации.
Например:
SELECT
PgConst("1234", PgInt4), -- то же что и 1234p
PgConst("true", PgBool)
;
Для некоторых типов в функции PgConst
можно указать дополнительные модификаторы. Возможные модификаторы для типа pginterval
перечислены в документации PostgreSQL.
SELECT
PgConst(90, pginterval, "day"), -- 90 days
PgConst(13.45, pgnumeric, 10, 1); -- 13.5
;
Операторы
Операторы PostgreSQL (унарные и бинарные) доступны через встроенную функцию PgOp(<оператор>, <операнды>)
:
SELECT
PgOp("*", 123456789987654321pn, 99999999999999999999pn), -- 12345678998765432099876543210012345679
PgOp('|/', 10000.0p), -- 100.0p (квадратный корень)
PgOp("-", 1p), -- -1p
-1p, -- унарный минус для литералов работает и без PgOp
;
Оператор приведения типа
Для приведения значения одного Pg типа к другому используется встроенная функция PgCast(<исходное значение>, <желаемый тип>)
:
SELECT
PgCast(123p, PgText), -- преобразуем число в строку
;
При преобразовании из строковых Pg типов в некоторые целевые типы можно указать дополнительные модификаторы. Возможные модификаторы для типа pginterval
перечислены в документации.
SELECT
PgCast('90'p, pginterval, "day"), -- 90 days
PgCast('13.45'p, pgnumeric, 10, 1); -- 13.5
;
Преобразование значений Pg типов в значения YQL типов и обратно
Для некоторых Pg типов возможна конвертация в YQL типы и обратно. Конвертация осуществляется с помощью встроенных функций
FromPg(<значение Pg типа>)
и ToPg(<значение YQL типа>)
:
SELECT
FromPg("тест"pt), -- Just(Utf8("тест")) - pg типы всегда nullable
ToPg(123.45), -- 123.45pf8
;
Список псевдонимов типов PostgreSQL при их использовании в YQL
Ниже приведены типы данных YQL, соответствующие им логические типы PostgreSQL и названия типов PostgreSQL при их использовании в YQL:
YQL | PostgreSQL | Название PostgreSQL-типа в YQL |
---|---|---|
Bool |
bool |
pgbool |
Int8 |
int2 |
pgint2 |
Uint8 |
int2 |
pgint2 |
Int16 |
int2 |
pgint2 |
Uint16 |
int4 |
pgint4 |
Int32 |
int4 |
pgint4 |
Uint32 |
int8 |
pgint8 |
Int64 |
int8 |
pgint8 |
Uint64 |
numeric |
pgnumeric |
Float |
float4 |
pgfloat4 |
Double |
float8 |
pgfloat8 |
String |
bytea |
pgbytea |
Utf8 |
text |
pgtext |
Yson |
bytea |
pgbytea |
Json |
json |
pgjson |
Uuid |
uuid |
pguuid |
JsonDocument |
jsonb |
pgjsonb |
Date |
date |
pgdate |
Datetime |
timestamp |
pgtimestamp |
Timestamp |
timestamp |
pgtimestamp |
Interval |
interval |
pginterval |
TzDate |
text |
pgtext |
TzDatetime |
text |
pgtext |
TzTimestamp |
text |
pgtext |
Date32 |
date |
pgdate |
Datetime64 |
timestamp |
pgtimestamp |
Timestamp64 |
timestamp |
pgtimestamp |
Interval64 |
interval |
pginterval |
TzDate32 |
text |
|
TzDatetime64 |
text |
|
TzTimestamp64 |
text |
|
Decimal |
numeric |
pgnumeric |
DyNumber |
numeric |
pgnumeric |
ToPg
Таблица соответствия типов Таблица соответствия типов данных YQL и PostgreSQL при использовании функции ToPg
:
YQL | PostgreSQL | Название PostgreSQL-типа в YDB |
---|---|---|
Bool |
bool |
pgbool |
Int8 |
int2 |
pgint2 |
Uint8 |
int2 |
pgint2 |
Int16 |
int2 |
pgint2 |
Uint16 |
int4 |
pgint4 |
Int32 |
int4 |
pgint4 |
Uint32 |
int8 |
pgint8 |
Int64 |
int8 |
pgint8 |
Uint64 |
numeric |
pgnumeric |
Float |
float4 |
pgfloat4 |
Double |
float8 |
pgfloat8 |
String |
bytea |
pgbytea |
Utf8 |
text |
pgtext |
Yson |
bytea |
pgbytea |
Json |
json |
pgjson |
Uuid |
uuid |
pguuid |
JsonDocument |
jsonb |
pgjsonb |
Date |
date |
pgdate |
Datetime |
timestamp |
pgtimestamp |
Timestamp |
timestamp |
pgtimestamp |
Interval |
interval |
pginterval |
TzDate |
text |
pgtext |
TzDatetime |
text |
pgtext |
TzTimestamp |
text |
pgtext |
Date32 |
date |
pgdate |
Datetime64 |
timestamp |
pgtimestamp |
Timestamp64 |
timestamp |
pgtimestamp |
Interval64 |
interval |
pginterval |
TzDate32 |
text |
|
TzDatetime64 |
text |
|
TzTimestamp64 |
text |
|
Decimal |
numeric |
pgnumeric |
DyNumber |
numeric |
pgnumeric |
FromPg
Таблица соответствия типов Таблица соответствия типов данных PostgreSQL и YQL при использовании функции FromPg
:
PostgreSQL | YQL |
---|---|
bool |
bool |
int2 |
Int16 |
int4 |
Int32 |
int8 |
Int64 |
float4 |
Float |
float8 |
Double |
bytea |
String |
varchar |
Utf8 |
text |
Utf8 |
cstring |
Utf8 |
uuid |
Uuid |
date |
Date32 |
timestamp |
Timestamp64 |
Вызов PostgreSQL функций
Чтобы вызвать PostgreSQL функцию, необходимо добавить префикс Pg::
к ее имени:
SELECT
Pg::extract('isodow'p,PgCast('1961-04-12'p,PgDate)), -- 3pn (среда) - работа с датами до 1970 года
Pg::generate_series(1p,5p), -- [1p,2p,3p,4p,5p] - для функций-генераторов возвращается ленивый список
;
Существует также альтернативный способ вызова функций через встроенную функцию PgCall(<имя функции>, <операнды>)
:
SELECT
PgCall('lower', 'Test'p), -- 'test'p
;
При вызове функции, возвращающей набор pgrecord
, можно распаковать результат в список структур, используя функцию PgRangeCall(<имя функции>, <операнды>)
:
SELECT * FROM
AS_TABLE(PgRangeCall("json_each", pgjson('{"a":"foo", "b":"bar"}')));
--- 'a'p,pgjson('"foo"')
--- 'b'p,pgjson('"bar"')
;
Вызов агрегационных PostgreSQL функций
Чтобы вызвать агрегационную PostgreSQL функцию, необходимо добавить префикс Pg::
к ее имени:
SELECT
Pg::string_agg(x,','p)
FROM (VALUES ('a'p),('b'p),('c'p)) as a(x); -- 'a,b,c'p
SELECT
Pg::string_agg(x,','p) OVER (ORDER BY x)
FROM (VALUES ('a'p),('b'p),('c'p)) as a(x); -- 'a'p,'a,b'p,'a,b,c'p
;
Также можно использовать агрегационную PostgreSQL функцию для построения фабрики агрегационных функций с последующим применением в AGGREGATE_BY
:
$agg_max = AggregationFactory("Pg::max");
SELECT
AGGREGATE_BY(x,$agg_max)
FROM (VALUES ('a'p),('b'p),('c'p)) as a(x); -- 'c'p
SELECT
AGGREGATE_BY(x,$agg_max) OVER (ORDER BY x),
FROM (VALUES ('a'p),('b'p),('c'p)) as a(x); -- 'a'p,'b'p,'c'p
В этом случае вызов AggregationFactory
принимает только имя функции с префиксом Pg::
, а все аргументы функции передаются в AGGREGATE_BY
.
Если в агрегационной функции не один аргумент, а ноль или два и более, необходимо использовать кортеж при вызове AGGREGATE_BY
:
$agg_string_agg = AggregationFactory("Pg::string_agg");
SELECT
AGGREGATE_BY((x,','p),$agg_string_agg)
FROM (VALUES ('a'p),('b'p),('c'p)) as a(x); -- 'a,b,c'p
SELECT
AGGREGATE_BY((x,','p),$agg_string_agg) OVER (ORDER BY x)
FROM (VALUES ('a'p),('b'p),('c'p)) as a(x); -- 'a'p,'a,b'p,'a,b,c'p
Внимание
Не поддерживается режим DISTINCT
над аргументами при вызове агрегационных PostgreSQL функций, а также использование MULTI_AGGREGATE_BY
.
Логические операции
Для выполнения логических операций используются функции PgAnd
, PgOr
, PgNot
:
SELECT
PgAnd(PgBool(true), PgBool(true)), -- PgBool(true)
PgOr(PgBool(false), null), -- PgCast(null, pgbool)
PgNot(PgBool(true)), -- PgBool(false)
;