Базовые встроенные функции

Ниже описаны функции общего назначения, а для специализированных функций есть отдельные статьи: агрегатные, оконные, а также для работы со списками, словарями, структурами, типами данных и генерацией кода.

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

Аргументы:

  1. Выражение, в котором нужно произвести замену.
  2. Значение, на которое нужно заменить 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') — Вызов udf Foo::Bar.
  • Udf(Foo::Bar, Int32, @@{"device":"AHCI"}@@ as TypeConfig")(1, 2, 'abc') — Вызов udf Foo::Bar с дополнительным типом Int32 и указанным TypeConfig.
  • Udf(Foo::Bar, "1e9+7" as RunConfig")(1, 'extended' As Precision) — Вызов udf Foo::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?

Аргументы:

  1. Дата - тип Date/Datetime/Timestamp;
  2. 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?

Аргументы:

  1. Дата - тип TzDate/TzDatetime/TzTimestamp.

Тип результата - Date/Datetime/Timestamp, в зависимости от типа данных входа.

Примеры

SELECT RemoveTimezone(TzDatetime("2018-02-01T12:00:00,Europe/Moscow"));

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, AsVariant

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(T, String)->Variant

Аргументы:

  • Значение
  • Строка с именем поля

Пример

SELECT
   AsVariant(6, "foo") as VariantValue

Enum, AsEnum

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(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?

Обязательные аргументы:

  1. Значение произвольного типа;
  2. Имя метки.

Возвращает копию значения из первого аргумента с указанной меткой в типе данных.

Примеры сценариев использования:

  • Возвращение на клиент для отображения в веб-интерфейсе медиа-файлов из 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

Аргументы:

  1. Выражение, которое станет результатом вызова функции в случае успеха проверки. Оно же подвергается проверке на тип данных в соответствующих функциях.
  2. В Ensure — булевый предикат, который проверяется на true. В остальных функциях — тип данных, который может быть получен через предназначенные для этого функции, либо строковый литерал с текстовым описанием типа.
  3. Опциональная строка с комментарием к ошибке, которая попадет в общее сообщение об ошибке при завершении запроса. Для проверок типов не может использовать сами данные, так как они выполняются на этапе валидации запроса, а для Ensure — может быть произвольным выражением.

Для проверки условий по финальному результату вычисления Ensure удобно использовать в сочетании с DISCARD SELECT.

Примеры

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 может использоваться в тех местах, где грамматикой уже ожидается выражение. Например, с его помощью можно:

  • округлить текущее время до дней, недель или месяцев и подставить в запрос, что затем позволит корректно работать кешированию запросов, хотя обычно использование функций для получения текущего времени его полностью отключает;
  • сделать тяжелое вычисление с небольшим результатом один раз на запрос вместо одного раза на каждую джобу.

EvaluateAtom позволяет динамически создать атом, но т.к. ими в основном оперирует более низкий уровень s-expressions, то использовать эту функцию напрямую как правило не рекомендуется.

Единственный аргумент у обоих функций — само выражение для вычисления и подстановки.

Ограничения:

  • выражение не должно приводить к запуску 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?

Аргументы:

  1. Строка: String или Utf8;
  2. Индекс: 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?

Аргументы:

  1. Беззнаковое число, над которым выполнять требуемую операцию. TestBit также реализован и для строк.
  2. Номер бита.

TestBit возвращает true/false. Остальные функции возвращают копию своего первого аргумента с проведенным соответствующим преобразованием.

Примеры:

SELECT
    TestBit(1u, 0), -- true
    SetBit(8u, 0); -- 9

Abs

Абсолютное значение числа.

Сигнатура

Abs(T)->T
Abs(T?)->T?

Примеры

SELECT Abs(-123); -- 123

Just, Unwrap, Nothing

Just() - Изменить тип данных значения на optional от текущего типа данных (то есть T превращается в T?).

Сигнатура

Just(T)->T?

Примеры

SELECT
  Just("my_string"); --  String?

Unwrap() - Преобразование значения optional типа данных в соответствующий не-optional тип с ошибкой времени выполнений, если в данных оказался NULL. Таким образом, T? превращается в T.

Если значение не является optional, то функция возвращает свой первый аргумент без изменений.

Сигнатура

Unwrap(T?)->T
Unwrap(T?, Utf8)->T
Unwrap(T?, String)->T

Аргументы:

  1. Значение для преобразования;
  2. Опциональная строка с комментарием для текста ошибки.

Обратная операция — Just.

Примеры

$value = Just("value");

SELECT Unwrap($value, "Unexpected NULL for $value");

Nothing() - Создать пустое значение указанного Optional типа данных.

Сигнатура

Nothing(Type<T?>)->T?

Примеры

SELECT
  Nothing(String?); -- пустое значение (NULL) с типом String?

Подробнее о ParseType и других функциях для работы с типами данных.

Callable

Создать вызываемое значение с заданной сигнатурой из лямбда-функции. Обычно используется для того, чтобы размещать вызываемые значения в контейнерах.

Сигнатура

Callable(Type<Callable<(...)->T>>, lambda)->Callable<(...)->T>

Аргументы:

  1. Тип;
  2. Лямбда-функция.

Примеры:

$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

Создать фабрику для агрегационных функций для того чтобы разделить процесс описания того, как агрегировать данные, и то, к каким данным это применять.

Аргументы:

  1. Строка в кавычках, являющаяся именем агрегационной функции, например "MIN".
  2. Опциональные параметры агрегационной функции, которые не зависят от данных. Например, значение 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;

AggregateTransform...

AggregateTransformInput() преобразует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory в другую фабрику, в которой перед началом выполнения агрегации производится указанное преобразование входных элементов.

Аргументы:

  1. Фабрика для агрегационных функций;
  2. Лямбда функция с одним аргументом, преобразующая входной элемент.

Примеры:

$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() преобразует фабрику для агрегационных функций, например, полученную через функцию AggregationFactory в другую фабрику, в которой после окончания выполнения агрегации производится указанное преобразование результата.

Аргументы:

  1. Фабрика для агрегационных функций;
  2. Лямбда функция с одним аргументом, преобразующая результат.

Примеры:

$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 - производится агрегация каждого элемента списка.

Аргументы:

  1. Фабрика для агрегационных функций.

Примеры:

$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]

Предыдущая
Следующая