[Tarantool-patches] [PATCH v5 12/52] sql: introduce mem_is_*() functions()
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Sun Apr 11 20:59:05 MSK 2021
Thanks for the fixes!
>> For the integers we have several functions because we split
>> unsigned, signed, and always negative integers. So we would
>> need more int-like names. For instance,
>>
>> mem_set_uint(uint64_t) - for MEM_UInt.
>> mem_set_nint(int64_t) - for MEM_Int.
>> mem_set_int(int64_t) - for both, checks the sign inside.
>> mem_set_sint(int64_t, bool) - for both, takes the sign flag
>> in the second argument
>>
>> This can be discussed. The main point - shorter is better IMO.
>>
> I do not hink that splitting is needed. I see it more like field_type -> name of
> function + some functions for internal use.
This does not work already, because MEM_Int != FIELD_TYPE_INTEGER and
mem_is_int() does not check for MEM_Int only.
>>> }
>>> }
>>> diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
>>> index ec6aaab64..abc9291ef 100644
>>> --- a/src/box/sql/mem.c
>>> +++ b/src/box/sql/mem.c
>>> @@ -37,6 +37,142 @@
>>> #include "box/tuple.h"
>>> #include "mpstream/mpstream.h"
>>>
>>> +bool
>>> +mem_is_null(const struct Mem *mem)
>>> +{
>>> + return (mem->flags & MEM_Null) != 0;
>>> +}
>>
>> 4. Maybe better move them all to mem.h. These one-liners easily
>> can be inlined (the ones which are <= 3 lines long could be moved).
>>
> In one of the patches I move MEM types to mem.c so they are not visible from
> outside anymore. I think it is right way, at least for now. We may return
> MEM types back after we convert them to enum, so there won't be a possiblity
> of setting two or more MEM types at the same moment.
But there is now already. AFAIS, MEM_Str might be set along with some
other type. Or was it fixed somewhere in this patchset? See one of
my comments below.
>>> +}
>>> +
>>> +bool
>>> +mem_is_frame(const struct Mem *mem)
>>> +{
>>> + return (mem->flags & MEM_Frame) != 0;
>>> +}
>>> +
>>> +bool
>>> +mem_is_undefined(const struct Mem *mem)
>>> +{
>>> + return (mem->flags & MEM_Undefined) != 0;
>>> +}
>>> +
>>> +bool
>>> +mem_is_static(const struct Mem *mem)
>>> +{
>>> + return (mem->flags & (MEM_Str | MEM_Blob)) != 0 &&
>>> + (mem->flags & MEM_Static) != 0;
>>> +}
>>> +
>>> +bool
>>> +mem_is_ephemeral(const struct Mem *mem)
>>> +{
>>> + return (mem->flags & (MEM_Str | MEM_Blob)) != 0 &&
>>> + (mem->flags & MEM_Ephem) != 0;
>>
>> 7. How can it be that MEM_Ephem is set, but Str/Blob are not?
>>
> There is actually a possiblity. After sqlVdbeMemAboutToChange() is called MEM
> may become invalid after which MEM_Undefined is changed to MEM_Ephem and then
Where is undefined changed to ephem?
> MEM become valid again. For now I disable this SCopyFrom mechanism, but did
> not remove it completely. May be we will enable it later.
<...>
See 4 comments below.
> diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
> index 805dc7054..25b2e75ee 100644
> --- a/src/box/sql/mem.c
> +++ b/src/box/sql/mem.c
> @@ -40,6 +40,149 @@
<...>
> +
> +bool
> +mem_is_map(const struct Mem *mem)
> +{
> + return (mem->flags & MEM_Blob) != 0 &&
> + (mem->flags & MEM_Subtype) != 0 &&
1. You could check that in one operation:
(mem->flags & (MEM_Blob | MEM_Subtype)) == (MEM_Blob | MEM_Subtype)
> + mem->subtype == SQL_SUBTYPE_MSGPACK &&
> + mp_typeof(*mem->z) == MP_MAP;
> +}
<...>
> +
> +bool
> +mem_is_cleared(const struct Mem *mem)
> +{
> + return (mem->flags & MEM_Null) != 0 && (mem->flags & MEM_Cleared) != 0;
2. Can be 1 operation:
(mem->flags & (MEM_Null | MEM_Cleared)) == (MEM_Null | MEM_Cleared)
But another question is how is it possible that Cleared is set, but
Null isn't?
> +}
> +
> +bool
> +mem_is_zerobin(const struct Mem *mem)
> +{
> + return (mem->flags & MEM_Blob) != 0 && (mem->flags & MEM_Zero) != 0;
3. The same, can be done in one operation. And the same question - how is it
possible that Zero is set, but Blob isn't?
> +}
> diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
> index 7cc72dc38..f054a0f43 100644
> --- a/src/box/sql/vdbe.c
> +++ b/src/box/sql/vdbe.c> @@ -1884,21 +1868,13 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
> goto compare_op;
> }
> } else if (type == FIELD_TYPE_STRING) {
> - if ((flags1 & MEM_Str) == 0 &&
> - (flags1 & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
> - testcase( pIn1->flags & MEM_Int);
> - testcase( pIn1->flags & MEM_Real);
> + if (!mem_is_str(pIn1) && mem_is_num(pIn1)) {
4. Are going to do anything with that hack when a string can be stored in
the same mem as the original value? Otherwise you can see yourself how
ugly and confusing the 'mem_is' checks might look.
Besides, all the mem functions doing something with the mem based on its
pure types mask won't work on such mutant mems I suppose. Because there
is more than 1 type.
More information about the Tarantool-patches
mailing list