Базовые встроенные функции
- COALESCE
- LENGTH
- SUBSTRING
- FIND
- RFIND
- StartsWith, EndsWith
- IF
- NANVL
- Random...
- Udf
- CurrentUtc...
- CurrentTz...
- AddTimezone
- RemoveTimezone
- Примеры
- MAX_OF, MIN_OF, GREATEST и LEAST
- AsTuple, AsStruct, AsList, AsDict, AsSet, AsListStrict, AsDictStrict и AsSetStrict
- Литералы контейнеров
- Variant
- AsVariant
- Visit, VisitOrDefault
- VariantItem
- Enum
- AsEnum
- AsTagged, Untag
- TableRow, JoinTableRow
- Ensure...
- AssumeStrict
- Likely
- EvaluateExpr, EvaluateAtom
- Литералы простых типов
- ToBytes и FromBytes
- ByteAt
- ...Bit
- Abs
- Just
- Unwrap
- Nothing
- Callable
- Pickle, Unpickle
- StaticMap
- StaticZip
- StaticFold, StaticFold1
- AggregationFactory
- AggregateTransformInput
- AggregateTransformOutput
- AggregateFlatten
Ниже описаны функции общего назначения, а для специализированных функций есть отдельные статьи: агрегатные, оконные, а также для работы со списками, словарями, структурами, типами данных и генерацией кода.
COALESCE
Перебирает аргументы слева направо и возвращает первый найденный непустой аргумент. Чтобы результат получился гарантированно непустым (не optional типа), самый правый аргумент должен быть такого типа (зачастую используют литерал). При одном аргументе возвращает его без изменений.
Сигнатура
COALESCE(T?, ..., T)->T
COALESCE(T?, ..., T?)->T?
Позволяет передавать потенциально пустые значения в функции, которые не умеют обрабатывать их самостоятельно.
Доступен краткий формат записи в виде оператора ??
. Можно использовать алиас NVL
.
Примеры
SELECT COALESCE(
maybe_empty_column,
"it's empty!"
) FROM my_table;
SELECT
maybe_empty_column ?? "it's empty!"
FROM my_table;
SELECT NVL(
maybe_empty_column,
"it's empty!"
) FROM my_table;
Все три примера выше эквивалентны.
LENGTH
Возвращает длину строки в байтах. Также эта функция доступна под именем LEN
.
Сигнатура
LENGTH(T)->Uint32
LENGTH(T?)->Uint32?
Примеры
SELECT LENGTH("foo");
SELECT LEN("bar");
Примечание
Для вычисления длины строки в unicode символах можно воспользоваться функцией Unicode::GetLength.
Для получения числа элементов в списке нужно использовать функцию ListLength.
SUBSTRING
Возвращает подстроку.
Сигнатура
Substring(String[, Uint32? [, Uint32?]])->String
Substring(String?[, Uint32? [, Uint32?]])->String?
Обязательные аргументы:
- Исходная строка;
- Позиция — отступ от начала строки в байтах (целое число) или
NULL
, означающий «от начала».
Опциональные аргументы:
- Длина подстроки — количество байт, начиная с указанной позиции (целое число, или
NULL
по умолчанию, означающий «до конца исходной строки»).
Индексация с нуля. Если указанные позиция и длина выходят за пределы строки, возвращает пустую строку.
Если входная строка является опциональной, то таким же является и результат.
Примеры
SELECT SUBSTRING("abcdefg", 3, 1); -- d
SELECT SUBSTRING("abcdefg", 3); -- defg
SELECT SUBSTRING("abcdefg", NULL, 3); -- abc
FIND
Поиск позиции подстроки в строке.
Сигнатура
Find(String, String[, Uint32?])->Uint32?
Find(String?, String[, Uint32?])->Uint32?
Find(Utf8, Utf8[, Uint32?])->Uint32?
Find(Utf8?, Utf8[, Uint32?])->Uint32?
Обязательные аргументы:
- Исходная строка;
- Искомая подстрока.
Опциональные аргументы:
- Позиция — в байтах, с которой начинать поиск (целое число, или
NULL
по умолчанию, означающий «от начала исходной строки»).
Возвращает первую найденную позицию подстроки или NULL
, означающий что искомая подстрока с указанной позиции не найдена.
Примеры
SELECT FIND("abcdefg_abcdefg", "abc"); -- 0
SELECT FIND("abcdefg_abcdefg", "abc", 1); -- 8
SELECT FIND("abcdefg_abcdefg", "abc", 9); -- null
RFIND
Обратный поиск позиции подстроки в строке, от конца к началу.
Сигнатура
RFind(String, String[, Uint32?])->Uint32?
RFind(String?, String[, Uint32?])->Uint32?
RFind(Utf8, Utf8[, Uint32?])->Uint32?
RFind(Utf8?, Utf8[, Uint32?])->Uint32?
Обязательные аргументы:
- Исходная строка;
- Искомая подстрока.
Опциональные аргументы:
- Позиция — в байтах, с которой начинать поиск (целое число, или
NULL
по умолчанию, означающий «от конца исходной строки»).
Возвращает первую найденную позицию подстроки или NULL
, означающий, что искомая подстрока с указанной позиции не найдена.
Примеры
SELECT RFIND("abcdefg_abcdefg", "bcd"); -- 9
SELECT RFIND("abcdefg_abcdefg", "bcd", 8); -- 1
SELECT RFIND("abcdefg_abcdefg", "bcd", 0); -- null
StartsWith, EndsWith
Проверка наличия префикса или суффикса в строке.
Сигнатуры
StartsWith(T str, U prefix)->Bool[?]
EndsWith(T str, U suffix)->Bool[?]
Обязательные аргументы:
- Исходная строка;
- Искомая подстрока.
Аргументы должны иметь тип String
/Utf8
(или опциональный String
/Utf8
) либо строковый PostgreSQL тип (PgText
/PgBytea
/PgVarchar
).
Результатом функции является опциональный Bool, за исключением случая, когда оба аргумента неопциональные – в этом случае возвращается Bool.
Примеры
SELECT StartsWith("abc_efg", "abc") AND EndsWith("abc_efg", "efg"); -- true
SELECT StartsWith("abc_efg", "efg") OR EndsWith("abc_efg", "abc"); -- false
SELECT StartsWith("abcd", NULL); -- null
SELECT EndsWith(NULL, Utf8("")); -- null
SELECT StartsWith("abc_efg"u, "abc"p) AND EndsWith("abc_efg", "efg"pv); -- true
IF
Проверяет условие IF(condition_expression, then_expression, else_expression)
.
Является упрощенной альтернативой для CASE WHEN ... THEN ... ELSE ... END.
Сигнатура
IF(Bool, T, T)->T
IF(Bool, T)->T?
Аргумент else_expression
можно не указывать. В этом случае, если условие ложно (condition_expression
вернул false
), будет возвращено пустое значение с типом, соответствующим then_expression
и допускающим значение NULL
. Таким образом, у результата получится optional тип данных.
Примеры
SELECT
IF(foo > 0, bar, baz) AS bar_or_baz,
IF(foo > 0, foo) AS only_positive_foo
FROM my_table;
NANVL
Заменяет значения NaN
(not a number) в выражениях типа Float
, Double
или Optional.
Сигнатура
NANVL(Float, Float)->Float
NANVL(Double, Double)->Double
Аргументы:
- Выражение, в котором нужно произвести замену.
- Значение, на которое нужно заменить
NaN
.
Если один из агрументов Double
, то в выдаче Double
, иначе Float
. Если один из агрументов Optional
, то и в выдаче Optional
.
Примеры
SELECT
NANVL(double_column, 0.0)
FROM my_table;
Random...
Генерирует псевдослучайное число:
Random()
— число с плавающей точкой (Double) от 0 до 1;RandomNumber()
— целое число из всего диапазона Uint64;RandomUuid()
— Uuid version 4.
Сигнатуры
Random(T1[, T2, ...])->Double
RandomNumber(T1[, T2, ...])->Uint64
RandomUuid(T1[, T2, ...])->Uuid
При генерации случайных чисел аргументы не используются и нужны исключительно для управления моментом вызова. В каждый момент вызова возвращается новое случайное число. Поэтому:
-
Повторный вызов Random в рамках одного запроса при идентичном наборе аргументов не гарантирует получения одинаковых наборов случайных чисел. Значения будут равны, если вызовы Random попадут в одну фазу исполнения.
-
Вызовы Random с одним и тем же набором аргументов в разных запросах вернут разные наборы случайных чисел.
Важно
Если Random используется в именованных выражениях, то его однократное вычисление не гарантируется. В зависимости от оптимизаторов и среды исполнения он может посчитаться как один раз, так и многократно. Для гарантированного однократного подсчета необходимо в этом случае материализовать именованное выражение в таблицу.
Сценарии использования:
SELECT RANDOM(1);
— получить одно случайное значение на весь запрос и несколько раз его использовать (чтобы получить несколько, можно передать разные константы любого типа);SELECT RANDOM(1) FROM table;
— одно и то же случайное число на каждую строку таблицы;SELECT RANDOM(1), RANDOM(2) FROM table;
— по два случайных числа на каждую строку таблицы, все числа в каждой из колонок одинаковые;SELECT RANDOM(some_column) FROM table;
— разные случайные числа на каждую строку таблицы;SELECT RANDOM(some_column), RANDOM(some_column) FROM table;
— разные случайные числа на каждую строку таблицы, но в рамках одной строки — два одинаковых числа;SELECT RANDOM(some_column), RANDOM(some_column + 1) FROM table;
илиSELECT RANDOM(some_column), RANDOM(other_column) FROM table;
— две колонки, и все с разными числами.
Примеры
SELECT
Random(key) -- [0, 1)
FROM my_table;
SELECT
RandomNumber(key) -- [0, Max<Uint64>)
FROM my_table;
SELECT
RandomUuid(key) -- Uuid version 4
FROM my_table;
SELECT
RANDOM(column) AS rand1,
RANDOM(column) AS rand2, -- same as rand1
RANDOM(column, 1) AS randAnd1, -- different from rand1/2
RANDOM(column, 2) AS randAnd2 -- different from randAnd1
FROM my_table;
Udf
Строит Callable
по заданному названию функции и опциональным external user types
, RunConfig
и TypeConfig
.
Udf(Foo::Bar)
— ФункцияFoo::Bar
без дополнительных параметров.Udf(Foo::Bar)(1, 2, 'abc')
— Вызов udfFoo::Bar
.Udf(Foo::Bar, Int32, @@{"device":"AHCI"}@@ as TypeConfig")(1, 2, 'abc')
— Вызов udfFoo::Bar
с дополнительным типомInt32
и указаннымTypeConfig
.Udf(Foo::Bar, "1e9+7" as RunConfig")(1, 'extended' As Precision)
— Вызов udfFoo::Bar
с указаннымRunConfig
и именоваными параметрами.
Сигнатуры
Udf(Callable[, T1, T2, ..., T_N][, V1 as TypeConfig][,V2 as RunConfig]])->Callable
Где T1
, T2
, и т. д. -- дополнительные (external
) пользовательские типы.
Примеры
$IsoParser = Udf(DateTime2::ParseIso8601);
SELECT $IsoParser("2022-01-01");
SELECT Udf(Unicode::IsUtf)("2022-01-01")
$config = @@{
"name":"MessageFoo",
"meta": "..."
}@@;
SELECT Udf(Protobuf::TryParse, $config As TypeConfig)("")
CurrentUtc...
CurrentUtcDate()
, CurrentUtcDatetime()
и CurrentUtcTimestamp()
- получение текущей даты и/или времени в UTC. Тип данных результата указан в конце названия функции.
Сигнатуры
CurrentUtcDate(...)->Date
CurrentUtcDatetime(...)->Datetime
CurrentUtcTimestamp(...)->Timestamp
Аргументы опциональны и работают по тому же принципу, что и у RANDOM.
Примеры
SELECT CurrentUtcDate();
SELECT CurrentUtcTimestamp(TableRow()) FROM my_table;
CurrentTz...
CurrentTzDate()
, CurrentTzDatetime()
и CurrentTzTimestamp()
- получение текущей даты и/или времени в указанной в первом аргументе IANA временной зоне. Тип данных результата указан в конце названия функции.
Сигнатуры
CurrentTzDate(String, ...)->TzDate
CurrentTzDatetime(String, ...)->TzDatetime
CurrentTzTimestamp(String, ...)->TzTimestamp
Последующие аргументы опциональны и работают по тому же принципу, что и у RANDOM.
Примеры
SELECT CurrentTzDate("Europe/Moscow");
SELECT CurrentTzTimestamp("Europe/Moscow", TableRow()) FROM my_table;
AddTimezone
Добавление информации о временной зоне к дате/времени, заданных в UTC. При выводе в результате SELECT
или после CAST
в String
будут применены правила временной зоны по вычислению смещения времени.
Сигнатура
AddTimezone(Date, String)->TzDate
AddTimezone(Date?, String)->TzDate?
AddTimezone(Datetime, String)->TzDatetime
AddTimezone(Datetime?, String)->TzDatetime?
AddTimezone(Timestamp, String)->TzTimestamp
AddTimezone(Timestamp?, String)->TzTimestamp?
Аргументы:
- Дата - тип
Date
/Datetime
/Timestamp
; - IANA имя временной зоны.
Тип результата - TzDate
/TzDatetime
/TzTimestamp
, в зависимости от типа данных входа.
Примеры
SELECT AddTimezone(Datetime("2018-02-01T12:00:00Z"), "Europe/Moscow");
RemoveTimezone
Удаление информации о временной зоне и перевод в дату/время, заданные в UTC.
Сигнатура
RemoveTimezone(TzDate)->Date
RemoveTimezone(TzDate?)->Date?
RemoveTimezone(TzDatetime)->Datetime
RemoveTimezone(TzDatetime?)->Datetime?
RemoveTimezone(TzTimestamp)->Timestamp
RemoveTimezone(TzTimestamp?)->Timestamp?
Аргументы:
- Дата - тип
TzDate
/TzDatetime
/TzTimestamp
.
Тип результата - Date
/Datetime
/Timestamp
, в зависимости от типа данных входа.
Примеры
SELECT RemoveTimezone(TzDatetime("2018-02-01T12:00:00,Europe/Moscow"));
Version
Version()
возвращает строку, описывающую текущую версию узла, обрабатывающего запрос. В некоторых случаях, например, во время постепенного обновлений кластера, она может возвращать разные строки в зависимости от того, какой узел обрабатывает запрос. Функция не принимает никаких аргументов.
Примеры
SELECT Version();
MAX_OF, MIN_OF, GREATEST и LEAST
Возвращает минимальный или максимальный среди N аргументов. Эти функции позволяют не использовать стандартную для SQL конструкцию CASE WHEN a < b THEN a ELSE b END
, которая была бы особенно громоздкой для N больше двух.
Сигнатуры
MIN_OF(T[,T,...})->T
MAX_OF(T[,T,...})->T
Типы аргументов должны быть приводимы друг к другу и могут допускать значение NULL
.
GREATEST
является синонимом к MAX_OF
, а LEAST
— к MIN_OF
.
Примеры
SELECT MIN_OF(1, 2, 3);
AsTuple, AsStruct, AsList, AsDict, AsSet, AsListStrict, AsDictStrict и AsSetStrict
Создает контейнеры соответствующих типов. Также доступна операторная запись литералов контейнеров.
Особенности:
- Элементы контейнеров передаются через аргументы, таким образом число элементов результирующего контейнера равно числу переданных аргументов, кроме случая, когда повторяются ключи словаря.
- В
AsTuple
иAsStruct
могут быть вызваны без аргументов, а также аргументы могут иметь разные типы. - Имена полей в
AsStruct
задаются черезAsStruct(field_value AS field_name)
. - Для создания списка требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого списка с заданным типом элементов используется функция ListCreate. Можно создать пустой список как вызов
AsList()
без аргументов, в этом случае это выражение будет иметь типEmptyList
. - Для создания словаря требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого словаря с заданным типом элементов используется функция DictCreate. Можно создать пустой словарь как вызов
AsDict()
без аргументов, в этом случае это выражение будет иметь типEmptyDict
. - Для создания множества требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого множества с заданным типом элементов используется функция SetCreate. Можно создать пустое множество как вызов
AsSet()
без аргументов, в этом случае это выражение будет иметь типEmptyDict
. AsList
выводит общий тип элементов списка. При несовместимых типах генерируется ошибка типизации.AsDict
выводит раздельно общие типы ключей и значений. При несовместимых типах генерируется ошибка типизации.AsSet
выводит общие типы ключей. При несовместимых типах генерируется ошибка типизации.AsListStrict
,AsDictStrict
,AsSetStrict
требуют одинакового типа для аргументов.- В
AsDict
иAsDictStrict
в качестве аргументов ожидаютсяTuple
из двух элементов: ключ и значение, соответственно. Если ключи повторяются, в словаре останется только значение для первого ключа. - В
AsSet
иAsSetStrict
в качестве аргументов ожидаются ключи.
Примеры
SELECT
AsTuple(1, 2, "3") AS `tuple`,
AsStruct(
1 AS a,
2 AS b,
"3" AS c
) AS `struct`,
AsList(1, 2, 3) AS `list`,
AsDict(
AsTuple("a", 1),
AsTuple("b", 2),
AsTuple("c", 3)
) AS `dict`,
AsSet(1, 2, 3) AS `set`
Литералы контейнеров
Для некоторых контейнеров возможна операторная форма записи их литеральных значений:
- Кортеж —
(value1, value2...)
; - Структура —
<|name1: value1, name2: value2...|>
; - Список —
[value1, value2,...]
; - Словарь —
{key1: value1, key2: value2...}
; - Множество —
{key1, key2...}
.
Во всех случаях допускается незначащая хвостовая запятая. Для кортежа с одним элементом эта запятая является обязательной - (value1,)
.
Для имен полей в литерале структуры допускается использовать выражение, которое можно посчитать в evaluation time, например, строковые литералы, а также идентификаторы (в том числе в backticks).
Для списка внутри используется функция AsList, словаря - AsDict, множества - AsSet, кортежа - AsTuple, структуры - AsStruct.
Примеры
$name = "computed " || "member name";
SELECT
(1, 2, "3") AS `tuple`,
<|
`complex member name`: 2.3,
b: 2,
$name: "3",
"inline " || "computed member name": false
|> AS `struct`,
[1, 2, 3] AS `list`,
{
"a": 1,
"b": 2,
"c": 3,
} AS `dict`,
{1, 2, 3} AS `set`
Variant
Variant()
создает значение варианта над кортежем или структурой.
Сигнатура
Variant(T, String, Type<Variant<...>>)->Variant<...>
Аргументы:
- Значение
- Строка с именем поля или индексом кортежа
- Тип варианта
Пример
$var_type = Variant<foo: Int32, bar: Bool>;
SELECT
Variant(6, "foo", $var_type) as Variant1Value,
Variant(false, "bar", $var_type) as Variant2Value;
AsVariant
AsVariant()
создает значение варианта над структурой с одним полем. Это значение может быть неявно преобразовано к любому варианту над структурой, в которой совпадает для этого имени поля тип данных и могут быть дополнительные поля с другими именами.
Сигнатура
AsVariant(T, String)->Variant
Аргументы:
- Значение
- Строка с именем поля
Пример
SELECT
AsVariant(6, "foo") as VariantValue
Visit, VisitOrDefault
Обрабатывает возможные значения варианта, представленного структурой или кортежем, с использованием предоставленных функций-обработчиков для каждого из его полей/элементов.
Сигнатура
Visit(Variant<key1: K1, key2: K2, ...>, K1->R AS key1, K2->R AS key2, ...)->R
Visit(Variant<K1, K2, ...>, K1->R, K2->R, ...)->R
VisitOrDefault(Variant<K1, K2, ...>{Flags:AutoMap}, [K1->R, [K2->R, ...]], R)->R
VisitOrDefault(Variant<key1: K1, key2: K2, ...>{Flags:AutoMap}, [K1->R AS key1, [K2->R AS key2, ...]], R)->R
Аргументы
- Для варианта над структурой функция принимает сам вариант в качестве позиционного аргумента и по одному именованному аргументу-обработчику для каждого поля этой структуры.
- Для варианта над кортежем функция принимает сам вариант и по одному обработчику на каждый элемент кортежа в качестве позиционных аргументов.
- Модификация
VisitOrDefault
принимает дополнительный последний позиционный аргумент, представляющий значение по умолчанию, и позволяет не указывать некоторые обработчики.
Пример
$vartype = Variant<num: Int32, flag: Bool, str: String>;
$handle_num = ($x) -> { return 2 * $x; };
$handle_flag = ($x) -> { return If($x, 200, 10); };
$handle_str = ($x) -> { return Unwrap(CAST(LENGTH($x) AS Int32)); };
$visitor = ($var) -> { return Visit($var, $handle_num AS num, $handle_flag AS flag, $handle_str AS str); };
SELECT
$visitor(Variant(5, "num", $vartype)), -- 10
$visitor(Just(Variant(True, "flag", $vartype))), -- Just(200)
$visitor(Just(Variant("somestr", "str", $vartype))), -- Just(7)
$visitor(Nothing(OptionalType($vartype))), -- Nothing(Optional<Int32>)
$visitor(NULL) -- NULL
;
VariantItem
Возвращает значение гомогенного варианта (т.е. содержащего поля/элементы одного типа).
Сигнатура
VariantItem(Variant<key1: K, key2: K, ...>{Flags:AutoMap})->K
VariantItem(Variant<K, K, ...>{Flags:AutoMap})->K
Пример
$vartype1 = Variant<num1: Int32, num2: Int32, num3: Int32>;
SELECT
VariantItem(Variant(7, "num2", $vartype1)), -- 7
VariantItem(Just(Variant(5, "num1", $vartype1))), -- Just(5)
VariantItem(Nothing(OptionalType($vartype1))), -- Nothing(Optional<Int32>)
VariantItem(NULL) -- NULL
;
Enum
Enum()
cоздает значение перечисления.
Сигнатура
Enum(String, Type<Enum<...>>)->Enum<...>
Аргументы:
- Строка с именем поля
- Тип перечисления
Пример
$enum_type = Enum<Foo, Bar>;
SELECT
Enum("Foo", $enum_type) as Enum1Value,
Enum("Bar", $enum_type) as Enum2Value;
AsEnum
AsEnum()
создает значение перечисления с одним элементом. Это значение может быть неявно преобразовано к любому перечислению, содержащему такое имя.
Сигнатура
AsEnum(String)->Enum<'tag'>
Аргументы:
- Строка с именем элемента перечисления
Пример
SELECT
AsEnum("Foo");
AsTagged, Untag
Оборачивает значение в Tagged тип данных с указанной меткой с сохранением физического типа данных. Untag
— обратная операция.
Сигнатура
AsTagged(T, tagName:String)->Tagged<T,tagName>
AsTagged(T?, tagName:String)->Tagged<T,tagName>?
Untag(Tagged<T, tagName>)->T
Untag(Tagged<T, tagName>?)->T?
Обязательные аргументы:
- Значение произвольного типа;
- Имя метки.
Возвращает копию значения из первого аргумента с указанной меткой в типе данных.
Примеры сценариев использования:
-
Возвращение на клиент для отображения в веб-интерфейсе медиа-файлов из base64-encoded строк.
-
Дополнительные уточнения на уровне типов возвращаемых колонок.
TableRow, JoinTableRow
Получение всей строки таблицы целиком в виде структуры. Аргументов нет. JoinTableRow
в случае JOIN
-ов всегда возвращает структуру с префиксами таблиц.
Сигнатура
TableRow()->Struct
Пример
SELECT TableRow() FROM my_table;
Ensure...
Проверка пользовательских условий:
Ensure()
— проверка верности предиката во время выполнения запроса.EnsureType()
— проверка точного соответствия типа выражения указанному.EnsureConvertibleTo()
— мягкая проверка соответствия типа выражения, работающая по тем же правилам, что и неявное приведение типов.
Если проверка не прошла успешно, то весь запрос завершается с ошибкой.
Сигнатуры
Ensure(T, Bool, String)->T
EnsureType(T, Type<T>, String)->T
EnsureConvertibleTo(T, Type<T>, String)->T
Аргументы:
- Выражение, которое станет результатом вызова функции в случае успеха проверки. Оно же подвергается проверке на тип данных в соответствующих функциях.
- В Ensure — булевый предикат, который проверяется на
true
. В остальных функциях — тип данных, который может быть получен через предназначенные для этого функции, либо строковый литерал с текстовым описанием типа. - Опциональная строка с комментарием к ошибке, которая попадет в общее сообщение об ошибке при завершении запроса. Для проверок типов не может использовать сами данные, так как они выполняются на этапе валидации запроса, а для Ensure — может быть произвольным выражением.
Примеры
SELECT Ensure(
value,
value < 100,
"value out or range"
) AS value FROM my_table;
SELECT EnsureType(
value,
TypeOf(other_value),
"expected value and other_value to be of same type"
) AS value FROM my_table;
SELECT EnsureConvertibleTo(
value,
Double?,
"expected value to be numeric"
) AS value FROM my_table;
AssumeStrict
Сигнатура
AssumeStrict(T)->T
Функция AssumeStrict
возвращает свой аргумент. Использование этой функции – способ сказать оптимизатору YQL, что выражение в аргументе является строгим, т.е. свободным от ошибок времени выполнения.
Большинство встроенных функций и операторов YQL являются строгими, но есть исключения – например Unwrap и Ensure.
Кроме того, нестрогим выражением считается вызов UDF.
Если есть уверенность, что при вычислении выражения ошибок времени выполнения на самом деле не возникает, то имеет смысл использовать AssumeStrict
.
Пример
SELECT * FROM T1 AS a JOIN T2 AS b USING(key)
WHERE AssumeStrict(Unwrap(CAST(a.key AS Int32))) == 1;
В данном примере мы считаем что все значения текстовой колонки a.key
в таблице T1
являются валидными числами, поэтому Unwrap не приводит к ошибке.
При налиичии AssumeStrict
оптимизатор сможет выполнить сначала фильтрацию, а потом JOIN.
Без AssumeStrict
такая оптимизация не выполняется – оптимизатор обязан учитывать ситуацию, при которой в колонке a.key
есть нечисловые значения, которые отфильтровываются JOIN
ом.
Likely
Сигнатура
Likely(Bool)->Bool
Likely(Bool?)->Bool?
Функция Likely
возвращает свой аргумент. Функция является подсказкой оптимизатору и говорит о том, что в большинстве случаев ее аргумент будет иметь значение True
.
Например, наличие такой функции в WHERE
означает что фильтр является слабоселективным.
Пример
SELECT * FROM T1 AS a JOIN T2 AS b USING(key)
WHERE Likely(a.amount > 0) -- почти всегда верно
При наличии Likely
оптимизатор не будет стараться выполнить фильтрацию перед JOIN
.
EvaluateExpr, EvaluateAtom
Возможность выполнить выражение до начала основного расчета и подставить его результат в запрос как литерал (константу). Во многих контекстах, где в стандартном SQL ожидалась бы только константа (например, в именах таблиц, количестве строк в LIMIT и т.п.) этот функционал активируется неявным образом автоматически.
EvaluateExpr может использоваться в тех местах, где грамматикой уже ожидается выражение. Например, с его помощью можно:
- округлить текущее время до дней, недель или месяцев и подставить в запрос, что затем позволит корректно работать кешированию запросов, хотя обычно использование функций для получения текущего времени его полностью отключает;
- сделать тяжелое вычисление с небольшим результатом один раз на запрос вместо одного раза на каждую джобу.
Единственный аргумент у обоих функций — само выражение для вычисления и подстановки.
Ограничения:
- выражение не должно приводить к запуску MapReduce операций;
- данный функционал полностью заблокирован в YQL over YDB.
Примеры
$now = CurrentUtcDate();
SELECT EvaluateExpr(
DateTime::MakeDate(DateTime::StartOfWeek($now)
)
);
Литералы простых типов
Для простых типов могут быть созданы литералы на основании строковых литералов.
Синтаксис
<Простой тип>( <строка>[, <дополнительные атрибуты>] )
В отличие от CAST("myString" AS MyType)
:
- Проверка на приводимость литерала к требуемому типу происходит на этапе валидации;
- Результат не является optional.
Для типов данных Date
, Datetime
, Timestamp
и Interval
поддерживаются литералы только в формате, соответствующем ISO 8601. У Interval
есть следующие отличия от стандарта:
- поддерживается отрицательный знак для сдвигов в прошлое;
- микросекунды могут быть записаны как дробная часть секунд;
- единицы измерения больше недель не доступны;
- не поддерживаются варианты с началом/концом интервала, а также повторами.
Для типов данных TzDate
, TzDatetime
, TzTimestamp
литералы также задаются в формате, соответствующем ISO 8601, но вместо опционального суффикса Z через запятую указывается IANA имя временной зоны, например, GMT или Europe/Moscow.
Для параметрического типа данных Decimal дополнительно указывается два аргумента:
- общее число десятичных знаков (до 35, включительно);
- число десятичных знаков после запятой (из общего числа, то есть строго не больше предыдущего аргумента).
Примеры
SELECT
Bool("true"),
Uint8("0"),
Int32("-1"),
Uint32("2"),
Int64("-3"),
Uint64("4"),
Float("-5"),
Double("6"),
Decimal("1.23", 5, 2), -- до 5 десятичных знаков, из которых 2 после запятой
String("foo"),
Utf8("привет"),
Yson("<a=1>[3;%false]"),
Json(@@{"a":1,"b":null}@@),
Date("2017-11-27"),
Datetime("2017-11-27T13:24:00Z"),
Timestamp("2017-11-27T13:24:00.123456Z"),
Interval("P1DT2H3M4.567890S"),
TzDate("2017-11-27,Europe/Moscow"),
TzDatetime("2017-11-27T13:24:00,America/Los_Angeles"),
TzTimestamp("2017-11-27T13:24:00.123456,GMT"),
Uuid("f9d5cc3f-f1dc-4d9c-b97e-766e57ca4ccb");
ToBytes и FromBytes
Конвертация простых типов данных в строку со своим бинарным представлением и обратно. Числа представляются в little endian.
Сигнатуры
ToBytes(T)->String
ToBytes(T?)->String?
FromBytes(String, Type<T>)->T?
FromBytes(String?, Type<T>)->T?
Примеры
SELECT
ToBytes(123), -- "\u0001\u0000\u0000\u0000"
FromBytes(
"\xd2\x02\x96\x49\x00\x00\x00\x00",
Uint64
); -- 1234567890ul
ByteAt
Получение значение байта в строке по индексу от её начала. В случае некорректного индекса возвращается NULL
.
Сигнатура
ByteAt(String, Uint32)->Uint8
ByteAt(String?, Uint32)->Uint8?
ByteAt(Utf8, Uint32)->Uint8
ByteAt(Utf8?, Uint32)->Uint8?
Аргументы:
- Строка:
String
илиUtf8
; - Индекс:
Uint32
.
Примеры
SELECT
ByteAt("foo", 0), -- 102
ByteAt("foo", 1), -- 111
ByteAt("foo", 9); -- NULL
...Bit
TestBit()
, ClearBit()
, SetBit()
и FlipBit()
- проверить, сбросить, установить или инвертировать бит в беззнаковом числе по указанному порядковому номеру бита.
Сигнатуры
TestBit(T, Uint8)->Bool
TestBit(T?, Uint8)->Bool?
ClearBit(T, Uint8)->T
ClearBit(T?, Uint8)->T?
SetBit(T, Uint8)->T
SetBit(T?, Uint8)->T?
FlipBit(T, Uint8)->T
FlipBit(T?, Uint8)->T?
Аргументы:
- Беззнаковое число, над которым выполнять требуемую операцию. TestBit также реализован и для строк.
- Номер бита.
TestBit возвращает true/false
. Остальные функции возвращают копию своего первого аргумента с проведенным соответствующим преобразованием.
Примеры
SELECT
TestBit(1u, 0), -- true
SetBit(8u, 0); -- 9
Abs
Абсолютное значение числа.
Сигнатура
Abs(T)->T
Abs(T?)->T?
Примеры
SELECT Abs(-123); -- 123
Just
Just()
- Изменить тип данных значения на optional от текущего типа данных (то есть T
превращается в T?
).
Сигнатура
Just(T)->T?
Примеры
SELECT
Just("my_string"); -- String?
Unwrap
Unwrap()
- Преобразование значения optional типа данных в соответствующий не-optional тип с ошибкой времени выполнений, если в данных оказался NULL
. Таким образом, T?
превращается в T
.
Если значение не является optional, то функция возвращает свой первый аргумент без изменений.
Сигнатура
Unwrap(T?)->T
Unwrap(T?, Utf8)->T
Unwrap(T?, String)->T
Аргументы:
- Значение для преобразования;
- Опциональная строка с комментарием для текста ошибки.
Обратная операция — Just.
Примеры
$value = Just("value");
SELECT Unwrap($value, "Unexpected NULL for $value");
Nothing
Nothing()
- Создать пустое значение указанного Optional типа данных.
Сигнатура
Nothing(Type<T?>)->T?
Примеры
SELECT
Nothing(String?); -- пустое значение (NULL) с типом String?
Подробнее о ParseType и других функциях для работы с типами данных.
Callable
Создать вызываемое значение с заданной сигнатурой из лямбда-функции. Обычно используется для того, чтобы размещать вызываемые значения в контейнерах.
Сигнатура
Callable(Type<Callable<(...)->T>>, lambda)->Callable<(...)->T>
Аргументы:
- Тип;
- Лямбда-функция.
Примеры
$lambda = ($x) -> {
RETURN CAST($x as String)
};
$callables = AsTuple(
Callable(Callable<(Int32)->String>, $lambda),
Callable(Callable<(Bool)->String>, $lambda),
);
SELECT $callables.0(10), $callables.1(true);
Pickle, Unpickle
Pickle()
и StablePickle()
сериализуют произвольный объект в последовательность байт, если это возможно. Типовыми несериализуемыми объектами являются Callable и Resource. Формат сериализации не версионируется, допускается использовать в пределах одного запроса. Для типа Dict функция StablePickle предварительно сортирует ключи, а для Pickle порядок элементов словаря в сериализованном представлении не определен.
Unpickle()
— обратная операция (десериализация), где первым аргументом передается тип данных результата, а вторым — строка с результатом Pickle()
или StablePickle()
.
Сигнатуры
Pickle(T)->String
StablePickle(T)->String
Unpickle(Type<T>, String)->T
Примеры
SELECT *
FROM my_table
WHERE Digest::MurMurHash32(
Pickle(TableRow())
) % 10 == 0; -- в реальности лучше использовать TABLESAMPLE
$buf = Pickle(123);
SELECT Unpickle(Int32, $buf);
StaticMap
Преобразует структуру или кортеж, применяя лямбду к каждому элементу.
Сигнатура
StaticMap(Struct<...>, lambda)->Struct<...>
StaticMap(Tuple<...>, lambda)->Tuple<...>
Аргументы:
- Структура или кортеж;
- Лямбда для обработки элементов.
Результат: структура или кортеж с аналогичным первому аргументу количеством и именованием элементов, а типы данных элементов определяются результатами лямбды.
Примеры
SELECT *
FROM (
SELECT
StaticMap(TableRow(), ($item) -> {
return CAST($item AS String);
})
FROM my_table
) FLATTEN COLUMNS; -- преобразование всех колонок в строки
StaticZip
Поэлементно "склеивает" структуры или кортежи. Все аргументы (один и более) должны быть либо структурами с одинаковым набором полей, либо кортежами одинаковой длины.
Результататом будет соответственно структура или кортеж.
Каждый элемент результата – кортеж с соответствующими элементами из аргументов.
Сигнатура
StaticZip(Struct, Struct)->Struct
StaticZip(Tuple, Tuple)->Tuple
Примеры
$one = <|k1:1, k2:2.0|>;
$two = <|k1:3.0, k2:4|>;
-- поэлементное сложение двух структур
SELECT StaticMap(StaticZip($one, $two), ($tuple)->($tuple.0 + $tuple.1)) AS sum;
StaticFold, StaticFold1
StaticFold(obj:Struct/Tuple, initVal, updateLambda)
StaticFold1(obj:Struct/Tuple, initLambda, updateLambda)
Статическая левоассоциативная свертка структуры или кортежа.
Для кортежей свертка производится в порядке от меньшего индекса к большему, для структур порядок не гарантируется.
obj
- объект, элементы которого нужно свернутьinitVal
- (для StaticFold) исходное состояние сверткиinitLambda
- (для StaticFold1) функция для получения исходного состояния по первому элементуupdateLambda
- функция обновления состояния (принимает в аргументах следующий элемент объекта и предыдущее состояние)
StaticFold(<|key_1:$el_1, key_2:$el_2, ..., key_n:$el_n|>, $init, $f)
преобразуется в свертку:
$f($el_n, ...$f($el_2, $f($init, el_1))...)
StaticFold1(<|key_1:$el_1, key_2:$el_2, ..., key_n:$el_n|>, $f0, $f)
:
$f($el_n, ...$f($el_2, $f($f0($init), el_1))...)
StaticFold1(<||>, $f0, $f)
вернет NULL
.
Аналогично работает и с кортежами.
AggregationFactory
Создать фабрику для агрегационных функций для того чтобы разделить процесс описания того, как агрегировать данные, и то, к каким данным это применять.
Аргументы:
- Строка в кавычках, являющаяся именем агрегационной функции, например "MIN".
- Опциональные параметры агрегационной функции, которые не зависят от данных. Например, значение percentile в PERCENTILE.
Полученную фабрику можно использовать как второй параметр функции AGGREGATE_BY.
Если агрегационная функция работает на двух колонках вместо одной, как например, MIN_BY, то в AGGREGATE_BY первым аргументом передается Tuple
из двух значений. Подробнее это указано при описании такой агрегационной функции.
Примеры
$factory = AggregationFactory("MIN");
SELECT
AGGREGATE_BY(value, $factory) AS min_value -- применить MIN агрегацию к колонке value
FROM my_table;
AggregateTransformInput
AggregateTransformInput()
преобразует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory в другую фабрику, в которой перед началом выполнения агрегации производится указанное преобразование входных элементов.
Аргументы:
- Фабрика для агрегационных функций;
- Лямбда функция с одним аргументом, преобразующая входной элемент.
Примеры
$f = AggregationFactory("sum");
$g = AggregateTransformInput($f, ($x) -> (cast($x as Int32)));
$h = AggregateTransformInput($f, ($x) -> ($x * 2));
SELECT ListAggregate([1,2,3], $f); -- 6
SELECT ListAggregate(["1","2","3"], $g); -- 6
SELECT ListAggregate([1,2,3], $h); -- 12
AggregateTransformOutput
AggregateTransformOutput()
преобразует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory в другую фабрику, в которой после окончания выполнения агрегации производится указанное преобразование результата.
Аргументы:
- Фабрика для агрегационных функций;
- Лямбда функция с одним аргументом, преобразующая результат.
Примеры
$f = AggregationFactory("sum");
$g = AggregateTransformOutput($f, ($x) -> ($x * 2));
SELECT ListAggregate([1,2,3], $f); -- 6
SELECT ListAggregate([1,2,3], $g); -- 12
AggregateFlatten
Адаптирует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory так, чтобы выполнять агрегацию над входными элементами - списками. Эта операция похожа на FLATTEN LIST BY - производится агрегация каждого элемента списка.
Аргументы:
- Фабрика для агрегационных функций.
Примеры
$i = AggregationFactory("AGGREGATE_LIST_DISTINCT");
$j = AggregateFlatten($i);
SELECT AggregateBy(x, $j) from (
SELECT [1,2] as x
union all
SELECT [2,3] as x
); -- [1, 2, 3]