# Базовые встроенные функции
Ниже описаны функции общего назначения, а для специализированных функций есть отдельные статьи: [агрегатные](aggregation.md), [оконные](window.md), а также для работы со [списками](list.md), [словарями](dict.md), [структурами](struct.md), [типами данных](types.md) и [генерацией кода](codegen.md).
## COALESCE {#coalesce}
Перебирает аргументы слева направо и возвращает первый найденный непустой аргумент. Чтобы результат получился гарантированно непустым (не [optional типа](../types/optional.md)), самый правый аргумент должен быть такого типа (зачастую используют литерал). При одном аргументе возвращает его без изменений.
### Сигнатура
```yql
COALESCE(T?, ..., T)->T
COALESCE(T?, ..., T?)->T?
```
Позволяет передавать потенциально пустые значения в функции, которые не умеют обрабатывать их самостоятельно.
Доступен краткий формат записи в виде оператора `??`. Можно использовать алиас `NVL`.
### Примеры
```yql
SELECT COALESCE(
maybe_empty_column,
"it's empty!"
) FROM my_table;
```
```yql
SELECT
maybe_empty_column ?? "it's empty!"
FROM my_table;
```
```yql
SELECT NVL(
maybe_empty_column,
"it's empty!"
) FROM my_table;
```
Все три примера выше эквивалентны.
## LENGTH {#length}
Возвращает длину строки в байтах. Также эта функция доступна под именем `LEN`.
### Сигнатура
```yql
LENGTH(T)->Uint32
LENGTH(T?)->Uint32?
```
### Примеры
```yql
SELECT LENGTH("foo");
```
```yql
SELECT LEN("bar");
```
{% note info %}
Для вычисления длины строки в unicode символах можно воспользоваться функцией [Unicode::GetLength](../udf/list/unicode.md).
Для получения числа элементов в списке нужно использовать функцию [ListLength](list.md#listlength).
{% endnote %}
## SUBSTRING {#substring}
Возвращает подстроку.
### Сигнатура
```yql
Substring(String[, Uint32? [, Uint32?]])->String
Substring(String?[, Uint32? [, Uint32?]])->String?
```
Обязательные аргументы:
* Исходная строка;
* Позиция — отступ от начала строки в байтах (целое число) или `NULL`, означающий «от начала».
Опциональные аргументы:
* Длина подстроки — количество байт, начиная с указанной позиции (целое число, или `NULL` по умолчанию, означающий «до конца исходной строки»).
Индексация с нуля. Если указанные позиция и длина выходят за пределы строки, возвращает пустую строку.
Если входная строка является опциональной, то таким же является и результат.
### Примеры
```yql
SELECT SUBSTRING("abcdefg", 3, 1); -- d
```
```yql
SELECT SUBSTRING("abcdefg", 3); -- defg
```
```yql
SELECT SUBSTRING("abcdefg", NULL, 3); -- abc
```
## FIND {#find}
Поиск позиции подстроки в строке.
### Сигнатура
```yql
Find(String, String[, Uint32?])->Uint32?
Find(String?, String[, Uint32?])->Uint32?
Find(Utf8, Utf8[, Uint32?])->Uint32?
Find(Utf8?, Utf8[, Uint32?])->Uint32?
```
Обязательные аргументы:
* Исходная строка;
* Искомая подстрока.
Опциональные аргументы:
* Позиция — в байтах, с которой начинать поиск (целое число, или `NULL` по умолчанию, означающий «от начала исходной строки»).
Возвращает первую найденную позицию подстроки или `NULL`, означающий что искомая подстрока с указанной позиции не найдена.
### Примеры
```yql
SELECT FIND("abcdefg_abcdefg", "abc"); -- 0
```
```yql
SELECT FIND("abcdefg_abcdefg", "abc", 1); -- 8
```
```yql
SELECT FIND("abcdefg_abcdefg", "abc", 9); -- null
```
## RFIND {#rfind}
Обратный поиск позиции подстроки в строке, от конца к началу.
### Сигнатура
```yql
RFind(String, String[, Uint32?])->Uint32?
RFind(String?, String[, Uint32?])->Uint32?
RFind(Utf8, Utf8[, Uint32?])->Uint32?
RFind(Utf8?, Utf8[, Uint32?])->Uint32?
```
Обязательные аргументы:
* Исходная строка;
* Искомая подстрока.
Опциональные аргументы:
* Позиция — в байтах, с которой начинать поиск (целое число, или `NULL` по умолчанию, означающий «от конца исходной строки»).
Возвращает первую найденную позицию подстроки или `NULL`, означающий, что искомая подстрока с указанной позиции не найдена.
### Примеры
```yql
SELECT RFIND("abcdefg_abcdefg", "bcd"); -- 9
```
```yql
SELECT RFIND("abcdefg_abcdefg", "bcd", 8); -- 1
```
```yql
SELECT RFIND("abcdefg_abcdefg", "bcd", 0); -- null
```
## StartsWith, EndsWith {#starts_ends_with}
Проверка наличия префикса или суффикса в строке.
### Сигнатуры
```yql
StartsWith(T str, U prefix)->Bool[?]
EndsWith(T str, U suffix)->Bool[?]
```
Обязательные аргументы:
* Исходная строка;
* Искомая подстрока.
Аргументы должны иметь тип `String`/`Utf8` (или опциональный `String`/`Utf8`) либо строковый PostgreSQL тип (`PgText`/`PgBytea`/`PgVarchar`).
Результатом функции является опциональный Bool, за исключением случая, когда оба аргумента неопциональные – в этом случае возвращается Bool.
### Примеры
```yql
SELECT StartsWith("abc_efg", "abc") AND EndsWith("abc_efg", "efg"); -- true
```
```yql
SELECT StartsWith("abc_efg", "efg") OR EndsWith("abc_efg", "abc"); -- false
```
```yql
SELECT StartsWith("abcd", NULL); -- null
```
```yql
SELECT EndsWith(NULL, Utf8("")); -- null
```
```yql
SELECT StartsWith("abc_efg"u, "abc"p) AND EndsWith("abc_efg", "efg"pv); -- true
```
## IF {#if}
Проверяет условие `IF(condition_expression, then_expression, else_expression)`.
Является упрощенной альтернативой для [CASE WHEN ... THEN ... ELSE ... END](../syntax/expressions.md#case).
### Сигнатура
```yql
IF(Bool, T, T)->T
IF(Bool, T)->T?
```
Аргумент `else_expression` можно не указывать. В этом случае, если условие ложно (`condition_expression` вернул `false`), будет возвращено пустое значение с типом, соответствующим `then_expression` и допускающим значение `NULL`. Таким образом, у результата получится [optional тип данных](../types/optional.md).
### Примеры
```yql
SELECT
IF(foo > 0, bar, baz) AS bar_or_baz,
IF(foo > 0, foo) AS only_positive_foo
FROM my_table;
```
## NANVL {#nanvl}
Заменяет значения `NaN` (not a number) в выражениях типа `Float`, `Double` или [Optional](../types/optional.md).
### Сигнатура
```yql
NANVL(Float, Float)->Float
NANVL(Double, Double)->Double
```
Аргументы:
1. Выражение, в котором нужно произвести замену.
2. Значение, на которое нужно заменить `NaN`.
Если один из агрументов `Double`, то в выдаче `Double`, иначе `Float`. Если один из агрументов `Optional`, то и в выдаче `Optional`.
### Примеры
```yql
SELECT
NANVL(double_column, 0.0)
FROM my_table;
```
## Random... {#random}
Генерирует псевдослучайное число:
* `Random()` — число с плавающей точкой (Double) от 0 до 1;
* `RandomNumber()` — целое число из всего диапазона Uint64;
* `RandomUuid()` — [Uuid version 4](https://tools.ietf.org/html/rfc4122#section-4.4).
### Сигнатуры
```yql
Random(T1[, T2, ...])->Double
RandomNumber(T1[, T2, ...])->Uint64
RandomUuid(T1[, T2, ...])->Uuid
```
При генерации случайных чисел аргументы не используются и нужны исключительно для управления моментом вызова. В каждый момент вызова возвращается новое случайное число. Поэтому:
* Повторный вызов Random в рамках **одного запроса** при идентичном наборе аргументов возвращает тот же самый набор случайных чисел. Важно понимать, что речь именно про сами аргументы (текст между круглыми скобками), а не их значения.
* Вызовы Random с одним и тем же набором аргументов в **разных запросах** вернут разные наборы случайных чисел.
{% note warning %}
Если Random используется в [именованных выражениях](../syntax/expressions.md#named-nodes), то его однократное вычисление не гарантируется. В зависимости от оптимизаторов и среды исполнения он может посчитаться как один раз, так и многократно. Для гарантированного однократного подсчета необходимо в этом случае материализовать именованное выражение в таблицу.
{% endnote %}
Сценарии использования:
* `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;` — две колонки, и все с разными числами.
### Примеры
```yql
SELECT
Random(key) -- [0, 1)
FROM my_table;
```
```yql
SELECT
RandomNumber(key) -- [0, Max)
FROM my_table;
```
```yql
SELECT
RandomUuid(key) -- Uuid version 4
FROM my_table;
```
```yql
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 {#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` и именоваными параметрами.
### Сигнатуры
```yql
Udf(Callable[, T1, T2, ..., T_N][, V1 as TypeConfig][,V2 as RunConfig]])->Callable
```
Где `T1`, `T2`, и т. д. -- дополнительные (`external`) пользовательские типы.
### Примеры
```yql
$IsoParser = Udf(DateTime2::ParseIso8601);
SELECT $IsoParser("2022-01-01");
```
```yql
SELECT Udf(Unicode::IsUtf)("2022-01-01")
```
```yql
$config = @@{
"name":"MessageFoo",
"meta": "..."
}@@;
SELECT Udf(Protobuf::TryParse, $config As TypeConfig)("")
```
## CurrentUtc... {#current-utc}
`CurrentUtcDate()`, `CurrentUtcDatetime()` и `CurrentUtcTimestamp()` - получение текущей даты и/или времени в UTC. Тип данных результата указан в конце названия функции.
### Сигнатуры
```yql
CurrentUtcDate(...)->Date
CurrentUtcDatetime(...)->Datetime
CurrentUtcTimestamp(...)->Timestamp
```
Аргументы опциональны и работают по тому же принципу, что и у [RANDOM](#random).
### Примеры
```yql
SELECT CurrentUtcDate();
```
```yql
SELECT CurrentUtcTimestamp(TableRow()) FROM my_table;
```
## CurrentTz... {#current-tz}
`CurrentTzDate()`, `CurrentTzDatetime()` и `CurrentTzTimestamp()` - получение текущей даты и/или времени в указанной в первом аргументе [IANA временной зоне](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Тип данных результата указан в конце названия функции.
### Сигнатуры
```yql
CurrentTzDate(String, ...)->TzDate
CurrentTzDatetime(String, ...)->TzDatetime
CurrentTzTimestamp(String, ...)->TzTimestamp
```
Последующие аргументы опциональны и работают по тому же принципу, что и у [RANDOM](#random).
### Примеры
```yql
SELECT CurrentTzDate("Europe/Moscow");
```
```yql
SELECT CurrentTzTimestamp("Europe/Moscow", TableRow()) FROM my_table;
```
## AddTimezone
Добавление информации о временной зоне к дате/времени, заданных в UTC. При выводе в результате `SELECT` или после `CAST` в `String` будут применены правила временной зоны по вычислению смещения времени.
### Сигнатура
```yql
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 имя временной зоны](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
Тип результата - `TzDate`/`TzDatetime`/`TzTimestamp`, в зависимости от типа данных входа.
### Примеры
```yql
SELECT AddTimezone(Datetime("2018-02-01T12:00:00Z"), "Europe/Moscow");
```
## RemoveTimezone
Удаление информации о временной зоне и перевод в дату/время, заданные в UTC.
### Сигнатура
```yql
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`, в зависимости от типа данных входа.
### Примеры
```yql
SELECT RemoveTimezone(TzDatetime("2018-02-01T12:00:00,Europe/Moscow"));
```
## Version {#version}
`Version()` возвращает строку, описывающую текущую версию узла, обрабатывающего запрос. В некоторых случаях, например, во время постепенного обновлений кластера, она может возвращать разные строки в зависимости от того, какой узел обрабатывает запрос. Функция не принимает никаких аргументов.
### Примеры
```yql
SELECT Version();
```
## MAX_OF, MIN_OF, GREATEST и LEAST {#max-min}
Возвращает минимальный или максимальный среди N аргументов. Эти функции позволяют не использовать стандартную для SQL конструкцию `CASE WHEN a < b THEN a ELSE b END`, которая была бы особенно громоздкой для N больше двух.
### Сигнатуры
```yql
MIN_OF(T[,T,...})->T
MAX_OF(T[,T,...})->T
```
Типы аргументов должны быть приводимы друг к другу и могут допускать значение `NULL`.
`GREATEST` является синонимом к `MAX_OF`, а `LEAST` — к `MIN_OF`.
### Примеры
```yql
SELECT MIN_OF(1, 2, 3);
```
## AsTuple, AsStruct, AsList, AsDict, AsSet, AsListStrict, AsDictStrict и AsSetStrict {#as-container}
Создает контейнеры соответствующих типов. Также доступна [операторная запись](#containerliteral) литералов контейнеров.
Особенности:
* Элементы контейнеров передаются через аргументы, таким образом число элементов результирующего контейнера равно числу переданных аргументов, кроме случая, когда повторяются ключи словаря.
* В `AsTuple` и `AsStruct` могут быть вызваны без аргументов, а также аргументы могут иметь разные типы.
* Имена полей в `AsStruct` задаются через `AsStruct(field_value AS field_name)`.
* Для создания списка требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого списка с заданным типом элементов используется функция [ListCreate](list.md#listcreate). Можно создать пустой список как вызов `AsList()` без аргументов, в этом случае это выражение будет иметь тип `EmptyList`.
* Для создания словаря требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого словаря с заданным типом элементов используется функция [DictCreate](dict.md#dictcreate). Можно создать пустой словарь как вызов `AsDict()` без аргументов, в этом случае это выражение будет иметь тип `EmptyDict`.
* Для создания множества требуется хотя бы один аргумент, если нужно вывести типы элементов. Для создания пустого множества с заданным типом элементов используется функция [SetCreate](dict.md#setcreate). Можно создать пустое множество как вызов `AsSet()` без аргументов, в этом случае это выражение будет иметь тип `EmptyDict`.
* `AsList` выводит общий тип элементов списка. При несовместимых типах генерируется ошибка типизации.
* `AsDict` выводит раздельно общие типы ключей и значений. При несовместимых типах генерируется ошибка типизации.
* `AsSet` выводит общие типы ключей. При несовместимых типах генерируется ошибка типизации.
* `AsListStrict`, `AsDictStrict`, `AsSetStrict` требуют одинакового типа для аргументов.
* В `AsDict` и `AsDictStrict` в качестве аргументов ожидаются `Tuple` из двух элементов: ключ и значение, соответственно. Если ключи повторяются, в словаре останется только значение для первого ключа.
* В `AsSet` и `AsSetStrict` в качестве аргументов ожидаются ключи.
### Примеры
```yql
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`
```
## Литералы контейнеров {#containerliteral}
Для некоторых контейнеров возможна операторная форма записи их литеральных значений:
* Кортеж — `(value1, value2...)`;
* Структура — `<|name1: value1, name2: value2...|>`;
* Список — `[value1, value2,...]`;
* Словарь — `{key1: value1, key2: value2...}`;
* Множество — `{key1, key2...}`.
Во всех случаях допускается незначащая хвостовая запятая. Для кортежа с одним элементом эта запятая является обязательной - `(value1,)`.
Для имен полей в литерале структуры допускается использовать выражение, которое можно посчитать в evaluation time, например, строковые литералы, а также идентификаторы (в том числе в backticks).
Для списка внутри используется функция [AsList](#as-container), словаря - [AsDict](#as-container), множества - [AsSet](#as-container), кортежа - [AsTuple](#as-container), структуры - [AsStruct](#as-container).
### Примеры
```yql
$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()` создает значение варианта над кортежем или структурой.
### Сигнатура
```yql
Variant(T, String, Type>)->Variant<...>
```
Аргументы:
* Значение
* Строка с именем поля или индексом кортежа
* Тип варианта
### Пример
```yql
$var_type = Variant;
SELECT
Variant(6, "foo", $var_type) as Variant1Value,
Variant(false, "bar", $var_type) as Variant2Value;
```
## AsVariant {#asvariant}
`AsVariant()` создает значение [варианта над структурой](../types/containers.md) с одним полем. Это значение может быть неявно преобразовано к любому варианту над структурой, в которой совпадает для этого имени поля тип данных и могут быть дополнительные поля с другими именами.
### Сигнатура
```yql
AsVariant(T, String)->Variant
```
Аргументы:
* Значение
* Строка с именем поля
### Пример
```yql
SELECT
AsVariant(6, "foo") as VariantValue
```
## Visit, VisitOrDefault {#visit}
Обрабатывает возможные значения варианта, представленного структурой или кортежем, с использованием предоставленных функций-обработчиков для каждого из его полей/элементов.
### Сигнатура
```yql
Visit(Variant, K1->R AS key1, K2->R AS key2, ...)->R
Visit(Variant, K1->R, K2->R, ...)->R
VisitOrDefault(Variant{Flags:AutoMap}, R, [K1->R, [K2->R, ...]])->R
VisitOrDefault(Variant{Flags:AutoMap}, R, [K1->R AS key1, [K2->R AS key2, ...]])->R
```
### Аргументы
* Для варианта над структурой функция принимает сам вариант в качестве позиционного аргумента и по одному именованному аргументу-обработчику для каждого поля этой структуры.
* Для варианта над кортежем функция принимает сам вариант и по одному обработчику на каждый элемент кортежа в качестве позиционных аргументов.
* Модификация `VisitOrDefault` принимает дополнительный позиционный аргумент (на втором месте), представляющий значение по умолчанию, и позволяет не указывать некоторые обработчики.
### Пример
```yql
$vartype = Variant;
$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)
$visitor(NULL) -- NULL
;
```
## VariantItem {#variantitem}
Возвращает значение гомогенного варианта (т.е. содержащего поля/элементы одного типа).
### Сигнатура
```yql
VariantItem(Variant{Flags:AutoMap})->K
VariantItem(Variant{Flags:AutoMap})->K
```
### Пример
```yql
$vartype1 = Variant;
SELECT
VariantItem(Variant(7, "num2", $vartype1)), -- 7
VariantItem(Just(Variant(5, "num1", $vartype1))), -- Just(5)
VariantItem(Nothing(OptionalType($vartype1))), -- Nothing(Optional)
VariantItem(NULL) -- NULL
;
```
## Way {#way}
Возвращает активное поле (активный индекс) варианта поверх структуры (кортежа).
### Сигнатура
```yql
Way(Variant{Flags:AutoMap})->Utf8
Way(Variant{Flags:AutoMap})->Uint32
```
### Пример
```yql
$vr = Variant(1, "0", Variant);
$vrs = Variant(1, "a", Variant);
SELECT Way($vr); -- 0
SELECT Way($vrs); -- "a"
```
## DynamicVariant {#dynamic_variant}
Создает экзмепляр гомогенного варианта (т.е. содержащего поля/элементы одного типа), причем индекс или поле варианта можно задавать динамически. При несуществующем индексе или имени поля будет возвращен `NULL`.
Обратная функция - [VariantItem](#variantitem).
### Сигнатура
```yql
DynamicVariant(item:T,index:Uint32?,Variant)->Optional>
DynamicVariant(item:T,index:Utf8?,Variant)->Optional>
```
### Пример
```yql
$dt = Int32;
$tvt = Variant<$dt,$dt>;
SELECT ListMap([(10,0u),(20,2u),(30,NULL)],($x)->(DynamicVariant($x.0,$x.1,$tvt))); -- [0: 10,NULL,NULL]
$dt = Int32;
$svt = Variant;
SELECT ListMap([(10,'x'u),(20,'z'u),(30,NULL)],($x)->(DynamicVariant($x.0,$x.1,$svt))); -- [x: 10,NULL,NULL]
```
## Enum {#enum}
`Enum()` cоздает значение перечисления.
### Сигнатура
```yql
Enum(String, Type>)->Enum<...>
```
Аргументы:
* Строка с именем поля
* Тип перечисления
### Пример
```yql
$enum_type = Enum;
SELECT
Enum("Foo", $enum_type) as Enum1Value,
Enum("Bar", $enum_type) as Enum2Value;
```
## AsEnum {#asenum}
`AsEnum()` создает значение [перечисления](../types/containers.md) с одним элементом. Это значение может быть неявно преобразовано к любому перечислению, содержащему такое имя.
### Сигнатура
```yql
AsEnum(String)->Enum<'tag'>
```
Аргументы:
* Строка с именем элемента перечисления
### Пример
```yql
SELECT
AsEnum("Foo");
```
## AsTagged, Untag {#as-tagged}
Оборачивает значение в [Tagged тип данных](../types/special.md) с указанной меткой с сохранением физического типа данных. `Untag` — обратная операция.
### Сигнатура
```yql
AsTagged(T, tagName:String)->Tagged
AsTagged(T?, tagName:String)->Tagged?
Untag(Tagged)->T
Untag(Tagged?)->T?
```
Обязательные аргументы:
1. Значение произвольного типа;
2. Имя метки.
Возвращает копию значения из первого аргумента с указанной меткой в типе данных.
Примеры сценариев использования:
* Возвращение на клиент для отображения в веб-интерфейсе медиа-файлов из base64-encoded строк.
* Защита на границах вызова UDF от передачи некорректных значений;
* Дополнительные уточнения на уровне типов возвращаемых колонок.
## TablePath {#tablepath}
Доступ к текущему имени таблицы, что бывает востребовано при использовании [CONCAT](../syntax/select/concat.md#concat) и других подобных механизмов.
### Сигнатура
```yql
TablePath()->String
```
Аргументов нет. Возвращает строку с полным путём, либо пустую строку и warning при использовании в неподдерживаемом контексте (например, при работе с подзапросом или диапазоном из 1000+ таблиц).
{% note info %}
Функции [TablePath](#tablepath), [TableName](#tablename) и [TableRecordIndex](#tablerecordindex) не работают для временных и анонимных таблиц (возвращают пустую строку или 0 для [TableRecordIndex](#tablerecordindex)).
Данные функции вычисляются в момент [выполнения](../syntax/select/index.md#selectexec) проекции в `SELECT`, и к этому моменту текущая таблица уже может быть временной.
Чтобы избежать такой ситуации, следует поместить вычисление этих функций в подзапрос, как это сделано во втором примере ниже.
{% endnote %}
### Примеры
```yql
SELECT TablePath() FROM CONCAT(table_a, table_b);
```
```yql
SELECT key, tpath_ AS path FROM (SELECT a.*, TablePath() AS tpath_ FROM RANGE(`my_folder`) AS a)
WHERE key IN $subquery;
```
## TableName {#tablename}
Получить имя таблицы из пути к таблице. Путь можно получить через функцию [TablePath](#tablepath).
### Сигнатура
```yql
TableName()->String
TableName(String)->String
TableName(String, String)->String
```
Необязательные аргументы:
* путь к таблице, по умолчанию используется `TablePath()` (также см. его ограничения);
* указание системы ("yt"), по правилам которой выделяется имя таблицы. Указание системы нужно только в том случае, если с помощью [USE](../syntax/use.md) не указан текущий кластер.
### Примеры
```yql
USE hahn;
SELECT TableName() FROM CONCAT(table_a, table_b);
```
## TableRecordIndex {#tablerecordindex}
Доступ к текущему порядковому номеру строки в исходной физической таблице, **начиная с 1** (зависит от реализации хранения).
### Сигнатура
```yql
TableRecordIndex()->Uint64
```
Аргументов нет. При использовании в сочетании с [CONCAT](../syntax/select/concat.md#concat) и другими подобными механизмами нумерация начинается заново для каждой таблицы на входе. В случае использования в некорректном контексте возвращает 0.
### Пример
```yql
SELECT TableRecordIndex() FROM my_table;
```
## TableRow, JoinTableRow {#tablerow}
Получение всей строки таблицы целиком в виде структуры. Аргументов нет. `JoinTableRow` в случае `JOIN`-ов всегда возвращает структуру с префиксами таблиц.
### Сигнатура
```yql
TableRow()->Struct
```
### Пример
```yql
SELECT TableRow() FROM my_table;
```
## FileContent и FilePath {#file-content-path}
### Сигнатуры
```yql
FilePath(String)->String
FileContent(String)->String
```
Аргумент `FileContent` и `FilePath` — строка с алиасом.
### Примеры
```yql
SELECT "Content of "
|| FilePath("my_file.txt")
|| ":\n"
|| FileContent("my_file.txt");
```
## FolderPath {#folderpath}
Получение пути до корня директории с несколькими «приложенными» файлами с указанным общим префиксом.
### Сигнатура
```yql
FolderPath(String)->String
```
Аргумент — строка с префиксом среди алиасов.
Также см. [PRAGMA File](../syntax/pragma.md#file) и [PRAGMA Folder](../syntax/pragma.md#folder).
### Примеры
```yql
PRAGMA File("foo/1.txt", "http://url/to/somewhere");
PRAGMA File("foo/2.txt", "http://url/to/somewhere/else");
PRAGMA File("bar/3.txt", "http://url/to/some/other/place");
SELECT FolderPath("foo"); -- в директории по возвращённому пути будут
-- находиться файлы 1.txt и 2.txt, скачанные по указанным выше ссылкам
```
## ParseFile
Получить из приложенного текстового файла список значений. Может использоваться в сочетании с [IN](../syntax/expressions.md#in) и прикладыванием файла по URL.
Поддерживается только один формат файла — по одному значению на строку.
### Сигнатура
```yql
ParseFile(String, String)->List
```
Два обязательных аргумента:
1. Тип ячейки списка: поддерживаются только строки и числовые типы;
2. Имя приложенного файла.
{% note info %}
Возвращаемое значение - ленивый список. Для многократного использования его нужно обернуть в функцию [ListCollect](list.md#listcollect)
{% endnote %}
### Примеры
```yql
SELECT ListLength(ParseFile("String", "my_file.txt"));
```
```yql
SELECT * FROM my_table
WHERE int_column IN ParseFile("Int64", "my_file.txt");
```
## Ensure... {#ensure}
Проверка пользовательских условий:
* `Ensure()` — проверка верности предиката во время выполнения запроса.
* `EnsureType()` — проверка точного соответствия типа выражения указанному.
* `EnsureConvertibleTo()` — мягкая проверка соответствия типа выражения, работающая по тем же правилам, что и неявное приведение типов.
Если проверка не прошла успешно, то весь запрос завершается с ошибкой.
### Сигнатуры
```yql
Ensure(T, Bool, String)->T
EnsureType(T, Type, String)->T
EnsureConvertibleTo(T, Type, String)->T
```
Аргументы:
1. Выражение, которое станет результатом вызова функции в случае успеха проверки. Оно же подвергается проверке на тип данных в соответствующих функциях.
2. В Ensure — булевый предикат, который проверяется на `true`. В остальных функциях — тип данных, который может быть получен через [предназначенные для этого функции](types.md), либо строковый литерал с [текстовым описанием типа](../types/type_string.md).
3. Опциональная строка с комментарием к ошибке, которая попадет в общее сообщение об ошибке при завершении запроса. Для проверок типов не может использовать сами данные, так как они выполняются на этапе валидации запроса, а для Ensure — может быть произвольным выражением.
Для проверки условий по финальному результату вычисления Ensure удобно использовать в сочетании с [DISCARD SELECT](../syntax/discard.md).
### Примеры
```yql
SELECT Ensure(
value,
value < 100,
"value out or range"
) AS value FROM my_table;
```
```yql
SELECT EnsureType(
value,
TypeOf(other_value),
"expected value and other_value to be of same type"
) AS value FROM my_table;
```
```yql
SELECT EnsureConvertibleTo(
value,
Double?,
"expected value to be numeric"
) AS value FROM my_table;
```
## AssumeStrict {#assumestrict}
### Сигнатура
```yql
AssumeStrict(T)->T
```
Функция `AssumeStrict` возвращает свой аргумент. Использование этой функции – способ сказать оптимизатору YQL, что выражение в аргументе является *строгим*, т.е. свободным от ошибок времени выполнения.
Большинство встроенных функций и операторов YQL являются строгими, но есть исключения – например [Unwrap](#optional-ops) и [Ensure](#ensure).
Кроме того, нестрогим выражением считается вызов UDF.
Если есть уверенность, что при вычислении выражения ошибок времени выполнения на самом деле не возникает, то имеет смысл использовать `AssumeStrict`.
### Пример
```yql
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}
### Сигнатура
```yql
Likely(Bool)->Bool
Likely(Bool?)->Bool?
```
Функция `Likely` возвращает свой аргумент. Функция является подсказкой оптимизатору и говорит о том, что в большинстве случаев ее аргумент будет иметь значение `True`.
Например, наличие такой функции в `WHERE` означает что фильтр является слабоселективным.
### Пример
```yql
SELECT * FROM T1 AS a JOIN T2 AS b USING(key)
WHERE Likely(a.amount > 0) -- почти всегда верно
```
При наличии `Likely` оптимизатор не будет стараться выполнить фильтрацию перед `JOIN`.
## EvaluateExpr, EvaluateAtom {#evaluate_expr_atom}
Возможность выполнить выражение до начала основного расчета и подставить его результат в запрос как литерал (константу). Во многих контекстах, где в стандартном SQL ожидалась бы только константа (например, в именах таблиц, количестве строк в [LIMIT](../syntax/select/limit_offset.md) и т.п.) этот функционал активируется неявным образом автоматически.
EvaluateExpr может использоваться в тех местах, где грамматикой уже ожидается выражение. Например, с его помощью можно:
* округлить текущее время до дней, недель или месяцев и подставить в запрос, что затем позволит корректно работать [кешированию запросов](../syntax/pragma.md#yt.querycachemode), хотя обычно использование [функций для получения текущего времени](#current-utc) его полностью отключает;
* сделать тяжелое вычисление с небольшим результатом один раз на запрос вместо одного раза на каждую джобу.
EvaluateAtom позволяет динамически создать [атом](../types/special.md), но т.к. ими в основном оперирует более низкий уровень [s-expressions](/docs/s_expressions/functions), то использовать эту функцию напрямую как правило не рекомендуется.
Единственный аргумент у обоих функций — само выражение для вычисления и подстановки.
Ограничения:
* выражение не должно приводить к запуску MapReduce операций;
* данный функционал полностью заблокирован в YQL over YDB.
### Примеры
```yql
$now = CurrentUtcDate();
SELECT EvaluateExpr(
DateTime::MakeDate(DateTime::StartOfWeek($now)
)
);
```
## Литералы простых типов {#data-type-literals}
Для простых типов могут быть созданы литералы на основании строковых литералов.
### Синтаксис
`<Простой тип>( <строка>[, <дополнительные атрибуты>] )`
В отличие от `CAST("myString" AS MyType)`:
* Проверка на приводимость литерала к требуемому типу происходит на этапе валидации;
* Результат не является optional.
Для типов данных `Date`, `Datetime`, `Timestamp` и `Interval` поддерживаются литералы только в формате, соответствующем [ISO 8601](https://ru.wikipedia.org/wiki/ISO_8601). У `Interval` есть следующие отличия от стандарта:
* поддерживается отрицательный знак для сдвигов в прошлое;
* микросекунды могут быть записаны как дробная часть секунд;
* единицы измерения больше недель не доступны;
* не поддерживаются варианты с началом/концом интервала, а также повторами.
Для типов данных `TzDate`, `TzDatetime`, `TzTimestamp` литералы также задаются в формате, соответствующем [ISO 8601](https://ru.wikipedia.org/wiki/ISO_8601), но вместо опционального суффикса Z через запятую указывается [IANA имя временной зоны](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), например, GMT или Europe/Moscow.
{% include [decimal args](../_includes/decimal_args.md) %}
### Примеры
```yql
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("[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 {#to-from-bytes}
Конвертация [простых типов данных](../types/primitive.md) в строку со своим бинарным представлением и обратно. Числа представляются в [little endian](https://en.wikipedia.org/wiki/Endianness#Little-endian).
### Сигнатуры
```yql
ToBytes(T)->String
ToBytes(T?)->String?
FromBytes(String, Type)->T?
FromBytes(String?, Type)->T?
```
### Примеры
```yql
SELECT
ToBytes(123), -- "\u0001\u0000\u0000\u0000"
FromBytes(
"\xd2\x02\x96\x49\x00\x00\x00\x00",
Uint64
); -- 1234567890ul
```
## ByteAt {#byteat}
Получение значение байта в строке по индексу от её начала. В случае некорректного индекса возвращается `NULL`.
### Сигнатура
```yql
ByteAt(String, Uint32)->Uint8
ByteAt(String?, Uint32)->Uint8?
ByteAt(Utf8, Uint32)->Uint8
ByteAt(Utf8?, Uint32)->Uint8?
```
Аргументы:
1. Строка: `String` или `Utf8`;
2. Индекс: `Uint32`.
### Примеры
```yql
SELECT
ByteAt("foo", 0), -- 102
ByteAt("foo", 1), -- 111
ByteAt("foo", 9); -- NULL
```
## ...Bit {#bitops}
`TestBit()`, `ClearBit()`, `SetBit()` и `FlipBit()` - проверить, сбросить, установить или инвертировать бит в беззнаковом числе по указанному порядковому номеру бита.
### Сигнатуры
```yql
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`. Остальные функции возвращают копию своего первого аргумента с проведенным соответствующим преобразованием.
### Примеры
```yql
SELECT
TestBit(1u, 0), -- true
SetBit(8u, 0); -- 9
```
## Abs {#abs}
Абсолютное значение числа.
### Сигнатура
```yql
Abs(T)->T
Abs(T?)->T?
```
### Примеры
```yql
SELECT Abs(-123); -- 123
```
## Just {#optional-ops}
`Just()` - Изменить тип данных значения на [optional](../types/optional.md) от текущего типа данных (то есть `T` превращается в `T?`).
### Сигнатура
```yql
Just(T)->T?
```
### Примеры
```yql
SELECT
Just("my_string"); -- String?
```
## Unwrap {#unwrap}
`Unwrap()` - Преобразование значения [optional](../types/optional.md) типа данных в соответствующий не-optional тип с ошибкой времени выполнений, если в данных оказался `NULL`. Таким образом, `T?` превращается в `T`.
Если значение не является [optional](../types/optional.md), то функция возвращает свой первый аргумент без изменений.
### Сигнатура
```yql
Unwrap(T?)->T
Unwrap(T?, Utf8)->T
Unwrap(T?, String)->T
```
Аргументы:
1. Значение для преобразования;
2. Опциональная строка с комментарием для текста ошибки.
Обратная операция — [Just](#optional-ops).
### Примеры
```yql
$value = Just("value");
SELECT Unwrap($value, "Unexpected NULL for $value");
```
## Nothing {#nothing}
`Nothing()` - Создать пустое значение указанного [Optional](../types/optional.md) типа данных.
### Сигнатура
```yql
Nothing(Type)->T?
```
### Примеры
```yql
SELECT
Nothing(String?); -- пустое значение (NULL) с типом String?
```
[Подробнее о ParseType и других функциях для работы с типами данных](types.md).
## Callable {#callable}
Создать вызываемое значение с заданной сигнатурой из лямбда-функции. Обычно используется для того, чтобы размещать вызываемые значения в контейнерах.
### Сигнатура
```yql
Callable(TypeT>>, lambda)->Callable<(...)->T>
```
Аргументы:
1. Тип;
2. Лямбда-функция.
### Примеры
```yql
$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}
`Pickle()` и `StablePickle()` сериализуют произвольный объект в последовательность байт, если это возможно. Типовыми несериализуемыми объектами являются Callable и Resource. Формат сериализации не версионируется, допускается использовать в пределах одного запроса. Для типа Dict функция StablePickle предварительно сортирует ключи, а для Pickle порядок элементов словаря в сериализованном представлении не определен.
`Unpickle()` — обратная операция (десериализация), где первым аргументом передается тип данных результата, а вторым — строка с результатом `Pickle()` или `StablePickle()`.
### Сигнатуры
```yql
Pickle(T)->String
StablePickle(T)->String
Unpickle(Type, String)->T
```
### Примеры
```yql
SELECT *
FROM my_table
WHERE Digest::MurMurHash32(
Pickle(TableRow())
) % 10 == 0; -- в реальности лучше использовать TABLESAMPLE
$buf = Pickle(123);
SELECT Unpickle(Int32, $buf);
```
## StaticMap
Преобразует структуру или кортеж, применяя лямбду к каждому элементу.
### Сигнатура
```yql
StaticMap(Struct<...>, lambda)->Struct<...>
StaticMap(Tuple<...>, lambda)->Tuple<...>
```
Аргументы:
* Структура или кортеж;
* Лямбда для обработки элементов.
Результат: структура или кортеж с аналогичным первому аргументу количеством и именованием элементов, а типы данных элементов определяются результатами лямбды.
### Примеры
```yql
SELECT *
FROM (
SELECT
StaticMap(TableRow(), ($item) -> {
return CAST($item AS String);
})
FROM my_table
) FLATTEN COLUMNS; -- преобразование всех колонок в строки
```
## StaticZip
Поэлементно "склеивает" структуры или кортежи. Все аргументы (один и более) должны быть либо структурами с одинаковым набором полей, либо кортежами одинаковой длины.
Результататом будет соответственно структура или кортеж.
Каждый элемент результата – кортеж с соответствующими элементами из аргументов.
### Сигнатура
```yql
StaticZip(Struct, Struct)->Struct
StaticZip(Tuple, Tuple)->Tuple
```
### Примеры
```yql
$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}
```yql
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)` преобразуется в свертку:
```yql
$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)`:
```yql
$f($el_n, ...$f($el_2, $f($f0($init), el_1))...)
```
`StaticFold1(<||>, $f0, $f)` вернет `NULL`.
Аналогично работает и с кортежами.
## AggregationFactory {#aggregationfactory}
Создать фабрику для [агрегационных функций](aggregation.md) для того чтобы разделить процесс описания того, как агрегировать данные, и то, к каким данным это применять.
Аргументы:
1. Строка в кавычках, являющаяся именем агрегационной функции, например ["MIN"](aggregation.md#min).
2. Опциональные параметры агрегационной функции, которые не зависят от данных. Например, значение percentile в [PERCENTILE](aggregation.md#percentile).
Полученную фабрику можно использовать как второй параметр функции [AGGREGATE_BY](aggregation.md#aggregateby).
Если агрегационная функция работает на двух колонках вместо одной, как например, [MIN_BY](aggregation.md#minby), то в [AGGREGATE_BY](aggregation.md#aggregateby) первым аргументом передается `Tuple` из двух значений. Подробнее это указано при описании такой агрегационной функции.
### Примеры
```yql
$factory = AggregationFactory("MIN");
SELECT
AGGREGATE_BY(value, $factory) AS min_value -- применить MIN агрегацию к колонке value
FROM my_table;
```
## AggregateTransformInput {#aggregatetransform}
`AggregateTransformInput()` преобразует фабрику для [агрегационных функций](aggregation.md), например, полученную через функцию [AggregationFactory](#aggregationfactory) в другую фабрику, в которой перед началом выполнения агрегации производится указанное преобразование входных элементов.
Аргументы:
1. Фабрика для агрегационных функций;
2. Лямбда функция с одним аргументом, преобразующая входной элемент.
### Примеры
```yql
$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}
`AggregateTransformOutput()` преобразует фабрику для [агрегационных функций](aggregation.md), например, полученную через функцию [AggregationFactory](#aggregationfactory) в другую фабрику, в которой после окончания выполнения агрегации производится указанное преобразование результата.
Аргументы:
1. Фабрика для агрегационных функций;
2. Лямбда функция с одним аргументом, преобразующая результат.
### Примеры
```yql
$f = AggregationFactory("sum");
$g = AggregateTransformOutput($f, ($x) -> ($x * 2));
SELECT ListAggregate([1,2,3], $f); -- 6
SELECT ListAggregate([1,2,3], $g); -- 12
```
## AggregateFlatten {#aggregateflatten}
Адаптирует фабрику для [агрегационных функций](aggregation.md), например, полученную через функцию [AggregationFactory](#aggregationfactory) так, чтобы выполнять агрегацию над входными элементами - списками. Эта операция похожа на [FLATTEN LIST BY](../syntax/flatten.md) - производится агрегация каждого элемента списка.
Аргументы:
1. Фабрика для агрегационных функций.
### Примеры
```yql
$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]
```
## YQL::, s-expressions {#s-expressions}
Полный список внутренних функций YQL находится в [документации к s-expressions](/docs/s_expressions/functions), альтернативному низкоуровневому синтаксису YQL. Любую из перечисленных там функций можно вызвать и из SQL синтаксиса, добавив к её имени префикс `YQL::`, но это не рекомендуется делать, т.к. данный механизм предназначен в первую очередь для временного обхода возможных проблем, а также для нужд внутреннего тестирования.
Если функция доступна в SQL синтаксисе без префикса `YQL::`, то её поведение имеет право отличаться от одноименной функции из документации по s-expressions, если таковая существует.