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 648D96B469; Tue, 23 Mar 2021 12:55:18 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 648D96B469 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1616493318; bh=jC7yTq+4+SmOQOKH3AlPpthluMNKP3THyLKQi9F7r1A=; 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=JloBq1mvEgSbTe59BnyJTusKWHOjVS56HwMnskiRdXnzllvyqZMEAIRlNzVy6tOPA ksOmnv1H77P0UWtaPz+d8NA+FAfoVmauJbxpREWyTbBbyFxGGQIK1FfMXwyuz++Xzg iy5/PUJDGclbDTjaSvf/8fcZQXymQfG+x4/3fD9s= Received: from smtp38.i.mail.ru (smtp38.i.mail.ru [94.100.177.98]) (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 4002E68F5E for ; Tue, 23 Mar 2021 12:36:28 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 4002E68F5E Received: by smtp38.i.mail.ru with esmtpa (envelope-from ) id 1lOdSd-0007Gp-Gl; Tue, 23 Mar 2021 12:36:27 +0300 To: v.shpilevoy@tarantool.org, tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Tue, 23 Mar 2021 12:36:27 +0300 Message-Id: <7b0c755e28e0c5617b544b127fd692b10434b404.1616491731.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-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD95D6E7CC48CB1F5F10D3016C09B407F8B88411E9FEB481E8E182A05F5380850405E2B6E856A36466DD46D2855DD77B62E818E458AB5BA02369ED2069F7095106D X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7DF2546A43F668C04EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637956E96668349D4418638F802B75D45FF914D58D5BE9E6BC131B5C99E7648C95C686AF563A045C75E5ABE6629EEC4BC3C4A348B691C7281E0A471835C12D1D9774AD6D5ED66289B5278DA827A17800CE7A4F00A9E8C511CEB9FA2833FD35BB23D2EF20D2F80756B5F868A13BD56FB6657A471835C12D1D977725E5C173C3A84C3543F342AA183667F117882F4460429728AD0CFFFB425014E868A13BD56FB6657D81D268191BDAD3DC09775C1D3CA48CF85267523C8841599BA3038C0950A5D36C8A9BA7A39EFB766EC990983EF5C0329BA3038C0950A5D36D5E8D9A59859A8B6CD063A04CBECCE1B76E601842F6C81A1F004C906525384307823802FF610243DF43C7A68FF6260569E8FC8737B5C2249EC8D19AE6D49635B3BBE47FD9DD3FB59A8DF7F3B2552694A57739F23D657EF2B13377AFFFEAFD26923F8577A6DFFEA7CD1D040B6C1ECEA3F93EC92FD9297F6715571747095F342E857739F23D657EF2BD5E8D9A59859A8B6A1DCCEB63E2F10FB089D37D7C0E48F6C5571747095F342E857739F23D657EF2B6825BDBE14D8E70285AA09D4B315C2C6BD9CCCA9EDD067B1EDA766A37F9254B7 X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A24A6D60772A99906F8E1CD14B953EB46D3A49327926422EBA355D89D7DBCDD132 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C686AF563A045C75E5ABE6629EEC4BC3C4A348B691C7281E09C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF0417BEADF48D1460699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3490011A262ADAEDFEF28FB5582545456D0E56719F78C7E6F77C69C3BF43DAC1D91085702D9301D0681D7E09C32AA3244C5C05D5219DA42C9B1CF204731CB2378D250262A5EE9971B0FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojWJZv20R+6UiAUPSkZDThTQ== X-Mailru-Sender: 5C3750E245F362008BC1685FEC6306EDEDC9D51F7D3F5760D46D2855DD77B62EFE5F7FEA15315F165105BD0848736F9966FEC6BF5C9C28D97E07721503EA2E00ED97202A5A4E92BF7402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v4 41/53] sql: introduce mem_convert_to_integer() 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 introduces mem_convert_to_integer() which is used to convert a MEM to a MEM that contains integer value. Part of #5818 --- src/box/sql/mem.c | 114 +++++++++++++++++++++++++++++---------------- src/box/sql/mem.h | 7 ++- src/box/sql/vdbe.c | 19 ++++---- 3 files changed, 88 insertions(+), 52 deletions(-) diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index 1209df1ce..b9bcd3d3a 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -695,6 +695,80 @@ mem_set_cleared(struct Mem *mem) mem->flags = MEM_Null | MEM_Cleared; } +static inline int +mem_convert_varstring_to_integer(struct Mem *mem) +{ + bool is_neg; + int64_t i; + if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) + return -1; + mem_set_integer(mem, i, is_neg); + return 0; +} + +static inline int +mem_convert_double_to_integer(struct Mem *mem) +{ + double d = mem->u.r; + if (d < 0 && d >= (double)INT64_MIN) { + mem_set_integer(mem, (int64_t)d, true); + return 0; + } + if (d >= 0 && d < (double)UINT64_MAX) { + mem_set_integer(mem, (int64_t)(uint64_t)d, false); + return 0; + } + return -1; +} + +static inline int +mem_convert_double_to_integer_lossless(struct Mem *mem) +{ + double d = mem->u.r; + if (d < 0 && d >= (double)INT64_MIN && (double)(int64_t)d == d) { + mem_set_integer(mem, (int64_t)d, true); + return 0; + } + if (d >= 0 && d < (double)UINT64_MAX && (double)(uint64_t)d == d) { + mem_set_integer(mem, (int64_t)(uint64_t)d, false); + return 0; + } + return -1; +} + +static inline int +mem_convert_boolean_to_integer(struct Mem *mem) +{ + mem_set_integer(mem, (int64_t)mem->u.b, false); + return 0; +} + +int +mem_convert_to_integer(struct Mem *mem) +{ + if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) + return 0; + if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) + return mem_convert_varstring_to_integer(mem); + if ((mem->flags & MEM_Real) != 0) + return mem_convert_double_to_integer(mem); + if ((mem->flags & MEM_Bool) != 0) + return mem_convert_boolean_to_integer(mem); + return -1; +} + +int +mem_convert_to_integer_lossless(struct Mem *mem) +{ + if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) + return 0; + if ((mem->flags & MEM_Str) != 0) + return mem_convert_varstring_to_integer(mem); + if ((mem->flags & MEM_Real) != 0) + return mem_convert_double_to_integer_lossless(mem); + return -1; +} + int mem_copy(struct Mem *to, const struct Mem *from) { @@ -1911,23 +1985,6 @@ sqlVdbeMemCast(Mem * pMem, enum field_type type) } } -/* - * The MEM structure is already a MEM_Real. Try to also make it a - * MEM_Int if we can. - */ -int -mem_apply_integer_type(Mem *pMem) -{ - int rc; - i64 ix; - assert(pMem->flags & MEM_Real); - assert(EIGHT_BYTE_ALIGNMENT(pMem)); - - if ((rc = doubleToInt64(pMem->u.r, (int64_t *) &ix)) == 0) - mem_set_integer(pMem, ix, pMem->u.r <= -1); - return rc; -} - /* * Add MEM_Str to the set of representations for the given Mem. Numbers * are converted using sql_snprintf(). Converting a BLOB to a string @@ -2192,29 +2249,6 @@ mem_convert_to_unsigned(struct Mem *mem) return 0; } -/** - * Convert the numeric value contained in MEM to integer. - * - * @param mem The MEM that contains the numeric value. - * @retval 0 if the conversion was successful, -1 otherwise. - */ -static int -mem_convert_to_integer(struct Mem *mem) -{ - if ((mem->flags & (MEM_UInt | MEM_Int)) != 0) - return 0; - if ((mem->flags & MEM_Real) == 0) - return -1; - double d = mem->u.r; - if (d >= (double)UINT64_MAX || d < (double)INT64_MIN) - return -1; - if (d < (double)INT64_MAX) - mem_set_integer(mem, (int64_t) d, d < 0); - else - mem_set_integer(mem, (uint64_t) d, false); - return 0; -} - int mem_convert_to_numeric(struct Mem *mem, enum field_type type) { diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 8b6f6749d..58cbdfe9f 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -318,6 +318,12 @@ int mem_compare(const struct Mem *left, const struct Mem *right, int *result, enum field_type type, struct coll *coll); +int +mem_convert_to_integer(struct Mem *mem); + +int +mem_convert_to_integer_lossless(struct Mem *mem); + /** * Simple type to str convertor. It is used to simplify * error reporting. @@ -395,7 +401,6 @@ int vdbe_mem_numerify(struct Mem *mem); int sqlVdbeMemCast(struct Mem *, enum field_type type); -int mem_apply_integer_type(struct Mem *); int sqlVdbeMemStringify(struct Mem *); int sqlVdbeMemNulTerminate(struct Mem *); int sqlVdbeMemExpandBlob(struct Mem *); diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index edf845d97..1aeed543f 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -1341,17 +1341,14 @@ case OP_AddImm: { /* in1 */ */ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; - if (!mem_is_integer(pIn1)) { - mem_apply_type(pIn1, FIELD_TYPE_INTEGER); - if (!mem_is_integer(pIn1)) { - if (pOp->p2==0) { - diag_set(ClientError, ER_SQL_TYPE_MISMATCH, - mem_str(pIn1), "integer"); - goto abort_due_to_error; - } else { - goto jump_to_p2; - } - } + if (mem_is_integer(pIn1)) + break; + if (mem_convert_to_integer_lossless(pIn1) != 0) { + if (pOp->p2 !=0 ) + goto jump_to_p2; + diag_set(ClientError, ER_SQL_TYPE_MISMATCH, + mem_str(pIn1), "integer"); + goto abort_due_to_error; } break; } -- 2.25.1