Модуль key_def
В модуле key_def есть функция, позволяющая создавать
определение номеров и типов полей кортежа. Это определение обычно
используется вместе с определением индекса, чтобы извлекать или
сравнивать значения ключей индекса.
Создание нового экземпляра key_def.
Параметры:
parts(table) — номера и типы полей. Должен быть указан хотя бы один компонент. Каждый компонент должен содержать атрибутыtypeиfieldno/field. Остальные атрибуты необязательны.
Возвращает
Таблица parts содержит компоненты, аналогичные тем, что указываются в
параметре parts
при создании объекта 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}})
Начиная с версии 3.2.0,
для проверки длины объекта key_def (количества компонентов) можно
использовать стандартный оператор Lua # (метаметод __len).
Пример:
function is_full_pkey(space, key)return #space.index[0].parts == #keyend
Объект key_def — это объект, возвращаемый функцией key_def.new(). У него есть следующие методы: extract_key(), compare(), compare_with_key(), merge(), totable().
Получение кортежа, содержащего только поля объекта key_def.
Параметры:
tuple(table) — кортеж или Lua-таблица со значениями полей
Возвращает
поля, определенные для объекта key_def
Пример №1:
-- Suppose an item has five fields-- 1, 99.5, 'X', nil, 99.5-- and the fields that we care about are-- #3 (a string) and #1 (an integer).-- We can define those fields with k = key_def.new-- and extract the values with 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}) dolocal key = key_def:extract_key(tuple)pk:delete(key)end
Сравнение полей кортежей tuple_1 и tuple_2 по определённому ключу.
Пользователю не нужно писать код для сравнения отдельных полей.
Учитываются типы полей и параметры сортировки. Фактически сравниваются
значения extract_key(tuple_1) и extract_key(tuple_2).
Параметры:
tuple_1(table) — кортеж или Lua-таблица со значениями полейtuple_2(table) — кортеж или Lua-таблица со значениями полей
Возвращает
<0, если ключевые поляtuple_1меньше ключевых полейtuple_20, если ключевые поляtuple_1равны ключевым полямtuple_2>0, если ключевые поляtuple_1больше ключевых полейtuple_2
Пример:
-- Результат этого кода будет 0key_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})
Сравнение полей кортежей tuple_1 с полями кортежа tuple_2 по
заданному ключу. Аналогично key_def_object:compare(), за исключением того,
что tuple_2 содержит только поля ключа. Фактически это сравнение
extract_key(tuple_1) с tuple_2.
Параметры:
tuple_1(table) — кортеж или Lua-таблица со значениями полейtuple_2(table) — кортеж или Lua-таблица со значениями полей
Возвращает
<0, если ключевые поляtuple_1меньше полейtuple_20, если ключевые поляtuple_1равны полямtuple_2>0, если ключевые поляtuple_1больше полейtuple_2
Пример:
-- Результат этого кода будет 0key_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 с другим объектом
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 = 1key_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)
Возвращает таблицу с содержимым key_def_object. Функция
противоположна функции key_def.new():
key_def.new()принимает таблицу и возвращает объектkey_def,key_def_object:totable()принимает объектkey_defи возвращает таблицу.
Это удобно при подготовке входных данных для методов сериализации
(_serialize).
Возвращает
таблица
Пример:
-- Результатом этого кода будет таблица с type = 'string', fieldno = 3key_def = require('key_def')k = key_def.new({{type = 'string', fieldno = 3}})k:totable()
Начиная с: 3.1.0
Проверка, что все части указанного ключа соответствуют определению ключа. Частичные ключи считаются допустимыми. При успешном выполнении ничего не возвращает.
Если ключ не проходит проверку, вызывается исключение типа
box.error.
Пример:
-- 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 raisedtarantool> 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)'...
Начиная с: 3.1.0
Проверка, что переданный key содержит все поля и соответствует
правилам объекта определения ключа. При успешном выполнении ничего не
возвращает.
Если ключ не проходит проверку, вызывается исключение типа
box.error.
Пример:
-- Create a rule: key = {1 ('unsigned'), 2 (string)}-- Validate key {100, "Testuser"}. Returns nothing-- Validate key ({100}). ER_EXACT_MATCH is raisedtarantool> 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)'...
Начиная с: 3.1.0
Проверка, что tuple соответствует правилам объекта определения
ключа. При успешном выполнении ничего не возвращает.
Если ключ не проходит проверку, вызывается исключение типа
box.error.
Пример:
-- Create a rule: tuple = {id (number), name (string), age (number)}-- Validate tuple {1001, "Testuser", 28}. Returns nothingtarantool> 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})---...
Начиная с: 3.1.0
Сравнение двух ключей друг с другом согласно объекту определения ключа. При успешном выполнении возвращает:
<0, если частиkey_aменьше частейkey_b0, если частиkey_aравны частямkey_b>0, если частиkey_aбольше частейkey_b
Если какой-либо ключ не соответствует правилам определения ключа,
вызывается исключение типа box.error.
Пример:
-- 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 1tarantool> 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...