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 8C62B6EC5E; Fri, 23 Apr 2021 15:57:32 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 8C62B6EC5E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1619182652; bh=dejil0AAfilcheod4vRllT2JvvhIAvaQElPANeuAzsE=; h=To:Cc:Date:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=jZynxtiGU2nVEy5yS7O5RlV+SBStlACNz9AHhLTxtbzWk63y0tCnLb3WFifxIme22 7RyBrAjG9du0LA2dEIjatbFzwgbpTsT5GENNjsm1GiThI+ktVgknpwqYAKlYrKAch0 Ul2akRbEqz6uBtgseSnQBn2A6PWWPjPZGRjNZBKs= Received: from smtpng2.m.smailru.net (smtpng2.m.smailru.net [94.100.179.3]) (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 D3DF26EC5E for ; Fri, 23 Apr 2021 15:57:30 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org D3DF26EC5E Received: by smtpng2.m.smailru.net with esmtpa (envelope-from ) id 1lZvNB-0008JR-NZ; Fri, 23 Apr 2021 15:57:30 +0300 To: v.shpilevoy@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Fri, 23 Apr 2021 15:57:29 +0300 Message-Id: <9f3ee5e450d2e133bae1e0c131246b1f113f5608.1619182541.git.imeevma@gmail.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD9203E2ABA940B7548DB5D504FB17EC32432A3176CEA2677EC182A05F538085040446E21782AE88631886B5D081614A99C260D1E2A33E98BAF863C1C4AD7FB7602 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7BCC85671EC7A750CEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637BB2557E27C12D3EF8638F802B75D45FF914D58D5BE9E6BC1A93B80C6DEB9DEE97C6FB206A91F05B216E925955FA24D6D94B050ED59A73022C5BC91295CC49E52D2E47CDBA5A96583C09775C1D3CA48CF17B107DEF921CE79117882F4460429724CE54428C33FAD30A8DF7F3B2552694AC26CFBAC0749D213D2E47CDBA5A9658378DA827A17800CE7850F8B975A76562C9FA2833FD35BB23DF004C906525384302BEBFE083D3B9BA71A620F70A64A45A98AA50765F79006372E808ACE2090B5E1725E5C173C3A84C3C5EA940A35A165FF2DBA43225CD8A89F83C798A30B85E16B57739F23D657EF2BB5C8C57E37DE458BEDA766A37F9254B7 X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A2AD77751E876CB595E8F7B195E1C97831543382272C6D5681D792DD908DDF4B51 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C3E7AEEB2EA3DACB3B21B935C0114AB54055A37C47024F8D99C2B6934AE262D3EE7EAB7254005DCED5EFA11C3473D072F9510FB958DCE06DB6ED91DBE5ABE359A3485EE9140A7D39D1B2EFE7B39F7738393EDB24507CE13387DFF0A840B692CF8 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D340A59E724FC7897F7F77909217F6F029949525E2B0D9088D45E9BAE1D2FEC856F4AE8ED2AC1078BB11D7E09C32AA3244C03D8D14EDC69DC6F2749CC8EF2FB9D6E63871F383B54D9B3729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojMA4lh0BuVjP6IcmdQBDqrA== X-Mailru-Sender: 689FA8AB762F73936BC43F508A06382257F5A5B9E838A807FA1329CBE829659983D72C36FC87018B9F80AB2734326CD2FB559BB5D741EB96352A0ABBE4FDA4210A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: [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: imeevma@tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" 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