YPATH

В данном разделе собрана информация про YPath — язык, описывающий пути к объектам в системе YTsaurus.

YPath представляет собой язык описания путей, которые идентифицируют объекты в системе YTsaurus. Язык позволяет обращаться к узлам и указывать аннотации, которые могут быть полезны при совершении операций над узлами, например, при записи в таблицу. При помощи аннотаций можно определить, будут ли новые данные дописаны в конце таблицы, или таблица будет полностью перезаписана.

Например:

  • //home/user/table — путь к таблице table в домашнем каталоге пользователя;
  • #0-25-3ec012f-406daf5c/@type — путь к атрибуту type объекта с идентификатором 0-25-3ec012f-406daf5c;
  • //home/user/table[#10:#20] — строки с 10-ю по 19-ю включительно таблицы table в домашнем каталоге пользователя.

Существует несколько разновидностей YPath. В самом простом случае YPath представляет собой строку, кодирующую путь.

Простой YPath

Лексика

Строка, кодирующая простой YPath, разбивается на следующие токены:

  1. Специальные символы: прямой слеш (/), «собака» (@), амперсанд (&), звёздочка (*);
  2. Литералы: максимальная непустая последовательность неспециальных символов. В литералах разрешен escaping вида \<escape-sequence>, где в качестве <escape-sequence> может выступать один из символов \, /, @, &, *, [, {, а также выражение вида x<hex1><hex2>, где <hex1> и <hex2> — шестнадцатеричные цифры.

Синтаксис и семантика

Структурно YPath имеет вид <root-designator><relative-path>. Здесь <root-designator> бывает двух видов:

  1. Корень Кипариса: токен /.
    Пример: //home/user; здесь <root-designator> равен /, а <relative-path> равен /home/user;
  2. Объектный корень: токен-литерал, кодирующий строку вида #<id>.
    Пример: #1-2-3-4/@type; здесь <root-designator> равен #1-2-3-4, а <relative-path> равен /@type.

Тем самым, <root-designator> определяет начальную точку отсчета, к которой применяется <relative-path>. Последний разбирается последовательно слева направо, в результате чего возникают шаги перемещения по дереву следующих видов:

  • Переход к потомку: последовательность из токена / и литерала.
    Данный тип шагов применим к словарям и спискам. В случае словаря литерал должен содержать имя потомка. Пример: /child — переход к потомку с именем child.
    В случае списка литерал должен содержать целое число в десятичной системе счисления — номер потомка. Потомки в списке нумеруются с нуля. Разрешены также отрицательные номера, которые нумеруют потомков с конца списка. Примеры: /1 — переход ко второму потомку в списке, /-1 — переход к последнему потомку в списке;
  • Переход к атрибуту: последовательность из токенов /@ и литерала.
    Данный тип шагов применим в любой точке пути и означает переход к атрибуту с данными именем. Пример: /@attr — переход к атрибуту с именем attr.

Примечание

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

Примеры

% Корень Кипариса
/

% В корневой директории узел home, в ней — узел user.
//home/user

% Начальный элемент в списке //home/user/list
//home/user/list/0

% Последний элемент в списке //home/user/list
//home/user/list/-1

% Атрибут attr узла //home/user
//home/user/@attr

% Объект с идентификатором 1-2-a-b
#1-2-a-b

% Потомок child объекта с идентификатором 1-2-a-b
#1-2-a-b/child

% Атрибут attr объекта с идентификатором 1-2-a-b
#1-2-a-b/@attr

Особенности поведения

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

  • Указание всех потомков: в команде remove_node есть возможность удалить всех потомков словаря или списка, для этого следует использовать вместо имени токен *.
    Пример:

    % Очистить домашний каталог пользователя
    yt remove //home/user/*
    
  • Указание всех атрибутов: в командах чтения (get_node, list_nodes), а также изменения (set_node) есть возможность обратиться к коллекции всех атрибутов объекта, для чего в качестве пути надо использовать путь вида /@. При этом изменение через set_node распространяется лишь на пользовательские атрибуты.

    Примеры:

    % Получить значения всех атрибутов домашнего каталога пользователя
    yt get //home/user/@
    
    % Получить имена всех атрибутов домашнего каталога пользователя
    yt list //home/user/@
    
    % Удалить все пользовательские атрибуты
    yt set //home/user/@ '{}'
    
    % Выставить один пользовательский атрибут, удалив все остальные имеющиеся
    yt set //home/user/@ '{attr=value}'
    
    % Выставить один пользовательский атрибут, не трогать остальные
    yt set //home/user/@attr value
    
    % Выставить вложенный пользовательский атрибут
    yt set //home/user/@attr/some/key value
    
  • Указание позиции вставки в список: в командах, создающих новые узлы (например set_node) есть возможность указать положение создаваемого узла в списке относительно уже имеющихся. Для этого нужно вместо номера потомка использовать специальные строки begin (начало списка), end (конец списка), before:<index> (позиция перед потомком с номером <index>), а также after:<index> (позиция после потомка с номером <index>). Примеры:

    % Добавить элемент "value" в конец списка //home/user/list
    yt set //home/user/list/end value
    
    % Вставить элемент "value" в начало списка //home/user/list
    yt set //home/user/list/before:0 value
    % Или
    yt set //home/user/list/begin value
    
    % Вставить элемент "value" перед вторым элементом списка //home/user/list
    yt set //home/user/list/before:2 value
    
    % Вставить элемент "value" после пятого элемента списка //home/user/list
    yt set //home/user/list/after:5 value
    
  • Отключение перенаправления: токен & может использоваться для подавления перенаправления по символической ссылке.
    Примеры:

    % Узнать идентификатор самого объекта-ссылки, а не объекта, на который ссылка указывает
    yt get //home/user/link&/@id
    

Сложный YPath

Сложный (rich) YPath представляет собой расширенный YPath, имеющий вид строки с дополнительными аннотациями. Эти аннотации могут быть заданы двумя способами: в виде атрибутов (пар вида ключ-значение), а также синтаксически с помощью добавления специальных префиксов и суффиксов к простому YPath, из-за чего он превращается в строку вида <prefix><simple-ypath><suffix>.

При отсутствии префикса <prefix> и суффикса <suffix> сложный YPath может иметь, например, такой вид:

<
  append = %true;
  compression_codec = lz4;
>
//home/user/table

Данный путь указывает на домашний каталог пользователя и несет в себе два атрибута.

На любом пути можно указать произвольный набор атрибутов. Точный их смысл зависит от того, как данный путь используется в системе. Например, при записи в таблицу имеет смысл атрибут append, позволяющий дописывать в конец, а не перезаписать результат. Для входных таблиц некоторых mapreduce-операций можно указать флаг foreign, означающий, что данная таблица является вторичной (таблицей-справочником), поэтому системе необходимо выполнять join специального вида.

Атрибуты, имена которых системе неизвестны, или которые не имеют смысла в заданном контексте, системой игнорируются.

Префикс и суффикс пути позволяют закодировать атрибуты в более компактном виде. Обе эти части используют лексику YSON. Подробнее об их устройстве:

Префикс

Часть <prefix> либо пуста, либо задает атрибуты в виде map-fragment в формате YSON.
Пример: <append=%true>//home/user/table задает путь к таблице в домашнем каталоге пользователя, а также сообщает нам дополнительный атрибут append.

Основное предназначение префикса — упростить передачу атрибутов при использовании команд из консоли.

Суффикс

Часть <suffix> либо пуста, либо указывает колонки и/или диапазоны строк обрабатываемой таблицы.

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

Модификатор выбора колонок представляет собой разделенный запятыми и взятый в фигурные скобки набор имен колонок. Каждое имя представлено YSON-строкой.

Примеры модификаторов выбора колонок: {a}, {a,b}, {} .

Формальная грамматика модификаторов выбора колонок:

<column-selector> = '{' { <column-selector-item> ',' } [ <column-selector-item> ] '}'
<column-selector-item> = <string>

Модификатор выбора строк представляет собой разделенный запятыми и взятый в квадратные скобки набор диапазонов строк таблицы. Каждый диапазон — пара из нижней и верхней границы диапазона, разделенных двоеточием, либо точное значение границы, которую нужно прочитать. В случае пары одна или обе границы могут отсутствовать.
Граница может быть либо числом с приписанным слева символом # — тогда это номер строки в таблице, либо списком значений — тогда это граница по значениям ключевых колонок, по которым таблица отсортирована. Указанный список может быть короче, чем количество полей, по котором отсортирована таблица. В случае, если список состоит из одного элемента, его можно не обрамлять в круглые скобки. Элемент должен быть корректным YSON-значением скалярного типа int64, uint64, string, double, bool.

Семантика модификатора выбора строк описана в разделе.

Примеры модификаторов выбора строк: [:], [#10:#100], [a:m], [(abc,8):(xyz,5)], [:5.0,10.0:], [#10], [a,#100,#1:#2], [100u:200u]. В последнем случае данные содержат беззнаковые числа.

Формальная грамматика модификаторов выбора строк:

<row-selector> = '[' { <row-range> ',' } [ <row-range> ] ']'

<row-range> = <row-index-range-selector> | <row-key-range-selector> | <row-index> | <row-composite-key> | ''

<row-index-range-selector> = [ <row-index> ] ':' [ <row-index> ]

<row-index> = '#' <int64>

<row-key-range-selector> = [ <row-composite-key> ] ':' [ <row-composite-key> ]

<row-composite-key> = <row-key> | <row-key-tuple>

<row-key-tuple> = '(' { <row-key> ',' } [ <row-key> ] ')'

<row-key> = <string> | <int64> | <uint64> | <bool> | <double>

Примеры

Примечание

Сложные пути взяты в одинарные кавычки для надлежащего парсинга шеллом.

% Прочитать целиком таблицу '//home/user/table'
yt read '//home/user/table'

% Прочитать все строки таблицы '//home/user/table', но не выбрать ни одной колонки
yt read '//home/user/table{}'

% Прочитать колонку 'a'
yt read '//home/user/table{a}'

% Прочитать колонки 'a', 'b'
yt read '//home/user/table{a,b}'

% Прочитать первые 100 строк таблицы '//home/user/table' (и выбрать все колонки)
yt read '//home/user/table[#0:#100]'

% Прочитать все строки, пропустив первые 100
yt read '//home/user/table[#100:]'

% Прочитать строку с номером 100 (считая с 0)
yt read '//home/user/table[#100]'

% Прочитать строки с ключом (или первой координатой ключа) 'abc'
yt read '//home/user/table["abc":"abc\x00"]'

% Запрос выше можно также выразить короче:
yt read '//home/user/table["abc"]'

% Прочитать строки с ключами, не меньшими '(a,1)'
yt read '//home/user/table[(a,1):]'

% Прочитать строки у которых первые две компоненты ключа равны 'a' и '1' соответственно
yt read '//home/user/table[(a,1)]'

% Прочитать строки, у которых первый ключ 'a', второй ключ начинается с 'b', и, если второй ключ равен 'b', то третий ключ не меньше '1'.
yt read '//home/user/table[(a,b,1):(a,c)]'

% Прочитать строки, у которых первый ключ начинается с 'a', а также строки, у которых первый ключ 'b', а второй - меньше '1'.
yt read '//home/user/table[a:(b,1)]'

% Прочитать строки, у которых первый ключ начинается с 'a', а также строки, у которых первый ключ 'b', а второй - меньше '1', а также строки, у которых первый ключ 'b', второй ключ - '1', а третий - отрицательный типа double. Выбрать колонки 'ab', 'ac'
yt read '//home/user/table{ab,ac}[a:(b,1,0.0)]'

% Преобразовать table1 со столбцами a,b,c,d в table2 со столбцами a,b,c и сортировкой по полям a,b
yt sort --src '//home/users/table1{a,b,c}' --dst //home/users/table2 --sort-by a --sort-by b --spec '{schema_inference_mode = from_output}'

% Преобразовать table1 со столбцами a,b,c,d в table2 со столбцами a,b,c
yt merge --src '//home/users/table1{a,b,c}' --dst //home/users/table2 --spec '{schema_inference_mode = from_output}'

Каноническая форма YPath

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

Пример: после канонизации пути <append=true>//home/user/table[#10:#20] получается следующая YSON-структура:

<
  append = true;
  ranges = [
    {
      lower_limit = {row_index = 10};
      upper_limit = {row_index = 20}
    }
  ]
>
"//home/user/table"

Внутри система YTsaurus предпочитает работать с канонической формой путей. Эта форма более громоздка, поэтому во всех путях, принимаемых системой на вход, разрешается использовать более удобную форму с префиксом и суффиксом:

<append=true>//home/user/table[#10:#20]

Префикс — <append=true>;

Суффикс — [#10:#20].

Внутри системы это будет развернуто в широкую запись:

  ranges = [
    {
      lower_limit = {row_index = 10};
      upper_limit = {row_index = 20}
    }
  ]

Существует команда parse_ypath драйвера, позволяющая канонизировать сложный YPath.

Поддерживаемые атрибуты

Сложный YPath может быть проаннотирован произвольными атрибутами, что дает возможность расширения. В таблице представлен список атрибутов, которые поддерживает система.

Атрибут Тип Описание
append bool Распознается командами записи данных (write_table и write_file) и означает, что новые данные дописываются в конец существующих, а не перезаписывают их. Также распознается на выходных путях таблиц в спецификациях всех операций планировщика и имеет аналогичную семантику.
sorted_by array<string> Распознается командой записи табличных данных ( write_table). При указании этого атрибута пользователь обещает, что записываемые данные упорядочены по указанному набору колонок. Система проверяет это свойство. Ключи должны идти в порядке неубывания, а в случае записи с добавлением проверяется также, что первый записываемый ключ не меньше последнего уже существующего. Атрибут также распознается системой на выходных путях таблиц в спецификациях всех операций планировщика и имеет там аналогичную семантику. В последнем случае также дополнительно требуется, чтобы диапазоны ключей, порождаемые различными джобами, не имели пересечения по внутренней точке, пересечения по границам разрешаются.
ranges array<ReadRange> Распознается командами чтения данных (read_table и read_file) и задает список читаемых диапазонов. Если отсутствует, читаются данные целиком. Также распознается на входных путях таблиц в спецификациях всех операций планировщика. Описание структуры словаря ReadRange представлено в таблице ниже.
columns array<string> Распознается командой чтения табличных данных ( read_table ) и задает список имен читаемых колонок. Если отсутствует, то читаются все колонки. Также распознается на входных путях таблиц в спецификациях всех операций планировщика.
optimize_for string Устанавливает формат хранения для создаваемой таблицы. Атрибут можно указывать c командой write_table и на выходных путях операций. Данный атрибут не совместим с <append=true>.
compression_codec string Устанавливает формат сжатия для создаваемой таблицы. Атрибут можно указывать с командами write_file , write_table и на выходных путях операций. Данный атрибут несовместим с <append=true>.
erasure_codec string Выключает erasure-кодирование для создаваемой таблицы. Атрибут можно указывать с командами write_file , write_table и на выходных путях операций. Данный атрибут несовместим с <append=true>.
schema yson-list с валидной схемой Валидирует данные относительно указанной схемы и проставляет данную схему на таблицу по окончании операции. Атрибут можно указывать с командой write_table и на выходных путях операций. Данный атрибут несовместим с <append=true>.
transaction_id string вида id Указание планировщику, под какой транзакцией необходимо обращаться к входной таблице, если на ней указан данный атрибут.
rename_columns yson-map Распознается на входящих путях таблиц. Переименовывает названия колонок согласно маппингу перед подачей таблицы на вход операции. Данный атрибут несовместим с teleport таблицами.

Атрибут ranges указывает, какие диапазоны строк таблицы следует прочитать. Указанные диапазоны будут читаться последовательно, в том порядке, в котором они указаны в атрибутах команды. В частности, если диапазоны пересекаются, то на выходе строки будут повторены соответствующее число раз.

Атрибут Тип Описание
lower_limit ReadLimit Нижняя граница чтения
upper_limit ReadLimit Верхняя граница чтения
exact ReadLimit Точное значение границы чтения (не может быть указано вместе с lower_limit или upper_limit)

За исключением ограничений типа key_bound все виды ограничений в lower_limit являются включительными, а все виды ограничений в upper_limit — исключительными. Включительность или исключительность ограничения типа key_bound указывается явно в самом key bound. См. также раздел, посвящённый срезам по ключам.

ReadLimit описывает отдельную границу чтения. Граница может определяться одним из шести селекторов: ключом, ключевым ограничением (key bound), номером строки, номером чанка, номером таблета или байтовым смещением. В границе может быть указано несколько селекторов, при этом они все действуют одновременно, усиливая друг друга.

Атрибут Тип Описание
key list Список значений, образующих ключ (только для сортированных таблиц). См. подробнее в разделе
key_bound list Включительное либо невключительное ограничение на префикс ключа; не может присутствовать в exact-границе. См. подробнее в разделе
row_index int Номер строки (только для таблиц)
offset int Байтовое смещение (только для файлов)
chunk_index int Номер чанка
tablet_index int Номер таблета (только для упорядоченных динамических таблиц)

Поддерживаемые системой YTsaurus YPath атрибуты на путях файлов

Атрибут Тип Описание
file_name string Распознается при заказе файла в sandbox джоба. Атрибут задает относительный путь, по которому надо положить файл.
executable bool Распознается при заказе файла в sandbox джоба. Атрибут указывает системе необходимость проставить executable-бит на заказанный файл.
bypass_artifact_cache bool Распознается при заказе файла в sandbox джоба. Атрибут включает прямое скачивание файла в sandbox джоба минуя файловый кэш на ноде.
format string Распознается при заказе табличного файла в sandbox джоба. Атрибут обозначает формат, в котором надо сформатировать таблицу при её скачивании в sandbox джоба.

Срезы сортированных таблиц по ключам

Система поддерживает два вида селекторов по значениям ключевых колонок таблицы, которые внешне напоминают друг друга, но отличаются по поведению. Первый вид является исторически более старым и реализуется селектором key, а также возможен для указания в суффиксе YPath. Второй вид является более новым и реализуется селектору key_bound; он доступен только через атрибут ranges в префиксе YPath.

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

Примечание

Напомним, что YTsaurus задаёт некоторый линейный порядок сравнения на всевозможных значениях, которые могут встретиться в таблице. В частности, значения типов int64, uint64, double, boolean внутри каждого из этих типов упорядочены естественным образом, значения типа string упорядочены лексикографически, а два значения разных типов данных сравниваются так, как сравниваются их типы в некотором implementation defined порядке. Например, любой int64 меньше любого uint64, а любой null меньше любого не null (#) значения.

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

Селектор key

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

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

[] < ["a"] < ["a"; 3] < ["a"; 4] < ["b"] < ["b"; 2]

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

Если селектор key указан как часть ограничения lower_limit (или в качестве нижней границы перед двоеточием в модификаторе выбора строк в суффиксе YPath), то он оставляет из множества всех строк только те, у которых полный ключ как кортеж больше либо равен кортежу key в смысле порядка сравнения выше. В частности, это означает, что селектор key может содержать кортеж, состоящий из меньшего или большего числа значений, чем число ключевых колонок в таблице, и это не нарушает корректности определения.

Если селектор key указан как часть ограничения upper_limit (или в качестве верхней границы после двоеточия в модификаторе выбора строк в суффиксе YPath), то он оставляет из множества всех строк только те, у которых полный ключ как кортеж строго меньше кортежа key.

Если селектор key указан как часть ограничения exact (или в качестве единственной границы без двоеточия в модификаторе выбора строк в суффиксе YPath), то он оставляет из множества всех строк только те, у которых полный ключ содержит кортеж key в качестве префикса.

Примеры

Пусть таблица //tmp/t имеет две ключевые колонки и содержит следующие ключи:

["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];
["c"; 0];

Срез //tmp/t[(b):], он же <ranges = [{lower_limit = {key = [b]}}]>//tmp/t:

["b"; 2];
["b"; 4];
["c"; 0];

Срез //tmp/t[(b, 2, 56):] (обратите внимание, что ключ в срезе может иметь больше значений, чем количество ключевых колонок в таблице):

["b"; 4];
["c"; 0];

Срез //tmp/t[:(c, 0)]:

["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];

Срез //tmp/t[(b)]:

["b"; 2];
["b"; 4];

Примечание

Для того, чтобы с использованием селектора типа key получить исключительную нижнюю границу или включительную верхнюю, необходимо вместо соответствующего кортежа указывать его последователя (successor) в смысле линейного порядка, определённого на кортежах выше, что в общем случае может быть непростой задачей. Данное обстоятельство послужило мотивацией для появления селектора типа key_bound, который обсуждается в следующем разделе.

Селектор key_bound

Селектор key_bound доступен к использованию в сортированных таблицах, ключевые колонки которых могут быть сортированы как по убыванию, так и по возрастанию. Значение селектора типа key_bound имеет вид списка, состоящего из двух значений, первое из которых задаёт отношение и представляется одной из четырёх строк ">", ">=", "<", "<=", а второе задаёт префикс ключа и является списком значений. Отношения > и >= могут встречаться только в ограничении lower_limit, а < и <= только в ограничении upper_limit; в ограничении exact селекторы типа key_bound не допускаются.

Примеры селекторов типа key_bound:

  • [">"; ["a"; 3]]
  • ["<="; ["b"]]
  • [">="; []]

Семантика данного селектора следующая. Рассмотрим таблицу, содержащую N ключевых колонок, а также некоторый key bound. Пусть длина префикса ключа в key bound равна K. Для использования key bound в применении к данной таблице, K должно находиться в пределах 0 до N; попытка указать более длинный префикс в key bound приведёт к ошибке.

Для того, чтобы понять, подходит ли строка с некоторым ключом под селектор, необходимо оставить от ключа префикс длины K, и сравнить результат с префиксом ключа из key bound лексикографически. Если результат сравнения соответствует указанному отношению, то строка попадает в результат, в противном случае нет.

Примечание

Если некоторая колонка является ключевой и отсортирована в обратном порядке (sort_order = descending), то результаты всех сравнений соответствующей компоненты кортежа ключа инвертируются; в частности, будут верны соотношения 5u < 2u и "foo" < #.

Также обратите внимание, что в определении поведения селектора key_bound сравниваются только кортежи одинаковой длины K, поэтому вопрос определения сравнения кортежей разной длины в присутствии обратного порядка сортировки не возникает.

В частности, по определению выше селекторы [">="; []], ["<="; []] допускают любую строку (так как после оставления префикса ключа длины 0 получается кортеж []), а селекторы [">"; []], ["<"; []] не допускают никакую строку.

Примеры

Рассмотрим таблицу //tmp/t с теми же ключами, что и в примере выше:

["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];
["c"; 0];

Срез <ranges = [{lower_limit = {key_bound = [">"; ["a"; 3]]}}]>//tmp/t:

["a"; 5];
["b"; 2];
["b"; 4];
["c"; 0];

Срез <ranges = [{upper_limit = {key_bound = ["<="; ["b"]]}}]>//tmp/t:

["a"; 1];
["a"; 3];
["a"; 5];
["b"; 2];
["b"; 4];

Примечание

Обратите внимание, что несмотря на то, что кортеж ["b"; 2] лексикографически превосходит кортеж ["b"], ключ ["b"; 2] при усечении до длины 1 превращается в кортеж ["b"], и поэтому он допускается key bound ["<="; ["b"]]. Это отличает поведение селектора key_bound в от селектора key, и расширяет возможности первого по сравнению со вторым, так как с помощью селектора key задать аналогичный срез нетривиально.

Срез <ranges = [{lower_limits = {key_bound = [">="; ["b"; 2; 56]]}}]>//tmp/t не является допустимым, и его использованием приведёт к ошибке Key bound length must not exceed schema key prefix length.

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