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 AC8C36EC5B; Wed, 14 Apr 2021 02:10:59 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org AC8C36EC5B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1618355459; bh=Fs2qJ/CZOpMtU63TOqynF4F2TmvHRDc2qRg8AadJ/E0=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=IVPIxNU6ZdOxS4XDleBq1mZSRhk+egZ7C10oBsRT02ZFA/kBTru3n18yOBOB5IUTi zSifJ6ezwJac+EqS7ZT+nJZyyUsk3P9JLYQV1dGnsG0DF4/ZFhGuAA917iJpeMMiPZ WbhG3G2t2slfic8S2H77ZZWziPMtXyW8tlzw7Ki4= Received: from smtp61.i.mail.ru (smtp61.i.mail.ru [217.69.128.41]) (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 EBF456EC5B for ; Wed, 14 Apr 2021 02:10:57 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org EBF456EC5B Received: by smtp61.i.mail.ru with esmtpa (envelope-from ) id 1lWSBN-00071H-2F; Wed, 14 Apr 2021 02:10:57 +0300 Date: Wed, 14 Apr 2021 02:10:55 +0300 To: Vladislav Shpilevoy , tarantool-patches@dev.tarantool.org Message-ID: <20210413231055.GA78475@tarantool.org> References: <8b70c648c1b907b04859cfc8bcef94870057bf9f.1617984948.git.imeevma@gmail.com> <20210413225833.GA70385@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20210413225833.GA70385@tarantool.org> X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD92FFCB8E6708E74807BAE725B9AE625DE765B0E193B5B7687182A05F53808504017645AEC7959E6F64F9424A1A1C6FD149A4A1EBA1BA9994DE987AFA889B71C87 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE72E2D36A15E1833D8EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006379347C0682FC030B08638F802B75D45FF914D58D5BE9E6BC1A93B80C6DEB9DEE97C6FB206A91F05B2CA5D6EC7C29CE8D922FB78D83AA2FE6D21114FFCE5AE9CDCD2E47CDBA5A96583C09775C1D3CA48CFCA5A41EBD8A3A0199FA2833FD35BB23D2EF20D2F80756B5F868A13BD56FB6657A471835C12D1D977725E5C173C3A84C327ED053E960B195E117882F4460429728AD0CFFFB425014E868A13BD56FB6657D81D268191BDAD3DC09775C1D3CA48CFF47CB4554E54479BBA3038C0950A5D36C8A9BA7A39EFB766EC990983EF5C0329BA3038C0950A5D36D5E8D9A59859A8B6FA31AF570DAA8E083AA81AA40904B5D9DBF02ECDB25306B2201CA6A4E26CD07C68655334FD4449CB9ECD01F8117BC8BEAAAE862A0553A39223F8577A6DFFEA7C3DDF88F19B2F251A43847C11F186F3C59DAA53EE0834AAEE X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A2368A440D3B0F6089093C9A16E5BC824A2A04A2ABAA09D2538DECB10C4E1BE3BCB8CCF60F6B7FD3948E1CD14B953EB46DB0ABED31E7839ABA355D89D7DBCDD132 X-C1DE0DAB: 0D63561A33F958A5CF637EED8AE62B89B291B6890F7ECEC560C57E68F84D3DF8D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA7502E6951B79FF9A3F410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34F804B400765FFFF99CBA4B75E3624383D7FC51DDF6827EB80AEB8C754F06ABDF3C13DC828B0DCC971D7E09C32AA3244CA4F835DF2ED2CB505AB727DFB0F3C75835DA7DC5AF9B58C0729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojnA7/qPBUIXHKLPGAabAvWg== X-Mailru-Sender: 5C3750E245F362008BC1685FEC6306ED2DA05EFCF2B08E2C4F9424A1A1C6FD146565FCDE7E403FA15105BD0848736F9966FEC6BF5C9C28D97E07721503EA2E00ED97202A5A4E92BF7402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v5 39/52] sql: introduce mem_to_int*() functions X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Mergen Imeev via Tarantool-patches Reply-To: Mergen Imeev Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" This is addition from review of patch "sql: introduce mem_to_str() and mem_to_str0()". I added assert to check that only simple types may be in mem_to_*() functions. Diff and new patch below. On Wed, Apr 14, 2021 at 01:58:33AM +0300, Mergen Imeev via Tarantool-patches wrote: > Thank you for the review! My answers, diff and new patch below. > > > On Tue, Apr 13, 2021 at 01:39:01AM +0200, Vladislav Shpilevoy wrote: > > Good job on the fixes! > > > > This is the last email for today, I will continue the review of > > the patchset tomorrow. > > > > See 2 comments below. > > > > > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c > > > index 71a827034..e61ad4251 100644 > > > --- a/src/box/sql/vdbe.c > > > +++ b/src/box/sql/vdbe.c > > > @@ -1432,17 +1432,14 @@ case OP_AddImm: { /* in1 */ > > > */ > > > case OP_MustBeInt: { /* jump, in1 */ > > > pIn1 = &aMem[pOp->p1]; > > > - if (!mem_is_int(pIn1)) { > > > - mem_apply_type(pIn1, FIELD_TYPE_INTEGER); > > > - if (!mem_is_int(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_int(pIn1)) > > > > 1. The same check is done inside mem_to_int_precise(). You > > don't need to do it manually. > > > Thanks, fixed. > > > > + break; > > > + if (mem_to_int_precise(pIn1) != 0) { > > > + if (pOp->p2 !=0 ) > > > > 2. Whitespace should be before '0', not after. > > > Fixed. > > > > + goto jump_to_p2; > > > + diag_set(ClientError, ER_SQL_TYPE_MISMATCH, > > > + mem_str(pIn1), "integer"); > > > + goto abort_due_to_error; > > > } > > > break; > > > } > > > > > > Diff: > > > diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c > index 061f77952..c908f13c0 100644 > --- a/src/box/sql/vdbe.c > +++ b/src/box/sql/vdbe.c > @@ -1435,10 +1435,8 @@ case OP_AddImm: { /* in1 */ > */ > case OP_MustBeInt: { /* jump, in1 */ > pIn1 = &aMem[pOp->p1]; > - if (mem_is_int(pIn1)) > - break; > if (mem_to_int_precise(pIn1) != 0) { > - if (pOp->p2 !=0 ) > + if (pOp->p2 != 0) > goto jump_to_p2; > diag_set(ClientError, ER_SQL_TYPE_MISMATCH, > mem_str(pIn1), "integer"); > > > New patch: > > > commit ecf63aa8a6887b3b1ac7a67a6b60fe3a62426ed9 > Author: Mergen Imeev > Date: Wed Mar 17 10:46:29 2021 +0300 > > sql: introduce mem_to_int*() functions > > This patch introduces mem_to_int() and mem_to_int_precise() functions. > These functions are used to convert a MEM to a MEM that contains > integer value. These functions defines the rules that are used during > convertion from values of all other types to INTEGER. > > Part of #5818 > > diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c > index 3930067e1..fd68acd6e 100644 > --- a/src/box/sql/mem.c > +++ b/src/box/sql/mem.c > @@ -492,6 +492,90 @@ mem_set_null_clear(struct Mem *mem) > mem->flags = MEM_Null | MEM_Cleared; > } > > +static inline int > +bytes_to_int(struct Mem *mem) > +{ > + bool is_neg; > + int64_t i; > + if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) > + return -1; > + mem_set_int(mem, i, is_neg); > + return 0; > +} > + > +static inline int > +double_to_int(struct Mem *mem) > +{ > + double d = mem->u.r; > + if (d < 0 && d >= (double)INT64_MIN) { > + mem->u.i = (int64_t)d; > + mem->flags = MEM_Int; > + 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->field_type = FIELD_TYPE_UNSIGNED; > + return 0; > + } > + return -1; > +} > + > +static inline int > +double_to_int_precise(struct Mem *mem) > +{ > + 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->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->field_type = FIELD_TYPE_UNSIGNED; > + return 0; > + } > + return -1; > +} > + > +static inline int > +bool_to_int(struct Mem *mem) > +{ > + mem->u.u = (uint64_t)mem->u.b; > + mem->flags = MEM_UInt; > + mem->field_type = FIELD_TYPE_UNSIGNED; > + return 0; > +} > + > +int > +mem_to_int(struct Mem *mem) > +{ > + if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + return 0; > + if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) > + return bytes_to_int(mem); > + if ((mem->flags & MEM_Real) != 0) > + return double_to_int(mem); > + if ((mem->flags & MEM_Bool) != 0) > + return bool_to_int(mem); > + return -1; > +} > + > +int > +mem_to_int_precise(struct Mem *mem) > +{ > + if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) > + return 0; > + if ((mem->flags & MEM_Str) != 0) > + return bytes_to_int(mem); > + if ((mem->flags & MEM_Real) != 0) > + return double_to_int_precise(mem); > + return -1; > +} > + > int > mem_copy(struct Mem *to, const struct Mem *from) > { > @@ -1694,26 +1778,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) { > - pMem->u.i = ix; > - pMem->flags = pMem->u.r <= -1 ? MEM_Int : MEM_UInt; > - pMem->field_type = FIELD_TYPE_INTEGER; > - } > - 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 > @@ -1985,34 +2049,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 < 0.) { > - mem->u.i = (int64_t)d; > - mem->flags = MEM_Int; > - mem->field_type = FIELD_TYPE_INTEGER; > - } else { > - mem->u.u = (uint64_t)d; > - mem->flags = MEM_UInt; > - mem->field_type = FIELD_TYPE_UNSIGNED; > - } > - return 0; > -} > - > int > mem_convert_to_numeric(struct Mem *mem, enum field_type type) > { > @@ -2023,7 +2059,7 @@ mem_convert_to_numeric(struct Mem *mem, enum field_type type) > if (type == FIELD_TYPE_UNSIGNED) > return mem_convert_to_unsigned(mem); > assert(type == FIELD_TYPE_INTEGER); > - return mem_convert_to_integer(mem); > + return mem_to_int(mem); > } > > static int > diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h > index 9890762e0..5aabcc1fd 100644 > --- a/src/box/sql/mem.h > +++ b/src/box/sql/mem.h > @@ -683,6 +683,24 @@ mem_cmp_str(const struct Mem *left, const struct Mem *right, int *result, > int > mem_cmp_num(const struct Mem *a, const struct Mem *b, int *result); > > +/** > + * Convert the given MEM to INTEGER. This function and the function below define > + * the rules that are used to convert values of all other types to INTEGER. In > + * this function, the conversion from double to integer may result in loss of > + * precision. > + */ > +int > +mem_to_int(struct Mem *mem); > + > +/** > + * Convert the given MEM to INTEGER. This function and the function above define > + * the rules that are used to convert values of all other types to INTEGER. In > + * this function, the conversion from double to integer is only possible if it > + * is lossless. > + */ > +int > +mem_to_int_precise(struct Mem *mem); > + > /** > * Simple type to str convertor. It is used to simplify > * error reporting. > @@ -743,7 +761,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 e07ff1be9..c908f13c0 100644 > --- a/src/box/sql/vdbe.c > +++ b/src/box/sql/vdbe.c > @@ -1435,17 +1435,12 @@ case OP_AddImm: { /* in1 */ > */ > case OP_MustBeInt: { /* jump, in1 */ > pIn1 = &aMem[pOp->p1]; > - if (!mem_is_int(pIn1)) { > - mem_apply_type(pIn1, FIELD_TYPE_INTEGER); > - if (!mem_is_int(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_to_int_precise(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; > } Diff: diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index fd68acd6e..b22b4ba21 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -553,6 +553,7 @@ bool_to_int(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) return 0; if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) @@ -567,6 +568,7 @@ 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) return 0; if ((mem->flags & MEM_Str) != 0) New patch: commit 5723ddfbed6c9fdf7e01bbbc51a47db496e605e2 Author: Mergen Imeev Date: Wed Mar 17 10:46:29 2021 +0300 sql: introduce mem_to_int*() functions This patch introduces mem_to_int() and mem_to_int_precise() functions. These functions are used to convert a MEM to a MEM that contains integer value. These functions defines the rules that are used during convertion from values of all other types to INTEGER. Part of #5818 diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index 3930067e1..b22b4ba21 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -492,6 +492,92 @@ mem_set_null_clear(struct Mem *mem) mem->flags = MEM_Null | MEM_Cleared; } +static inline int +bytes_to_int(struct Mem *mem) +{ + bool is_neg; + int64_t i; + if (sql_atoi64(mem->z, &i, &is_neg, mem->n) != 0) + return -1; + mem_set_int(mem, i, is_neg); + return 0; +} + +static inline int +double_to_int(struct Mem *mem) +{ + double d = mem->u.r; + if (d < 0 && d >= (double)INT64_MIN) { + mem->u.i = (int64_t)d; + mem->flags = MEM_Int; + 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->field_type = FIELD_TYPE_UNSIGNED; + return 0; + } + return -1; +} + +static inline int +double_to_int_precise(struct Mem *mem) +{ + 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->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->field_type = FIELD_TYPE_UNSIGNED; + return 0; + } + return -1; +} + +static inline int +bool_to_int(struct Mem *mem) +{ + mem->u.u = (uint64_t)mem->u.b; + mem->flags = MEM_UInt; + mem->field_type = FIELD_TYPE_UNSIGNED; + return 0; +} + +int +mem_to_int(struct Mem *mem) +{ + assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); + if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) + return 0; + if ((mem->flags & (MEM_Str | MEM_Blob)) != 0) + return bytes_to_int(mem); + if ((mem->flags & MEM_Real) != 0) + return double_to_int(mem); + if ((mem->flags & MEM_Bool) != 0) + return bool_to_int(mem); + return -1; +} + +int +mem_to_int_precise(struct Mem *mem) +{ + assert((mem->flags & MEM_PURE_TYPE_MASK) != 0); + if ((mem->flags & (MEM_Int | MEM_UInt)) != 0) + return 0; + if ((mem->flags & MEM_Str) != 0) + return bytes_to_int(mem); + if ((mem->flags & MEM_Real) != 0) + return double_to_int_precise(mem); + return -1; +} + int mem_copy(struct Mem *to, const struct Mem *from) { @@ -1694,26 +1780,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) { - pMem->u.i = ix; - pMem->flags = pMem->u.r <= -1 ? MEM_Int : MEM_UInt; - pMem->field_type = FIELD_TYPE_INTEGER; - } - 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 @@ -1985,34 +2051,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 < 0.) { - mem->u.i = (int64_t)d; - mem->flags = MEM_Int; - mem->field_type = FIELD_TYPE_INTEGER; - } else { - mem->u.u = (uint64_t)d; - mem->flags = MEM_UInt; - mem->field_type = FIELD_TYPE_UNSIGNED; - } - return 0; -} - int mem_convert_to_numeric(struct Mem *mem, enum field_type type) { @@ -2023,7 +2061,7 @@ mem_convert_to_numeric(struct Mem *mem, enum field_type type) if (type == FIELD_TYPE_UNSIGNED) return mem_convert_to_unsigned(mem); assert(type == FIELD_TYPE_INTEGER); - return mem_convert_to_integer(mem); + return mem_to_int(mem); } static int diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 9890762e0..5aabcc1fd 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -683,6 +683,24 @@ mem_cmp_str(const struct Mem *left, const struct Mem *right, int *result, int mem_cmp_num(const struct Mem *a, const struct Mem *b, int *result); +/** + * Convert the given MEM to INTEGER. This function and the function below define + * the rules that are used to convert values of all other types to INTEGER. In + * this function, the conversion from double to integer may result in loss of + * precision. + */ +int +mem_to_int(struct Mem *mem); + +/** + * Convert the given MEM to INTEGER. This function and the function above define + * the rules that are used to convert values of all other types to INTEGER. In + * this function, the conversion from double to integer is only possible if it + * is lossless. + */ +int +mem_to_int_precise(struct Mem *mem); + /** * Simple type to str convertor. It is used to simplify * error reporting. @@ -743,7 +761,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 e07ff1be9..c908f13c0 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -1435,17 +1435,12 @@ case OP_AddImm: { /* in1 */ */ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; - if (!mem_is_int(pIn1)) { - mem_apply_type(pIn1, FIELD_TYPE_INTEGER); - if (!mem_is_int(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_to_int_precise(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; }