From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 975D96EC55; Fri, 16 Jul 2021 11:59:53 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 975D96EC55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1626425993; bh=Z22AV3ZPU0Bx2DPwAMUxKdryYHZPvUVTa/QEC0auJBM=; h=To:Cc:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=YPaudxfRjt/MqtDT2t0DnU5knoFx87rdvj/PQ0+EM5egxrvobG5tSQ+dwbe7LeWyv 3ziFtktFoE7q3OasSUczMAVGywwYsUHYPRfEEqk7XRAcPfijOo9iVSkwX2J3aeFoUM i+upOvuvtctsvvYauaPVbZIPcEW9YRvlLzgDC/wk= Received: from smtp55.i.mail.ru (smtp55.i.mail.ru [217.69.128.35]) (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 75D2A6EC57 for ; Fri, 16 Jul 2021 11:57:58 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 75D2A6EC57 Received: by smtp55.i.mail.ru with esmtpa (envelope-from ) id 1m4JfR-0006Go-PZ; Fri, 16 Jul 2021 11:57:58 +0300 To: tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Fri, 16 Jul 2021 11:57:57 +0300 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD941C43E597735A9C3038391AAE5FBFA76FBCFDED1455B43CD182A05F538085040A753095F61D660DF5CEEB2768537893A89C5148F9E04A2BA99CB1074828B1C0E X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE73B2A9F8A35432468EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637F898CA578D17CA188638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D864594CA482CA185ED4B765612A3D1E75117882F4460429724CE54428C33FAD305F5C1EE8F4F765FC8C7ADC89C2F0B2A5A471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352033AC447995A7AD18E5D25F19253116ADD2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE902A1BE408319B29C3123C4324A5CF10D8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE365B78C30F681404D302FCEF25BFAB345C4224003CC836476EA7A3FFF5B025636E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F79006377AA2284B41911753EFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CAA8DC07915BC95B7772B2E619A0BEF27A470F9935BA67D469C2B6934AE262D3EE7EAB7254005DCED114C52B35DBB74F4E7EAB7254005DCEDA5DF9383870C0FED1E0A4E2319210D9B64D260DF9561598F01A9E91200F654B06B3BBFFE09419C2B8E8E86DC7131B365E7726E8460B7C23C X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34A1AF43396E40A36FB9124C740D46D3F5AEA4E2FF5948E2CE1F0F55C87F032B43CC96DF8E3222FC851D7E09C32AA3244C3BF7FD751484C921DC8F09758DB5885763871F383B54D9B3729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojk34dk3RWCsbEE7MeMtuDuQ== X-Mailru-Sender: 5C3750E245F362008BC1685FEC6306EDC601625F31DF284C5CEEB2768537893A6ECF975C7BB2667F5105BD0848736F9966FEC6BF5C9C28D97E07721503EA2E00ED97202A5A4E92BF7402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v2 4/4] sql: introduce mem_cmp_msgpack() X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Mergen Imeev via Tarantool-patches Reply-To: imeevma@tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" This patch introduces the mem_cmp_msgpack() function that compares MEM and packed to msgpack value using SCALAR rules. MEM and packed value must be scalars. Prior to this patch, there was a function that used SCALAR rules to compare MEM and packed value, but its design became overly complex as new types appeared. Closes #6164 --- src/box/sql.c | 9 +- src/box/sql/mem.c | 289 +++++------------- src/box/sql/mem.h | 24 +- test/sql-tap/gh-6164-uuid-follow-ups.test.lua | 14 +- 4 files changed, 107 insertions(+), 229 deletions(-) diff --git a/src/box/sql.c b/src/box/sql.c index 790ca7f70..7471c3832 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -765,10 +765,13 @@ tarantoolsqlIdxKeyCompare(struct BtCursor *cursor, } } next_fieldno = fieldno + 1; - rc = sqlVdbeCompareMsgpack(&p, unpacked, i); + struct key_part *part = &unpacked->key_def->parts[i]; + struct Mem *mem = unpacked->aMem + i; + struct coll *coll = part->coll; + if (mem_cmp_msgpack(mem, &p, &rc, coll) != 0) + rc = 0; if (rc != 0) { - if (unpacked->key_def->parts[i].sort_order != - SORT_ORDER_ASC) + if (part->sort_order == SORT_ORDER_ASC) rc = -rc; goto out; } diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index a8cde6769..fa80f6d5a 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -2098,35 +2098,77 @@ mem_cmp_scalar(const struct Mem *a, const struct Mem *b, int *result, return 0; } -/* - * Both *pMem1 and *pMem2 contain string values. Compare the two values - * using the collation sequence pColl. As usual, return a negative , zero - * or positive value if *pMem1 is less than, equal to or greater than - * *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);". - * - * Strungs assume to be UTF-8 encoded - */ -static int -vdbeCompareMemString(const Mem * pMem1, const Mem * pMem2, - const struct coll * pColl) -{ - return pColl->cmp(pMem1->z, (size_t)pMem1->n, - pMem2->z, (size_t)pMem2->n, pColl); -} - -/* - * The input pBlob is guaranteed to be a Blob that is not marked - * with MEM_Zero. Return true if it could be a zero-blob. - */ -static int -isAllZero(const char *z, int n) -{ - int i; - for (i = 0; i < n; i++) { - if (z[i]) - return 0; +int +mem_cmp_msgpack(const struct Mem *a, const char **b, int *result, + const struct coll *coll) +{ + struct Mem mem; + switch (mp_typeof(**b)) { + case MP_NIL: + mem.type = MEM_TYPE_NULL; + mp_decode_nil(b); + break; + case MP_BOOL: + mem.type = MEM_TYPE_BOOL; + mem.u.b = mp_decode_bool(b); + break; + case MP_UINT: + mem.type = MEM_TYPE_UINT; + mem.u.u = mp_decode_uint(b); + break; + case MP_INT: + mem.type = MEM_TYPE_INT; + mem.u.i = mp_decode_int(b); + break; + case MP_FLOAT: + mem.type = MEM_TYPE_DOUBLE; + mem.u.r = mp_decode_float(b); + break; + case MP_DOUBLE: + mem.type = MEM_TYPE_DOUBLE; + mem.u.r = mp_decode_double(b); + break; + case MP_STR: + mem.type = MEM_TYPE_STR; + mem.n = mp_decode_strl(b); + mem.z = (char *)*b; + *b += mem.n; + mem.flags = MEM_Ephem; + break; + case MP_BIN: + mem.type = MEM_TYPE_BIN; + mem.n = mp_decode_binl(b); + mem.z = (char *)*b; + *b += mem.n; + mem.flags = MEM_Ephem; + break; + case MP_ARRAY: + case MP_MAP: + mp_next(b); + *result = -1; + return 0; + case MP_EXT: { + int8_t type; + const char *buf = *b; + uint32_t len = mp_decode_extl(b, &type); + if (type == MP_UUID) { + assert(len == UUID_LEN); + mem.type = MEM_TYPE_UUID; + if (uuid_unpack(b, len, &mem.u.uuid) == NULL) + return -1; + break; + } + *b += len; + mem.type = MEM_TYPE_BIN; + mem.z = (char *)buf; + mem.n = *b - buf; + mem.flags = MEM_Ephem; + break; } - return 1; + default: + unreachable(); + } + return mem_cmp_scalar(a, &mem, result, coll); } char * @@ -2557,183 +2599,6 @@ sql_vdbemem_finalize(struct Mem *mem, struct func *func) return ctx.is_aborted ? -1 : 0; } -int -sqlVdbeCompareMsgpack(const char **key1, - struct UnpackedRecord *unpacked, int key2_idx) -{ - const char *aKey1 = *key1; - Mem *pKey2 = unpacked->aMem + key2_idx; - Mem mem1; - int rc = 0; - switch (mp_typeof(*aKey1)) { - default:{ - /* FIXME */ - rc = -1; - break; - } - case MP_NIL:{ - rc = -(pKey2->type != MEM_TYPE_NULL); - mp_decode_nil(&aKey1); - break; - } - case MP_BOOL:{ - mem1.u.b = mp_decode_bool(&aKey1); - if (pKey2->type == MEM_TYPE_BOOL) { - if (mem1.u.b != pKey2->u.b) - rc = mem1.u.b ? 1 : -1; - } else { - rc = pKey2->type == MEM_TYPE_NULL ? 1 : -1; - } - break; - } - case MP_UINT:{ - mem1.u.u = mp_decode_uint(&aKey1); - if (pKey2->type == MEM_TYPE_INT) { - rc = +1; - } else if (pKey2->type == MEM_TYPE_UINT) { - if (mem1.u.u < pKey2->u.u) - rc = -1; - else if (mem1.u.u > pKey2->u.u) - rc = +1; - } else if (pKey2->type == MEM_TYPE_DOUBLE) { - rc = double_compare_uint64(pKey2->u.r, - mem1.u.u, -1); - } else if (pKey2->type == MEM_TYPE_NULL) { - rc = 1; - } else if (pKey2->type == MEM_TYPE_BOOL) { - rc = 1; - } else { - rc = -1; - } - break; - } - case MP_INT:{ - mem1.u.i = mp_decode_int(&aKey1); - if (pKey2->type == MEM_TYPE_UINT) { - rc = -1; - } else if (pKey2->type == MEM_TYPE_INT) { - if (mem1.u.i < pKey2->u.i) { - rc = -1; - } else if (mem1.u.i > pKey2->u.i) { - rc = +1; - } - } else if (pKey2->type == MEM_TYPE_DOUBLE) { - rc = double_compare_nint64(pKey2->u.r, mem1.u.i, - -1); - } else if (pKey2->type == MEM_TYPE_NULL) { - rc = 1; - } else if (pKey2->type == MEM_TYPE_BOOL) { - rc = 1; - } else { - rc = -1; - } - break; - } - case MP_FLOAT:{ - mem1.u.r = mp_decode_float(&aKey1); - goto do_float; - } - case MP_DOUBLE:{ - mem1.u.r = mp_decode_double(&aKey1); - do_float: - if (pKey2->type == MEM_TYPE_INT) { - rc = double_compare_nint64(mem1.u.r, pKey2->u.i, - 1); - } else if (pKey2->type == MEM_TYPE_UINT) { - rc = double_compare_uint64(mem1.u.r, - pKey2->u.u, 1); - } else if (pKey2->type == MEM_TYPE_DOUBLE) { - if (mem1.u.r < pKey2->u.r) { - rc = -1; - } else if (mem1.u.r > pKey2->u.r) { - rc = +1; - } - } else if (pKey2->type == MEM_TYPE_NULL) { - rc = 1; - } else if (pKey2->type == MEM_TYPE_BOOL) { - rc = 1; - } else { - rc = -1; - } - break; - } - case MP_STR:{ - if (pKey2->type == MEM_TYPE_STR) { - struct key_def *key_def = unpacked->key_def; - mem1.n = mp_decode_strl(&aKey1); - mem1.z = (char *)aKey1; - aKey1 += mem1.n; - struct coll *coll = - key_def->parts[key2_idx].coll; - if (coll != NULL) { - mem1.type = MEM_TYPE_STR; - mem1.flags = 0; - rc = vdbeCompareMemString(&mem1, pKey2, - coll); - } else { - goto do_bin_cmp; - } - } else { - rc = pKey2->type == MEM_TYPE_BIN ? -1 : +1; - } - break; - } - case MP_BIN:{ - mem1.n = mp_decode_binl(&aKey1); - mem1.z = (char *)aKey1; - aKey1 += mem1.n; - do_blob: - if (pKey2->type == MEM_TYPE_BIN) { - if (pKey2->flags & MEM_Zero) { - if (!isAllZero - ((const char *)mem1.z, mem1.n)) { - rc = 1; - } else { - rc = mem1.n - pKey2->u.nZero; - } - } else { - int nCmp; - do_bin_cmp: - nCmp = MIN(mem1.n, pKey2->n); - rc = memcmp(mem1.z, pKey2->z, nCmp); - if (rc == 0) - rc = mem1.n - pKey2->n; - } - } else { - rc = 1; - } - break; - } - case MP_ARRAY: - case MP_MAP: { - mem1.z = (char *)aKey1; - mp_next(&aKey1); - mem1.n = aKey1 - (char *)mem1.z; - goto do_blob; - } - case MP_EXT: { - int8_t type; - const char *buf = aKey1; - uint32_t len = mp_decode_extl(&aKey1, &type); - if (type == MP_UUID) { - assert(len == UUID_LEN); - mem1.type = MEM_TYPE_UUID; - aKey1 = buf; - if (mp_decode_uuid(&aKey1, &mem1.u.uuid) == NULL || - mem_cmp_uuid(&mem1, pKey2, &rc) != 0) - rc = 1; - break; - } - aKey1 += len; - mem1.z = (char *)buf; - mem1.n = aKey1 - buf; - goto do_blob; - } - } - *key1 = aKey1; - return rc; -} - int sqlVdbeRecordCompareMsgpack(const void *key1, struct UnpackedRecord *key2) @@ -2744,13 +2609,15 @@ sqlVdbeRecordCompareMsgpack(const void *key1, n = MIN(n, key2->nField); for (i = 0; i != n; i++) { - rc = sqlVdbeCompareMsgpack((const char**)&key1, key2, i); + struct key_part *part = &key2->key_def->parts[i]; + struct Mem *mem = key2->aMem + i; + struct coll *coll = part->coll; + if (mem_cmp_msgpack(mem, (const char **)&key1, &rc, coll) != 0) + rc = 0; if (rc != 0) { - if (key2->key_def->parts[i].sort_order != - SORT_ORDER_ASC) { - rc = -rc; - } - return rc; + if (part->sort_order != SORT_ORDER_ASC) + return rc; + return -rc; } } diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index dd8666f53..645d0ee27 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -706,6 +706,16 @@ int mem_cmp_scalar(const struct Mem *a, const struct Mem *b, int *result, const struct coll *coll); +/** + * Compare MEM and packed to msgpack value using SCALAR rules and return the + * result of comparison. Both values should be scalars. Original MEM is not + * changed. If successful, the second argument will contain the address + * following the specified packed value. + */ +int +mem_cmp_msgpack(const struct Mem *a, const char **b, int *result, + const struct coll *coll); + /** * Convert the given MEM to INTEGER. This function and the function below define * the rules that are used to convert values of all other types to INTEGER. In @@ -983,20 +993,6 @@ int sqlVdbeMemTooBig(Mem *); int sql_vdbemem_finalize(struct Mem *mem, struct func *func); -/** MEM and msgpack functions. */ - -/** - * Perform comparison of two keys: one is packed and one is not. - * - * @param key1 Pointer to pointer to first key. - * @param unpacked Pointer to unpacked tuple. - * @param key2_idx index of key in umpacked record to compare. - * - * @retval +1 if key1 > pUnpacked[iKey2], -1 ptherwise. - */ -int sqlVdbeCompareMsgpack(const char **key1, - struct UnpackedRecord *unpacked, int key2_idx); - /** * Perform comparison of two tuples: unpacked (key1) and packed (key2) * diff --git a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua index 6b4a811c3..dd041c0b4 100755 --- a/test/sql-tap/gh-6164-uuid-follow-ups.test.lua +++ b/test/sql-tap/gh-6164-uuid-follow-ups.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool local test = require("sqltester") -test:plan(8) +test:plan(9) -- Make sure that function quote() can work with uuid. test:do_execsql_test( @@ -76,6 +76,18 @@ test:do_execsql_test( 2 }) +box.execute([[DELETE FROM t;]]) + +box.execute([[INSERT INTO t VALUES (1, X'00'), (2, ?);]], {uuid1}) + +test:do_execsql_test( + "gh-6164-9", + [[ + SELECT i FROM t ORDER BY s; + ]], { + 1, 2 + }) + box.execute([[DROP TABLE t;]]) test:finish_test() -- 2.25.1