From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp36.i.mail.ru (smtp36.i.mail.ru [94.100.177.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 9135A469719 for ; Wed, 11 Nov 2020 23:04:11 +0300 (MSK) From: olegrok@tarantool.org Date: Wed, 11 Nov 2020 23:04:08 +0300 Message-Id: <20201111200408.49148-1-olegrok@tarantool.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH] lua: introduce function for uuid comparison List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: v.shpilevoy@tarantool.org, lvasiliev@tarantool.org Cc: tarantool-patches@dev.tarantool.org From: Oleg Babin Since Tarantool has uuid data type sometimes we want to compare uuid vaues as it's possible for primitive types and decimals. This patch exports function for uuid comparison and implements le and lt metamethods for uuid type. To be consistent with decimal type this patch allows to compare uuid with uuid string representation. @TarantoolBot document Title: uuid compare Currently comparison between uuid values is supported. Example: ```lua u1 = uuid.fromstr('aaaaaaaa-aaaa-4000-b000-000000000001') u2 = uuid.fromstr('bbbbbbbb-bbbb-4000-b000-000000000001') u1 > u2 -- false u1 >= u2 -- false u1 <= u2 -- true u1 < u2 -- true -- Comparison with string uuid representation supported as well u1 > 'bbbbbbbb-bbbb-4000-b000-000000000001' -- false u1 < 'bbbbbbbb-bbbb-4000-b000-000000000001' -- true u1 < 'not-uuid-string' -- error ``` --- Issue: https://github.com/tarantool/tarantool/issues/5511 Branch: https://github.com/tarantool/tarantool/tree/olegrok/5511-uuid-cmp @Changelog: - Allow to compare uuid values (gh-5511) src/exports.h | 1 + src/lua/uuid.lua | 31 +++++++++++++ test/app/uuid.result | 98 ++++++++++++++++++++++++++++++++++++++++++ test/app/uuid.test.lua | 35 +++++++++++++++ 4 files changed, 165 insertions(+) diff --git a/src/exports.h b/src/exports.h index 867a027dc..ffbb84e3b 100644 --- a/src/exports.h +++ b/src/exports.h @@ -508,6 +508,7 @@ EXPORT(tnt_iconv_close) EXPORT(tnt_iconv_open) EXPORT(tt_uuid_bswap) EXPORT(tt_uuid_create) +EXPORT(tt_uuid_compare) EXPORT(tt_uuid_from_string) EXPORT(tt_uuid_is_equal) EXPORT(tt_uuid_is_nil) diff --git a/src/lua/uuid.lua b/src/lua/uuid.lua index 42016601d..0ab937877 100644 --- a/src/lua/uuid.lua +++ b/src/lua/uuid.lua @@ -19,6 +19,8 @@ bool tt_uuid_is_equal(const struct tt_uuid *lhs, const struct tt_uuid *rhs); char * tt_uuid_str(const struct tt_uuid *uu); +int +tt_uuid_compare(const struct tt_uuid *a, const struct tt_uuid *b); extern const struct tt_uuid uuid_nil; ]] @@ -118,9 +120,38 @@ local uuid_new_str = function() return uuid_tostring(uuidbuf) end +local check_uuid = function(value, index) + if is_uuid(value) then + return value + end + + if type(value) == 'string' then + value = uuid_fromstr(value) + if value ~= nil then + return value + end + end + + error(('incorrect value to convert to uuid as %d argument'):format(index), 0) +end + +local uuid_cmp = function(lhs, rhs) + lhs = check_uuid(lhs, 1) + rhs = check_uuid(rhs, 2) + return builtin.tt_uuid_compare(lhs, rhs) +end +local uuid_lt = function(lhs, rhs) + return uuid_cmp(lhs, rhs) < 0 +end +local uuid_le = function(lhs, rhs) + return uuid_cmp(lhs, rhs) <= 0 +end + local uuid_mt = { __tostring = uuid_tostring; __eq = uuid_eq; + __lt = uuid_lt; + __le = uuid_le; __index = { isnil = uuid_isnil; bin = uuid_tobin; -- binary host byteorder diff --git a/test/app/uuid.result b/test/app/uuid.result index 9fe0e7fb4..36388aed3 100644 --- a/test/app/uuid.result +++ b/test/app/uuid.result @@ -291,6 +291,104 @@ uuid.is_uuid(require('decimal').new('123')) --- - false ... +-- +-- gh-5511: allow to compare uuid values +-- +u1 = uuid.fromstr('aaaaaaaa-aaaa-4000-b000-000000000001') +--- +... +u2_str = 'bbbbbbbb-bbbb-4000-b000-000000000001' +--- +... +u2 = uuid.fromstr(u2_str) +--- +... +u1 > u1 +--- +- false +... +u1 >= u1 +--- +- true +... +u1 <= u1 +--- +- true +... +u1 < u1 +--- +- false +... +u1 > u2 +--- +- false +... +u1 >= u2 +--- +- false +... +u1 <= u2 +--- +- true +... +u1 < u2 +--- +- true +... +u1 > u2_str +--- +- false +... +u1 >= u2_str +--- +- false +... +u1 <= u2_str +--- +- true +... +u1 < u2_str +--- +- true +... +u1 < 1 +--- +- error: incorrect value to convert to uuid as 2 argument +... +u1 <= 1 +--- +- error: incorrect value to convert to uuid as 2 argument +... +u1 < 'abc' +--- +- error: incorrect value to convert to uuid as 2 argument +... +u1 <= 'abc' +--- +- error: incorrect value to convert to uuid as 2 argument +... +1 < u1 +--- +- error: incorrect value to convert to uuid as 1 argument +... +1 <= u1 +--- +- error: incorrect value to convert to uuid as 1 argument +... +'abc' < u1 +--- +- error: incorrect value to convert to uuid as 1 argument +... +'abc' <= u1 +--- +- error: incorrect value to convert to uuid as 1 argument +... +u1 = nil +--- +... +u2 = nil +--- +... uuid = nil --- ... diff --git a/test/app/uuid.test.lua b/test/app/uuid.test.lua index 47a96f3c6..5a57976e1 100644 --- a/test/app/uuid.test.lua +++ b/test/app/uuid.test.lua @@ -108,6 +108,41 @@ uuid.is_uuid(uuid.new():str()) uuid.is_uuid(1) uuid.is_uuid(require('decimal').new('123')) +-- +-- gh-5511: allow to compare uuid values +-- + +u1 = uuid.fromstr('aaaaaaaa-aaaa-4000-b000-000000000001') +u2_str = 'bbbbbbbb-bbbb-4000-b000-000000000001' +u2 = uuid.fromstr(u2_str) + +u1 > u1 +u1 >= u1 +u1 <= u1 +u1 < u1 + +u1 > u2 +u1 >= u2 +u1 <= u2 +u1 < u2 + +u1 > u2_str +u1 >= u2_str +u1 <= u2_str +u1 < u2_str + +u1 < 1 +u1 <= 1 +u1 < 'abc' +u1 <= 'abc' +1 < u1 +1 <= u1 +'abc' < u1 +'abc' <= u1 + +u1 = nil +u2 = nil + uuid = nil test_run:cmd("clear filter") -- 2.29.0