From: Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: imeevma@tarantool.org, tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCH v5 20/52] sql: introduce mem_compare() Date: Sun, 11 Apr 2021 20:16:30 +0200 [thread overview] Message-ID: <85edf743-dd85-d4f7-2aad-05802ea67e9e@tarantool.org> (raw) In-Reply-To: <5a71515faac5f305fc3bd1ebbc20d1dd65bf027c.1617984948.git.imeevma@gmail.com> Nice fixes! This is the last email for today, I will continue the review of the patchset tomorrow. See 6 comments below. > diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c > index 859e337aa..eee72a7fe 100644 > --- a/src/box/sql/mem.c > +++ b/src/box/sql/mem.c > @@ -624,6 +624,211 @@ mem_rem(const struct Mem *left, const struct Mem *right, struct Mem *result) > return 0; > } > > +static int > +compare_blobs(const struct Mem *a, const struct Mem *b, int *result) > +{ 1. Would be good to have an assertion here that both types are MEM_Blob. > + int an = a->n; > + int bn = b->n; > + int minlen = MIN(an, bn); > + > + /* > + * It is possible to have a Blob value that has some non-zero content > + * followed by zero content. But that only comes up for Blobs formed > + * by the OP_MakeRecord opcode, and such Blobs never get passed into > + * mem_compare(). > + */ > + assert((a->flags & MEM_Zero) == 0 || an == 0); > + assert((b->flags & MEM_Zero) == 0 || bn == 0); > + > + if ((a->flags & b->flags & MEM_Zero) != 0) { > + *result = a->u.nZero - b->u.nZero; > + return 0; > + } > + if ((a->flags & MEM_Zero) != 0) { > + for (int i = 0; i < minlen; ++i) { > + if (b->z[i] != 0) { > + *result = -1; > + return 0; > + } > + } > + *result = a->u.nZero - bn; > + return 0; > + } > + if ((b->flags & MEM_Zero) != 0) { > + for (int i = 0; i < minlen; ++i) { > + if (a->z[i] != 0){ > + *result = 1; > + return 0; > + } > + } > + *result = b->u.nZero - an; > + return 0; > + } > + *result = memcmp(a->z, b->z, minlen); > + if (*result != 0) > + return 0; > + *result = an - bn; > + return 0; 2. compare_blobs never fails. So you can drop result out argument and return the comparison result as 'return'. > +} > + > +static int > +compare_numbers(const struct Mem *left, const struct Mem *right, int *result) > +{ > + struct sql_num a, b; > + /* TODO: Here should be check for right value type. */ 3. What if 'b' is a string, which can't be converted to a number? > + if (get_number(right, &b) != 0) { > + *result = -1; > + return 0; > + } > + if (get_number(left, &a) != 0) {> + diag_set(ClientError, ER_SQL_TYPE_MISMATCH, mem_str(left), > + "numeric"); > + return -1; > + } > + if (a.type == MEM_Real) { > + if (b.type == MEM_Real) { > + if (a.d > b.d) > + *result = 1; > + else if (a.d < b.d) > + *result = -1; > + else > + *result = 0; > + return 0; > + } > + if (b.type == MEM_Int) > + *result = double_compare_nint64(a.d, b.i, 1); > + else > + *result = double_compare_uint64(a.d, b.u, 1); > + return 0; > + } > + if (a.type == MEM_Int) { > + if (b.type == MEM_Int) { > + if (a.i > b.i) > + *result = 1; > + else if (a.i < b.i) > + *result = -1; > + else > + *result = 0; > + return 0; > + } > + if (b.type == MEM_UInt) > + *result = -1; > + else > + *result = double_compare_nint64(b.d, a.i, -1); > + return 0; > + } > + assert(a.type == MEM_UInt); > + if (b.type == MEM_UInt) { > + if (a.u > b.u) > + *result = 1; > + else if (a.u < b.u) > + *result = -1; > + else > + *result = 0; > + return 0; > + } > + if (b.type == MEM_Int) > + *result = 1; > + else > + *result = double_compare_uint64(b.d, a.u, -1); > + return 0; > +} > + > +static int > +compare_strings(const struct Mem *left, const struct Mem *right, int *result, > + const struct coll *coll) > +{ > + char *a; > + uint32_t an; > + char bufl[BUF_SIZE]; > + if ((left->flags & MEM_Str) != 0) { > + a = left->z; > + an = left->n; > + } else { > + assert((left->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0); > + a = &bufl[0]; > + if ((left->flags & MEM_Int) != 0) > + sql_snprintf(BUF_SIZE, a, "%lld", left->u.i); > + else if ((left->flags & MEM_UInt) != 0) > + sql_snprintf(BUF_SIZE, a, "%llu", left->u.u); > + else > + sql_snprintf(BUF_SIZE, a, "%!.15g", left->u.r); > + an = strlen(a); > + } > + > + char *b; > + uint32_t bn; > + char bufr[BUF_SIZE]; > + if ((right->flags & MEM_Str) != 0) { > + b = right->z; > + bn = right->n; > + } else { > + assert((right->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0); > + b = &bufr[0]; > + if ((right->flags & MEM_Int) != 0) > + sql_snprintf(BUF_SIZE, b, "%lld", right->u.i); > + else if ((right->flags & MEM_UInt) != 0) > + sql_snprintf(BUF_SIZE, b, "%llu", right->u.u); > + else > + sql_snprintf(BUF_SIZE, b, "%!.15g", right->u.r); > + bn = strlen(b); > + } > + if (coll) { > + *result = coll->cmp(a, an, b, bn, coll); > + return 0; > + } > + uint32_t minlen = MIN(an, bn); > + *result = memcmp(a, b, minlen); > + if (*result != 0) > + return 0; > + *result = an - bn; > + return 0; 4. It can't fail either. You can return result as 'return'. > +} > + > +int > +mem_compare(const struct Mem *left, const struct Mem *right, int *result, > + enum field_type type, struct coll *coll) > +{ > + assert(((left->flags | right->flags) & MEM_Null) == 0); > + int flags_any = left->flags | right->flags; 5. 'any' isn't needed until the next branch. You can move it right above if ((flags_any & MEM_Bool) != 0) { > + int flags_all = left->flags & right->flags; > + > + if ((flags_all & MEM_Bool) != 0) { > + if (left->u.b == right->u.b) > + *result = 0; > + else if (left->u.b) > + *result = 1; > + else > + *result = -1; > + return 0; > + } > + if ((flags_any & MEM_Bool) != 0) { > + char *str = (left->flags & MEM_Bool) == 0 ? > + mem_type_to_str(left) : mem_type_to_str(right); > + diag_set(ClientError, ER_SQL_TYPE_MISMATCH, str, "boolean"); > + return -1; > + } > + > + if ((flags_all & MEM_Blob) != 0) > + return compare_blobs(left, right, result); > + if ((flags_any & MEM_Blob) != 0) { > + char *str = (left->flags & MEM_Blob) == 0 ? > + mem_type_to_str(left) : mem_type_to_str(right); > + diag_set(ClientError, ER_SQL_TYPE_MISMATCH, str, "varbinary"); > + return -1; > + } > + > + if (type == FIELD_TYPE_STRING) > + return compare_strings(left, right, result, coll); > + > + if (sql_type_is_numeric(type) || > + (flags_any & (MEM_Int | MEM_UInt | MEM_Real)) != 0) > + return compare_numbers(left, right, result); > + > + assert((left->flags & MEM_Str) != 0 && (right->flags & MEM_Str) != 0); > + return compare_strings(left, right, result, coll); > +} > diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h > index 69a7d9f7a..6c022d8d8 100644 > --- a/src/box/sql/mem.h > +++ b/src/box/sql/mem.h > @@ -226,6 +226,11 @@ mem_div(const struct Mem *left, const struct Mem *right, struct Mem *result); > int > mem_rem(const struct Mem *left, const struct Mem *right, struct Mem *result); > > +/** Compare two non-NULL MEMs and return the result of comparison. */ > +int > +mem_compare(const struct Mem *left, const struct Mem *right, int *result, > + enum field_type type, struct coll *coll); 6. What is 'type'? Can you keep it out of the comparator somehow? For example, make it 3 functions: mem_cmp_as_str, mem_cmp_as_num, and just a generic mem_cmp without any types calling the first 2 comparators. Otherwise the type thing is super ugly. It leaks the details of opcodes into mem.c.
next prev parent reply other threads:[~2021-04-11 18:16 UTC|newest] Thread overview: 107+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-04-09 16:51 [Tarantool-patches] [PATCH v5 00/52] Move mem-related functions to mem.c/mem.h Mergen Imeev via Tarantool-patches 2021-04-09 16:51 ` [Tarantool-patches] [PATCH v5 01/52] sql: enhance vdbe_decode_msgpack_into_mem() Mergen Imeev via Tarantool-patches 2021-04-11 17:42 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 12:01 ` Mergen Imeev via Tarantool-patches 2021-04-13 12:12 ` Mergen Imeev via Tarantool-patches 2021-04-13 23:22 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 23:34 ` Mergen Imeev via Tarantool-patches 2021-04-09 16:51 ` [Tarantool-patches] [PATCH v5 02/52] sql: disable unused code in sql/analyze.c Mergen Imeev via Tarantool-patches 2021-04-09 16:51 ` [Tarantool-patches] [PATCH v5 03/52] sql: disable unused code in sql/legacy.c Mergen Imeev via Tarantool-patches 2021-04-09 16:51 ` [Tarantool-patches] [PATCH v5 04/52] sql: remove NULL-termination in OP_ResultRow Mergen Imeev via Tarantool-patches 2021-04-14 22:23 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 22:37 ` Mergen Imeev via Tarantool-patches 2021-04-09 16:51 ` [Tarantool-patches] [PATCH v5 05/52] sql: move MEM-related functions to mem.c/mem.h Mergen Imeev via Tarantool-patches 2021-04-09 16:59 ` [Tarantool-patches] [PATCH v5 06/52] sql: refactor port_vdbemem_*() functions Mergen Imeev via Tarantool-patches 2021-04-09 16:59 ` [Tarantool-patches] [PATCH v5 07/52] sql: remove unused MEM-related functions Mergen Imeev via Tarantool-patches 2021-04-09 16:59 ` [Tarantool-patches] [PATCH v5 08/52] sql: disable unused code in sql/vdbemem.c Mergen Imeev via Tarantool-patches 2021-04-09 16:59 ` [Tarantool-patches] [PATCH v5 09/52] sql: introduce mem_str() Mergen Imeev via Tarantool-patches 2021-04-11 17:44 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 12:36 ` Mergen Imeev via Tarantool-patches 2021-04-14 22:23 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 22:42 ` Mergen Imeev via Tarantool-patches 2021-04-09 16:59 ` [Tarantool-patches] [PATCH v5 10/52] sql: introduce mem_create() Mergen Imeev via Tarantool-patches 2021-04-09 17:36 ` [Tarantool-patches] [PATCH v5 11/52] sql: introduce mem_destroy() Mergen Imeev via Tarantool-patches 2021-04-11 17:46 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 12:42 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:36 ` [Tarantool-patches] [PATCH v5 12/52] sql: introduce mem_is_*() functions() Mergen Imeev via Tarantool-patches 2021-04-11 17:59 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 16:09 ` Mergen Imeev via Tarantool-patches 2021-04-14 22:48 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 23:07 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:36 ` [Tarantool-patches] [PATCH v5 13/52] sql: introduce mem_copy() Mergen Imeev via Tarantool-patches 2021-04-11 18:06 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 16:18 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:36 ` [Tarantool-patches] [PATCH v5 14/52] sql: introduce mem_copy_as_ephemeral() Mergen Imeev via Tarantool-patches 2021-04-11 18:10 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 16:31 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:37 ` [Tarantool-patches] [PATCH v5 15/52] sql: rework mem_move() Mergen Imeev via Tarantool-patches 2021-04-11 18:10 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 16:38 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:57 ` [Tarantool-patches] [PATCH v5 16/52] sql: rework vdbe_decode_msgpack_into_mem() Mergen Imeev via Tarantool-patches 2021-04-09 17:57 ` [Tarantool-patches] [PATCH v5 17/52] sql: remove sql_column_to_messagepack() Mergen Imeev via Tarantool-patches 2021-04-14 22:58 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 23:14 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:57 ` [Tarantool-patches] [PATCH v5 18/52] sql: introduce mem_concat() Mergen Imeev via Tarantool-patches 2021-04-11 18:11 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 16:57 ` Mergen Imeev via Tarantool-patches 2021-04-14 23:04 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 23:22 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:57 ` [Tarantool-patches] [PATCH v5 19/52] sql: introduce arithmetic operations for MEM Mergen Imeev via Tarantool-patches 2021-04-11 18:13 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 17:06 ` Mergen Imeev via Tarantool-patches 2021-04-14 23:10 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 23:33 ` Mergen Imeev via Tarantool-patches 2021-04-09 17:57 ` [Tarantool-patches] [PATCH v5 20/52] sql: introduce mem_compare() Mergen Imeev via Tarantool-patches 2021-04-11 18:16 ` Vladislav Shpilevoy via Tarantool-patches [this message] 2021-04-13 18:33 ` Mergen Imeev via Tarantool-patches 2021-04-14 23:20 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-14 23:40 ` Mergen Imeev via Tarantool-patches 2021-04-09 18:11 ` [Tarantool-patches] [PATCH v5 21/52] sql: introduce bitwise operations for MEM Mergen Imeev via Tarantool-patches 2021-04-12 23:31 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 20:49 ` Mergen Imeev via Tarantool-patches 2021-04-09 18:11 ` [Tarantool-patches] [PATCH v5 22/52] sql: Initialize MEM in sqlVdbeAllocUnpackedRecord() Mergen Imeev via Tarantool-patches 2021-04-09 18:11 ` [Tarantool-patches] [PATCH v5 23/52] sql: introduce mem_set_null() Mergen Imeev via Tarantool-patches 2021-04-09 18:11 ` [Tarantool-patches] [PATCH v5 24/52] sql: introduce mem_set_int() Mergen Imeev via Tarantool-patches 2021-04-12 23:32 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 20:56 ` Mergen Imeev via Tarantool-patches 2021-04-09 18:11 ` [Tarantool-patches] [PATCH v5 25/52] sql: introduce mem_set_uint() Mergen Imeev via Tarantool-patches 2021-04-09 19:45 ` [Tarantool-patches] [PATCH v5 26/52] sql: move mem_set_bool() and mem_set_double() Mergen Imeev via Tarantool-patches 2021-04-09 19:45 ` [Tarantool-patches] [PATCH v5 27/52] sql: introduce mem_set_str_*() functions Mergen Imeev via Tarantool-patches 2021-04-12 23:34 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 21:36 ` Mergen Imeev via Tarantool-patches 2021-04-14 23:49 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-15 1:25 ` Mergen Imeev via Tarantool-patches 2021-04-09 19:45 ` [Tarantool-patches] [PATCH v5 28/52] sql: introduce mem_copy_str() and mem_copy_str0() Mergen Imeev via Tarantool-patches 2021-04-12 23:35 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:00 ` Mergen Imeev via Tarantool-patches 2021-04-14 23:54 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-15 0:30 ` Mergen Imeev via Tarantool-patches 2021-04-09 19:45 ` [Tarantool-patches] [PATCH v5 29/52] sql: introduce mem_set_bin_*() functions Mergen Imeev via Tarantool-patches 2021-04-09 19:45 ` [Tarantool-patches] [PATCH v5 30/52] sql: introduce mem_copy_bin() Mergen Imeev via Tarantool-patches 2021-04-12 23:36 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:06 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:05 ` [Tarantool-patches] [PATCH v5 31/52] sql: introduce mem_set_zerobin() Mergen Imeev via Tarantool-patches 2021-04-09 20:05 ` [Tarantool-patches] [PATCH v5 32/52] sql: introduce mem_set_*() for map and array Mergen Imeev via Tarantool-patches 2021-04-12 23:36 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:08 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:05 ` [Tarantool-patches] [PATCH v5 33/52] sql: introduce mem_set_invalid() Mergen Imeev via Tarantool-patches 2021-04-09 20:05 ` [Tarantool-patches] [PATCH v5 34/52] sql: refactor mem_set_ptr() Mergen Imeev via Tarantool-patches 2021-04-09 20:05 ` [Tarantool-patches] [PATCH v5 35/52] sql: introduce mem_set_frame() Mergen Imeev via Tarantool-patches 2021-04-12 23:37 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:19 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:25 ` [Tarantool-patches] [PATCH v5 36/52] sql: introduce mem_set_agg() Mergen Imeev via Tarantool-patches 2021-04-12 23:37 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:46 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:25 ` [Tarantool-patches] [PATCH v5 37/52] sql: introduce mem_set_null_clear() Mergen Imeev via Tarantool-patches 2021-04-12 23:38 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:50 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:25 ` [Tarantool-patches] [PATCH v5 38/52] sql: move MEM flags to mem.c Mergen Imeev via Tarantool-patches 2021-04-13 20:42 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:25 ` [Tarantool-patches] [PATCH v5 39/52] sql: introduce mem_to_int*() functions Mergen Imeev via Tarantool-patches 2021-04-12 23:39 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-13 22:58 ` Mergen Imeev via Tarantool-patches 2021-04-13 23:10 ` Mergen Imeev via Tarantool-patches 2021-04-09 20:26 ` [Tarantool-patches] [PATCH v5 40/52] sql: introduce mem_to_double() Mergen Imeev via Tarantool-patches 2021-04-13 23:21 ` Mergen Imeev via Tarantool-patches 2021-04-15 0:39 ` [Tarantool-patches] [PATCH v5 00/52] Move mem-related functions to mem.c/mem.h Vladislav Shpilevoy via Tarantool-patches 2021-04-15 6:49 ` Kirill Yukhin via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=85edf743-dd85-d4f7-2aad-05802ea67e9e@tarantool.org \ --to=tarantool-patches@dev.tarantool.org \ --cc=imeevma@tarantool.org \ --cc=tsafin@tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v5 20/52] sql: introduce mem_compare()' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox