From: Stanislav Zudin <szudin@tarantool.org> To: tarantool-patches@freelists.org, korablev@tarantool.org Cc: Stanislav Zudin <szudin@tarantool.org> Subject: [tarantool-patches] [PATCH v2 13/15] sql: support -2^63 .. 2^64-1 integer type Date: Mon, 1 Apr 2019 23:44:51 +0300 [thread overview] Message-ID: <4c88b8cd5be67d643dcbc229f394aa6d78558615.1554150265.git.szudin@tarantool.org> (raw) In-Reply-To: <cover.1554150265.git.szudin@tarantool.org> In-Reply-To: <cover.1554150265.git.szudin@tarantool.org> Returns correct text name for unsigned data type. Applies a coding standard. Improves mapping of vdbe data types to sql data types. Part of #3810 --- src/box/sql/func.c | 11 +-- src/box/sql/sqlInt.h | 15 ++-- src/box/sql/util.c | 153 +++++++++++++++++++++-------------------- src/box/sql/vdbe.c | 2 + src/box/sql/vdbeInt.h | 4 +- src/box/sql/vdbeapi.c | 109 +++++++++-------------------- test/sql/iproto.result | 2 +- 7 files changed, 132 insertions(+), 164 deletions(-) diff --git a/src/box/sql/func.c b/src/box/sql/func.c index f1b894f16..74b56d780 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -121,6 +121,9 @@ typeofFunc(sql_context * context, int NotUsed, sql_value ** argv) case SQL_BLOB: z = "blob"; break; + case SQL_UNSIGNED: + z = "unsigned"; + break; default: z = "null"; break; @@ -1410,7 +1413,7 @@ struct SumCtx { i64 cnt; /* Number of elements summed */ u8 overflow; /* True if integer overflow seen */ u8 approx; /* True if non-integer value was input to the sum */ - u8 is_unsigned; /* True if value exceeded 2^63 */ + bool is_unsigned; /* True if value exceeded 2^63 */ }; /* @@ -1441,14 +1444,14 @@ sumStep(sql_context * context, int argc, sql_value ** argv) p->rSum += v; if ((p->approx | p->overflow) == 0) rc = sqlAddInt64(&p->iSum, - p->is_unsigned == 0, + !p->is_unsigned, v, true); } else if (type == SQL_UNSIGNED) { u64 v = sql_value_uint64(argv[0]); p->rSum += v; if ((p->approx | p->overflow) == 0) rc = sqlAddInt64(&p->iSum, - p->is_unsigned == 0, + !p->is_unsigned, v, false); } else { p->rSum += sql_value_double(argv[0]); @@ -1462,7 +1465,7 @@ sumStep(sql_context * context, int argc, sql_value ** argv) case ATHR_SIGNED: break; case ATHR_UNSIGNED: - p->is_unsigned = 1; + p->is_unsigned = true; break; default: p->overflow = 1; diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index fd87366df..509879cf7 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -4383,11 +4383,16 @@ enum arithmetic_result { ATHR_DIVBYZERO }; -enum arithmetic_result sqlAddInt64(i64 *, bool, i64, bool); -enum arithmetic_result sqlSubInt64(i64 *, bool, i64, bool); -enum arithmetic_result sqlMulInt64(i64 *, bool, i64, bool); -enum arithmetic_result sqlDivInt64(i64 *, bool, i64, bool); -enum arithmetic_result sqlRemInt64(i64 *, bool, i64, bool); +enum arithmetic_result +sqlAddInt64(i64 *, bool, i64, bool); +enum arithmetic_result +sqlSubInt64(i64 *, bool, i64, bool); +enum arithmetic_result +sqlMulInt64(i64 *, bool, i64, bool); +enum arithmetic_result +sqlDivInt64(i64 *, bool, i64, bool); +enum arithmetic_result +sqlRemInt64(i64 *, bool, i64, bool); int sqlAbsInt32(int); u8 sqlGetBoolean(const char *z, u8); diff --git a/src/box/sql/util.c b/src/box/sql/util.c index ce3f1b5c3..e56ae6e05 100644 --- a/src/box/sql/util.c +++ b/src/box/sql/util.c @@ -1275,102 +1275,103 @@ apply_sign(i64* pOut, u64 value, bool is_neg) } /* - * Attempt to add, substract, or multiply the 64-bit value iB against - * the other 64-bit integer at *pA and store the result in *pA. + * Attempt to add, substract, or multiply the 64-bit value irhs against + * the other 64-bit integer at *plhs and store the result in *plhs. * Return ATHR_SIGNED or ATHR_UNSIGNED on success. * Or if the operation would have resulted in an * overflow, leave *pA unchanged and return ATHR_OVERFLOW. */ enum arithmetic_result -sqlAddInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) +sqlAddInt64(i64 * plhs, bool is_lhs_signed, i64 irhs, bool is_rhs_signed) { - i64 iA = *pA; + i64 ilhs = *plhs; - bool is_negA = iA < 0 && is_signedA; - bool is_negB = iB < 0 && is_signedB; + bool is_lhs_neg = ilhs < 0 && is_lhs_signed; + bool is_rhs_neg = irhs < 0 && is_rhs_signed; - if (is_negA != is_negB) { - /* Make sure we've got only one combination of + if (is_lhs_neg != is_rhs_neg) { + /* + * Make sure we've got only one combination of * positive and negative operands */ - if (is_negA > is_negB) { - SWAP(is_negA, is_negB); - SWAP(iA, iB); + if (is_lhs_neg > is_rhs_neg) { + SWAP(is_lhs_neg, is_rhs_neg); + SWAP(ilhs, irhs); } - assert(is_negA == false && is_negB == true); + assert(is_lhs_neg == false && is_rhs_neg == true); - u64 uB = mod64(iB, true); + u64 uB = mod64(irhs, true); - if ((u64)iA >= uB) { - u64 sum = (u64)iA - uB; - *pA = (i64)sum; + if ((u64)ilhs >= uB) { + u64 sum = (u64)ilhs - uB; + *plhs = (i64)sum; return (sum <= INT64_MAX) ? ATHR_SIGNED : ATHR_UNSIGNED; } else { - u64 sum = uB - (u64)iA; + u64 sum = uB - (u64)ilhs; if (sum == INT64_MIN_MOD) { - *pA = INT64_MIN; + *plhs = INT64_MIN; } else { assert(sum <= INT64_MAX); - *pA = -(i64)sum; + *plhs = -(i64)sum; } return ATHR_SIGNED; } } - if (is_negA) { - assert(is_signedA && is_signedB); - if (-(iA + LARGEST_INT64) > iB + 1) + if (is_lhs_neg) { + assert(is_lhs_signed && is_rhs_signed); + if (-(ilhs + LARGEST_INT64) > irhs + 1) return ATHR_OVERFLOW; - *pA = iA + iB; + *plhs = ilhs + irhs; return ATHR_SIGNED; } else { - if (UINT64_MAX - (u64)iA < (u64)iB) + if (UINT64_MAX - (u64)ilhs < (u64)irhs) return ATHR_OVERFLOW; - u64 sum = (u64)iA + (u64)iB; - *pA = (i64)sum; + u64 sum = (u64)ilhs + (u64)irhs; + *plhs = (i64)sum; return (sum <= INT64_MAX) ? ATHR_SIGNED : ATHR_UNSIGNED; } } enum arithmetic_result -sqlSubInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) +sqlSubInt64(i64 * plhs, bool is_lhs_signed, i64 irhs, bool is_rhs_signed) { - i64 iA = *pA; + i64 ilhs = *plhs; - bool is_negA = iA < 0 && is_signedA; - bool is_negB = iB < 0 && is_signedB; + bool is_lhs_neg = ilhs < 0 && is_lhs_signed; + bool is_rhs_neg = irhs < 0 && is_rhs_signed; - if (is_negA) { - if (!is_signedB){ - assert((u64)iB > INT64_MAX); + if (is_lhs_neg) { + if (!is_rhs_signed){ + assert((u64)irhs > INT64_MAX); return ATHR_OVERFLOW; } - if (iB == INT64_MIN) + if (irhs == INT64_MIN) return ATHR_OVERFLOW; else - return sqlAddInt64(pA, true, -iB, true); + return sqlAddInt64(plhs, true, -irhs, true); } - if (is_negB) { - /* iA - (-iB) => iA + iB */ - u64 uB = mod64(iB, true); - if (iB == INT64_MIN) - is_signedB = false; + if (is_rhs_neg) { + /* ilhs - (-irhs) => ilhs + irhs */ + u64 uB = mod64(irhs, true); + if (irhs == INT64_MIN) + is_rhs_signed = false; - return sqlAddInt64(pA, is_signedA, uB, is_signedB); + return sqlAddInt64(plhs, is_lhs_signed, uB, is_rhs_signed); } else { - /* Both iA & iB are positive */ - if ((u64)iA < (u64)iB) { + /* Both ilhs & irhs are positive */ + if ((u64)ilhs < (u64)irhs) { /* subtract with sign changing */ - u64 val = (u64)iB - (u64)iA; - return apply_sign(pA, val, true); + u64 val = (u64)irhs - (u64)ilhs; + return apply_sign(plhs, val, true); } else { - u64 val = (u64)iA - (u64)iB; - *pA = (i64)val; + u64 val = (u64)ilhs - (u64)irhs; + *plhs = (i64)val; return (val > INT64_MAX) ? ATHR_UNSIGNED : ATHR_SIGNED; } @@ -1378,56 +1379,56 @@ sqlSubInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) } enum arithmetic_result -sqlMulInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) +sqlMulInt64(i64 * plhs, bool is_lhs_signed, i64 irhs, bool is_rhs_signed) { - if (*pA == 0 || iB == 0) { - *pA = 0; + if (*plhs == 0 || irhs == 0) { + *plhs = 0; return ATHR_SIGNED; } - bool is_negA = *pA < 0 && is_signedA; - bool is_negB = iB < 0 && is_signedB; + bool is_lhs_neg = *plhs < 0 && is_lhs_signed; + bool is_rhs_neg = irhs < 0 && is_rhs_signed; - bool is_neg = is_negA != is_negB; + bool is_neg = is_lhs_neg != is_rhs_neg; - u64 uA = mod64(*pA, is_signedA); - u64 uB = mod64(iB, is_signedB); + u64 ulhs = mod64(*plhs, is_lhs_signed); + u64 urhs = mod64(irhs, is_rhs_signed); if (is_neg) { - if (INT64_MIN_MOD / uA < uB) + if (INT64_MIN_MOD / ulhs < urhs) return ATHR_OVERFLOW; } else { - if (UINT64_MAX / uA < uB) + if (UINT64_MAX / ulhs < urhs) return ATHR_OVERFLOW; } - u64 mul = uA * uB; - return apply_sign(pA, mul, is_neg); + u64 mul = ulhs * urhs; + return apply_sign(plhs, mul, is_neg); } enum arithmetic_result -sqlDivInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) { - if (*pA == 0) +sqlDivInt64(i64 * plhs, bool is_lhs_signed, i64 irhs, bool is_rhs_signed) { + if (*plhs == 0) return ATHR_SIGNED; - if (iB == 0) + if (irhs == 0) return ATHR_DIVBYZERO; - bool is_negA = *pA < 0 && is_signedA; - bool is_negB = iB < 0 && is_signedB; + bool is_lhs_neg = *plhs < 0 && is_lhs_signed; + bool is_rhs_neg = irhs < 0 && is_rhs_signed; - bool is_neg = is_negA != is_negB; + bool is_neg = is_lhs_neg != is_rhs_neg; - u64 uA = mod64(*pA, is_signedA); - u64 uB = mod64(iB, is_signedB); + u64 ulhs = mod64(*plhs, is_lhs_signed); + u64 urhs = mod64(irhs, is_rhs_signed); - u64 div = uA / uB; - return apply_sign(pA, div, is_neg); + u64 div = ulhs / urhs; + return apply_sign(plhs, div, is_neg); } enum arithmetic_result -sqlRemInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) { +sqlRemInt64(i64 * plhs, bool is_lhs_signed, i64 irhs, bool is_rhs_signed) { - if (iB == 0) + if (irhs == 0) return ATHR_DIVBYZERO; /* * The sign of the remainder is defined in such @@ -1437,12 +1438,12 @@ sqlRemInt64(i64 * pA, bool is_signedA, i64 iB, bool is_signedB) { * The 2nd operand doesn't affect the sign of result. */ - bool is_neg = *pA < 0 && is_signedA; - u64 uA = mod64(*pA, is_signedA); - u64 uB = mod64(iB, is_signedB); + bool is_neg = *plhs < 0 && is_lhs_signed; + u64 ulhs = mod64(*plhs, is_lhs_signed); + u64 urhs = mod64(irhs, is_rhs_signed); - u64 rem = uA % uB; - return apply_sign(pA, rem, is_neg); + u64 rem = ulhs % urhs; + return apply_sign(plhs, rem, is_neg); } /* diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 3df5006c8..787fdadab 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -646,6 +646,8 @@ mem_type_to_str(const struct Mem *p) return "BLOB"; case MEM_Bool: return "BOOLEAN"; + case MEM_UInt: + return "UNSIGNED"; default: unreachable(); } diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h index f986d136c..78e211c97 100644 --- a/src/box/sql/vdbeInt.h +++ b/src/box/sql/vdbeInt.h @@ -265,7 +265,9 @@ struct Mem { * auxiliary flags. */ enum { - MEM_PURE_TYPE_MASK = 0x1f + MEM_PURE_TYPE_MASK = MEM_Null | MEM_Str | MEM_Int | + MEM_Real | MEM_Blob | MEM_Bool | + MEM_UInt }; diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index 66fceb444..fe948dd26 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -257,83 +257,38 @@ sql_value_text(sql_value * pVal) int sql_value_type(sql_value * pVal) { - static const u8 aType[] = { - SQL_BLOB, /* 0x00 */ - SQL_NULL, /* 0x01 */ - SQL_TEXT, /* 0x02 */ - SQL_NULL, /* 0x03 */ - SQL_INTEGER, /* 0x04 */ - SQL_NULL, /* 0x05 */ - SQL_INTEGER, /* 0x06 */ - SQL_NULL, /* 0x07 */ - SQL_FLOAT, /* 0x08 */ - SQL_NULL, /* 0x09 */ - SQL_FLOAT, /* 0x0a */ - SQL_NULL, /* 0x0b */ - SQL_INTEGER, /* 0x0c */ - SQL_NULL, /* 0x0d */ - SQL_INTEGER, /* 0x0e */ - SQL_NULL, /* 0x0f */ - SQL_BLOB, /* 0x10 */ - SQL_NULL, /* 0x11 */ - SQL_TEXT, /* 0x12 */ - SQL_NULL, /* 0x13 */ - SQL_INTEGER, /* 0x14 */ - SQL_NULL, /* 0x15 */ - SQL_INTEGER, /* 0x16 */ - SQL_NULL, /* 0x17 */ - SQL_FLOAT, /* 0x18 */ - SQL_NULL, /* 0x19 */ - SQL_FLOAT, /* 0x1a */ - SQL_NULL, /* 0x1b */ - SQL_INTEGER, /* 0x1c */ - SQL_NULL, /* 0x1d */ - SQL_INTEGER, /* 0x1e */ - SQL_NULL, /* 0x1f */ - - SQL_BLOB, /* 0x20 */ - SQL_NULL, /* 0x21 */ - SQL_TEXT, /* 0x22 */ - SQL_NULL, /* 0x23 */ - SQL_UNSIGNED, /* 0x24 */ - SQL_NULL, /* 0x25 */ - SQL_UNSIGNED, /* 0x26 */ - SQL_NULL, /* 0x27 */ - SQL_FLOAT, /* 0x28 */ - SQL_NULL, /* 0x29 */ - SQL_FLOAT, /* 0x2a */ - SQL_NULL, /* 0x2b */ - SQL_INTEGER, /* 0x2c */ - SQL_NULL, /* 0x2d */ - SQL_INTEGER, /* 0x2e */ - SQL_NULL, /* 0x2f */ - SQL_BLOB, /* 0x30 */ - SQL_NULL, /* 0x31 */ - SQL_TEXT, /* 0x32 */ - SQL_NULL, /* 0x33 */ - SQL_INTEGER, /* 0x34 */ - SQL_NULL, /* 0x35 */ - SQL_INTEGER, /* 0x36 */ - SQL_NULL, /* 0x37 */ - SQL_FLOAT, /* 0x38 */ - SQL_NULL, /* 0x39 */ - SQL_FLOAT, /* 0x3a */ - SQL_NULL, /* 0x3b */ - SQL_INTEGER, /* 0x3c */ - SQL_NULL, /* 0x3d */ - SQL_INTEGER, /* 0x3e */ - SQL_NULL, /* 0x3f */ - }; - - assert(MEM_Unsigned == 0x20000); - /* compress the unsigned bit with the pure - * type bits, to make them applicable for - * array indexing. + /* + * The order of the comparisons is essential. + * Once the value change its type, + * e.g. string or blob to integer/real + * the dynamic data are not disposed, + * they are kept together with scalar value. + * Thus the field 'flags' accumulates several + * bits responsible for data type. + * So the right order is following: + * - Null + * - Unsigned integer + * - Signed integer + * - Real + * - Bool + * - String + * - Blob */ - u32 offset = ((pVal->flags & MEM_Unsigned) >> 12) | - (pVal->flags & MEM_PURE_TYPE_MASK); - assert(offset < 0x40); - return aType[offset]; + if ((pVal->flags & MEM_Null) != 0) + return SQL_NULL; + if ((pVal->flags & MEM_Unsigned) != 0) + return SQL_UNSIGNED; + if ((pVal->flags & MEM_Int) != 0) + return SQL_INTEGER; + if ((pVal->flags & MEM_Real) != 0) + return SQL_FLOAT; + if ((pVal->flags & MEM_Bool) != 0) + return SQL_INTEGER; + if ((pVal->flags & MEM_Str) != 0) + return SQL_TEXT; + if ((pVal->flags & MEM_Blob) != 0) + return SQL_BLOB; + return SQL_NULL; /* Unknown type */ } /* Make a copy of an sql_value object @@ -1444,7 +1399,7 @@ sql_bind_uint64(sql_stmt * pStmt, int i, sql_uint64 iValue) Vdbe *p = (Vdbe *) pStmt; rc = vdbeUnbind(p, i); if (rc == SQL_OK) { - rc = sql_bind_type(p, i, "INTEGER"); + rc = sql_bind_type(p, i, "UNSIGNED"); sqlVdbeMemSetUInt64(&p->aVar[i - 1], iValue); } return rc; diff --git a/test/sql/iproto.result b/test/sql/iproto.result index deb0c5309..1b31e9db3 100644 --- a/test/sql/iproto.result +++ b/test/sql/iproto.result @@ -387,7 +387,7 @@ cn:execute('select ? as big_uint', {0xefffffffffffffffULL}) --- - metadata: - name: BIG_UINT - type: INTEGER + type: UNSIGNED rows: - [17293822569102704639] ... -- 2.17.1
next prev parent reply other threads:[~2019-04-01 20:45 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-01 20:44 [tarantool-patches] [PATCH v2 00/15] " Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 01/15] sql: Convert big integers from string Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 02/15] sql: make VDBE recognize big integers Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 03/15] sql: removes unused function Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 04/15] sql: support big integers within sql binding Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 05/15] sql: removes redundant function Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 06/15] sql: arithmetic functions support big integers Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 07/15] sql: aggregate sql functions support big int Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 08/15] sql: fixes errors Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 09/15] sql: support -2^63 .. 2^64-1 integer type Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 10/15] " Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 11/15] " Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 12/15] " Stanislav Zudin 2019-04-01 20:44 ` Stanislav Zudin [this message] 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 14/15] " Stanislav Zudin 2019-04-01 20:44 ` [tarantool-patches] [PATCH v2 15/15] " Stanislav Zudin 2019-04-02 16:54 ` [tarantool-patches] Re: [PATCH v2 00/15] " n.pettik
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=4c88b8cd5be67d643dcbc229f394aa6d78558615.1554150265.git.szudin@tarantool.org \ --to=szudin@tarantool.org \ --cc=korablev@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='Re: [tarantool-patches] [PATCH v2 13/15] sql: support -2^63 .. 2^64-1 integer type' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox