Модуль key_def
В модуле key_def есть функция, позволяющая создавать определение номеров и типов полей кортежа. Это определение обычно используется вместе с определением индекса, чтобы извлекать или сравнивать значения ключей индекса.
-
key_def.new(parts)¶ Создание нового экземпляра key_def.
Параметры: - parts (
table) – типы и номера полей. В таблицеpartsдолжен быть хотя бы один элемент. Для каждого элемента обязательны только атрибутыtypeиfieldno/field.
возвращает: The parts table has components which are the same as the
partsoption in Options for space_object:create_index().fieldno(целое число), напримерfieldno = 1. Вместоfieldnoможно использоватьfield.type(строка), напримерtype = 'string'.Остальные компоненты необязательны.
Пример №1:
key_def.new({{type = 'unsigned', fieldno = 1}})Пример №2:
key_def.new({{type = 'string', collation = 'unicode', field = 2}})Since version 3.2.0, you can use the standard lua operator
#(__len metamethod) to check thekey_deflength (parts count).Example
function is_full_pkey(space, key) return #space.index[0].parts == #key end
- parts (
-
object
key_def_object¶ Объект key_def возвращается функцией key_def.new(). У него есть следующие методы: extract_key(), compare(), compare_with_key(), merge(), totable().
-
key_def_object:extract_key(tuple)¶ Получение кортежа, содержащего только поля объекта
key_def.Параметры: - tuple (
table) – кортеж или Lua-таблица с содержимым поля
возвращает: поля, определенные для объекта
key_def,Пример №1:
-- Предположим, что у некоторого элемента пять полей: -- 1, 99.5, 'X', nil, 99.5 -- Нас интересуют только два из них: -- третье (строка) и первое (целое число). -- Мы можем определить эти поля инструкцией k = key_def.new -- и извлечь значения командой k:extract_key. tarantool> key_def = require('key_def') --- ... tarantool> k = key_def.new({{type = 'string', fieldno = 3}, > {type = 'unsigned', fieldno = 1}}) --- ... tarantool> k:extract_key({1, 99.5, 'X', nil, 99.5}) --- - ['X', 1] ...
Пример №2
-- Теперь предположим, что элемент является кортежем в спейсе. -- У спейса есть составной индекс, построенный по полям 3 и 1. -- Мы можем передать определение индекса в качестве аргумента функции key_def.new, -- а не заполнять определение, как в примере №1. -- Результат будет тот же. key_def = require('key_def') box.schema.space.create('T') i = box.space.T:create_index('I', {parts={3, 'string', 1, 'unsigned'}}) box.space.T:insert{1, 99.5, 'X', nil, 99.5} k = key_def.new(i.parts) k:extract_key(box.space.T:get({'X', 1}))
Пример №3
-- Проходим по всем кортежам во вторичном неуникальном индексе -- и извлекаем из них значения по первичному ключу. -- Затем удаляем значения, используя уникальный индекс. -- Этот код должен входить в Lua-функцию. local key_def_lib = require('key_def') local s = box.schema.space.create('test') local pk = s:create_index('pk') local sk = s:create_index('test', {unique = false, parts = { {2, 'number', path = 'a'}, {2, 'number', path = 'b'}}}) s:insert{1, {a = 1, b = 1}} s:insert{2, {a = 1, b = 2}} local key_def = key_def_lib.new(pk.parts) for _, tuple in sk:pairs({1})) do local key = key_def:extract_key(tuple) pk:delete(key) end
- tuple (
-
key_def_object:compare(tuple_1, tuple_2)¶ Сравнение полей кортежей
tuple_1иtuple_2по определённому ключу. Пользователю не нужно писать код для сравнения отдельных полей. Учитываются типы полей и параметры сортировки. Фактически сравниваются значенияextract_key(tuple_1)иextract_key(tuple_2).Параметры: возвращает: положительное число, если значения полей tuple_1 больше значений полей tuple_2 по ключу; 0, если они равны; отрицательное число, если значения полей tuple_1 меньше значений полей tuple_2 по ключу
Пример:
-- Результат этого кода будет 0 key_def = require('key_def') k = key_def.new({{type = 'string', fieldno = 3, collation = 'unicode_ci'}, {type = 'unsigned', fieldno = 1}}) k:compare({1, 99.5, 'X', nil, 99.5}, {1, 99.5, 'x', nil, 99.5})
-
key_def_object:compare_with_key(tuple_1, tuple_2)¶ Сравнение полей кортежей
tuple_1с полями кортежаtuple_2по заданному ключу. Аналогично key_def_object:compare(), за исключением того, чтоtuple_2содержит только поля ключа. Фактически это сравнениеextract_key(tuple_1)сtuple_2.Параметры: возвращает: положительное число, если значения полей tuple_1 больше значений полей tuple_2 по ключу; 0, если они равны; отрицательное число, если значения полей tuple_1 меньше значений полей tuple_2 по ключу
Пример:
-- Результат этого кода будет 0 key_def = require('key_def') k = key_def.new({{type = 'string', fieldno = 3, collation = 'unicode_ci'}, {type = 'unsigned', fieldno = 1}}) k:compare_with_key({1, 99.5, 'X', nil, 99.5}, {'x', 1})
-
key_def_object:merge(other_key_def_object)¶ Объединение основного объекта
key_def_objectс другим объектомother_key_def_object. Возвращает новый объектkey_def_object, содержащий сначала все поля основного объектаkey_def_object, а потом те поля объектаother_key_def_object, которых не было в основном объектеkey_def_object.Параметры: - other_key_def_object (
key_def_object) – определение полей, которые нужно добавить
возвращает: key_def_object
Пример:
-- Результатом этого кода будет определение ключа -- по полям с fieldno = 3 и fieldno = 1 key_def = require('key_def') k = key_def.new({{type = 'string', fieldno = 3}}) k2= key_def.new({{type = 'unsigned', fieldno = 1}, {type = 'string', fieldno = 3}}) k:merge(k2)
- other_key_def_object (
-
key_def_object:totable()¶ Возвращает таблицу с содержимым
key_def_object. Функция противоположна функцииkey_def.new():key_def.new()принимает таблицу, а возвращает объектkey_def.key_def_object:totable()принимает объектkey_def, а возвращает таблицу.
Это удобно при подготовке входных данных для методов сериализации (
_serialize).возвращает: таблица Пример:
-- Результатом этого кода будет таблица с type = 'string', fieldno = 3 key_def = require('key_def') k = key_def.new({{type = 'string', fieldno = 3}}) k:totable()
-
key_def_object:validate_key(key)¶ Since version 3.1.0
Validates all parts of the specified key match the key definition. Partial keys are considered valid. Returns nothing on success.
If the key fails the validation, a
box.errortype exception is raised.Пример:
-- Create a rule: key = {1 ('unsigned'), 2 (string)} -- Validate key {1001} (only id data type). Returns nothing -- Validate key {'x'}. ER_KEY_PART_TYPE is raised -- Validate key ({1000, 2000}). ER_KEY_PART_TYPE is raised -- Validate key ({1000, 'abc', 'xyz'}). ER_KEY_PART_COUNT is raised tarantool> key_def = require('key_def').new({{fieldno = 1, type = 'unsigned'}, > {fieldno = 2, type = 'string'}}) --- ... tarantool> key_def:validate_key({1001}) --- ... tarantool> key_def:validate_key({'x'}) --- - error: 'Supplied key type of part 0 does not match index part type: expected unsigned' ... tarantool> key_def:validate_key({1000, 2000}) --- - error: 'Supplied key type of part 1 does not match index part type: expected string' ... tarantool> key_def:validate_key({1000, 'abc', 'xyz'}) --- - error: 'Invalid key part count: (expected [0..2], got 3) ...
-
key_def_object:validate_full_key(key)¶ Since version 3.1.0
Validates whether they input
keycontains all fields and mathces the rules of the key definition object. Returns nothing on success.If the key fails the validation, a
box.errortype exception is raised.Пример:
-- Create a rule: key = {1 ('unsigned'), 2 (string)} -- Validate key {100, "Testuser"}. Returns nothing -- Validate key ({100}). ER_EXACT_MATCH is raised tarantool> key_def = require('key_def').new({{fieldno = 1, type = 'unsigned'}, > {fieldno = 2, type = 'string'}}) --- ... tarantool> key_def:validate_full_key({100, "Testuser"}) --- ... tarantool> key_def:validate_full_key({100}) --- - error: 'Invalid key part count in an exact match: (expected 2, got 1) ...
-
key_def_object:validate_tuple(tuple)¶ Since version 3.1.0
Validates whether the
tuplematches the rules of the key definition object Returns nothing on success.If the key fails the validation, a
box.errortype exception is raised.Пример:
-- Create a rule: tuple = {id (number), name (string), age (number)} -- Validate tuple {1001, "Testuser", 28}. Returns nothing tarantool> key_def = require('key_def').new({ > {fieldno = 1, type = 'number'}, > {fieldno = 2, type = 'string'}, > {fieldno = 3, type = 'number'}) --- ... tarantool> key_def:validate_tuple({1001, "Testuser", 28}) --- ...
-
key_def_object:compare_keys(key_a, key_b)¶ Since version 3.1.0
Compares two keys against each other and according to the key definition object. On success, returns:
<0ifkey_aparts are less thankey_bparts0ifkey_aparts are equal tokey_bparts>0ifkey_aparts are greater thankey_bparts
If any key does not match the key definition rules, a
box.errortype exception is raised.Пример:
-- Create a rule: key = {1 ('unsigned'), 2 (string)} -- Validate keys ({1000, 'x'}, {1000, 'y'}). Returns -1 -- Validate keys ({1000, 'x'}, {1000, 'x'}). Returns 0 -- Validate keys ({1000, 'x'}, {1000}). Returns 0 -- Validate keys ({2000, 'x'}, {1000, 'x'}). Returns 1 tarantool> key_def = require('key_def').new({{fieldno = 1, type = 'unsigned'}, > {fieldno = 2, type = 'string'}}) --- ... tarantool> key_def:compare_keys({1000, 'x'}, {1000, 'y'}) --- - -1 ... tarantool> key_def:compare_keys({1000, 'x'}, {1000, 'x'}) --- - 0 ... tarantool> key_def:compare_keys({1000, 'x'}, {1000}) --- - 0 ... tarantool> key_def:compare_keys({2000, 'x'}, {1000, 'x'}) --- - 1 ...
-