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 023A36EC41; Wed, 11 Aug 2021 19:02:18 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 023A36EC41 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1628697738; bh=9n0dOdxYb9HkvlklMEsBXfGLOleFBzQjg2K7wNNIWxg=; h=To:Cc:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=DbrGsfBaelD+OVpjquesRH+2/7o3r1u1786nQHXDyLsVqpEspbLwn62KoRUBWmzcm 1ROPQZQayjcm/Rt4VGsvtDc4XHY8+E5eD0T7qRwFfexTNkVebyqaNK2eh9IUshWAo1 KK668h04JB5HrOjAeLZbrGHJqPLjwYOZpIuig6BA= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [94.100.181.251]) (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 2AFDD6EC41 for ; Wed, 11 Aug 2021 19:01:42 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 2AFDD6EC41 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1mDqfk-0005gQ-DJ; Wed, 11 Aug 2021 19:01:40 +0300 To: v.shpilevoy@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Wed, 11 Aug 2021 19:01:40 +0300 Message-Id: <53edb7f037875e1bb0ce509518524f3a6b862440.1628697448.git.imeevma@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD92087353F0EC44DD9ECFD080E047A606F6525B29142351271182A05F5380850409638F84A74482A7CF109E12C501E2B437844B688B81F8F7B28BD204D11FFCE4D X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7495A032B936E882FEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006374D78D7F7271F09E9EA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BBCA57AF85F7723F2E867EFE58C702292C6170E350D950C30CC7F00164DA146DAFE8445B8C89999728AA50765F790063783E00425F71A4181389733CBF5DBD5E9C8A9BA7A39EFB766F5D81C698A659EA7CC7F00164DA146DA9985D098DBDEAEC8C2B5EEE3591E0D35F6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA7E827F84554CEF5019E625A9149C048EE9ECD01F8117BC8BEE2021AF6380DFAD18AA50765F790063735872C767BF85DA227C277FBC8AE2E8BDC0F6C5B2EEF3D0C75ECD9A6C639B01B4E70A05D1297E1BBCB5012B2E24CD356 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C6B668463F4F89F864D01CF005AF2DA6C0BE20225C68C966F9C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EFA183FDCE24978B01699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D340D3A19269BBEBAAF9A113221A6095A257468F84003AFB40C329C65F817E6DC07C4642A769F46ADE41D7E09C32AA3244CE5EF120F893D974A65DAFC5EE17A25B3B4DF56057A86259F729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj6qlzQV0oSZPQaq/eG3dgfg== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5D9DFC4799439D5A5B6CC876B89F47676A83D72C36FC87018B9F80AB2734326CD2FB559BB5D741EB96352A0ABBE4FDA4210A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH v1 1/7] sql: remove enum field_type from struct Mem 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 removes the enum field_type from the struct MEM since the only place where this field was used is in the typeof() function. After this patch, typeof() will return "NULL" if it receives NULL. Prior to this patch, the field type was returned if it was set, otherwise it was returned "boolean". Another reason for the removal was that field_type was quite volatile and could change in unexpected places. Also, this patch made another change: values of the field type NUMBER will now be processed by the typeof() as INTEGER or DOUBLE, depending on the storage type. However, this will be fixed in the next patch. Part of #5956 Needed for #6221 --- .../gh-5956-remove-field-types-from-mem.md | 3 + src/box/sql/func.c | 15 +-- src/box/sql/mem.c | 120 +++--------------- src/box/sql/mem.h | 7 - src/box/sql/vdbe.c | 25 +--- src/box/sql/vdbeInt.h | 3 - src/box/sql/vdbesort.c | 6 - test/sql-tap/cast.test.lua | 16 +-- test/sql-tap/default.test.lua | 2 +- test/sql-tap/func.test.lua | 12 +- test/sql-tap/func5.test.lua | 75 ++++++++++- test/sql-tap/select7.test.lua | 4 +- test/sql-tap/table.test.lua | 4 +- test/sql-tap/tkt-3998683a16.test.lua | 1 - test/sql/boolean.result | 4 +- test/sql/gh-4697-scalar-bool-sort-cmp.result | 4 +- test/sql/types.result | 8 +- 17 files changed, 128 insertions(+), 181 deletions(-) create mode 100644 changelogs/unreleased/gh-5956-remove-field-types-from-mem.md diff --git a/changelogs/unreleased/gh-5956-remove-field-types-from-mem.md b/changelogs/unreleased/gh-5956-remove-field-types-from-mem.md new file mode 100644 index 000000000..81fc21233 --- /dev/null +++ b/changelogs/unreleased/gh-5956-remove-field-types-from-mem.md @@ -0,0 +1,3 @@ +## feature/sql + +* The typeof() function with NULL as an argument now returns "NULL" (gh-5956). diff --git a/src/box/sql/func.c b/src/box/sql/func.c index 1622104d3..5ac5c5e56 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -162,17 +162,6 @@ typeofFunc(sql_context * context, int NotUsed, sql_value ** argv) { const char *z = 0; UNUSED_PARAMETER(NotUsed); - enum field_type f_t = argv[0]->field_type; - /* - * SCALAR is not a basic type, but rather an aggregation of - * types. Thus, ignore SCALAR field type and return msgpack - * format type. - */ - if (f_t != field_type_MAX && f_t != FIELD_TYPE_SCALAR) { - sql_result_text(context, field_type_strs[argv[0]->field_type], - -1, SQL_STATIC); - return; - } switch (argv[0]->type) { case MEM_TYPE_INT: case MEM_TYPE_UINT: @@ -190,9 +179,11 @@ typeofFunc(sql_context * context, int NotUsed, sql_value ** argv) z = "varbinary"; break; case MEM_TYPE_BOOL: - case MEM_TYPE_NULL: z = "boolean"; break; + case MEM_TYPE_NULL: + z = "NULL"; + break; case MEM_TYPE_UUID: z = "uuid"; break; diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index d1ef92a86..773ef4d40 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -193,7 +193,6 @@ mem_create(struct Mem *mem) { mem->type = MEM_TYPE_NULL; mem->flags = 0; - mem->field_type = field_type_MAX; mem->n = 0; mem->z = NULL; mem->zMalloc = NULL; @@ -226,7 +225,6 @@ mem_clear(struct Mem *mem) } mem->type = MEM_TYPE_NULL; mem->flags = 0; - mem->field_type = field_type_MAX; } void @@ -255,7 +253,6 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg) mem->u.i = value; mem->type = is_neg ? MEM_TYPE_INT : MEM_TYPE_UINT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_INTEGER; } void @@ -265,7 +262,6 @@ mem_set_uint(struct Mem *mem, uint64_t value) mem->u.u = value; mem->type = MEM_TYPE_UINT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_UNSIGNED; } void @@ -275,14 +271,12 @@ mem_set_bool(struct Mem *mem, bool value) mem->u.b = value; mem->type = MEM_TYPE_BOOL; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_BOOLEAN; } void mem_set_double(struct Mem *mem, double value) { mem_clear(mem); - mem->field_type = FIELD_TYPE_DOUBLE; assert(mem->flags == 0); if (sqlIsNaN(value)) return; @@ -294,7 +288,6 @@ void mem_set_uuid(struct Mem *mem, const struct tt_uuid *uuid) { mem_clear(mem); - mem->field_type = FIELD_TYPE_UUID; mem->u.uuid = *uuid; mem->type = MEM_TYPE_UUID; assert(mem->flags == 0); @@ -309,7 +302,6 @@ set_str_const(struct Mem *mem, char *value, uint32_t len, int alloc_type) mem->n = len; mem->type = MEM_TYPE_STR; mem->flags = alloc_type; - mem->field_type = FIELD_TYPE_STRING; } static inline void @@ -323,7 +315,6 @@ set_str_dynamic(struct Mem *mem, char *value, uint32_t len, int alloc_type) mem->n = len; mem->type = MEM_TYPE_STR; mem->flags = alloc_type; - mem->field_type = FIELD_TYPE_STRING; if (alloc_type == MEM_Dyn) { mem->xDel = sql_free; } else { @@ -395,7 +386,6 @@ mem_copy_str(struct Mem *mem, const char *value, uint32_t len) return -1; mem->type = MEM_TYPE_STR; mem->flags = 0; - mem->field_type = FIELD_TYPE_STRING; return 0; } mem_clear(mem); @@ -405,7 +395,6 @@ mem_copy_str(struct Mem *mem, const char *value, uint32_t len) mem->n = len; mem->type = MEM_TYPE_STR; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_STRING; return 0; } @@ -429,7 +418,6 @@ set_bin_const(struct Mem *mem, char *value, uint32_t size, int alloc_type) mem->n = size; mem->type = MEM_TYPE_BIN; mem->flags = alloc_type; - mem->field_type = FIELD_TYPE_VARBINARY; } static inline void @@ -443,7 +431,6 @@ set_bin_dynamic(struct Mem *mem, char *value, uint32_t size, int alloc_type) mem->n = size; mem->type = MEM_TYPE_BIN; mem->flags = alloc_type; - mem->field_type = FIELD_TYPE_VARBINARY; if (alloc_type == MEM_Dyn) { mem->xDel = sql_free; } else { @@ -487,7 +474,6 @@ mem_copy_bin(struct Mem *mem, const char *value, uint32_t size) return -1; mem->type = MEM_TYPE_BIN; mem->flags = 0; - mem->field_type = FIELD_TYPE_VARBINARY; return 0; } mem_clear(mem); @@ -497,7 +483,6 @@ mem_copy_bin(struct Mem *mem, const char *value, uint32_t size) mem->n = size; mem->type = MEM_TYPE_BIN; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_VARBINARY; return 0; } @@ -512,76 +497,73 @@ mem_set_zerobin(struct Mem *mem, int n) mem->n = 0; mem->type = MEM_TYPE_BIN; mem->flags = MEM_Zero; - mem->field_type = FIELD_TYPE_VARBINARY; } static inline void set_msgpack_value(struct Mem *mem, char *value, uint32_t size, int alloc_type, - enum field_type type) + enum mem_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->type = type == FIELD_TYPE_MAP ? MEM_TYPE_MAP : MEM_TYPE_ARRAY; - mem->field_type = type; + mem->type = type; } void mem_set_map_ephemeral(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_MAP); - set_msgpack_value(mem, value, size, MEM_Ephem, FIELD_TYPE_MAP); + set_msgpack_value(mem, value, size, MEM_Ephem, MEM_TYPE_MAP); } void mem_set_map_static(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_MAP); - set_msgpack_value(mem, value, size, MEM_Static, FIELD_TYPE_MAP); + set_msgpack_value(mem, value, size, MEM_Static, MEM_TYPE_MAP); } void mem_set_map_dynamic(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_MAP); - set_msgpack_value(mem, value, size, MEM_Dyn, FIELD_TYPE_MAP); + set_msgpack_value(mem, value, size, MEM_Dyn, MEM_TYPE_MAP); } void mem_set_map_allocated(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_MAP); - set_msgpack_value(mem, value, size, 0, FIELD_TYPE_MAP); + set_msgpack_value(mem, value, size, 0, MEM_TYPE_MAP); } void mem_set_array_ephemeral(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_ARRAY); - set_msgpack_value(mem, value, size, MEM_Ephem, FIELD_TYPE_ARRAY); + set_msgpack_value(mem, value, size, MEM_Ephem, MEM_TYPE_ARRAY); } void mem_set_array_static(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_ARRAY); - set_msgpack_value(mem, value, size, MEM_Static, FIELD_TYPE_ARRAY); + set_msgpack_value(mem, value, size, MEM_Static, MEM_TYPE_ARRAY); } void mem_set_array_dynamic(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_ARRAY); - set_msgpack_value(mem, value, size, MEM_Dyn, FIELD_TYPE_ARRAY); + set_msgpack_value(mem, value, size, MEM_Dyn, MEM_TYPE_ARRAY); } void mem_set_array_allocated(struct Mem *mem, char *value, uint32_t size) { assert(mp_typeof(*value) == MP_ARRAY); - set_msgpack_value(mem, value, size, 0, FIELD_TYPE_ARRAY); + set_msgpack_value(mem, value, size, 0, MEM_TYPE_ARRAY); } void @@ -623,7 +605,6 @@ mem_set_agg(struct Mem *mem, struct func *func, int size) mem->type = MEM_TYPE_AGG; assert(mem->flags == 0); mem->u.func = func; - mem->field_type = field_type_MAX; return 0; } @@ -646,7 +627,6 @@ int_to_double(struct Mem *mem) mem->u.r = d; mem->type = MEM_TYPE_DOUBLE; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_DOUBLE; return 0; } @@ -660,7 +640,6 @@ int_to_double_precise(struct Mem *mem) return -1; mem->u.r = d; mem->type = MEM_TYPE_DOUBLE; - mem->field_type = FIELD_TYPE_DOUBLE; return 0; } @@ -677,7 +656,6 @@ int_to_double_forced(struct Mem *mem) double d = (double)i; mem->u.r = d; mem->type = MEM_TYPE_DOUBLE; - mem->field_type = FIELD_TYPE_DOUBLE; return CMP_OLD_NEW(i, d, int64_t); } @@ -691,7 +669,6 @@ uint_to_double_precise(struct Mem *mem) return -1; mem->u.r = d; mem->type = MEM_TYPE_DOUBLE; - mem->field_type = FIELD_TYPE_DOUBLE; return 0; } @@ -708,7 +685,6 @@ uint_to_double_forced(struct Mem *mem) double d = (double)u; mem->u.r = d; mem->type = MEM_TYPE_DOUBLE; - mem->field_type = FIELD_TYPE_DOUBLE; return CMP_OLD_NEW(u, d, uint64_t); } @@ -732,7 +708,6 @@ str_to_str0(struct Mem *mem) return -1; mem->z[mem->n] = '\0'; mem->flags |= MEM_Term; - mem->field_type = FIELD_TYPE_STRING; return 0; } @@ -742,7 +717,6 @@ str_to_bin(struct Mem *mem) assert(mem->type == MEM_TYPE_STR); mem->type = MEM_TYPE_BIN; mem->flags &= ~MEM_Term; - mem->field_type = FIELD_TYPE_VARBINARY; return 0; } @@ -791,7 +765,6 @@ bin_to_str(struct Mem *mem) if (ExpandBlob(mem) != 0) return -1; mem->type = MEM_TYPE_STR; - mem->field_type = FIELD_TYPE_STRING; return 0; } @@ -806,7 +779,6 @@ bin_to_str0(struct Mem *mem) mem->z[mem->n] = '\0'; mem->type = MEM_TYPE_STR; mem->flags = MEM_Term; - mem->field_type = FIELD_TYPE_STRING; return 0; } @@ -869,14 +841,12 @@ double_to_int(struct Mem *mem) mem->u.i = (int64_t)d; mem->type = MEM_TYPE_INT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_INTEGER; return 0; } if (d > -1.0 && d < (double)UINT64_MAX) { mem->u.u = (uint64_t)d; mem->type = MEM_TYPE_UINT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_UNSIGNED; return 0; } return -1; @@ -891,14 +861,12 @@ double_to_int_precise(struct Mem *mem) mem->u.i = (int64_t)d; mem->type = MEM_TYPE_INT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_INTEGER; return 0; } if (d > -1.0 && d < (double)UINT64_MAX && (double)(uint64_t)d == d) { mem->u.u = (uint64_t)d; mem->type = MEM_TYPE_UINT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_UNSIGNED; return 0; } return -1; @@ -937,7 +905,6 @@ double_to_int_forced(struct Mem *mem) } mem->u.i = i; mem->type = type; - mem->field_type = FIELD_TYPE_INTEGER; return res; } @@ -950,7 +917,6 @@ double_to_uint(struct Mem *mem) mem->u.u = (uint64_t)d; mem->type = MEM_TYPE_UINT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_UNSIGNED; return 0; } return -1; @@ -965,7 +931,6 @@ double_to_uint_precise(struct Mem *mem) mem->u.u = (uint64_t)d; mem->type = MEM_TYPE_UINT; assert(mem->flags == 0); - mem->field_type = FIELD_TYPE_UNSIGNED; return 0; } return -1; @@ -995,7 +960,6 @@ double_to_uint_forced(struct Mem *mem) } mem->u.u = u; mem->type = MEM_TYPE_UINT; - mem->field_type = FIELD_TYPE_UNSIGNED; return res; } @@ -1009,7 +973,6 @@ double_to_str0(struct Mem *mem) mem->n = strlen(mem->z); mem->type = MEM_TYPE_STR; mem->flags = MEM_Term; - mem->field_type = FIELD_TYPE_STRING; return 0; } @@ -1165,10 +1128,8 @@ mem_to_str(struct Mem *mem) int mem_cast_explicit(struct Mem *mem, enum field_type type) { - if (mem->type == MEM_TYPE_NULL) { - mem->field_type = type; + if (mem->type == MEM_TYPE_NULL) return 0; - } switch (type) { case FIELD_TYPE_UNSIGNED: switch (mem->type) { @@ -1227,10 +1188,8 @@ mem_cast_explicit(struct Mem *mem, enum field_type type) int mem_cast_implicit(struct Mem *mem, enum field_type type) { - if (mem->type == MEM_TYPE_NULL) { - mem->field_type = type; + if (mem->type == MEM_TYPE_NULL) return 0; - } switch (type) { case FIELD_TYPE_UNSIGNED: if (mem->type == MEM_TYPE_UINT) @@ -1301,12 +1260,10 @@ mem_cast_implicit_number(struct Mem *mem, enum field_type type) case FIELD_TYPE_UNSIGNED: switch (mem->type) { case MEM_TYPE_UINT: - mem->field_type = FIELD_TYPE_UNSIGNED; return 0; case MEM_TYPE_INT: mem->u.u = 0; mem->type = MEM_TYPE_UINT; - mem->field_type = FIELD_TYPE_UNSIGNED; return -1; case MEM_TYPE_DOUBLE: return double_to_uint_forced(mem); @@ -1330,7 +1287,6 @@ mem_cast_implicit_number(struct Mem *mem, enum field_type type) switch (mem->type) { case MEM_TYPE_UINT: case MEM_TYPE_INT: - mem->field_type = FIELD_TYPE_INTEGER; return 0; case MEM_TYPE_DOUBLE: return double_to_int_forced(mem); @@ -1487,7 +1443,6 @@ mem_copy(struct Mem *to, const struct Mem *from) to->u = from->u; to->type = from->type; to->flags = from->flags; - to->field_type = from->field_type; to->n = from->n; to->z = from->z; if (!mem_is_bytes(to)) @@ -1514,7 +1469,6 @@ mem_copy_as_ephemeral(struct Mem *to, const struct Mem *from) to->u = from->u; to->type = from->type; to->flags = from->flags; - to->field_type = from->field_type; to->n = from->n; to->z = from->z; if (!mem_is_bytes(to)) @@ -1537,30 +1491,13 @@ mem_move(struct Mem *to, struct Mem *from) from->zMalloc = NULL; } -static bool -try_return_null(const struct Mem *a, const struct Mem *b, struct Mem *result, - enum field_type type) -{ - mem_clear(result); - result->field_type = type; - return ((a->type | b->type) & MEM_TYPE_NULL) != 0; -} - int mem_concat(struct Mem *a, struct Mem *b, struct Mem *result) { - assert(result != b); - if (a != result) { - if (try_return_null(a, b, result, FIELD_TYPE_STRING)) - return 0; - } else { - if (((a->type | b->type) & MEM_TYPE_NULL) != 0) { - mem_clear(a); - result->field_type = FIELD_TYPE_STRING; - return 0; - } + if (mem_is_any_null(a, b)) { + mem_set_null(result); + return 0; } - /* Concatenation operation can be applied only to strings and blobs. */ if (((b->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) == 0)) { diag_set(ClientError, ER_INCONSISTENT_TYPES, @@ -1593,8 +1530,6 @@ mem_concat(struct Mem *a, struct Mem *b, struct Mem *result) result->type = a->type; result->flags = 0; - if (result->type == MEM_TYPE_BIN) - result->field_type = FIELD_TYPE_VARBINARY; if (result != a) memcpy(result->z, a->z, a->n); memcpy(&result->z[a->n], b->z, b->n); @@ -1607,7 +1542,6 @@ mem_add(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_NUMBER; return 0; } if (!mem_is_num(right)) { @@ -1644,7 +1578,6 @@ mem_sub(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_NUMBER; return 0; } if (!mem_is_num(right)) { @@ -1681,7 +1614,6 @@ mem_mul(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_NUMBER; return 0; } if (!mem_is_num(right)) { @@ -1718,7 +1650,6 @@ mem_div(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_NUMBER; return 0; } if (!mem_is_num(right)) { @@ -1764,7 +1695,6 @@ mem_rem(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_INTEGER; return 0; } if (!mem_is_int(right)) { @@ -1797,7 +1727,6 @@ mem_bit_and(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_UNSIGNED; return 0; } if (right->type != MEM_TYPE_UINT) { @@ -1819,7 +1748,6 @@ mem_bit_or(const struct Mem *left, const struct Mem *right, struct Mem *result) { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_UNSIGNED; return 0; } if (right->type != MEM_TYPE_UINT) { @@ -1842,7 +1770,6 @@ mem_shift_left(const struct Mem *left, const struct Mem *right, { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_UNSIGNED; return 0; } if (right->type != MEM_TYPE_UINT) { @@ -1865,7 +1792,6 @@ mem_shift_right(const struct Mem *left, const struct Mem *right, { if (mem_is_any_null(left, right)) { mem_set_null(result); - result->field_type = FIELD_TYPE_UNSIGNED; return 0; } if (right->type != MEM_TYPE_UINT) { @@ -1887,7 +1813,6 @@ mem_bit_not(const struct Mem *mem, struct Mem *result) { if (mem_is_null(mem)) { mem_set_null(result); - result->field_type = FIELD_TYPE_UNSIGNED; return 0; } if (mem->type != MEM_TYPE_UINT) { @@ -2557,7 +2482,6 @@ sql_vdbemem_finalize(struct Mem *mem, struct func *func) t.type = MEM_TYPE_NULL; assert(t.flags == 0); t.db = mem->db; - t.field_type = field_type_MAX; ctx.pOut = &t; ctx.pMem = mem; ctx.func = func; @@ -2604,7 +2528,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) mem->n = buf - mem->z; mem->type = MEM_TYPE_ARRAY; mem->flags = MEM_Ephem; - mem->field_type = FIELD_TYPE_ARRAY; break; } case MP_MAP: { @@ -2613,7 +2536,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) mem->n = buf - mem->z; mem->type = MEM_TYPE_MAP; mem->flags = MEM_Ephem; - mem->field_type = FIELD_TYPE_MAP; break; } case MP_EXT: { @@ -2630,7 +2552,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) } mem->type = MEM_TYPE_UUID; mem->flags = 0; - mem->field_type = FIELD_TYPE_UUID; break; } buf += size; @@ -2638,21 +2559,18 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) mem->n = buf - svp; mem->type = MEM_TYPE_BIN; mem->flags = MEM_Ephem; - mem->field_type = FIELD_TYPE_VARBINARY; break; } case MP_NIL: { mp_decode_nil(&buf); mem->type = MEM_TYPE_NULL; mem->flags = 0; - mem->field_type = field_type_MAX; break; } case MP_BOOL: { mem->u.b = mp_decode_bool(&buf); mem->type = MEM_TYPE_BOOL; mem->flags = 0; - mem->field_type = FIELD_TYPE_BOOLEAN; break; } case MP_UINT: { @@ -2660,14 +2578,12 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) mem->u.u = v; mem->type = MEM_TYPE_UINT; mem->flags = 0; - mem->field_type = FIELD_TYPE_INTEGER; break; } case MP_INT: { mem->u.i = mp_decode_int(&buf); mem->type = MEM_TYPE_INT; mem->flags = 0; - mem->field_type = FIELD_TYPE_INTEGER; break; } case MP_STR: { @@ -2675,7 +2591,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len) mem->n = (int) mp_decode_strl(&buf); mem->type = MEM_TYPE_STR; mem->flags = MEM_Ephem; - mem->field_type = FIELD_TYPE_STRING; install_blob: mem->z = (char *)buf; buf += mem->n; @@ -2686,7 +2601,6 @@ install_blob: mem->n = (int) mp_decode_binl(&buf); mem->type = MEM_TYPE_BIN; mem->flags = MEM_Ephem; - mem->field_type = FIELD_TYPE_VARBINARY; goto install_blob; } case MP_FLOAT: { @@ -2694,11 +2608,9 @@ install_blob: if (sqlIsNaN(mem->u.r)) { mem->type = MEM_TYPE_NULL; mem->flags = 0; - mem->field_type = FIELD_TYPE_DOUBLE; } else { mem->type = MEM_TYPE_DOUBLE; mem->flags = 0; - mem->field_type = FIELD_TYPE_DOUBLE; } break; } @@ -2707,11 +2619,9 @@ install_blob: if (sqlIsNaN(mem->u.r)) { mem->type = MEM_TYPE_NULL; mem->flags = 0; - mem->field_type = FIELD_TYPE_DOUBLE; } else { mem->type = MEM_TYPE_DOUBLE; mem->flags = 0; - mem->field_type = FIELD_TYPE_DOUBLE; } break; } diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 9681fc736..958907aaf 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -79,13 +79,6 @@ struct Mem { /** Type of the value this MEM contains. */ enum mem_type type; u32 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ - /** - * If value is fetched from tuple, then this property - * contains type of corresponding space's field. If it's - * value field_type_MAX then we can rely on on format - * (msgpack) type which is represented by 'flags'. - */ - enum field_type field_type; int n; /* size (in bytes) of string value, excluding trailing '\0' */ char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 14caa6f82..db5f96b62 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -277,7 +277,6 @@ vdbe_prepare_null_out(struct Vdbe *v, int n) struct Mem *out = &v->aMem[n]; memAboutToChange(v, out); mem_set_null(out); - out->field_type = field_type_MAX; return out; } @@ -1354,7 +1353,7 @@ case OP_BitAnd: { /* same as TK_BITAND, in1, in2, out3 */ pOut = &aMem[pOp->p3]; if (mem_bit_and(pIn2, pIn1, pOut) != 0) goto abort_due_to_error; - assert(pOut->field_type == FIELD_TYPE_UNSIGNED); + assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL); break; } @@ -1371,7 +1370,7 @@ case OP_BitOr: { /* same as TK_BITOR, in1, in2, out3 */ pOut = &aMem[pOp->p3]; if (mem_bit_or(pIn2, pIn1, pOut) != 0) goto abort_due_to_error; - assert(pOut->field_type == FIELD_TYPE_UNSIGNED); + assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL); break; } @@ -1389,7 +1388,7 @@ case OP_ShiftLeft: { /* same as TK_LSHIFT, in1, in2, out3 */ pOut = &aMem[pOp->p3]; if (mem_shift_left(pIn2, pIn1, pOut) != 0) goto abort_due_to_error; - assert(pOut->field_type == FIELD_TYPE_UNSIGNED); + assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL); break; } @@ -1407,7 +1406,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ pOut = &aMem[pOp->p3]; if (mem_shift_right(pIn2, pIn1, pOut) != 0) goto abort_due_to_error; - assert(pOut->field_type == FIELD_TYPE_UNSIGNED); + assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL); break; } @@ -1465,13 +1464,6 @@ case OP_Cast: { /* in1 */ if (ExpandBlob(pIn1) != 0) goto abort_due_to_error; rc = mem_cast_explicit(pIn1, pOp->p2); - /* - * SCALAR is not type itself, but rather an aggregation - * of types. Hence, cast to this type shouldn't change - * original type of argument. - */ - if (pOp->p2 != FIELD_TYPE_SCALAR) - pIn1->field_type = pOp->p2; UPDATE_MAX_BLOBSIZE(pIn1); if (rc == 0) break; @@ -1809,7 +1801,6 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ case OP_Not: { /* same as TK_NOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; pOut = vdbe_prepare_null_out(p, pOp->p2); - pOut->field_type = FIELD_TYPE_BOOLEAN; if (!mem_is_null(pIn1)) { if (!mem_is_bool(pIn1)) { diag_set(ClientError, ER_SQL_TYPE_MISMATCH, @@ -1979,11 +1970,8 @@ case OP_Column: { } pC->cacheStatus = p->cacheCtr; } - enum field_type field_type = field_type_MAX; - if (pC->eCurType == CURTYPE_TARANTOOL) - field_type = pC->uc.pCursor->space->def->fields[p2].type; - else if (pC->eCurType == CURTYPE_SORTER) - field_type = vdbe_sorter_get_field_type(pC->uc.pSorter, p2); + assert(pC->eCurType == CURTYPE_TARANTOOL || + pC->eCurType == CURTYPE_PSEUDO); struct Mem *default_val_mem = pOp->p4type == P4_MEM ? pOp->p4.pMem : NULL; if (vdbe_field_ref_fetch(&pC->field_ref, p2, pDest) != 0) @@ -1994,7 +1982,6 @@ case OP_Column: { default_val_mem != NULL) { mem_copy_as_ephemeral(pDest, default_val_mem); } - pDest->field_type = field_type; op_column_out: REGISTER_TRACE(p, pOp->p3, pDest); break; diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h index b4ad8b774..cfe743b94 100644 --- a/src/box/sql/vdbeInt.h +++ b/src/box/sql/vdbeInt.h @@ -341,9 +341,6 @@ int sqlVdbeFrameRestore(VdbeFrame *); int sqlVdbeSorterInit(struct sql *db, struct VdbeCursor *cursor); void sqlVdbeSorterReset(sql *, VdbeSorter *); -enum field_type -vdbe_sorter_get_field_type(struct VdbeSorter *sorter, uint32_t field_no); - void sqlVdbeSorterClose(sql *, VdbeCursor *); int sqlVdbeSorterRowkey(const VdbeCursor *, Mem *); int sqlVdbeSorterNext(sql *, const VdbeCursor *, int *); diff --git a/src/box/sql/vdbesort.c b/src/box/sql/vdbesort.c index 3da425be4..aadafeabd 100644 --- a/src/box/sql/vdbesort.c +++ b/src/box/sql/vdbesort.c @@ -969,12 +969,6 @@ sqlVdbeSorterReset(sql * db, VdbeSorter * pSorter) pSorter->pUnpacked = 0; } -enum field_type -vdbe_sorter_get_field_type(struct VdbeSorter *sorter, uint32_t field_no) -{ - return sorter->key_def->parts[field_no].type; -} - /* * Free any cursor components allocated by sqlVdbeSorterXXX routines. */ diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua index 927114772..4f2bff93e 100755 --- a/test/sql-tap/cast.test.lua +++ b/test/sql-tap/cast.test.lua @@ -120,7 +120,7 @@ test:do_execsql_test( SELECT typeof(NULL) ]], { -- - "boolean" + "NULL" -- }) @@ -140,7 +140,7 @@ test:do_execsql_test( SELECT typeof(CAST(NULL AS text)) ]], { -- - "string" + "NULL" -- }) @@ -160,7 +160,7 @@ test:do_execsql_test( SELECT typeof(CAST(NULL AS NUMBER)) ]], { -- - "number" + "NULL" -- }) @@ -180,7 +180,7 @@ test:do_execsql_test( SELECT typeof(CAST(NULL AS SCALAR)) ]], { -- - "boolean" + "NULL" -- }) @@ -200,7 +200,7 @@ test:do_execsql_test( SELECT typeof(CAST(NULL AS integer)) ]], { -- - "integer" + "NULL" -- }) @@ -511,7 +511,7 @@ test:do_execsql_test( SELECT typeof(CAST(null AS NUMBER)) ]], { -- - "number" + "NULL" -- }) @@ -531,7 +531,7 @@ test:do_execsql_test( SELECT typeof(CAST(1 AS NUMBER)) ]], { -- - "number" + "integer" -- }) @@ -551,7 +551,7 @@ test:do_execsql_test( SELECT typeof(CAST('1' AS NUMBER)) ]], { -- - "number" + "integer" -- }) diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua index 9c15220eb..59dc2a2a1 100755 --- a/test/sql-tap/default.test.lua +++ b/test/sql-tap/default.test.lua @@ -115,7 +115,7 @@ test:do_execsql_test( g, typeof(g) FROM t3; ]], { -- - 1, "integer", 5, "integer", "row1", "string", 5.25, "number", 8.67, "number", "321", "string", 432, "integer" + 1, "integer", 5, "integer", "row1", "string", 5.25, "double", 8.67, "double", "321", "string", 432, "integer" -- }) diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua index df55ff9cf..4cc722d1e 100755 --- a/test/sql-tap/func.test.lua +++ b/test/sql-tap/func.test.lua @@ -1814,7 +1814,7 @@ test:do_execsql_test( SELECT typeof(replace('This is the main test string', NULL, 'ALT')); ]], { -- - "boolean" + "NULL" -- }) @@ -1824,7 +1824,7 @@ test:do_execsql_test( SELECT typeof(replace(NULL, 'main', 'ALT')); ]], { -- - "boolean" + "NULL" -- }) @@ -1834,7 +1834,7 @@ test:do_execsql_test( SELECT typeof(replace('This is the main test string', 'main', NULL)); ]], { -- - "boolean" + "NULL" -- }) @@ -2055,7 +2055,7 @@ test:do_execsql_test( SELECT typeof(trim(NULL)); ]], { -- - "boolean" + "NULL" -- }) @@ -2065,7 +2065,7 @@ test:do_execsql_test( SELECT typeof(TRIM('xyz' FROM NULL)); ]], { -- - "boolean" + "NULL" -- }) @@ -2075,7 +2075,7 @@ test:do_execsql_test( SELECT typeof(TRIM(NULL FROM 'hello')); ]], { -- - "boolean" + "NULL" -- }) diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua index f07fc5fd9..44755b1f7 100755 --- a/test/sql-tap/func5.test.lua +++ b/test/sql-tap/func5.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool local test = require("sqltester") -test:plan(29) +test:plan(38) --!./tcltestrunner.lua -- 2010 August 27 @@ -371,4 +371,77 @@ test:do_execsql_test( 111 }) +-- gh-5956: typeof(NULL) now returns 'NULL'. +test:do_execsql_test( + "func-8.1", + [[ + SELECT typeof(CAST(NULL AS UUID)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.2", + [[ + SELECT typeof(CAST(NULL AS SCALAR)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.3", + [[ + SELECT typeof(CAST(NULL AS BOOLEAN)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.4", + [[ + SELECT typeof(CAST(NULL AS INTEGER)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.5", + [[ + SELECT typeof(CAST(NULL AS UNSIGNED)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.6", + [[ + SELECT typeof(CAST(NULL AS DOUBLE)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.7", + [[ + SELECT typeof(CAST(NULL AS NUMBER)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.8", + [[ + SELECT typeof(CAST(NULL AS STRING)); + ]], { + 'NULL' + }) + +test:do_execsql_test( + "func-8.9", + [[ + SELECT typeof(CAST(NULL AS VARBINARY)); + ]], { + 'NULL' + }) + test:finish_test() diff --git a/test/sql-tap/select7.test.lua b/test/sql-tap/select7.test.lua index 815f9110b..47e7240ed 100755 --- a/test/sql-tap/select7.test.lua +++ b/test/sql-tap/select7.test.lua @@ -235,7 +235,7 @@ test:do_execsql_test( SELECT a=0, typeof(a) FROM t4 ]], { -- - false, "number", false, "number" + false, "double", false, "double" -- }) @@ -245,7 +245,7 @@ test:do_execsql_test( SELECT a=0, typeof(a) FROM t4 GROUP BY a ]], { -- - false, "number", false, "number" + false, "double", false, "double" -- }) diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua index ecd9adcd8..4592909ff 100755 --- a/test/sql-tap/table.test.lua +++ b/test/sql-tap/table.test.lua @@ -906,7 +906,7 @@ test:do_execsql_test( FROM t7 LIMIT 1; ]], { -- - "integer", "number", "string", "string", "boolean", "boolean", "string", "string" + "integer", "NULL", "NULL", "NULL", "NULL", "NULL", "NULL", "NULL" -- }) @@ -917,7 +917,7 @@ test:do_execsql_test( FROM t7 LIMIT 1; ]], { -- - "number", "string", "number", "string" + "NULL", "NULL", "NULL", "NULL" -- }) diff --git a/test/sql-tap/tkt-3998683a16.test.lua b/test/sql-tap/tkt-3998683a16.test.lua index 44ce7087a..81c7806ad 100755 --- a/test/sql-tap/tkt-3998683a16.test.lua +++ b/test/sql-tap/tkt-3998683a16.test.lua @@ -36,7 +36,6 @@ test:do_test( ]] end, { -- - 1, 2, 3, 4, 5, 6 -- }) diff --git a/test/sql/boolean.result b/test/sql/boolean.result index 6e7ad179f..d027a56e3 100644 --- a/test/sql/boolean.result +++ b/test/sql/boolean.result @@ -331,8 +331,8 @@ SELECT typeof(a) FROM t0; | rows: | - ['boolean'] | - ['boolean'] - | - ['boolean'] - | - ['boolean'] + | - ['NULL'] + | - ['NULL'] | ... -- Check BOOLEAN as argument of aggregate function. diff --git a/test/sql/gh-4697-scalar-bool-sort-cmp.result b/test/sql/gh-4697-scalar-bool-sort-cmp.result index 6f7fbd62b..e69c625bd 100644 --- a/test/sql/gh-4697-scalar-bool-sort-cmp.result +++ b/test/sql/gh-4697-scalar-bool-sort-cmp.result @@ -33,7 +33,7 @@ SELECT s2, typeof(s2) FROM test ORDER BY s2; | - name: COLUMN_1 | type: string | rows: - | - [null, 'boolean'] + | - [null, 'NULL'] | - [true, 'boolean'] | - [1, 'integer'] | - [1.1, 'double'] @@ -46,7 +46,7 @@ SELECT s3, typeof(s3) FROM test ORDER BY s3; | - name: COLUMN_1 | type: string | rows: - | - [null, 'boolean'] + | - [null, 'NULL'] | - [true, 'boolean'] | - [1, 'integer'] | - [1.1, 'double'] diff --git a/test/sql/types.result b/test/sql/types.result index 07d5b46e4..e8ebdae84 100644 --- a/test/sql/types.result +++ b/test/sql/types.result @@ -1481,7 +1481,7 @@ box.execute("SELECT typeof(a), typeof(s) FROM t;") type: string rows: - ['integer', 'integer'] - - ['integer', 'boolean'] + - ['NULL', 'NULL'] ... box.execute('CREATE TABLE t1 (id INTEGER PRIMARY KEY, a INTEGER, b INTEGER)') --- @@ -1497,7 +1497,7 @@ box.execute('SELECT typeof(a & b) FROM t1;') - name: COLUMN_1 type: string rows: - - ['unsigned'] + - ['NULL'] ... box.execute('SELECT typeof(a), typeof(b), typeof(a & b) FROM t1') --- @@ -1509,7 +1509,7 @@ box.execute('SELECT typeof(a), typeof(b), typeof(a & b) FROM t1') - name: COLUMN_3 type: string rows: - - ['integer', 'integer', 'unsigned'] + - ['NULL', 'NULL', 'NULL'] ... box.execute("SELECT typeof(CAST(0 AS UNSIGNED));") --- @@ -1517,7 +1517,7 @@ box.execute("SELECT typeof(CAST(0 AS UNSIGNED));") - name: COLUMN_1 type: string rows: - - ['unsigned'] + - ['integer'] ... box.space.T:drop() --- -- 2.25.1