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 F14146C1AE; Thu, 20 May 2021 11:26:06 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org F14146C1AE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1621499167; bh=w4OEVVozhiLuYETpif1APMlK6jN3dKsmh2kNUYmCgRg=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=QKTxs3xtiArcK+iUfxOHJ9KpgRCfhsqPDEbJniV0j8RhJ1diEY0OZFNDSP7ivKLuU pC7hHBq1YLlbDAIqwBKGCb6F07/nRi1h0QlA9/l9Q+ktxLOvZMA9vV9s+Pwx3ddlXJ NpjEIa6WSW7tWjvGe9o6dABHAr95s/3QG61J2OCg= Received: from smtp45.i.mail.ru (smtp45.i.mail.ru [94.100.177.105]) (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 7406E6C1AE for ; Thu, 20 May 2021 11:26:05 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 7406E6C1AE Received: by smtp45.i.mail.ru with esmtpa (envelope-from ) id 1lje0K-00062h-Cj; Thu, 20 May 2021 11:26:04 +0300 Date: Thu, 20 May 2021 11:26:03 +0300 To: v.shpilevoy@tarantool.org, tarantool-patches@dev.tarantool.org Message-ID: <20210520082603.GA19422@tarantool.org> References: <9f3ee5e450d2e133bae1e0c131246b1f113f5608.1619182541.git.imeevma@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <9f3ee5e450d2e133bae1e0c131246b1f113f5608.1619182541.git.imeevma@gmail.com> X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD91B019B01C53E51AF9055931F25A1C7413A6B5BA1B6C38DA100894C459B0CD1B9BE6098352C34A0D21A0C17F657E5F0CB487EBAEDF80D21F394B48DAF27F3F842 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE705B093C0FC4B30B9EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637CDA1F22AAA442F218638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D85D6B196107B8E59486559043FEA5FBED117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8B974A882099E279BDA471835C12D1D977C4224003CC836476EB9C4185024447017B076A6E789B0E975F5C1EE8F4F765FC026AE486969454463AA81AA40904B5D9CF19DD082D7633A078D18283394535A93AA81AA40904B5D98AA50765F7900637F67BC5A37083E0DFD81D268191BDAD3D698AB9A7B718F8C4D1B931868CE1C5781A620F70A64A45A98AA50765F79006372E808ACE2090B5E1725E5C173C3A84C3C5EA940A35A165FF2DBA43225CD8A89F83C798A30B85E16B57739F23D657EF2BB5C8C57E37DE458BEDA766A37F9254B7 X-C1DE0DAB: 0D63561A33F958A597D7B0369A4D3FB8DB9DEBE5A2C5A3EB9D7598CF883A1240D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA752546FE575EB473F1410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D341B5517184E88C1BDA84D80C3ADAC21F9E9EB240B9D0C48C6B0EE553EAD88D53DF138F6CF909BCE901D7E09C32AA3244C631F8B5EDD17A986475D04EF8A37E4501E098CBE561D6343729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojF35yOkZDoIXQIDnCsAP4Jw== X-Mailru-Sender: 11C2EC085EDE56FAC07928AF2646A7697E848CA27B0F65771C225795D2F898B87AD558DE3329E3445105BD0848736F9966FEC6BF5C9C28D97E07721503EA2E00ED97202A5A4E92BF7402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH 1/1] sql: replace MEM-type flags by enum mem_type 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: Mergen Imeev Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Hi! I removed MEM_TYPE_FLOAT since there is no values with such field type. It appeared when I tried to match enum mem_type to enum mp_type. Diff below. Diff: diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index f855c111f..f7788021d 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -1974,8 +1974,6 @@ mem_mp_type(struct Mem *mem) return MP_MAP; case MEM_TYPE_BOOL: return MP_BOOL; - case MEM_TYPE_FLOAT: - return MP_FLOAT; case MEM_TYPE_DOUBLE: return MP_DOUBLE; default: diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 204d98129..15d97da0e 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -46,12 +46,11 @@ enum mem_type { MEM_TYPE_ARRAY = 1 << 5, MEM_TYPE_MAP = 1 << 6, MEM_TYPE_BOOL = 1 << 7, - MEM_TYPE_FLOAT = 1 << 8, - MEM_TYPE_DOUBLE = 1 << 9, - MEM_TYPE_INVALID = 1 << 10, - MEM_TYPE_FRAME = 1 << 11, - MEM_TYPE_PTR = 1 << 12, - MEM_TYPE_AGG = 1 << 13, + MEM_TYPE_DOUBLE = 1 << 8, + MEM_TYPE_INVALID = 1 << 9, + MEM_TYPE_FRAME = 1 << 10, + MEM_TYPE_PTR = 1 << 11, + MEM_TYPE_AGG = 1 << 12, }; /* On Fri, Apr 23, 2021 at 03:57:29PM +0300, Mergen Imeev via Tarantool-patches wrote: > This patch moves MEM types from the 'u32 flags' field to the new > 'enum mem_type type' field. Now, we can be sure that only one type is > set for MEM. In addition, it is now easier to distinguish MAP and ARRAY > from VARBINARY, and this makes it easier to add extension types - UUID > and DECIMAL. > > Closes #4906 > Needed for #5886 > --- > https://github.com/tarantool/tarantool/issues/4906 > https://github.com/tarantool/tarantool/tree/imeevma/gh-4906-rework-mem-types > > src/box/sql/func.c | 12 +- > src/box/sql/mem.c | 959 +++++++++++++++++++++++------------------- > src/box/sql/mem.h | 138 +++--- > src/box/sql/vdbemem.c | 3 +- > 4 files changed, 594 insertions(+), 518 deletions(-) > > diff --git a/src/box/sql/func.c b/src/box/sql/func.c > index 9c28d5122..2ce7a3871 100644 > --- a/src/box/sql/func.c > +++ b/src/box/sql/func.c > @@ -1766,14 +1766,20 @@ minmaxStep(sql_context * context, int NotUsed, sql_value ** argv) > > struct func_sql_builtin *func = > (struct func_sql_builtin *)context->func; > + /* > + * TODO: Make proper initialization for aggregate accumulation > + * structures. Currently a hack is applied here: in case mem pBest is a > + * newly created MEM, it bytes are set to 0 using memset(). Since > + * MEM_NULL == 0, it works. However, it does not look right. > + */ > pBest = (Mem *) sql_aggregate_context(context, sizeof(*pBest)); > if (!pBest) > return; > > if (mem_is_null(argv[0])) { > - if (pBest->flags) > + if (!mem_is_null(pBest)) > sqlSkipAccumulatorLoad(context); > - } else if (pBest->flags) { > + } else if (!mem_is_null(pBest)) { > int cmp; > struct coll *pColl = sqlGetFuncCollSeq(context); > /* > @@ -1801,7 +1807,7 @@ minMaxFinalize(sql_context * context) > sql_value *pRes; > pRes = (sql_value *) sql_aggregate_context(context, 0); > if (pRes) { > - if (pRes->flags) { > + if (!mem_is_null(pRes)) { > sql_result_value(context, pRes); > } > mem_destroy(pRes); > diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c > index b6ff6397f..90883ee21 100644 > --- a/src/box/sql/mem.c > +++ b/src/box/sql/mem.c > @@ -60,26 +60,26 @@ const char * > mem_str(const struct Mem *mem) > { > char buf[BUF_SIZE]; > - switch (mem->flags & MEM_PURE_TYPE_MASK) { > - case MEM_Null: > + switch (mem->type) { > + case MEM_NULL: > return "NULL"; > - case MEM_Str: > + case MEM_STR: > if ((mem->flags & MEM_Term) != 0) > return mem->z; > return tt_cstr(mem->z, mem->n); > - case MEM_Int: > + case MEM_INT: > return tt_sprintf("%lld", mem->u.i); > - case MEM_UInt: > + case MEM_UINT: > return tt_sprintf("%llu", mem->u.u); > - case MEM_Real: > + case MEM_DOUBLE: > sql_snprintf(BUF_SIZE, &buf[0], "%!.15g", mem->u.r); > return tt_sprintf("%s", buf); > - case MEM_Blob: > - if ((mem->flags & MEM_Subtype) == 0) > - return "varbinary"; > - assert(mem->subtype == SQL_SUBTYPE_MSGPACK); > + case MEM_BIN: > + return "varbinary"; > + case MEM_MAP: > + case MEM_ARRAY: > return mp_str(mem->z); > - case MEM_Bool: > + case MEM_BOOL: > return mem->u.b ? "TRUE" : "FALSE"; > default: > return "unknown"; > @@ -89,8 +89,8 @@ mem_str(const struct Mem *mem) > void > mem_create(struct Mem *mem) > { > - mem->flags = MEM_Null; > - mem->subtype = SQL_SUBTYPE_NO; > + mem->type = MEM_NULL; > + mem->flags = 0; > mem->field_type = field_type_MAX; > mem->n = 0; > mem->z = NULL; > @@ -108,20 +108,19 @@ mem_create(struct Mem *mem) > static inline void > mem_clear(struct Mem *mem) > { > - if ((mem->flags & (MEM_Agg | MEM_Dyn | MEM_Frame)) != 0) { > - if ((mem->flags & MEM_Agg) != 0) > - sql_vdbemem_finalize(mem, mem->u.func); > - assert((mem->flags & MEM_Agg) == 0); > - if ((mem->flags & MEM_Dyn) != 0) { > - assert(mem->xDel != SQL_DYNAMIC && mem->xDel != NULL); > - mem->xDel((void *)mem->z); > - } else if ((mem->flags & MEM_Frame) != 0) { > - struct VdbeFrame *frame = mem->u.pFrame; > - frame->pParent = frame->v->pDelFrame; > - frame->v->pDelFrame = frame; > - } > - } > - mem->flags = MEM_Null; > + if (mem->type == MEM_AGG) { > + sql_vdbemem_finalize(mem, mem->u.func); > + assert(mem->type != MEM_AGG); > + } else if (mem->type == MEM_FRAME) { > + struct VdbeFrame *frame = mem->u.pFrame; > + frame->pParent = frame->v->pDelFrame; > + frame->v->pDelFrame = frame; > + } else if ((mem->flags & MEM_Dyn) != 0) { > + assert(mem->xDel != SQL_DYNAMIC && mem->xDel != NULL); > + mem->xDel((void *)mem->z); > + } > + mem->type = MEM_NULL; > + mem->flags = 0; > mem->field_type = field_type_MAX; > } > > @@ -149,7 +148,8 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg) > { > mem_clear(mem); > mem->u.i = value; > - mem->flags = is_neg ? MEM_Int : MEM_UInt; > + mem->type = is_neg ? MEM_INT : MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_INTEGER; > } > > @@ -158,7 +158,8 @@ mem_set_uint(struct Mem *mem, uint64_t value) > { > mem_clear(mem); > mem->u.u = value; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_UNSIGNED; > } > > @@ -167,7 +168,8 @@ mem_set_bool(struct Mem *mem, bool value) > { > mem_clear(mem); > mem->u.b = value; > - mem->flags = MEM_Bool; > + mem->type = MEM_BOOL; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_BOOLEAN; > } > > @@ -179,7 +181,8 @@ mem_set_double(struct Mem *mem, double value) > if (sqlIsNaN(value)) > return; > mem->u.r = value; > - mem->flags = MEM_Real; > + mem->type = MEM_DOUBLE; > + mem->flags = 0; > } > > static inline void > @@ -189,7 +192,8 @@ set_str_const(struct Mem *mem, char *value, uint32_t len, int alloc_type) > mem_clear(mem); > mem->z = value; > mem->n = len; > - mem->flags = MEM_Str | alloc_type; > + mem->type = MEM_STR; > + mem->flags = alloc_type; > mem->field_type = FIELD_TYPE_STRING; > } > > @@ -202,7 +206,8 @@ set_str_dynamic(struct Mem *mem, char *value, uint32_t len, int alloc_type) > mem_destroy(mem); > mem->z = value; > mem->n = len; > - mem->flags = MEM_Str | alloc_type; > + mem->type = MEM_STR; > + mem->flags = alloc_type; > mem->field_type = FIELD_TYPE_STRING; > if (alloc_type == MEM_Dyn) { > mem->xDel = sql_free; > @@ -268,11 +273,12 @@ mem_set_str0_allocated(struct Mem *mem, char *value) > int > mem_copy_str(struct Mem *mem, const char *value, uint32_t len) > { > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0 && mem->z == value) { > + if ((mem->type == MEM_STR || mem->type == MEM_BIN) && mem->z == value) { > /* Own value, but might be ephemeral. Make it own if so. */ > if (sqlVdbeMemGrow(mem, len, 1) != 0) > return -1; > - mem->flags = MEM_Str; > + mem->type = MEM_STR; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_STRING; > return 0; > } > @@ -281,7 +287,8 @@ mem_copy_str(struct Mem *mem, const char *value, uint32_t len) > return -1; > memcpy(mem->z, value, len); > mem->n = len; > - mem->flags = MEM_Str; > + mem->type = MEM_STR; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_STRING; > return 0; > } > @@ -304,7 +311,8 @@ set_bin_const(struct Mem *mem, char *value, uint32_t size, int alloc_type) > mem_clear(mem); > mem->z = value; > mem->n = size; > - mem->flags = MEM_Blob | alloc_type; > + mem->type = MEM_BIN; > + mem->flags = alloc_type; > mem->field_type = FIELD_TYPE_VARBINARY; > } > > @@ -317,7 +325,8 @@ set_bin_dynamic(struct Mem *mem, char *value, uint32_t size, int alloc_type) > mem_destroy(mem); > mem->z = value; > mem->n = size; > - mem->flags = MEM_Blob | alloc_type; > + mem->type = MEM_BIN; > + mem->flags = alloc_type; > mem->field_type = FIELD_TYPE_VARBINARY; > if (alloc_type == MEM_Dyn) { > mem->xDel = sql_free; > @@ -355,11 +364,12 @@ mem_set_bin_allocated(struct Mem *mem, char *value, uint32_t size) > int > mem_copy_bin(struct Mem *mem, const char *value, uint32_t size) > { > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0 && mem->z == value) { > + if ((mem->type == MEM_STR || mem->type == MEM_BIN) && mem->z == value) { > /* Own value, but might be ephemeral. Make it own if so. */ > if (sqlVdbeMemGrow(mem, size, 1) != 0) > return -1; > - mem->flags = MEM_Blob; > + mem->type = MEM_BIN; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_VARBINARY; > return 0; > } > @@ -368,7 +378,8 @@ mem_copy_bin(struct Mem *mem, const char *value, uint32_t size) > return -1; > memcpy(mem->z, value, size); > mem->n = size; > - mem->flags = MEM_Blob; > + mem->type = MEM_BIN; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_VARBINARY; > return 0; > } > @@ -382,7 +393,8 @@ mem_set_zerobin(struct Mem *mem, int n) > mem->u.nZero = n; > mem->z = NULL; > mem->n = 0; > - mem->flags = MEM_Blob | MEM_Zero; > + mem->type = MEM_BIN; > + mem->flags = MEM_Zero; > mem->field_type = FIELD_TYPE_VARBINARY; > } > > @@ -390,12 +402,12 @@ static inline void > set_msgpack_value(struct Mem *mem, char *value, uint32_t size, int alloc_type, > enum field_type type) > { > + assert(type == FIELD_TYPE_MAP || type == FIELD_TYPE_ARRAY); > if (alloc_type == MEM_Ephem || alloc_type == MEM_Static) > set_bin_const(mem, value, size, alloc_type); > else > set_bin_dynamic(mem, value, size, alloc_type); > - mem->flags |= MEM_Subtype; > - mem->subtype = SQL_SUBTYPE_MSGPACK; > + mem->type = type == FIELD_TYPE_MAP ? MEM_MAP : MEM_ARRAY; > mem->field_type = type; > } > > @@ -459,14 +471,16 @@ void > mem_set_invalid(struct Mem *mem) > { > mem_clear(mem); > - mem->flags = MEM_Undefined; > + mem->type = MEM_INVALID; > + mem->flags = 0; > } > > void > mem_set_ptr(struct Mem *mem, void *ptr) > { > mem_clear(mem); > - mem->flags = MEM_Ptr; > + mem->type = MEM_PTR; > + mem->flags = 0; > mem->u.p = ptr; > } > > @@ -474,7 +488,8 @@ void > mem_set_frame(struct Mem *mem, struct VdbeFrame *frame) > { > mem_clear(mem); > - mem->flags = MEM_Frame; > + mem->type = MEM_FRAME; > + mem->flags = 0; > mem->u.pFrame = frame; > } > > @@ -488,7 +503,8 @@ mem_set_agg(struct Mem *mem, struct func *func, int size) > return -1; > memset(mem->z, 0, size); > mem->n = size; > - mem->flags = MEM_Agg; > + mem->type = MEM_AGG; > + mem->flags = 0; > mem->u.func = func; > mem->field_type = field_type_MAX; > return 0; > @@ -498,19 +514,21 @@ void > mem_set_null_clear(struct Mem *mem) > { > mem_clear(mem); > - mem->flags = MEM_Null | MEM_Cleared; > + mem->flags = MEM_Cleared; > } > > static inline int > int_to_double(struct Mem *mem) > { > + assert(mem->type == MEM_INT || mem->type == MEM_UINT); > double d; > - if ((mem->flags & MEM_UInt) != 0) > + if (mem->type == MEM_UINT) > d = (double)mem->u.u; > else > d = (double)mem->u.i; > mem->u.r = d; > - mem->flags = MEM_Real; > + mem->type = MEM_DOUBLE; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_DOUBLE; > return 0; > } > @@ -518,8 +536,9 @@ int_to_double(struct Mem *mem) > static inline int > int_to_str0(struct Mem *mem) > { > + assert(mem->type == MEM_INT || mem->type == MEM_UINT); > const char *str; > - if ((mem->flags & MEM_UInt) != 0) > + if (mem->type == MEM_UINT) > str = tt_sprintf("%llu", mem->u.u); > else > str = tt_sprintf("%lld", mem->u.i); > @@ -529,8 +548,10 @@ int_to_str0(struct Mem *mem) > static inline int > int_to_bool(struct Mem *mem) > { > + assert(mem->type == MEM_INT || mem->type == MEM_UINT); > mem->u.b = mem->u.i != 0; > - mem->flags = MEM_Bool; > + mem->type = MEM_BOOL; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_BOOLEAN; > return 0; > } > @@ -538,7 +559,7 @@ int_to_bool(struct Mem *mem) > static inline int > str_to_str0(struct Mem *mem) > { > - assert((mem->flags | MEM_Str) != 0); > + assert(mem->type == MEM_STR); > if (sqlVdbeMemGrow(mem, mem->n + 1, 1) != 0) > return -1; > mem->z[mem->n] = '\0'; > @@ -550,8 +571,9 @@ str_to_str0(struct Mem *mem) > static inline int > str_to_bin(struct Mem *mem) > { > - mem->flags = (mem->flags & (MEM_Dyn | MEM_Static | MEM_Ephem)) | > - MEM_Blob; > + assert(mem->type == MEM_STR); > + mem->type = MEM_BIN; > + mem->flags = mem->flags & (MEM_Dyn | MEM_Static | MEM_Ephem); > mem->field_type = FIELD_TYPE_VARBINARY; > return 0; > } > @@ -559,6 +581,7 @@ str_to_bin(struct Mem *mem) > static inline int > str_to_bool(struct Mem *mem) > { > + assert(mem->type == MEM_STR); > char *str = mem->z; > bool b; > const char *str_true = "TRUE"; > @@ -586,10 +609,11 @@ str_to_bool(struct Mem *mem) > static inline int > bin_to_str(struct Mem *mem) > { > + assert(mem->type == MEM_BIN); > if (ExpandBlob(mem) != 0) > return -1; > - mem->flags = (mem->flags & (MEM_Dyn | MEM_Static | MEM_Ephem)) | > - MEM_Str; > + mem->type = MEM_STR; > + mem->flags = mem->flags & (MEM_Dyn | MEM_Static | MEM_Ephem); > mem->field_type = FIELD_TYPE_STRING; > return 0; > } > @@ -597,12 +621,14 @@ bin_to_str(struct Mem *mem) > static inline int > bin_to_str0(struct Mem *mem) > { > + assert(mem->type == MEM_BIN); > if (ExpandBlob(mem) != 0) > return -1; > if (sqlVdbeMemGrow(mem, mem->n + 1, 1) != 0) > return -1; > mem->z[mem->n] = '\0'; > - mem->flags = MEM_Str | MEM_Term; > + mem->type = MEM_STR; > + mem->flags = MEM_Term; > mem->field_type = FIELD_TYPE_STRING; > return 0; > } > @@ -610,6 +636,7 @@ bin_to_str0(struct Mem *mem) > static inline int > bytes_to_int(struct Mem *mem) > { > + assert(mem->type == MEM_STR || mem->type == MEM_BIN); > bool is_neg; > int64_t i; > if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) > @@ -621,6 +648,7 @@ bytes_to_int(struct Mem *mem) > static inline int > bytes_to_uint(struct Mem *mem) > { > + assert(mem->type == MEM_STR || mem->type == MEM_BIN); > bool is_neg; > int64_t i; > if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) > @@ -634,6 +662,7 @@ bytes_to_uint(struct Mem *mem) > static inline int > bytes_to_double(struct Mem *mem) > { > + assert(mem->type == MEM_STR || mem->type == MEM_BIN); > double d; > if (sqlAtoF(mem->z, &d, mem->n) == 0) > return -1; > @@ -644,16 +673,19 @@ bytes_to_double(struct Mem *mem) > static inline int > double_to_int(struct Mem *mem) > { > + assert(mem->type == MEM_DOUBLE); > double d = mem->u.r; > if (d < 0 && d >= (double)INT64_MIN) { > mem->u.i = (int64_t)d; > - mem->flags = MEM_Int; > + mem->type = MEM_INT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_INTEGER; > return 0; > } > if (d >= 0 && d < (double)UINT64_MAX) { > mem->u.u = (uint64_t)d; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_UNSIGNED; > return 0; > } > @@ -663,16 +695,19 @@ double_to_int(struct Mem *mem) > static inline int > double_to_int_precise(struct Mem *mem) > { > + assert(mem->type == MEM_DOUBLE); > double d = mem->u.r; > if (d < 0 && d >= (double)INT64_MIN && (double)(int64_t)d == d) { > mem->u.i = (int64_t)d; > - mem->flags = MEM_Int; > + mem->type = MEM_INT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_INTEGER; > return 0; > } > if (d >= 0 && d < (double)UINT64_MAX && (double)(uint64_t)d == d) { > mem->u.u = (uint64_t)d; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_UNSIGNED; > return 0; > } > @@ -682,10 +717,12 @@ double_to_int_precise(struct Mem *mem) > static inline int > double_to_uint(struct Mem *mem) > { > + assert(mem->type == MEM_DOUBLE); > double d = mem->u.r; > if (d >= 0 && d < (double)UINT64_MAX) { > mem->u.u = (uint64_t)d; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_UNSIGNED; > return 0; > } > @@ -695,10 +732,12 @@ double_to_uint(struct Mem *mem) > static inline int > double_to_uint_precise(struct Mem *mem) > { > + assert(mem->type == MEM_DOUBLE); > double d = mem->u.r; > if (d >= 0 && d < (double)UINT64_MAX && (double)(uint64_t)d == d) { > mem->u.u = (uint64_t)d; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_UNSIGNED; > return 0; > } > @@ -708,11 +747,13 @@ double_to_uint_precise(struct Mem *mem) > static inline int > double_to_str0(struct Mem *mem) > { > + assert(mem->type == MEM_DOUBLE); > if (sqlVdbeMemGrow(mem, BUF_SIZE, 0) != 0) > return -1; > sql_snprintf(BUF_SIZE, mem->z, "%!.15g", mem->u.r); > mem->n = strlen(mem->z); > - mem->flags = MEM_Str | MEM_Term; > + mem->type = MEM_STR; > + mem->flags = MEM_Term; > mem->field_type = FIELD_TYPE_STRING; > return 0; > } > @@ -720,8 +761,10 @@ double_to_str0(struct Mem *mem) > static inline int > double_to_bool(struct Mem *mem) > { > + assert(mem->type == MEM_DOUBLE); > mem->u.b = mem->u.r != 0.; > - mem->flags = MEM_Bool; > + mem->type = MEM_BOOL; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_BOOLEAN; > return 0; > } > @@ -729,8 +772,10 @@ double_to_bool(struct Mem *mem) > static inline int > bool_to_int(struct Mem *mem) > { > + assert(mem->type == MEM_BOOL); > mem->u.u = (uint64_t)mem->u.b; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_UNSIGNED; > return 0; > } > @@ -738,6 +783,7 @@ bool_to_int(struct Mem *mem) > static inline int > bool_to_str0(struct Mem *mem) > { > + assert(mem->type == MEM_BOOL); > const char *str = mem->u.b ? "TRUE" : "FALSE"; > return mem_copy_str0(mem, str); > } > @@ -745,6 +791,7 @@ bool_to_str0(struct Mem *mem) > static inline int > array_to_str0(struct Mem *mem) > { > + assert(mem->type == MEM_ARRAY); > const char *str = mp_str(mem->z); > return mem_copy_str0(mem, str); > } > @@ -752,6 +799,7 @@ array_to_str0(struct Mem *mem) > static inline int > map_to_str0(struct Mem *mem) > { > + assert(mem->type == MEM_MAP); > const char *str = mp_str(mem->z); > return mem_copy_str0(mem, str); > } > @@ -759,14 +807,15 @@ map_to_str0(struct Mem *mem) > int > mem_to_int(struct Mem *mem) > { > - assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + assert(mem->type < MEM_INVALID); > + enum mem_type type = mem->type; > + if (type == MEM_INT || type == MEM_UINT) > return 0; > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) > + if (type == MEM_STR || type == MEM_BIN) > return bytes_to_int(mem); > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_int(mem); > - if ((mem->flags & MEM_Bool) != 0) > + if (type == MEM_BOOL) > return bool_to_int(mem); > return -1; > } > @@ -774,12 +823,13 @@ mem_to_int(struct Mem *mem) > int > mem_to_int_precise(struct Mem *mem) > { > - assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + assert(mem->type < MEM_INVALID); > + enum mem_type type = mem->type; > + if (type == MEM_INT || type == MEM_UINT) > return 0; > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return bytes_to_int(mem); > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_int_precise(mem); > return -1; > } > @@ -787,12 +837,13 @@ mem_to_int_precise(struct Mem *mem) > int > mem_to_double(struct Mem *mem) > { > - assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); > - if ((mem->flags & MEM_Real) != 0) > + assert(mem->type < MEM_INVALID); > + enum mem_type type = mem->type; > + if (type == MEM_DOUBLE) > return 0; > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + if (type == MEM_INT || type == MEM_UINT) > return int_to_double(mem); > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return bytes_to_double(mem); > return -1; > } > @@ -800,12 +851,13 @@ mem_to_double(struct Mem *mem) > int > mem_to_number(struct Mem *mem) > { > - assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); > - if ((mem->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0) > + assert(mem->type < MEM_INVALID); > + enum mem_type type = mem->type; > + if (type == MEM_INT || type == MEM_UINT || type == MEM_DOUBLE) > return 0; > - if ((mem->flags & MEM_Bool) != 0) > + if (type == MEM_BOOL) > return bool_to_int(mem); > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) { > + if (type == MEM_STR || type == MEM_BIN) { > if (bytes_to_int(mem) == 0) > return 0; > return bytes_to_double(mem); > @@ -816,72 +868,78 @@ mem_to_number(struct Mem *mem) > int > mem_to_str0(struct Mem *mem) > { > - assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); > - if ((mem->flags & (MEM_Str | MEM_Term)) == (MEM_Str | MEM_Term)) > - return 0; > - if ((mem->flags & MEM_Str) != 0) > + assert(mem->type < MEM_INVALID); > + switch (mem->type) { > + case MEM_STR: > + if ((mem->flags & MEM_Term) != 0) > + return 0; > return str_to_str0(mem); > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + case MEM_INT: > + case MEM_UINT: > return int_to_str0(mem); > - if ((mem->flags & MEM_Real) != 0) > + case MEM_DOUBLE: > return double_to_str0(mem); > - if ((mem->flags & MEM_Bool) != 0) > - return bool_to_str0(mem); > - if ((mem->flags & MEM_Blob) != 0) { > - if ((mem->flags & MEM_Subtype) == 0) > - return bin_to_str0(mem); > - if (mp_typeof(*mem->z) == MP_MAP) > - return map_to_str0(mem); > + case MEM_BIN: > + return bin_to_str0(mem); > + case MEM_MAP: > + return map_to_str0(mem); > + case MEM_ARRAY: > return array_to_str0(mem); > + case MEM_BOOL: > + return bool_to_str0(mem); > + default: > + return -1; > } > - return -1; > } > > int > mem_to_str(struct Mem *mem) > { > - assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); > - if ((mem->flags & MEM_Str) != 0) > + assert(mem->type < MEM_INVALID); > + switch (mem->type) { > + case MEM_STR: > return 0; > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + case MEM_INT: > + case MEM_UINT: > return int_to_str0(mem); > - if ((mem->flags & MEM_Real) != 0) > + case MEM_DOUBLE: > return double_to_str0(mem); > - if ((mem->flags & MEM_Bool) != 0) > - return bool_to_str0(mem); > - if ((mem->flags & MEM_Blob) != 0) { > - if ((mem->flags & MEM_Subtype) == 0) > - return bin_to_str(mem); > - if (mp_typeof(*mem->z) == MP_MAP) > - return map_to_str0(mem); > + case MEM_BIN: > + return bin_to_str(mem); > + case MEM_MAP: > + return map_to_str0(mem); > + case MEM_ARRAY: > return array_to_str0(mem); > + case MEM_BOOL: > + return bool_to_str0(mem); > + default: > + return -1; > } > - return -1; > } > > int > -mem_cast_explicit(struct Mem *mem, enum field_type type) > +mem_cast_explicit(struct Mem *mem, enum field_type field_type) > { > - if ((mem->flags & MEM_Null) != 0) { > - mem->field_type = type; > + enum mem_type type = mem->type; > + if (type == MEM_NULL) { > + mem->field_type = field_type; > return 0; > } > - switch (type) { > + switch (field_type) { > case FIELD_TYPE_UNSIGNED: > - if ((mem->flags & MEM_UInt) != 0) > + switch (type) { > + case MEM_UINT: > return 0; > - if ((mem->flags & MEM_Int) != 0) > - return -1; > - if ((mem->flags & MEM_Blob) != 0 && > - (mem->flags & MEM_Subtype) != 0) > - return -1; > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) > + case MEM_STR: > + case MEM_BIN: > return bytes_to_uint(mem); > - if ((mem->flags & MEM_Real) != 0) > + case MEM_DOUBLE: > return double_to_int(mem); > - if ((mem->flags & MEM_Bool) != 0) > + case MEM_BOOL: > return bool_to_int(mem); > - return -1; > + default: > + return -1; > + } > case FIELD_TYPE_STRING: > return mem_to_str(mem); > case FIELD_TYPE_DOUBLE: > @@ -889,26 +947,29 @@ mem_cast_explicit(struct Mem *mem, enum field_type type) > case FIELD_TYPE_INTEGER: > return mem_to_int(mem); > case FIELD_TYPE_BOOLEAN: > - if ((mem->flags & MEM_Bool) != 0) > + switch (type) { > + case MEM_BOOL: > return 0; > - if ((mem->flags & (MEM_UInt | MEM_Int)) != 0) > + case MEM_INT: > + case MEM_UINT: > return int_to_bool(mem); > - if ((mem->flags & MEM_Str) != 0) > + case MEM_STR: > return str_to_bool(mem); > - if ((mem->flags & MEM_Real) != 0) > + case MEM_DOUBLE: > return double_to_bool(mem); > - return -1; > + default: > + return -1; > + } > case FIELD_TYPE_VARBINARY: > - if ((mem->flags & MEM_Blob) != 0) > + if (type == MEM_BIN || type == MEM_MAP || type == MEM_ARRAY) > return 0; > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return str_to_bin(mem); > return -1; > case FIELD_TYPE_NUMBER: > return mem_to_number(mem); > case FIELD_TYPE_SCALAR: > - if ((mem->flags & MEM_Blob) != 0 && > - (mem->flags & MEM_Subtype) != 0) > + if (type == MEM_MAP || type == MEM_ARRAY) > return -1; > return 0; > default: > @@ -918,58 +979,58 @@ mem_cast_explicit(struct Mem *mem, enum field_type type) > } > > int > -mem_cast_implicit(struct Mem *mem, enum field_type type) > +mem_cast_implicit(struct Mem *mem, enum field_type field_type) > { > - if ((mem->flags & MEM_Null) != 0) { > - mem->field_type = type; > + enum mem_type type = mem->type; > + if (type == MEM_NULL) { > + mem->field_type = field_type; > return 0; > } > - switch (type) { > + switch (field_type) { > case FIELD_TYPE_UNSIGNED: > - if ((mem->flags & MEM_UInt) != 0) > + if (type == MEM_UINT) > return 0; > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_uint(mem); > return -1; > case FIELD_TYPE_STRING: > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return 0; > return -1; > case FIELD_TYPE_DOUBLE: > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return 0; > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + if (type == MEM_INT || type == MEM_UINT) > return int_to_double(mem); > return -1; > case FIELD_TYPE_INTEGER: > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + if (type == MEM_INT || type == MEM_UINT) > return 0; > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_int(mem); > return -1; > case FIELD_TYPE_BOOLEAN: > - if ((mem->flags & MEM_Bool) != 0) > + if (type == MEM_BOOL) > return 0; > return -1; > case FIELD_TYPE_VARBINARY: > - if ((mem->flags & MEM_Blob) != 0) > + if (type == MEM_BIN || type == MEM_MAP || type == MEM_ARRAY) > return 0; > return -1; > case FIELD_TYPE_NUMBER: > - if ((mem->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0) > + if (type == MEM_INT || type == MEM_UINT || type == MEM_DOUBLE) > return 0; > return -1; > case FIELD_TYPE_MAP: > - if (mem_is_map(mem)) > + if (type == MEM_MAP) > return 0; > return -1; > case FIELD_TYPE_ARRAY: > - if (mem_is_array(mem)) > + if (type == MEM_ARRAY) > return 0; > return -1; > case FIELD_TYPE_SCALAR: > - if ((mem->flags & MEM_Blob) != 0 && > - (mem->flags & MEM_Subtype) != 0) > + if (type == MEM_MAP || type == MEM_ARRAY) > return -1; > return 0; > case FIELD_TYPE_ANY: > @@ -981,68 +1042,68 @@ mem_cast_implicit(struct Mem *mem, enum field_type type) > } > > int > -mem_cast_implicit_old(struct Mem *mem, enum field_type type) > +mem_cast_implicit_old(struct Mem *mem, enum field_type field_type) > { > - if (mem_is_null(mem)) > + enum mem_type type = mem->type; > + if (type == MEM_NULL) > return 0; > - switch (type) { > + switch (field_type) { > case FIELD_TYPE_UNSIGNED: > - if ((mem->flags & MEM_UInt) != 0) > + if (type == MEM_UINT) > return 0; > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_uint_precise(mem); > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return bytes_to_uint(mem); > return -1; > case FIELD_TYPE_STRING: > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) > + if (type == MEM_STR || type == MEM_BIN) > return 0; > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + if (type == MEM_INT || type == MEM_UINT) > return int_to_str0(mem); > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_str0(mem); > return -1; > case FIELD_TYPE_DOUBLE: > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return 0; > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + if (type == MEM_INT || type == MEM_UINT) > return int_to_double(mem); > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return bin_to_str(mem); > return -1; > case FIELD_TYPE_INTEGER: > - if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + if (type == MEM_INT || type == MEM_UINT) > return 0; > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return bytes_to_int(mem); > - if ((mem->flags & MEM_Real) != 0) > + if (type == MEM_DOUBLE) > return double_to_int_precise(mem); > return -1; > case FIELD_TYPE_BOOLEAN: > - if ((mem->flags & MEM_Bool) != 0) > + if (type == MEM_BOOL) > return 0; > return -1; > case FIELD_TYPE_VARBINARY: > - if ((mem->flags & MEM_Blob) != 0) > + if (type == MEM_BIN) > return 0; > return -1; > case FIELD_TYPE_NUMBER: > - if ((mem->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0) > + if (type == MEM_INT || type == MEM_UINT || type == MEM_DOUBLE) > return 0; > - if ((mem->flags & MEM_Str) != 0) > + if (type == MEM_STR) > return mem_to_number(mem); > return -1; > case FIELD_TYPE_MAP: > - if (mem_is_map(mem)) > + if (type == MEM_MAP) > return 0; > return -1; > case FIELD_TYPE_ARRAY: > - if (mem_is_array(mem)) > + if (type == MEM_ARRAY) > return 0; > return -1; > case FIELD_TYPE_SCALAR: > - if ((mem->flags & MEM_Blob) != 0 && > - (mem->flags & MEM_Subtype) != 0) > + if (type == MEM_MAP || type == MEM_ARRAY) > return -1; > return 0; > default: > @@ -1054,19 +1115,19 @@ mem_cast_implicit_old(struct Mem *mem, enum field_type type) > int > mem_get_int(const struct Mem *mem, int64_t *i, bool *is_neg) > { > - if ((mem->flags & MEM_Int) != 0) { > + if (mem->type == MEM_INT) { > *i = mem->u.i; > *is_neg = true; > return 0; > } > - if ((mem->flags & MEM_UInt) != 0) { > + if (mem->type == MEM_UINT) { > *i = mem->u.i; > *is_neg = false; > return 0; > } > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) > + if (mem->type == MEM_STR || mem->type == MEM_BIN) > return sql_atoi64(mem->z, i, is_neg, mem->n); > - if ((mem->flags & MEM_Real) != 0) { > + if (mem->type == MEM_DOUBLE) { > double d = mem->u.r; > if (d < 0 && d >= (double)INT64_MIN) { > *i = (int64_t)d; > @@ -1086,20 +1147,20 @@ mem_get_int(const struct Mem *mem, int64_t *i, bool *is_neg) > int > mem_get_uint(const struct Mem *mem, uint64_t *u) > { > - if ((mem->flags & MEM_Int) != 0) > + if (mem->type == MEM_INT) > return -1; > - if ((mem->flags & MEM_UInt) != 0) { > + if (mem->type == MEM_UINT) { > *u = mem->u.u; > return 0; > } > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) { > + if (mem->type == MEM_STR || mem->type == MEM_BIN) { > bool is_neg; > if (sql_atoi64(mem->z, (int64_t *)u, &is_neg, mem->n) != 0 || > is_neg) > return -1; > return 0; > } > - if ((mem->flags & MEM_Real) != 0) { > + if (mem->type == MEM_DOUBLE) { > double d = mem->u.r; > if (d >= 0 && d < (double)UINT64_MAX) { > *u = (uint64_t)d; > @@ -1113,19 +1174,19 @@ mem_get_uint(const struct Mem *mem, uint64_t *u) > int > mem_get_double(const struct Mem *mem, double *d) > { > - if ((mem->flags & MEM_Real) != 0) { > + if (mem->type == MEM_DOUBLE) { > *d = mem->u.r; > return 0; > } > - if ((mem->flags & MEM_Int) != 0) { > + if (mem->type == MEM_INT) { > *d = (double)mem->u.i; > return 0; > } > - if ((mem->flags & MEM_UInt) != 0) { > + if (mem->type == MEM_UINT) { > *d = (double)mem->u.u; > return 0; > } > - if ((mem->flags & MEM_Str) != 0) { > + if (mem->type == MEM_STR) { > if (sqlAtoF(mem->z, d, mem->n) == 0) > return -1; > return 0; > @@ -1136,7 +1197,7 @@ mem_get_double(const struct Mem *mem, double *d) > int > mem_get_bool(const struct Mem *mem, bool *b) > { > - if ((mem->flags & MEM_Bool) != 0) { > + if (mem->type == MEM_BOOL) { > *b = mem->u.b; > return 0; > } > @@ -1146,7 +1207,7 @@ mem_get_bool(const struct Mem *mem, bool *b) > int > mem_get_str0(const struct Mem *mem, const char **s) > { > - if ((mem->flags & MEM_Str) == 0 || (mem->flags & MEM_Term) == 0) > + if (mem->type != MEM_STR || (mem->flags & MEM_Term) == 0) > return -1; > *s = mem->z; > return 0; > @@ -1155,11 +1216,11 @@ mem_get_str0(const struct Mem *mem, const char **s) > int > mem_get_bin(const struct Mem *mem, const char **s) > { > - if ((mem->flags & MEM_Str) != 0) { > + if (mem->type == MEM_STR) { > *s = mem->n > 0 ? mem->z : NULL; > return 0; > } > - if ((mem->flags & MEM_Blob) == 0 || (mem->flags & MEM_Zero) != 0) > + if (mem->type != MEM_BIN || (mem->flags & MEM_Zero) != 0) > return -1; > *s = mem->z; > return 0; > @@ -1168,9 +1229,9 @@ mem_get_bin(const struct Mem *mem, const char **s) > int > mem_len(const struct Mem *mem, uint32_t *len) > { > - if ((mem->flags & (MEM_Str | MEM_Blob)) == 0) > + if (mem->type != MEM_STR && mem->type != MEM_BIN) > return -1; > - if ((mem->flags & MEM_Blob) !=0 && (mem->flags & MEM_Zero) != 0) > + if (mem->type == MEM_BIN && (mem->flags & MEM_Zero) != 0) > *len = mem->n + mem->u.nZero; > else > *len = mem->n; > @@ -1180,7 +1241,7 @@ mem_len(const struct Mem *mem, uint32_t *len) > int > mem_get_agg(const struct Mem *mem, void **accum) > { > - if ((mem->flags & MEM_Agg) == 0) > + if (mem->type != MEM_AGG) > return -1; > *accum = mem->z; > return 0; > @@ -1191,16 +1252,17 @@ mem_copy(struct Mem *to, const struct Mem *from) > { > mem_clear(to); > to->u = from->u; > + to->type = from->type; > to->flags = from->flags; > - to->subtype = from->subtype; > to->field_type = from->field_type; > to->n = from->n; > to->z = from->z; > - if ((to->flags & (MEM_Str | MEM_Blob)) == 0) > + if (!mem_is_bytes(to)) > return 0; > if ((to->flags & MEM_Static) != 0) > return 0; > - if ((to->flags & (MEM_Zero | MEM_Blob)) == (MEM_Zero | MEM_Blob)) > + assert((to->flags & MEM_Zero) == 0 || to->type == MEM_BIN); > + if ((to->flags & MEM_Zero) != 0) > return sqlVdbeMemExpandBlob(to); > to->zMalloc = sqlDbReallocOrFree(to->db, to->zMalloc, to->n); > if (to->zMalloc == NULL) > @@ -1208,7 +1270,7 @@ mem_copy(struct Mem *to, const struct Mem *from) > to->szMalloc = sqlDbMallocSize(to->db, to->zMalloc); > memcpy(to->zMalloc, to->z, to->n); > to->z = to->zMalloc; > - to->flags &= (MEM_Str | MEM_Blob | MEM_Term | MEM_Subtype); > + to->flags &= MEM_Term; > return 0; > } > > @@ -1217,16 +1279,16 @@ mem_copy_as_ephemeral(struct Mem *to, const struct Mem *from) > { > mem_clear(to); > to->u = from->u; > + to->type = from->type; > to->flags = from->flags; > - to->subtype = from->subtype; > to->field_type = from->field_type; > to->n = from->n; > to->z = from->z; > - if ((to->flags & (MEM_Str | MEM_Blob)) == 0) > + if (!mem_is_bytes(to)) > return; > if ((to->flags & (MEM_Static | MEM_Ephem)) != 0) > return; > - to->flags &= (MEM_Str | MEM_Blob | MEM_Term | MEM_Zero | MEM_Subtype); > + to->flags &= MEM_Term | MEM_Zero; > to->flags |= MEM_Ephem; > return; > } > @@ -1236,7 +1298,8 @@ mem_move(struct Mem *to, struct Mem *from) > { > mem_destroy(to); > memcpy(to, from, sizeof(*to)); > - from->flags = MEM_Null; > + from->type = MEM_NULL; > + from->flags = 0; > from->szMalloc = 0; > from->zMalloc = NULL; > } > @@ -1247,7 +1310,7 @@ try_return_null(const struct Mem *a, const struct Mem *b, struct Mem *result, > { > mem_clear(result); > result->field_type = type; > - return (((a->flags | b->flags) & MEM_Null) != 0); > + return a->type == MEM_NULL || b->type == MEM_NULL; > } > > int > @@ -1258,7 +1321,7 @@ mem_concat(struct Mem *a, struct Mem *b, struct Mem *result) > if (try_return_null(a, b, result, FIELD_TYPE_STRING)) > return 0; > } else { > - if (((a->flags | b->flags) & MEM_Null) != 0) { > + if (a->type == MEM_NULL || b->type == MEM_NULL) { > mem_clear(a); > result->field_type = FIELD_TYPE_STRING; > return 0; > @@ -1266,19 +1329,19 @@ mem_concat(struct Mem *a, struct Mem *b, struct Mem *result) > } > > /* Concatenation operation can be applied only to strings and blobs. */ > - if ((b->flags & (MEM_Str | MEM_Blob)) == 0) { > + if (b->type != MEM_STR && b->type != MEM_BIN) { > diag_set(ClientError, ER_INCONSISTENT_TYPES, > "text or varbinary", mem_type_to_str(b)); > return -1; > } > - if ((a->flags & (MEM_Str | MEM_Blob)) == 0) { > + if (a->type != MEM_STR && a->type != MEM_BIN) { > diag_set(ClientError, ER_INCONSISTENT_TYPES, > "text or varbinary", mem_type_to_str(a)); > return -1; > } > > /* Moreover, both operands must be of the same type. */ > - if ((b->flags & MEM_Str) != (a->flags & MEM_Str)) { > + if (b->type != a->type) { > diag_set(ClientError, ER_INCONSISTENT_TYPES, > mem_type_to_str(a), mem_type_to_str(b)); > return -1; > @@ -1295,8 +1358,9 @@ mem_concat(struct Mem *a, struct Mem *b, struct Mem *result) > if (sqlVdbeMemGrow(result, size, result == a) != 0) > return -1; > > - result->flags = a->flags & (MEM_Str | MEM_Blob); > - if ((result->flags & MEM_Blob) != 0) > + result->type = a->type; > + result->flags = 0; > + if (result->type == MEM_BIN) > result->field_type = FIELD_TYPE_VARBINARY; > if (result != a) > memcpy(result->z, a->z, a->n); > @@ -1311,36 +1375,34 @@ struct sql_num { > uint64_t u; > double d; > }; > - int type; > + enum mem_type type; > bool is_neg; > }; > > static int > get_number(const struct Mem *mem, struct sql_num *number) > { > - if ((mem->flags & MEM_Real) != 0) { > + if (mem->type == MEM_DOUBLE) { > number->d = mem->u.r; > - number->type = MEM_Real; > + number->type = MEM_DOUBLE; > return 0; > } > - if ((mem->flags & MEM_Int) != 0) { > + if (mem->type == MEM_INT) { > number->i = mem->u.i; > - number->type = MEM_Int; > + number->type = MEM_INT; > number->is_neg = true; > return 0; > } > - if ((mem->flags & MEM_UInt) != 0) { > + if (mem->type == MEM_UINT) { > number->u = mem->u.u; > - number->type = MEM_UInt; > + number->type = MEM_UINT; > number->is_neg = false; > return 0; > } > - if ((mem->flags & (MEM_Str | MEM_Blob)) == 0) > - return -1; > - if ((mem->flags & MEM_Subtype) != 0) > + if (mem->type != MEM_STR && mem->type != MEM_BIN) > return -1; > if (sql_atoi64(mem->z, &number->i, &number->is_neg, mem->n) == 0) { > - number->type = number->is_neg ? MEM_Int : MEM_UInt; > + number->type = number->is_neg ? MEM_INT : MEM_UINT; > /* > * The next line should be removed along with the is_neg field > * of struct sql_num. The integer type tells us about the sign. > @@ -1351,7 +1413,7 @@ get_number(const struct Mem *mem, struct sql_num *number) > return 0; > } > if (sqlAtoF(mem->z, &number->d, mem->n) != 0) { > - number->type = MEM_Real; > + number->type = MEM_DOUBLE; > return 0; > } > return -1; > @@ -1372,14 +1434,14 @@ arithmetic_prepare(const struct Mem *left, const struct Mem *right, > return -1; > } > assert(a->type != 0 && b->type != 0); > - if (a->type == MEM_Real && b->type != MEM_Real) { > - b->d = b->type == MEM_Int ? (double)b->i : (double)b->u; > - b->type = MEM_Real; > + if (a->type == MEM_DOUBLE && b->type != MEM_DOUBLE) { > + b->d = b->type == MEM_INT ? (double)b->i : (double)b->u; > + b->type = MEM_DOUBLE; > return 0; > } > - if (a->type != MEM_Real && b->type == MEM_Real) { > - a->d = a->type == MEM_Int ? (double)a->i : (double)a->u; > - a->type = MEM_Real; > + if (a->type != MEM_DOUBLE && b->type == MEM_DOUBLE) { > + a->d = a->type == MEM_INT ? (double)a->i : (double)a->u; > + a->type = MEM_DOUBLE; > return 0; > } > return 0; > @@ -1395,10 +1457,11 @@ mem_add(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (arithmetic_prepare(left, right, &a, &b) != 0) > return -1; > > - assert(a.type != MEM_Real || a.type == b.type); > - if (a.type == MEM_Real) { > + assert(a.type != MEM_DOUBLE || a.type == b.type); > + if (a.type == MEM_DOUBLE) { > result->u.r = a.d + b.d; > - result->flags = MEM_Real; > + result->type = MEM_DOUBLE; > + result->flags = 0; > return 0; > } > > @@ -1409,7 +1472,8 @@ mem_add(const struct Mem *left, const struct Mem *right, struct Mem *result) > return -1; > } > result->u.i = res; > - result->flags = is_neg ? MEM_Int : MEM_UInt; > + result->type = is_neg ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1423,10 +1487,11 @@ mem_sub(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (arithmetic_prepare(left, right, &a, &b) != 0) > return -1; > > - assert(a.type != MEM_Real || a.type == b.type); > - if (a.type == MEM_Real) { > + assert(a.type != MEM_DOUBLE || a.type == b.type); > + if (a.type == MEM_DOUBLE) { > result->u.r = a.d - b.d; > - result->flags = MEM_Real; > + result->type = MEM_DOUBLE; > + result->flags = 0; > return 0; > } > > @@ -1437,7 +1502,8 @@ mem_sub(const struct Mem *left, const struct Mem *right, struct Mem *result) > return -1; > } > result->u.i = res; > - result->flags = is_neg ? MEM_Int : MEM_UInt; > + result->type = is_neg ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1451,10 +1517,11 @@ mem_mul(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (arithmetic_prepare(left, right, &a, &b) != 0) > return -1; > > - assert(a.type != MEM_Real || a.type == b.type); > - if (a.type == MEM_Real) { > + assert(a.type != MEM_DOUBLE || a.type == b.type); > + if (a.type == MEM_DOUBLE) { > result->u.r = a.d * b.d; > - result->flags = MEM_Real; > + result->type = MEM_DOUBLE; > + result->flags = 0; > return 0; > } > > @@ -1465,7 +1532,8 @@ mem_mul(const struct Mem *left, const struct Mem *right, struct Mem *result) > return -1; > } > result->u.i = res; > - result->flags = is_neg ? MEM_Int : MEM_UInt; > + result->type = is_neg ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1479,15 +1547,16 @@ mem_div(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (arithmetic_prepare(left, right, &a, &b) != 0) > return -1; > > - assert(a.type != MEM_Real || a.type == b.type); > - if (a.type == MEM_Real) { > + assert(a.type != MEM_DOUBLE || a.type == b.type); > + if (a.type == MEM_DOUBLE) { > if (b.d == 0.) { > diag_set(ClientError, ER_SQL_EXECUTE, > "division by zero"); > return -1; > } > result->u.r = a.d / b.d; > - result->flags = MEM_Real; > + result->type = MEM_DOUBLE; > + result->flags = 0; > return 0; > } > > @@ -1502,7 +1571,8 @@ mem_div(const struct Mem *left, const struct Mem *right, struct Mem *result) > return -1; > } > result->u.i = res; > - result->flags = is_neg ? MEM_Int : MEM_UInt; > + result->type = is_neg ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1516,14 +1586,14 @@ mem_rem(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (arithmetic_prepare(left, right, &a, &b) != 0) > return -1; > > - assert(a.type != MEM_Real || a.type == b.type); > + assert(a.type != MEM_DOUBLE || a.type == b.type); > /* > * TODO: This operation works wrong when double d > INT64_MAX and > * d < UINT64_MAX. Also, there may be precision losses due to > * conversion integer to double and back. > */ > - a.i = a.type == MEM_Real ? (int64_t)a.d : a.i; > - b.i = b.type == MEM_Real ? (int64_t)b.d : b.i; > + a.i = a.type == MEM_DOUBLE ? (int64_t)a.d : a.i; > + b.i = b.type == MEM_DOUBLE ? (int64_t)b.d : b.i; > if (b.i == 0) { > diag_set(ClientError, ER_SQL_EXECUTE, "division by zero"); > return -1; > @@ -1535,7 +1605,8 @@ mem_rem(const struct Mem *left, const struct Mem *right, struct Mem *result) > return -1; > } > result->u.i = res; > - result->flags = is_neg ? MEM_Int : MEM_UInt; > + result->type = is_neg ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1567,7 +1638,8 @@ mem_bit_and(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (bitwise_prepare(left, right, &a, &b) != 0) > return -1; > result->u.i = a & b; > - result->flags = result->u.i < 0 ? MEM_Int : MEM_UInt; > + result->type = result->u.i < 0 ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1581,7 +1653,8 @@ mem_bit_or(const struct Mem *left, const struct Mem *right, struct Mem *result) > if (bitwise_prepare(left, right, &a, &b) != 0) > return -1; > result->u.i = a | b; > - result->flags = result->u.i < 0 ? MEM_Int : MEM_UInt; > + result->type = result->u.i < 0 ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1603,7 +1676,8 @@ mem_shift_left(const struct Mem *left, const struct Mem *right, > result->u.i = 0; > else > result->u.i = a << b; > - result->flags = result->u.i < 0 ? MEM_Int : MEM_UInt; > + result->type = result->u.i < 0 ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1625,7 +1699,8 @@ mem_shift_right(const struct Mem *left, const struct Mem *right, > result->u.i = a >= 0 ? 0 : -1; > else > result->u.i = a >> b; > - result->flags = result->u.i < 0 ? MEM_Int : MEM_UInt; > + result->type = result->u.i < 0 ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > @@ -1634,7 +1709,7 @@ mem_bit_not(const struct Mem *mem, struct Mem *result) > { > mem_clear(result); > result->field_type = FIELD_TYPE_INTEGER; > - if ((mem->flags & MEM_Null) != 0) > + if (mem->type == MEM_NULL) > return 0; > int64_t i; > bool unused; > @@ -1644,14 +1719,15 @@ mem_bit_not(const struct Mem *mem, struct Mem *result) > return -1; > } > result->u.i = ~i; > - result->flags = result->u.i < 0 ? MEM_Int : MEM_UInt; > + result->type = result->u.i < 0 ? MEM_INT : MEM_UINT; > + result->flags = 0; > return 0; > } > > int > mem_cmp_bool(const struct Mem *a, const struct Mem *b, int *result) > { > - if ((a->flags & b->flags & MEM_Bool) == 0) > + if (a->type != MEM_BOOL || b->type != MEM_BOOL) > return -1; > if (a->u.b == b->u.b) > *result = 0; > @@ -1665,7 +1741,7 @@ mem_cmp_bool(const struct Mem *a, const struct Mem *b, int *result) > int > mem_cmp_bin(const struct Mem *a, const struct Mem *b, int *result) > { > - if ((a->flags & b->flags & MEM_Blob) == 0) > + if (a->type != MEM_BIN || b->type != MEM_BIN) > return -1; > int an = a->n; > int bn = b->n; > @@ -1722,8 +1798,8 @@ mem_cmp_num(const struct Mem *left, const struct Mem *right, int *result) > } > if (get_number(left, &a) != 0) > return -1; > - if (a.type == MEM_Real) { > - if (b.type == MEM_Real) { > + if (a.type == MEM_DOUBLE) { > + if (b.type == MEM_DOUBLE) { > if (a.d > b.d) > *result = 1; > else if (a.d < b.d) > @@ -1732,14 +1808,14 @@ mem_cmp_num(const struct Mem *left, const struct Mem *right, int *result) > *result = 0; > return 0; > } > - if (b.type == MEM_Int) > + 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.type == MEM_INT) { > + if (b.type == MEM_INT) { > if (a.i > b.i) > *result = 1; > else if (a.i < b.i) > @@ -1748,14 +1824,14 @@ mem_cmp_num(const struct Mem *left, const struct Mem *right, int *result) > *result = 0; > return 0; > } > - if (b.type == MEM_UInt) > + 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) { > + assert(a.type == MEM_UINT); > + if (b.type == MEM_UINT) { > if (a.u > b.u) > *result = 1; > else if (a.u < b.u) > @@ -1764,7 +1840,7 @@ mem_cmp_num(const struct Mem *left, const struct Mem *right, int *result) > *result = 0; > return 0; > } > - if (b.type == MEM_Int) > + if (b.type == MEM_INT) > *result = 1; > else > *result = double_compare_uint64(b.d, a.u, -1); > @@ -1778,15 +1854,17 @@ mem_cmp_str(const struct Mem *left, const struct Mem *right, int *result, > char *a; > uint32_t an; > char bufl[BUF_SIZE]; > - if ((left->flags & MEM_Str) != 0) { > + if (left->type == MEM_STR) { > a = left->z; > an = left->n; > } else { > - assert((left->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0); > + enum mem_type type = left->type; > + assert(type == MEM_INT || type == MEM_UINT || > + type == MEM_DOUBLE); > a = &bufl[0]; > - if ((left->flags & MEM_Int) != 0) > + if (type == MEM_INT) > sql_snprintf(BUF_SIZE, a, "%lld", left->u.i); > - else if ((left->flags & MEM_UInt) != 0) > + else if (type == MEM_UINT) > sql_snprintf(BUF_SIZE, a, "%llu", left->u.u); > else > sql_snprintf(BUF_SIZE, a, "%!.15g", left->u.r); > @@ -1796,15 +1874,17 @@ mem_cmp_str(const struct Mem *left, const struct Mem *right, int *result, > char *b; > uint32_t bn; > char bufr[BUF_SIZE]; > - if ((right->flags & MEM_Str) != 0) { > + if (right->type == MEM_STR) { > b = right->z; > bn = right->n; > } else { > - assert((right->flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0); > + enum mem_type type = right->type; > + assert(type == MEM_INT || type == MEM_UINT || > + type == MEM_DOUBLE); > b = &bufr[0]; > - if ((right->flags & MEM_Int) != 0) > + if (type == MEM_INT) > sql_snprintf(BUF_SIZE, b, "%lld", right->u.i); > - else if ((right->flags & MEM_UInt) != 0) > + else if (type == MEM_UINT) > sql_snprintf(BUF_SIZE, b, "%llu", right->u.u); > else > sql_snprintf(BUF_SIZE, b, "%!.15g", right->u.r); > @@ -1822,13 +1902,6 @@ mem_cmp_str(const struct Mem *left, const struct Mem *right, int *result, > return 0; > } > > -static inline bool > -mem_has_msgpack_subtype(struct Mem *mem) > -{ > - return (mem->flags & MEM_Subtype) != 0 && > - mem->subtype == SQL_SUBTYPE_MSGPACK; > -} > - > /* > * Both *pMem1 and *pMem2 contain string values. Compare the two values > * using the collation sequence pColl. As usual, return a negative , zero > @@ -1864,20 +1937,22 @@ char * > mem_type_to_str(const struct Mem *p) > { > assert(p != NULL); > - switch (p->flags & MEM_PURE_TYPE_MASK) { > - case MEM_Null: > + switch (p->type) { > + case MEM_NULL: > return "NULL"; > - case MEM_Str: > + case MEM_STR: > return "text"; > - case MEM_Int: > + case MEM_INT: > return "integer"; > - case MEM_UInt: > + case MEM_UINT: > return "unsigned"; > - case MEM_Real: > + case MEM_DOUBLE: > return "real"; > - case MEM_Blob: > + case MEM_ARRAY: > + case MEM_MAP: > + case MEM_BIN: > return "varbinary"; > - case MEM_Bool: > + case MEM_BOOL: > return "boolean"; > default: > unreachable(); > @@ -1887,28 +1962,8 @@ mem_type_to_str(const struct Mem *p) > enum mp_type > mem_mp_type(struct Mem *mem) > { > - switch (mem->flags & MEM_PURE_TYPE_MASK) { > - case MEM_Int: > - return MP_INT; > - case MEM_UInt: > - return MP_UINT; > - case MEM_Real: > - return MP_DOUBLE; > - case MEM_Str: > - return MP_STR; > - case MEM_Blob: > - if ((mem->flags & MEM_Subtype) == 0 || > - mem->subtype != SQL_SUBTYPE_MSGPACK) > - return MP_BIN; > - assert(mp_typeof(*mem->z) == MP_MAP || > - mp_typeof(*mem->z) == MP_ARRAY); > - return mp_typeof(*mem->z); > - case MEM_Bool: > - return MP_BOOL; > - case MEM_Null: > - return MP_NIL; > - default: unreachable(); > - } > + assert(mem->type < MEM_INVALID); > + return (enum mp_type)mem->type; > } > > /* EVIDENCE-OF: R-12793-43283 Every value in sql has one of five > @@ -1944,11 +1999,6 @@ sqlVdbeCheckMemInvariants(Mem * p) > */ > assert((p->flags & MEM_Dyn) == 0 || p->szMalloc == 0); > > - /* Cannot be both MEM_Int and MEM_Real at the same time */ > - assert((p->flags & (MEM_Int | MEM_Real)) != (MEM_Int | MEM_Real)); > - /* Can't be both UInt and Int at the same time. */ > - assert((p->flags & (MEM_Int | MEM_UInt)) != (MEM_Int | MEM_UInt)); > - > /* The szMalloc field holds the correct memory allocation size */ > assert(p->szMalloc == 0 || > p->szMalloc == sqlDbMallocSize(p->db, p->zMalloc)); > @@ -1961,7 +2011,7 @@ sqlVdbeCheckMemInvariants(Mem * p) > * (3) An ephemeral string or blob > * (4) A static string or blob > */ > - if ((p->flags & (MEM_Str | MEM_Blob)) && p->n > 0) { > + if ((p->type == MEM_STR || p->type == MEM_BIN) && p->n > 0) { > assert(((p->szMalloc > 0 && p->z == p->zMalloc) ? 1 : 0) + > ((p->flags & MEM_Dyn) != 0 ? 1 : 0) + > ((p->flags & MEM_Ephem) != 0 ? 1 : 0) + > @@ -1980,7 +2030,7 @@ sqlVdbeMemPrettyPrint(Mem *pMem, char *zBuf) > char *zCsr = zBuf; > int f = pMem->flags; > > - if (f&MEM_Blob) { > + if (pMem->type == MEM_BIN) { > int i; > char c; > if (f & MEM_Dyn) { > @@ -2016,7 +2066,7 @@ sqlVdbeMemPrettyPrint(Mem *pMem, char *zBuf) > zCsr += sqlStrlen30(zCsr); > } > *zCsr = '\0'; > - } else if (f & MEM_Str) { > + } else if (pMem->type == MEM_STR) { > int j, k; > zBuf[0] = ' '; > if (f & MEM_Dyn) { > @@ -2056,26 +2106,34 @@ sqlVdbeMemPrettyPrint(Mem *pMem, char *zBuf) > static void > memTracePrint(Mem *p) > { > - if (p->flags & MEM_Undefined) { > - printf(" undefined"); > - } else if (p->flags & MEM_Null) { > + switch (p->type) { > + case MEM_NULL: > printf(" NULL"); > - } else if ((p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str)) { > - printf(" si:%lld", p->u.i); > - } else if (p->flags & MEM_Int) { > + return; > + case MEM_INT: > printf(" i:%lld", p->u.i); > - } else if (p->flags & MEM_UInt) { > + return; > + case MEM_UINT: > printf(" u:%"PRIu64"", p->u.u); > - } else if (p->flags & MEM_Real) { > + return; > + case MEM_DOUBLE: > printf(" r:%g", p->u.r); > - } else if (p->flags & MEM_Bool) { > + return; > + case MEM_INVALID: > + printf(" undefined"); > + return; > + case MEM_BOOL: > printf(" bool:%s", SQL_TOKEN_BOOLEAN(p->u.b)); > - } else { > + return; > + default: { > char zBuf[200]; > sqlVdbeMemPrettyPrint(p, zBuf); > printf(" %s", zBuf); > + if (p->type == MEM_MAP || p->type == MEM_ARRAY) > + printf(" subtype=0x%02x", SQL_SUBTYPE_MSGPACK); > + return; > + } > } > - if (p->flags & MEM_Subtype) printf(" subtype=0x%02x", p->subtype); > } > > void > @@ -2095,7 +2153,7 @@ sqlVdbeMemExpandBlob(Mem * pMem) > { > int nByte; > assert(pMem->flags & MEM_Zero); > - assert(pMem->flags & MEM_Blob); > + assert(pMem->type == MEM_BIN); > > /* Set nByte to the number of bytes required to store the expanded blob. */ > nByte = pMem->n + pMem->u.nZero; > @@ -2121,7 +2179,7 @@ sqlVdbeMemGrow(struct Mem *pMem, int n, int bPreserve) > /* If the bPreserve flag is set to true, then the memory cell must already > * contain a valid string or blob value. > */ > - assert(bPreserve == 0 || pMem->flags & (MEM_Blob | MEM_Str)); > + assert(bPreserve == 0 || mem_is_bytes(pMem)); > testcase(bPreserve && pMem->z == 0); > > assert(pMem->szMalloc == 0 || > @@ -2168,9 +2226,8 @@ sqlVdbeMemGrow(struct Mem *pMem, int n, int bPreserve) > * routine is a no-op. > * > * Any prior string or blob content in the pMem object may be discarded. > - * The pMem->xDel destructor is called, if it exists. Though MEM_Str > - * and MEM_Blob values may be discarded, MEM_Int, MEM_Real, and MEM_Null > - * values are preserved. > + * The pMem->xDel destructor is called, if it exists. Though STRING, VARBINARY, > + * MAP and ARRAY values may be discarded, all other values are preserved. > * > * Return 0 on success or -1 if unable to complete the resizing. > */ > @@ -2184,7 +2241,6 @@ sqlVdbeMemClearAndResize(Mem * pMem, int szNew) > } > assert((pMem->flags & MEM_Dyn) == 0); > pMem->z = pMem->zMalloc; > - pMem->flags &= (MEM_Null | MEM_Int | MEM_Real); > return 0; > } > > @@ -2208,7 +2264,8 @@ sqlValueNew(sql * db) > { > Mem *p = sqlDbMallocZero(db, sizeof(*p)); > if (p) { > - p->flags = MEM_Null; > + p->type = MEM_NULL; > + p->flags = 0; > p->db = db; > } > return p; > @@ -2223,7 +2280,8 @@ releaseMemArray(Mem * p, int N) > assert((&p[1]) == pEnd || p[0].db == p[1].db); > assert(sqlVdbeCheckMemInvariants(p)); > mem_destroy(p); > - p->flags = MEM_Undefined; > + p->type = MEM_INVALID; > + p->flags = 0; > } while ((++p) < pEnd); > } > } > @@ -2236,7 +2294,7 @@ int > sqlVdbeMemTooBig(Mem * p) > { > assert(p->db != 0); > - if (p->flags & (MEM_Str | MEM_Blob)) { > + if (mem_is_bytes(p)) { > int n = p->n; > if (p->flags & MEM_Zero) { > n += p->u.nZero; > @@ -2258,40 +2316,36 @@ sqlVdbeMemTooBig(Mem * p) > int > sqlMemCompare(const Mem * pMem1, const Mem * pMem2, const struct coll * pColl) > { > - int f1, f2; > int res; > - int combined_flags; > > - f1 = pMem1->flags; > - f2 = pMem2->flags; > - combined_flags = f1 | f2; > + enum mem_type type1 = pMem1->type; > + enum mem_type type2 = pMem2->type; > > /* If one value is NULL, it is less than the other. If both values > * are NULL, return 0. > */ > - if (combined_flags & MEM_Null) { > - return (f2 & MEM_Null) - (f1 & MEM_Null); > - } > + if (type1 == MEM_NULL || type2 == MEM_NULL) > + return (int)(type2 == MEM_NULL) - (int)(type1 == MEM_NULL); > > - if ((combined_flags & MEM_Bool) != 0) { > - if ((f1 & f2 & MEM_Bool) != 0) { > + if (type1 == MEM_BOOL || type2 == MEM_BOOL) { > + if (type1 == MEM_BOOL && type2 == MEM_BOOL) { > if (pMem1->u.b == pMem2->u.b) > return 0; > if (pMem1->u.b) > return 1; > return -1; > } > - if ((f2 & MEM_Bool) != 0) > + if (type2 == MEM_BOOL) > return +1; > return -1; > } > > /* At least one of the two values is a number > */ > - if ((combined_flags & (MEM_Int | MEM_UInt | MEM_Real)) != 0) { > - if ((f1 & (MEM_Real | MEM_Int | MEM_UInt)) == 0) > + if (mem_is_num(pMem1) || mem_is_num(pMem2)) { > + if (!mem_is_num(pMem1)) > return +1; > - if ((f2 & (MEM_Real | MEM_Int | MEM_UInt)) == 0) > + if (!mem_is_num(pMem2)) > return -1; > mem_cmp_num(pMem1, pMem2, &res); > return res; > @@ -2300,11 +2354,11 @@ sqlMemCompare(const Mem * pMem1, const Mem * pMem2, const struct coll * pColl) > /* If one value is a string and the other is a blob, the string is less. > * If both are strings, compare using the collating functions. > */ > - if (combined_flags & MEM_Str) { > - if ((f1 & MEM_Str) == 0) { > + if (type1 == MEM_STR || type2 == MEM_STR) { > + if (type1 != MEM_STR) { > return 1; > } > - if ((f2 & MEM_Str) == 0) { > + if (type2 != MEM_STR) { > return -1; > } > mem_cmp_str(pMem1, pMem2, &res, pColl); > @@ -2322,12 +2376,13 @@ sql_vdbemem_finalize(struct Mem *mem, struct func *func) > assert(func != NULL); > assert(func->def->language == FUNC_LANGUAGE_SQL_BUILTIN); > assert(func->def->aggregate == FUNC_AGGREGATE_GROUP); > - assert((mem->flags & MEM_Null) != 0 || func == mem->u.func); > + assert(mem->type == MEM_NULL || func == mem->u.func); > sql_context ctx; > memset(&ctx, 0, sizeof(ctx)); > Mem t; > memset(&t, 0, sizeof(t)); > - t.flags = MEM_Null; > + t.type = MEM_NULL; > + t.flags = 0; > t.db = mem->db; > t.field_type = field_type_MAX; > ctx.pOut = &t; > @@ -2356,35 +2411,35 @@ sqlVdbeCompareMsgpack(const char **key1, > break; > } > case MP_NIL:{ > - rc = -((pKey2->flags & MEM_Null) == 0); > + rc = -(pKey2->type != MEM_NULL); > mp_decode_nil(&aKey1); > break; > } > case MP_BOOL:{ > mem1.u.b = mp_decode_bool(&aKey1); > - if ((pKey2->flags & MEM_Bool) != 0) { > + if (pKey2->type == MEM_BOOL) { > if (mem1.u.b != pKey2->u.b) > rc = mem1.u.b ? 1 : -1; > } else { > - rc = (pKey2->flags & MEM_Null) != 0 ? 1 : -1; > + rc = pKey2->type == MEM_NULL ? 1 : -1; > } > break; > } > case MP_UINT:{ > mem1.u.u = mp_decode_uint(&aKey1); > - if ((pKey2->flags & MEM_Int) != 0) { > + if (pKey2->type == MEM_INT) { > rc = +1; > - } else if ((pKey2->flags & MEM_UInt) != 0) { > + } else if (pKey2->type == MEM_UINT) { > if (mem1.u.u < pKey2->u.u) > rc = -1; > else if (mem1.u.u > pKey2->u.u) > rc = +1; > - } else if ((pKey2->flags & MEM_Real) != 0) { > + } else if (pKey2->type == MEM_DOUBLE) { > rc = double_compare_uint64(pKey2->u.r, > mem1.u.u, -1); > - } else if ((pKey2->flags & MEM_Null) != 0) { > + } else if (pKey2->type == MEM_NULL) { > rc = 1; > - } else if ((pKey2->flags & MEM_Bool) != 0) { > + } else if (pKey2->type == MEM_BOOL) { > rc = 1; > } else { > rc = -1; > @@ -2393,20 +2448,20 @@ sqlVdbeCompareMsgpack(const char **key1, > } > case MP_INT:{ > mem1.u.i = mp_decode_int(&aKey1); > - if ((pKey2->flags & MEM_UInt) != 0) { > + if (pKey2->type == MEM_UINT) { > rc = -1; > - } else if ((pKey2->flags & MEM_Int) != 0) { > + } else if (pKey2->type == MEM_INT) { > if (mem1.u.i < pKey2->u.i) { > rc = -1; > } else if (mem1.u.i > pKey2->u.i) { > rc = +1; > } > - } else if (pKey2->flags & MEM_Real) { > + } else if (pKey2->type == MEM_DOUBLE) { > rc = double_compare_nint64(pKey2->u.r, mem1.u.i, > -1); > - } else if ((pKey2->flags & MEM_Null) != 0) { > + } else if (pKey2->type == MEM_NULL) { > rc = 1; > - } else if ((pKey2->flags & MEM_Bool) != 0) { > + } else if (pKey2->type == MEM_BOOL) { > rc = 1; > } else { > rc = -1; > @@ -2420,21 +2475,21 @@ sqlVdbeCompareMsgpack(const char **key1, > case MP_DOUBLE:{ > mem1.u.r = mp_decode_double(&aKey1); > do_float: > - if ((pKey2->flags & MEM_Int) != 0) { > + if (pKey2->type == MEM_INT) { > rc = double_compare_nint64(mem1.u.r, pKey2->u.i, > 1); > - } else if (pKey2->flags & MEM_UInt) { > + } else if (pKey2->type == MEM_UINT) { > rc = double_compare_uint64(mem1.u.r, > pKey2->u.u, 1); > - } else if (pKey2->flags & MEM_Real) { > + } else if (pKey2->type == MEM_DOUBLE) { > if (mem1.u.r < pKey2->u.r) { > rc = -1; > } else if (mem1.u.r > pKey2->u.r) { > rc = +1; > } > - } else if ((pKey2->flags & MEM_Null) != 0) { > + } else if (pKey2->type == MEM_NULL) { > rc = 1; > - } else if ((pKey2->flags & MEM_Bool) != 0) { > + } else if (pKey2->type == MEM_BOOL) { > rc = 1; > } else { > rc = -1; > @@ -2442,7 +2497,7 @@ sqlVdbeCompareMsgpack(const char **key1, > break; > } > case MP_STR:{ > - if (pKey2->flags & MEM_Str) { > + if (pKey2->type == MEM_STR) { > struct key_def *key_def = unpacked->key_def; > mem1.n = mp_decode_strl(&aKey1); > mem1.z = (char *)aKey1; > @@ -2450,14 +2505,15 @@ sqlVdbeCompareMsgpack(const char **key1, > struct coll *coll = > key_def->parts[key2_idx].coll; > if (coll != NULL) { > - mem1.flags = MEM_Str; > + mem1.type = MEM_STR; > + mem1.flags = 0; > rc = vdbeCompareMemString(&mem1, pKey2, > coll); > } else { > goto do_bin_cmp; > } > } else { > - rc = (pKey2->flags & MEM_Blob) ? -1 : +1; > + rc = pKey2->type == MEM_BIN ? -1 : +1; > } > break; > } > @@ -2466,7 +2522,7 @@ sqlVdbeCompareMsgpack(const char **key1, > mem1.z = (char *)aKey1; > aKey1 += mem1.n; > do_blob: > - if (pKey2->flags & MEM_Blob) { > + if (pKey2->type == MEM_BIN) { > if (pKey2->flags & MEM_Zero) { > if (!isAllZero > ((const char *)mem1.z, mem1.n)) { > @@ -2533,8 +2589,8 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) > mem->z = (char *)buf; > mp_next(&buf); > mem->n = buf - mem->z; > - mem->flags = MEM_Blob | MEM_Ephem | MEM_Subtype; > - mem->subtype = SQL_SUBTYPE_MSGPACK; > + mem->type = MEM_ARRAY; > + mem->flags = MEM_Ephem; > mem->field_type = FIELD_TYPE_ARRAY; > break; > } > @@ -2542,8 +2598,8 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) > mem->z = (char *)buf; > mp_next(&buf); > mem->n = buf - mem->z; > - mem->flags = MEM_Blob | MEM_Ephem | MEM_Subtype; > - mem->subtype = SQL_SUBTYPE_MSGPACK; > + mem->type = MEM_MAP; > + mem->flags = MEM_Ephem; > mem->field_type = FIELD_TYPE_MAP; > break; > } > @@ -2551,39 +2607,45 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) > mem->z = (char *)buf; > mp_next(&buf); > mem->n = buf - mem->z; > - mem->flags = MEM_Blob | MEM_Ephem; > + mem->type = MEM_BIN; > + mem->flags = MEM_Ephem; > mem->field_type = FIELD_TYPE_VARBINARY; > break; > } > case MP_NIL: { > mp_decode_nil(&buf); > - mem->flags = MEM_Null; > + mem->type = MEM_NULL; > + mem->flags = 0; > mem->field_type = field_type_MAX; > break; > } > case MP_BOOL: { > mem->u.b = mp_decode_bool(&buf); > - mem->flags = MEM_Bool; > + mem->type = MEM_BOOL; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_BOOLEAN; > break; > } > case MP_UINT: { > uint64_t v = mp_decode_uint(&buf); > mem->u.u = v; > - mem->flags = MEM_UInt; > + mem->type = MEM_UINT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_INTEGER; > break; > } > case MP_INT: { > mem->u.i = mp_decode_int(&buf); > - mem->flags = MEM_Int; > + mem->type = MEM_INT; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_INTEGER; > break; > } > case MP_STR: { > /* XXX u32->int */ > mem->n = (int) mp_decode_strl(&buf); > - mem->flags = MEM_Str | MEM_Ephem; > + mem->type = MEM_STR; > + mem->flags = MEM_Ephem; > mem->field_type = FIELD_TYPE_STRING; > install_blob: > mem->z = (char *)buf; > @@ -2593,17 +2655,20 @@ install_blob: > case MP_BIN: { > /* XXX u32->int */ > mem->n = (int) mp_decode_binl(&buf); > - mem->flags = MEM_Blob | MEM_Ephem; > + mem->type = MEM_BIN; > + mem->flags = MEM_Ephem; > mem->field_type = FIELD_TYPE_VARBINARY; > goto install_blob; > } > case MP_FLOAT: { > mem->u.r = mp_decode_float(&buf); > if (sqlIsNaN(mem->u.r)) { > - mem->flags = MEM_Null; > + mem->type = MEM_NULL; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_DOUBLE; > } else { > - mem->flags = MEM_Real; > + mem->type = MEM_DOUBLE; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_DOUBLE; > } > break; > @@ -2611,10 +2676,12 @@ install_blob: > case MP_DOUBLE: { > mem->u.r = mp_decode_double(&buf); > if (sqlIsNaN(mem->u.r)) { > - mem->flags = MEM_Null; > + mem->type = MEM_NULL; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_DOUBLE; > } else { > - mem->flags = MEM_Real; > + mem->type = MEM_DOUBLE; > + mem->flags = 0; > mem->field_type = FIELD_TYPE_DOUBLE; > } > break; > @@ -2631,7 +2698,7 @@ mem_from_mp(struct Mem *mem, const char *buf, uint32_t *len) > { > if (mem_from_mp_ephemeral(mem, buf, len) != 0) > return -1; > - if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) { > + if (mem_is_bytes(mem)) { > assert((mem->flags & MEM_Ephem) != 0); > if (sqlVdbeMemGrow(mem, mem->n, 1) != 0) > return -1; > @@ -2643,35 +2710,41 @@ void > mpstream_encode_vdbe_mem(struct mpstream *stream, struct Mem *var) > { > assert(memIsValid(var)); > - int64_t i; > - if (var->flags & MEM_Null) { > + switch (var->type) { > + case MEM_NULL: > mpstream_encode_nil(stream); > - } else if (var->flags & MEM_Real) { > - mpstream_encode_double(stream, var->u.r); > - } else if (var->flags & MEM_Int) { > - i = var->u.i; > - mpstream_encode_int(stream, i); > - } else if (var->flags & MEM_UInt) { > - i = var->u.u; > - mpstream_encode_uint(stream, i); > - } else if (var->flags & MEM_Str) { > + return; > + case MEM_STR: > mpstream_encode_strn(stream, var->z, var->n); > - } else if (var->flags & MEM_Bool) { > - mpstream_encode_bool(stream, var->u.b); > - } else { > - /* > - * Emit BIN header iff the BLOB doesn't store > - * MsgPack content. > - */ > - if (!mem_has_msgpack_subtype(var)) { > - uint32_t binl = var->n + > - ((var->flags & MEM_Zero) ? > - var->u.nZero : 0); > - mpstream_encode_binl(stream, binl); > + return; > + case MEM_INT: > + mpstream_encode_int(stream, var->u.i); > + return; > + case MEM_UINT: > + mpstream_encode_uint(stream, var->u.u); > + return; > + case MEM_DOUBLE: > + mpstream_encode_double(stream, var->u.r); > + return; > + case MEM_BIN: > + if ((var->flags & MEM_Zero) != 0) { > + mpstream_encode_binl(stream, var->n + var->u.nZero); > + mpstream_memcpy(stream, var->z, var->n); > + mpstream_memset(stream, 0, var->u.nZero); > + } else { > + mpstream_encode_binl(stream, var->n); > + mpstream_memcpy(stream, var->z, var->n); > } > + return; > + case MEM_ARRAY: > + case MEM_MAP: > mpstream_memcpy(stream, var->z, var->n); > - if (var->flags & MEM_Zero) > - mpstream_memset(stream, 0, var->u.nZero); > + return; > + case MEM_BOOL: > + mpstream_encode_bool(stream, var->u.b); > + return; > + default: > + unreachable(); > } > } > > @@ -2734,24 +2807,26 @@ port_vdbemem_dump_lua(struct port *base, struct lua_State *L, bool is_flat) > assert(is_flat == true); > for (uint32_t i = 0; i < port->mem_count; i++) { > struct Mem *mem = (struct Mem *)port->mem + i; > - switch (mem->flags & MEM_PURE_TYPE_MASK) { > - case MEM_Int: > + switch (mem->type) { > + case MEM_INT: > luaL_pushint64(L, mem->u.i); > break; > - case MEM_UInt: > + case MEM_UINT: > luaL_pushuint64(L, mem->u.u); > break; > - case MEM_Real: > + case MEM_DOUBLE: > lua_pushnumber(L, mem->u.r); > break; > - case MEM_Str: > - case MEM_Blob: > + case MEM_STR: > + case MEM_BIN: > + case MEM_MAP: > + case MEM_ARRAY: > lua_pushlstring(L, mem->z, mem->n); > break; > - case MEM_Null: > + case MEM_NULL: > lua_pushnil(L); > break; > - case MEM_Bool: > + case MEM_BOOL: > lua_pushboolean(L, mem->u.b); > break; > default: > @@ -2844,23 +2919,28 @@ port_lua_get_vdbemem(struct port *base, uint32_t *size) > mem_clear(&val[i]); > switch (field.type) { > case MP_BOOL: > - val[i].flags = MEM_Bool; > + val[i].type = MEM_BOOL; > + val[i].flags = 0; > val[i].u.b = field.bval; > break; > case MP_FLOAT: > - val[i].flags = MEM_Real; > + val[i].type = MEM_DOUBLE; > + val[i].flags = 0; > val[i].u.r = field.fval; > break; > case MP_DOUBLE: > - val[i].flags = MEM_Real; > + val[i].type = MEM_DOUBLE; > + val[i].flags = 0; > val[i].u.r = field.dval; > break; > case MP_INT: > - val[i].flags = MEM_Int; > + val[i].type = MEM_INT; > + val[i].flags = 0; > val[i].u.i = field.ival; > break; > case MP_UINT: > - val[i].flags = MEM_UInt; > + val[i].type = MEM_UINT; > + val[i].flags = 0; > val[i].u.i = field.ival; > break; > case MP_STR: > @@ -2919,23 +2999,28 @@ port_c_get_vdbemem(struct port *base, uint32_t *size) > const char *str; > switch (mp_typeof(*data)) { > case MP_BOOL: > - val[i].flags = MEM_Bool; > + val[i].type = MEM_BOOL; > + val[i].flags = 0; > val[i].u.b = mp_decode_bool(&data); > break; > case MP_FLOAT: > - val[i].flags = MEM_Real; > + val[i].type = MEM_DOUBLE; > + val[i].flags = 0; > val[i].u.r = mp_decode_float(&data); > break; > case MP_DOUBLE: > - val[i].flags = MEM_Real; > + val[i].type = MEM_DOUBLE; > + val[i].flags = 0; > val[i].u.r = mp_decode_double(&data); > break; > case MP_INT: > - val[i].flags = MEM_Int; > + val[i].type = MEM_INT; > + val[i].flags = 0; > val[i].u.i = mp_decode_int(&data); > break; > case MP_UINT: > - val[i].flags = MEM_UInt; > + val[i].type = MEM_UINT; > + val[i].flags = 0; > val[i].u.u = mp_decode_uint(&data); > break; > case MP_STR: > diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h > index 1db7f4deb..48c1850d4 100644 > --- a/src/box/sql/mem.h > +++ b/src/box/sql/mem.h > @@ -37,6 +37,35 @@ struct region; > struct mpstream; > struct VdbeFrame; > > +enum mem_type { > + MEM_NULL = 0, > + MEM_UINT, > + MEM_INT, > + MEM_STR, > + MEM_BIN, > + MEM_ARRAY, > + MEM_MAP, > + MEM_BOOL, > + MEM_FLOAT, > + MEM_DOUBLE, > + MEM_INVALID, > + MEM_FRAME, > + MEM_PTR, > + MEM_AGG, > +}; > + > +static_assert((int)MP_NIL == (int)MEM_NULL); > +static_assert((int)MP_UINT == (int)MEM_UINT); > +static_assert((int)MP_INT == (int)MEM_INT); > +static_assert((int)MP_STR == (int)MEM_STR); > +static_assert((int)MP_BIN == (int)MEM_BIN); > +static_assert((int)MP_ARRAY == (int)MEM_ARRAY); > +static_assert((int)MP_MAP == (int)MEM_MAP); > +static_assert((int)MP_BOOL == (int)MEM_BOOL); > +static_assert((int)MP_FLOAT == (int)MEM_FLOAT); > +static_assert((int)MP_DOUBLE == (int)MEM_DOUBLE); > +static_assert((int)MP_EXT == (int)MEM_INVALID); > + > /* > * Internally, the vdbe manipulates nearly all SQL values as Mem > * structures. Each Mem struct may cache multiple representations (string, > @@ -57,9 +86,8 @@ struct Mem { > struct func *func; > struct VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ > } u; > - u32 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ > - /** Subtype for this value. */ > - enum sql_subtype subtype; > + enum mem_type type; > + u32 flags; /* Some combination of MEM_Term, MEM_Zero, MEM_Dyn, etc. */ > /** > * If value is fetched from tuple, then this property > * contains type of corresponding space's field. If it's > @@ -81,29 +109,7 @@ struct Mem { > #endif > }; > > -/* One or more of the following flags are set to indicate the validOK > - * representations of the value stored in the Mem struct. > - * > - * If the MEM_Null flag is set, then the value is an SQL NULL value. > - * No other flags may be set in this case. > - * > - * If the MEM_Str flag is set then Mem.z points at a string representation. > - * Usually this is encoded in the same unicode encoding as the main > - * database (see below for exceptions). If the MEM_Term flag is also > - * set, then the string is nul terminated. The MEM_Int and MEM_Real > - * flags may coexist with the MEM_Str flag. > - */ > -#define MEM_Null 0x0001 /* Value is NULL */ > -#define MEM_Str 0x0002 /* Value is a string */ > -#define MEM_Int 0x0004 /* Value is an integer */ > -#define MEM_Real 0x0008 /* Value is a real number */ > -#define MEM_Blob 0x0010 /* Value is a BLOB */ > -#define MEM_Bool 0x0020 /* Value is a bool */ > -#define MEM_UInt 0x0040 /* Value is an unsigned integer */ > -#define MEM_Frame 0x0080 /* Value is a VdbeFrame object */ > -#define MEM_Undefined 0x0100 /* Value is undefined */ > #define MEM_Cleared 0x0200 /* NULL set by OP_Null, not from data */ > -#define MEM_TypeMask 0x83ff /* Mask of type bits */ > > /* Whenever Mem contains a valid string or blob representation, one of > * the following flags must be set to determine the memory management > @@ -114,175 +120,153 @@ struct Mem { > #define MEM_Dyn 0x0800 /* Need to call Mem.xDel() on Mem.z */ > #define MEM_Static 0x1000 /* Mem.z points to a static string */ > #define MEM_Ephem 0x2000 /* Mem.z points to an ephemeral string */ > -#define MEM_Agg 0x4000 /* Mem.z points to an agg function context */ > #define MEM_Zero 0x8000 /* Mem.i contains count of 0s appended to blob */ > -#define MEM_Subtype 0x10000 /* Mem.eSubtype is valid */ > -#define MEM_Ptr 0x20000 /* Value is a generic pointer */ > - > -/** > - * In contrast to Mem_TypeMask, this one allows to get > - * pure type of memory cell, i.e. without _Dyn/_Zero and other > - * auxiliary flags. > - */ > -enum { > - MEM_PURE_TYPE_MASK = 0x7f > -}; > - > -static_assert(MEM_PURE_TYPE_MASK == (MEM_Null | MEM_Str | MEM_Int | MEM_Real | > - MEM_Blob | MEM_Bool | MEM_UInt), > - "value of type mask must consist of corresponding to memory "\ > - "type bits"); > > static inline bool > mem_is_null(const struct Mem *mem) > { > - return (mem->flags & MEM_Null) != 0; > + return mem->type == MEM_NULL; > } > > static inline bool > mem_is_uint(const struct Mem *mem) > { > - return (mem->flags & MEM_UInt) != 0; > + return mem->type == MEM_UINT; > } > > static inline bool > mem_is_nint(const struct Mem *mem) > { > - return (mem->flags & MEM_Int) != 0; > + return mem->type == MEM_INT; > } > > static inline bool > mem_is_str(const struct Mem *mem) > { > - return (mem->flags & MEM_Str) != 0; > + return mem->type == MEM_STR; > } > > static inline bool > mem_is_num(const struct Mem *mem) > { > - return (mem->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0; > + enum mem_type type = mem->type; > + return type == MEM_UINT || type == MEM_INT || type == MEM_DOUBLE; > } > > static inline bool > mem_is_double(const struct Mem *mem) > { > - return (mem->flags & MEM_Real) != 0; > + return mem->type == MEM_DOUBLE; > } > > static inline bool > mem_is_int(const struct Mem *mem) > { > - return (mem->flags & (MEM_Int | MEM_UInt)) != 0; > + return mem->type == MEM_UINT || mem->type == MEM_INT; > } > > static inline bool > mem_is_bool(const struct Mem *mem) > { > - return (mem->flags & MEM_Bool) != 0; > + return mem->type == MEM_BOOL; > } > > static inline bool > mem_is_bin(const struct Mem *mem) > { > - return (mem->flags & MEM_Blob) != 0; > + enum mem_type type = mem->type; > + return type == MEM_BIN || type == MEM_MAP || type == MEM_ARRAY; > } > > static inline bool > mem_is_map(const struct Mem *mem) > { > - assert((mem->flags & MEM_Subtype) == 0 || (mem->flags & MEM_Blob) != 0); > - assert((mem->flags & MEM_Subtype) == 0 || > - mem->subtype == SQL_SUBTYPE_MSGPACK); > - return (mem->flags & MEM_Subtype) != 0 && mp_typeof(*mem->z) == MP_MAP; > + return mem->type == MEM_MAP; > } > > static inline bool > mem_is_array(const struct Mem *mem) > { > - assert((mem->flags & MEM_Subtype) == 0 || (mem->flags & MEM_Blob) != 0); > - assert((mem->flags & MEM_Subtype) == 0 || > - mem->subtype == SQL_SUBTYPE_MSGPACK); > - return (mem->flags & MEM_Subtype) != 0 && > - mp_typeof(*mem->z) == MP_ARRAY; > + return mem->type == MEM_ARRAY; > } > > static inline bool > mem_is_agg(const struct Mem *mem) > { > - return (mem->flags & MEM_Agg) != 0; > + return mem->type == MEM_AGG; > } > > static inline bool > mem_is_bytes(const struct Mem *mem) > { > - return (mem->flags & (MEM_Blob | MEM_Str)) != 0; > + enum mem_type type = mem->type; > + return type == MEM_BIN || type == MEM_MAP || type == MEM_ARRAY || > + type == MEM_STR; > } > > static inline bool > mem_is_frame(const struct Mem *mem) > { > - return (mem->flags & MEM_Frame) != 0; > + return mem->type == MEM_FRAME; > } > > static inline bool > mem_is_invalid(const struct Mem *mem) > { > - return (mem->flags & MEM_Undefined) != 0; > + return mem->type == MEM_INVALID; > } > > static inline bool > mem_is_static(const struct Mem *mem) > { > - assert((mem->flags & (MEM_Str | MEM_Blob)) != 0); > + assert(mem_is_bytes(mem)); > return (mem->flags & MEM_Static) != 0; > } > > static inline bool > mem_is_ephemeral(const struct Mem *mem) > { > - assert((mem->flags & (MEM_Str | MEM_Blob)) != 0); > + assert(mem_is_bytes(mem)); > return (mem->flags & MEM_Ephem) != 0; > } > > static inline bool > mem_is_dynamic(const struct Mem *mem) > { > - assert((mem->flags & (MEM_Str | MEM_Blob)) != 0); > + assert(mem_is_bytes(mem)); > return (mem->flags & MEM_Dyn) != 0; > } > > static inline bool > mem_is_allocated(const struct Mem *mem) > { > - return (mem->flags & (MEM_Str | MEM_Blob)) != 0 && > - mem->z == mem->zMalloc; > + return mem_is_bytes(mem) && mem->z == mem->zMalloc; > } > > static inline bool > mem_is_cleared(const struct Mem *mem) > { > - assert((mem->flags & MEM_Cleared) == 0 || (mem->flags & MEM_Null) != 0); > + assert((mem->flags & MEM_Cleared) == 0 || mem->type == MEM_NULL); > return (mem->flags & MEM_Cleared) != 0; > } > > static inline bool > mem_is_zerobin(const struct Mem *mem) > { > - assert((mem->flags & MEM_Zero) == 0 || (mem->flags & MEM_Blob) != 0); > + assert((mem->flags & MEM_Zero) == 0 || mem->type == MEM_BIN); > return (mem->flags & MEM_Zero) != 0; > } > > static inline bool > mem_is_same_type(const struct Mem *mem1, const struct Mem *mem2) > { > - return (mem1->flags & MEM_PURE_TYPE_MASK) == > - (mem2->flags & MEM_PURE_TYPE_MASK); > + return mem1->type == mem2->type; > } > > static inline bool > mem_is_any_null(const struct Mem *mem1, const struct Mem *mem2) > { > - return ((mem1->flags | mem2->flags) & MEM_Null) != 0; > + return mem1->type == MEM_NULL || mem2->type == MEM_NULL; > } > > /** > @@ -943,7 +927,7 @@ registerTrace(int iReg, Mem *p); > * Return true if a memory cell is not marked as invalid. This macro > * is for use inside assert() statements only. > */ > -#define memIsValid(M) ((M)->flags & MEM_Undefined)==0 > +#define memIsValid(M) ((M)->type != MEM_INVALID) > #endif > > int sqlVdbeMemExpandBlob(struct Mem *); > @@ -969,8 +953,8 @@ int sqlVdbeMemTooBig(Mem *); > /* Return TRUE if Mem X contains dynamically allocated content - anything > * that needs to be deallocated to avoid a leak. > */ > -#define VdbeMemDynamic(X) \ > - (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_Frame))!=0) > +#define VdbeMemDynamic(X) (((X)->type == MEM_AGG || (X)->type == MEM_FRAME ||\ > + ((X)->flags & MEM_Dyn) != 0)) > > > int sqlMemCompare(const Mem *, const Mem *, const struct coll *); > diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c > index ba5c08a00..1aa201466 100644 > --- a/src/box/sql/vdbemem.c > +++ b/src/box/sql/vdbemem.c > @@ -93,7 +93,8 @@ valueNew(sql * db, struct ValueNewStat4Ctx *p) > pRec->aMem = (Mem *)((char *) pRec + > ROUND8(sizeof(UnpackedRecord))); > for (uint32_t i = 0; i < part_count; i++) { > - pRec->aMem[i].flags = MEM_Null; > + pRec->aMem[i].type = MEM_NULL; > + pRec->aMem[i].flags = 0; > pRec->aMem[i].db = db; > } > p->ppRec[0] = pRec; > -- > 2.25.1 >