From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 298C52A524 for ; Mon, 1 Apr 2019 16:45:15 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id NmJR9AZlYoyc for ; Mon, 1 Apr 2019 16:45:15 -0400 (EDT) Received: from smtp18.mail.ru (smtp18.mail.ru [94.100.176.155]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id ABF8B2A50B for ; Mon, 1 Apr 2019 16:45:14 -0400 (EDT) From: Stanislav Zudin Subject: [tarantool-patches] [PATCH v2 15/15] sql: support -2^63 .. 2^64-1 integer type Date: Mon, 1 Apr 2019 23:44:53 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org, korablev@tarantool.org Cc: Stanislav Zudin Makes VDBE treat unsigned as a separate type. Closes #3810 --- src/box/sql/vdbe.c | 94 +++++++++++++++++++++++++++------------ src/box/sql/vdbeInt.h | 9 ++-- src/box/sql/vdbeapi.c | 2 +- src/box/sql/vdbeaux.c | 98 ++++++++++++++++++++++++++++++++++++----- src/box/sql/vdbemem.c | 47 ++++++++++++-------- src/box/sql/vdbetrace.c | 2 + 6 files changed, 187 insertions(+), 65 deletions(-) diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c index 787fdadab..a148bb7d4 100644 --- a/src/box/sql/vdbe.c +++ b/src/box/sql/vdbe.c @@ -293,13 +293,13 @@ mem_apply_numeric_type(Mem *pRec, int bTryForInt) { double rValue; i64 iValue; - assert((pRec->flags & (MEM_Str|MEM_Int|MEM_Real))==MEM_Str); + assert((pRec->flags & (MEM_Str|MEM_Int|MEM_Real|MEM_UInt))==MEM_Str); if (sqlAtoF(pRec->z, &rValue, pRec->n) == 0) return -1; bool is_unsigned = false; if (0 == sql_atoi64(pRec->z, (int64_t *)&iValue, &is_unsigned, pRec->n)) { pRec->u.i = iValue; - pRec->flags |= is_unsigned ? (MEM_Int | MEM_Unsigned) + pRec->flags |= is_unsigned ? MEM_UInt : MEM_Int; } else { pRec->u.r = rValue; @@ -338,9 +338,13 @@ mem_apply_type(struct Mem *record, enum field_type type) assert(type < field_type_MAX); switch (type) { case FIELD_TYPE_INTEGER: - case FIELD_TYPE_UNSIGNED: - if ((record->flags & MEM_Int) == MEM_Int) + if ((record->flags & MEM_Int) == MEM_Int) { + return 0; + } + if ((record->flags & MEM_UInt) == MEM_UInt) { + MemSetTypeFlag(record, MEM_Int); return 0; + } if ((record->flags & MEM_Real) == MEM_Real) { int64_t i = (int64_t) record->u.r; if (i == record->u.r) { @@ -350,8 +354,24 @@ mem_apply_type(struct Mem *record, enum field_type type) return 0; } return sqlVdbeMemIntegerify(record, false); + case FIELD_TYPE_UNSIGNED: + if ((record->flags & MEM_UInt) == MEM_UInt) + return 0; + if ((record->flags & MEM_Int) == MEM_Int){ + MemSetTypeFlag(record, MEM_UInt); + return 0; + } + if ((record->flags & MEM_Real) == MEM_Real) { + uint64_t i = (uint64_t) record->u.r; + if (i == record->u.r) { + record->u.u = i; + MemSetTypeFlag(record, MEM_UInt); + } + return 0; + } + return sqlVdbeMemIntegerify(record, false); case FIELD_TYPE_NUMBER: - if ((record->flags & (MEM_Real | MEM_Int)) != 0) + if ((record->flags & (MEM_Real | MEM_Int | MEM_UInt)) != 0) return 0; return sqlVdbeMemRealify(record); case FIELD_TYPE_STRING: @@ -361,10 +381,10 @@ mem_apply_type(struct Mem *record, enum field_type type) * NULL do not get converted). */ if ((record->flags & MEM_Str) == 0) { - if ((record->flags & (MEM_Real | MEM_Int))) + if ((record->flags & (MEM_Real | MEM_Int | MEM_UInt))) sqlVdbeMemStringify(record, 1); } - record->flags &= ~(MEM_Real | MEM_Int); + record->flags &= ~(MEM_Real | MEM_Int | MEM_UInt); return 0; case FIELD_TYPE_SCALAR: return 0; @@ -409,7 +429,7 @@ sql_value_apply_type( */ static u32 SQL_NOINLINE computeNumericType(Mem *pMem) { - assert((pMem->flags & (MEM_Int|MEM_Real))==0); + assert((pMem->flags & (MEM_Int|MEM_Real|MEM_UInt))==0); assert((pMem->flags & (MEM_Str|MEM_Blob))!=0); if (sqlAtoF(pMem->z, &pMem->u.r, pMem->n)==0) return 0; @@ -417,7 +437,7 @@ static u32 SQL_NOINLINE computeNumericType(Mem *pMem) if (sql_atoi64(pMem->z, (int64_t *)&pMem->u.i, &is_unsigned, pMem->n) != 0) return MEM_Real; - return is_unsigned ? (MEM_Int | MEM_Unsigned) + return is_unsigned ? MEM_UInt : MEM_Int; } @@ -430,10 +450,8 @@ static u32 SQL_NOINLINE computeNumericType(Mem *pMem) */ static u32 numericType(Mem *pMem) { - if ((pMem->flags & (MEM_Int|MEM_Unsigned)) == (MEM_Int|MEM_Unsigned)) - return (MEM_Int|MEM_Unsigned); - if (pMem->flags & (MEM_Int|MEM_Real)) { - return pMem->flags & (MEM_Int|MEM_Real); + if (pMem->flags & (MEM_Int|MEM_Real|MEM_UInt)) { + return pMem->flags & (MEM_Int|MEM_Real|MEM_UInt); } if (pMem->flags & (MEM_Str|MEM_Blob)) { return computeNumericType(pMem); @@ -538,6 +556,10 @@ memTracePrint(Mem *p) printf(" si:%lld", p->u.i); } else if (p->flags & MEM_Int) { printf(" i:%lld", p->u.i); + } else if ((p->flags & (MEM_UInt|MEM_Str))==(MEM_UInt|MEM_Str)) { + printf(" su:%llu", p->u.u); + } else if (p->flags & MEM_UInt) { + printf(" u:%llu", p->u.u); #ifndef SQL_OMIT_FLOATING_POINT } else if (p->flags & MEM_Real) { printf(" r:%g", p->u.r); @@ -1152,7 +1174,7 @@ case OP_Int64: { /* out2 */ assert(pOp->p4.pI64!=0); pOut->u.i = *pOp->p4.pI64; if (pOp->p4type == P4_UINT64) - pOut->flags = MEM_Int | MEM_Unsigned; + pOut->flags = MEM_UInt; break; } @@ -1447,9 +1469,9 @@ case OP_SCopy: { /* out2 */ */ case OP_IntCopy: { /* out2 */ pIn1 = &aMem[pOp->p1]; - assert((pIn1->flags & MEM_Int)!=0); + assert((pIn1->flags & (MEM_Int|MEM_UInt))!=0); pOut = &aMem[pOp->p2]; - if (pIn1->flags & MEM_Unsigned) + if (pIn1->flags & MEM_UInt) sqlVdbeMemSetUInt64(pOut, pIn1->u.u); else sqlVdbeMemSetInt64(pOut, pIn1->u.i); @@ -1675,11 +1697,11 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if ((flags & MEM_Null)!=0) goto arithmetic_result_is_null; - if ((type1 & type2 & MEM_Int)!=0) { + if ((type1 & (MEM_Int | MEM_UInt)) && (type2 & (MEM_Int | MEM_UInt))) { iA = pIn1->u.i; iB = pIn2->u.i; - bool is_signedA = (type1 & MEM_Unsigned) == 0; - bool is_signedB = (type2 & MEM_Unsigned) == 0; + bool is_signedA = (type1 & MEM_UInt) == 0; + bool is_signedB = (type2 & MEM_UInt) == 0; bIntint = 1; enum arithmetic_result arr; switch( pOp->opcode) { @@ -1695,7 +1717,7 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ MemSetTypeFlag(pOut, MEM_Int); break; case ATHR_UNSIGNED: - MemSetTypeFlag(pOut, MEM_Int|MEM_Unsigned); + MemSetTypeFlag(pOut, MEM_UInt); break; case ATHR_OVERFLOW: goto integer_overflow; case ATHR_DIVBYZERO: goto division_by_zero; @@ -2024,6 +2046,9 @@ case OP_AddImm: { /* in1 */ */ case OP_MustBeInt: { /* jump, in1 */ pIn1 = &aMem[pOp->p1]; + if ((pIn1->flags & MEM_UInt)!=0) + break; + if ((pIn1->flags & MEM_Int)==0) { mem_apply_type(pIn1, FIELD_TYPE_INTEGER); VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2); @@ -2052,7 +2077,7 @@ case OP_MustBeInt: { /* jump, in1 */ */ case OP_Realify: { /* in1 */ pIn1 = &aMem[pOp->p1]; - if (pIn1->flags & MEM_Int) { + if (pIn1->flags & (MEM_Int|MEM_UInt)) { sqlVdbeMemRealify(pIn1); } break; @@ -2229,12 +2254,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ enum field_type type = pOp->p5 & FIELD_TYPE_MASK; if (sql_type_is_numeric(type)) { if ((flags1 | flags3)&MEM_Str) { - if ((flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str) { + if ((flags1 & (MEM_Int|MEM_UInt|MEM_Real|MEM_Str))==MEM_Str) { mem_apply_numeric_type(pIn1, 0); testcase( flags3!=pIn3->flags); /* Possible if pIn1==pIn3 */ flags3 = pIn3->flags; } - if ((flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str) { + if ((flags3 & (MEM_Int|MEM_UInt|MEM_Real|MEM_Str))==MEM_Str) { if (mem_apply_numeric_type(pIn3, 0) != 0) { diag_set(ClientError, ER_SQL_TYPE_MISMATCH, @@ -2255,17 +2280,25 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ res = 0; goto compare_op; } + if ((pIn1->flags & pIn3->flags & MEM_UInt)!=0) { + if (pIn3->u.u > pIn1->u.u) { res = +1; goto compare_op; } + if (pIn3->u.u < pIn1->u.u) { res = -1; goto compare_op; } + res = 0; + goto compare_op; + } } else if (type == FIELD_TYPE_STRING) { - if ((flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0) { + if ((flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real|MEM_UInt))!=0) { testcase( pIn1->flags & MEM_Int); + testcase( pIn1->flags & MEM_UInt); testcase( pIn1->flags & MEM_Real); sqlVdbeMemStringify(pIn1, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn)); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); assert(pIn1!=pIn3); } - if ((flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0) { + if ((flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real|MEM_UInt))!=0) { testcase( pIn3->flags & MEM_Int); + testcase( pIn3->flags & MEM_UInt); testcase( pIn3->flags & MEM_Real); sqlVdbeMemStringify(pIn3, 1); testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn)); @@ -3559,6 +3592,7 @@ case OP_SeekGT: { /* jump, in3 */ UnpackedRecord r; /* The key to seek for */ int nField; /* Number of columns or fields in the key */ i64 iKey; /* The id we are to seek to */ + u32 key_type = MEM_Int; /* Type of the iKey, integer by default */ int eqOnly; /* Only interested in == results */ int reg_ipk=0; /* Register number which holds IPK. */ @@ -3587,12 +3621,14 @@ case OP_SeekGT: { /* jump, in3 */ * the seek, so convert it. */ pIn3 = &aMem[reg_ipk]; - if ((pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str) { + if ((pIn3->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_UInt))==MEM_Str) { mem_apply_numeric_type(pIn3, 0); + key_type = pIn3->flags & MEM_PURE_TYPE_MASK; } int64_t i; - if ((pIn3->flags & MEM_Int) == MEM_Int) { + if ((pIn3->flags & (MEM_Int | MEM_UInt)) != 0) { i = pIn3->u.i; + key_type = pIn3->flags & MEM_PURE_TYPE_MASK; } else if ((pIn3->flags & MEM_Real) == MEM_Real) { if (pIn3->u.r > INT64_MAX) i = INT64_MAX; @@ -3611,7 +3647,7 @@ case OP_SeekGT: { /* jump, in3 */ /* If the P3 value could not be converted into an integer without * loss of information, then special processing is required... */ - if ((pIn3->flags & MEM_Int)==0) { + if ((pIn3->flags & (MEM_Int | MEM_UInt))==0) { if ((pIn3->flags & MEM_Real)==0) { /* If the P3 value cannot be converted into any kind of a number, * then the seek is not possible, so jump to P2 @@ -3669,7 +3705,7 @@ case OP_SeekGT: { /* jump, in3 */ if (reg_ipk > 0) { aMem[reg_ipk].u.i = iKey; - aMem[reg_ipk].flags = MEM_Int; + aMem[reg_ipk].flags = key_type; } r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1); diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h index 78e211c97..5b2d129f7 100644 --- a/src/box/sql/vdbeInt.h +++ b/src/box/sql/vdbeInt.h @@ -235,7 +235,7 @@ struct Mem { #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 */ +#define MEM_TypeMask 0x283ff /* 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 @@ -249,10 +249,7 @@ struct Mem { #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_Unsigned 0x20000 /* Value is unsigned integer. - * Combine this flag with MEM_Int - * if necessary */ -#define MEM_UInt (MEM_Int | MEM_Unsigned) +#define MEM_UInt 0x20000 /* Value is unsigned integer. */ #ifdef SQL_OMIT_INCRBLOB #undef MEM_Zero @@ -281,7 +278,7 @@ enum { * Clear any existing type flags from a Mem and replace them with f */ #define MemSetTypeFlag(p, f) \ - ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero|MEM_Unsigned))|f) + ((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero|MEM_UInt))|f) /* * Return true if a memory cell is not marked as invalid. This macro diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index fe948dd26..e138c5abd 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -276,7 +276,7 @@ sql_value_type(sql_value * pVal) */ if ((pVal->flags & MEM_Null) != 0) return SQL_NULL; - if ((pVal->flags & MEM_Unsigned) != 0) + if ((pVal->flags & MEM_UInt) != 0) return SQL_UNSIGNED; if ((pVal->flags & MEM_Int) != 0) return SQL_INTEGER; diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c index 37cfe0431..3fbce2f01 100644 --- a/src/box/sql/vdbeaux.c +++ b/src/box/sql/vdbeaux.c @@ -1373,6 +1373,8 @@ displayP4(Op * pOp, char *zTemp, int nTemp) zP4 = pMem->z; } else if (pMem->flags & MEM_Int) { sqlXPrintf(&x, "%lld", pMem->u.i); + } else if (pMem->flags & MEM_UInt) { + sqlXPrintf(&x, "%llu", pMem->u.u); } else if (pMem->flags & MEM_Real) { sqlXPrintf(&x, "%.16g", pMem->u.r); } else if (pMem->flags & MEM_Null) { @@ -2856,7 +2858,7 @@ sqlVdbeSerialType(Mem * pMem, int file_format, u32 * pLen) *pLen = 0; return 0; } - if (flags & MEM_Int) { + if (flags & (MEM_Int|MEM_UInt)) { /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */ #define MAX_6BYTE ((((i64)0x00008000)<<32)-1) i64 i = pMem->u.i; @@ -3362,6 +3364,44 @@ sqlIntFloatCompare(i64 i, double r) } } +/* + * Do a comparison between a 64-bit signed integer and a 64-bit + * unsigned integer. + * Return negative, zero, or positive if the first (i64) is less than, + * equal to, or greater than the second (u64). + */ +static int +sqlIntUIntCompare(i64 i, u64 u) +{ + if (i < 0) + return -1; + if ((u64)i < u) + return -1; + else if ((u64)i > u) + return +1; + else + return 0; +} + +/* + * Do a comparison between a 64-bit unsigned integer and a 64-bit + * floating-point number. + * Return negative, zero, or positive if the first (u64) + * is less than, equal to, or greater than the second (double). + */ +static int +sqlUIntFloatCompare(u64 u, double r) +{ + if (r < 0.0) + return +1; + double s = (double)u; + if (s < r) + return -1; + if (s > r) + return +1; + return 0; +} + /* * Compare the values contained by the two memory cells, returning * negative, zero or positive if pMem1 is less than, equal to, or greater @@ -3390,7 +3430,7 @@ sqlMemCompare(const Mem * pMem1, const Mem * pMem2, const struct coll * pColl) /* At least one of the two values is a number */ - if (combined_flags & (MEM_Int | MEM_Real)) { + if (combined_flags & (MEM_Int | MEM_Real | MEM_UInt)) { if ((f1 & f2 & MEM_Int) != 0) { if (pMem1->u.i < pMem2->u.i) return -1; @@ -3398,6 +3438,13 @@ sqlMemCompare(const Mem * pMem1, const Mem * pMem2, const struct coll * pColl) return +1; return 0; } + if ((f1 & f2 & MEM_UInt) != 0) { + if (pMem1->u.u < pMem2->u.u) + return -1; + if (pMem1->u.u > pMem2->u.u) + return +1; + return 0; + } if ((f1 & f2 & MEM_Real) != 0) { if (pMem1->u.r < pMem2->u.r) return -1; @@ -3409,6 +3456,20 @@ sqlMemCompare(const Mem * pMem1, const Mem * pMem2, const struct coll * pColl) if ((f2 & MEM_Real) != 0) { return sqlIntFloatCompare(pMem1->u.i, pMem2->u.r); + } else if ((f2 & MEM_UInt) != 0){ + return sqlIntUIntCompare(pMem1->u.i, + pMem2->u.u); + } else { + return -1; + } + } + if ((f1 & MEM_UInt) != 0) { + if ((f2 & MEM_Real) != 0) { + return sqlUIntFloatCompare(pMem1->u.u, + pMem2->u.r); + } else if ((f2 & MEM_Int) != 0){ + return -sqlIntUIntCompare(pMem2->u.i, + pMem1->u.u); } else { return -1; } @@ -3416,7 +3477,10 @@ sqlMemCompare(const Mem * pMem1, const Mem * pMem2, const struct coll * pColl) if ((f1 & MEM_Real) != 0) { if ((f2 & MEM_Int) != 0) { return -sqlIntFloatCompare(pMem2->u.i, - pMem1->u.r); + pMem1->u.r); + } else if ((f2 & MEM_UInt) != 0) { + return -sqlUIntFloatCompare(pMem2->u.u, + pMem1->u.r); } else { return -1; } @@ -3572,13 +3636,24 @@ sqlVdbeCompareMsgpack(const char **key1, goto do_int; } case MP_UINT:{ - uint64_t v = mp_decode_uint(&aKey1); - if (v > INT64_MAX) { - mem1.u.r = (double)v; - goto do_float; + mem1.u.u = mp_decode_uint(&aKey1); + + if (pKey2->flags & MEM_Int) { + rc = -sqlIntUIntCompare(pKey2->u.i, + mem1.u.u); + } else if (pKey2->flags & MEM_Real) { + rc = sqlUIntFloatCompare(mem1.u.u, + pKey2->u.r); + } else if (pKey2->flags & MEM_UInt) { + if (mem1.u.u < pKey2->u.u) { + rc = -1; + } else if (mem1.u.u > pKey2->u.u) { + rc = +1; + } + } else { + rc = (pKey2->flags & MEM_Null) ? +1 : -1; } - mem1.u.i = v; - goto do_int; + break; } case MP_INT:{ mem1.u.i = mp_decode_int(&aKey1); @@ -3592,6 +3667,9 @@ sqlVdbeCompareMsgpack(const char **key1, } else if (pKey2->flags & MEM_Real) { rc = sqlIntFloatCompare(mem1.u.i, pKey2->u.r); + } else if (pKey2->flags & MEM_UInt) { + rc = sqlIntUIntCompare(mem1.u.i, + pKey2->u.u); } else { rc = (pKey2->flags & MEM_Null) ? +1 : -1; } @@ -3732,7 +3810,7 @@ vdbe_decode_msgpack_into_mem(const char *buf, struct Mem *mem, uint32_t *len) mem->u.i = v; mem->flags = MEM_Int; if (v > INT64_MAX) - mem->flags |= MEM_Unsigned; + mem->flags = MEM_UInt; break; } case MP_INT: { diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c index 2d61ca675..a30b131a6 100644 --- a/src/box/sql/vdbemem.c +++ b/src/box/sql/vdbemem.c @@ -66,7 +66,8 @@ 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)); + assert((p->flags & (MEM_Int | MEM_Real | MEM_UInt)) != + (MEM_Int | MEM_Real| MEM_UInt)); /* The szMalloc field holds the correct memory allocation size */ assert(p->szMalloc == 0 @@ -173,7 +174,7 @@ sqlVdbeMemClearAndResize(Mem * pMem, int szNew) } assert((pMem->flags & MEM_Dyn) == 0); pMem->z = pMem->zMalloc; - pMem->flags &= (MEM_Null | MEM_Int | MEM_Real); + pMem->flags &= (MEM_Null | MEM_Int | MEM_Real | MEM_UInt); return SQL_OK; } @@ -289,7 +290,7 @@ sqlVdbeMemStringify(Mem * pMem, u8 bForce) return SQL_OK; assert(!(fg & MEM_Zero)); - assert(fg & (MEM_Int | MEM_Real)); + assert(fg & (MEM_Int | MEM_Real | MEM_UInt)); assert(EIGHT_BYTE_ALIGNMENT(pMem)); if (sqlVdbeMemClearAndResize(pMem, nByte)) { @@ -297,6 +298,8 @@ sqlVdbeMemStringify(Mem * pMem, u8 bForce) } if (fg & MEM_Int) { sql_snprintf(nByte, pMem->z, "%lld", pMem->u.i); + } else if (fg & MEM_UInt) { + sql_snprintf(nByte, pMem->z, "%llu", pMem->u.u); } else { assert(fg & MEM_Real); sql_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); @@ -304,7 +307,7 @@ sqlVdbeMemStringify(Mem * pMem, u8 bForce) pMem->n = sqlStrlen30(pMem->z); pMem->flags |= MEM_Str | MEM_Term; if (bForce) - pMem->flags &= ~(MEM_Int | MEM_Real); + pMem->flags &= ~(MEM_Int | MEM_Real | MEM_UInt); return SQL_OK; } @@ -462,7 +465,11 @@ sqlVdbeIntValue(Mem * pMem, int64_t *i, bool *is_unsigned) flags = pMem->flags; if (flags & MEM_Int) { *i = pMem->u.i; - *is_unsigned = (flags & MEM_Unsigned) != 0; + *is_unsigned = false; + return 0; + } else if (flags & MEM_UInt) { + *i = (i64)pMem->u.u; + *is_unsigned = true; return 0; } else if (flags & MEM_Real) { return doubleToInt64(pMem->u.r, i, is_unsigned); @@ -486,8 +493,8 @@ sqlVdbeRealValue(Mem * pMem, double *v) if (pMem->flags & MEM_Real) { *v = pMem->u.r; return 0; - } else if ((pMem->flags & MEM_UInt) == MEM_UInt) { - *v = (double)(u64)pMem->u.i; + } else if (pMem->flags & MEM_UInt) { + *v = (double)pMem->u.u; return 0; } else if (pMem->flags & MEM_Int) { *v = (double)pMem->u.i; @@ -516,7 +523,7 @@ mem_apply_integer_type(Mem *pMem) if ((rc = doubleToInt64(pMem->u.r, (int64_t *) &ix, &is_unsigned)) == 0) { pMem->u.i = ix; if (is_unsigned) - MemSetTypeFlag(pMem, MEM_Int | MEM_Unsigned); + MemSetTypeFlag(pMem, MEM_UInt); else MemSetTypeFlag(pMem, MEM_Int); } @@ -537,7 +544,7 @@ sqlVdbeMemIntegerify(Mem * pMem, bool is_forced) pMem->u.i = i; if (is_unsigned) - MemSetTypeFlag(pMem, MEM_Int | MEM_Unsigned); + MemSetTypeFlag(pMem, MEM_UInt); else MemSetTypeFlag(pMem, MEM_Int); return 0; @@ -546,7 +553,7 @@ sqlVdbeMemIntegerify(Mem * pMem, bool is_forced) return -1; if (is_unsigned) - MemSetTypeFlag(pMem, MEM_Int | MEM_Unsigned); + MemSetTypeFlag(pMem, MEM_UInt); else MemSetTypeFlag(pMem, MEM_Int); return 0; @@ -589,7 +596,7 @@ sqlVdbeMemRealify(Mem * pMem) int sqlVdbeMemNumerify(Mem * pMem) { - if ((pMem->flags & (MEM_Int | MEM_Real | MEM_Null)) == 0) { + if ((pMem->flags & (MEM_Int | MEM_Real | MEM_Null | MEM_UInt)) == 0) { assert((pMem->flags & (MEM_Blob | MEM_Str)) != 0); bool is_unsigned = false; if (0 == sql_atoi64(pMem->z, @@ -597,7 +604,7 @@ sqlVdbeMemNumerify(Mem * pMem) &is_unsigned, pMem->n)) { if (is_unsigned) - MemSetTypeFlag(pMem, MEM_Int | MEM_Unsigned); + MemSetTypeFlag(pMem, MEM_UInt); else MemSetTypeFlag(pMem, MEM_Int); } else { @@ -609,7 +616,7 @@ sqlVdbeMemNumerify(Mem * pMem) mem_apply_integer_type(pMem); } } - assert((pMem->flags & (MEM_Int | MEM_Real | MEM_Null)) != 0); + assert((pMem->flags & (MEM_Int | MEM_Real | MEM_Null | MEM_UInt)) != 0); pMem->flags &= ~(MEM_Str | MEM_Blob | MEM_Zero); return SQL_OK; } @@ -652,7 +659,7 @@ sqlVdbeMemCast(Mem * pMem, enum field_type type) pMem->n) != 0) return -1; if (is_unsigned) - MemSetTypeFlag(pMem, MEM_Int | MEM_Unsigned); + MemSetTypeFlag(pMem, MEM_UInt); else MemSetTypeFlag(pMem, MEM_Int); return 0; @@ -666,7 +673,7 @@ sqlVdbeMemCast(Mem * pMem, enum field_type type) pMem->flags |= (pMem->flags & MEM_Blob) >> 3; sql_value_apply_type(pMem, FIELD_TYPE_STRING); assert(pMem->flags & MEM_Str || pMem->db->mallocFailed); - pMem->flags &= ~(MEM_Int | MEM_Real | MEM_Blob | MEM_Zero); + pMem->flags &= ~(MEM_Int | MEM_Real | MEM_Blob | MEM_Zero | MEM_UInt); return SQL_OK; } } @@ -747,7 +754,7 @@ vdbeReleaseAndSetUInt64(Mem * pMem, u64 val) { sqlVdbeMemSetNull(pMem); pMem->u.u = val; - pMem->flags = MEM_Int | MEM_Unsigned; + pMem->flags = MEM_UInt; } /* @@ -772,7 +779,7 @@ sqlVdbeMemSetUInt64(Mem * pMem, u64 val) vdbeReleaseAndSetUInt64(pMem, val); } else { pMem->u.u = val; - pMem->flags = MEM_Int | MEM_Unsigned; + pMem->flags = MEM_UInt; } } @@ -1362,7 +1369,7 @@ valueFromExpr(sql * db, /* The database connection */ } else { sql_value_apply_type(pVal, type); } - if (pVal->flags & (MEM_Int | MEM_Real)) + if (pVal->flags & (MEM_Int | MEM_Real | MEM_UInt)) pVal->flags &= ~MEM_Str; } else if (op == TK_UMINUS) { /* This branch happens for multiple negative signs. Ex: -(-5) */ @@ -1773,10 +1780,12 @@ mpstream_encode_vdbe_mem(struct mpstream *stream, struct Mem *var) } else if (var->flags & MEM_Int) { i = var->u.i; encode_int: - if (var->u.i >= 0 || var->flags & MEM_Unsigned) + if (var->u.i >= 0) mpstream_encode_uint(stream, i); else mpstream_encode_int(stream, i); + } else if (var->flags & MEM_UInt) { + mpstream_encode_uint(stream, var->u.u); } else if (var->flags & MEM_Str) { mpstream_encode_strn(stream, var->z, var->n); } else if (var->flags & MEM_Bool) { diff --git a/src/box/sql/vdbetrace.c b/src/box/sql/vdbetrace.c index cb930538d..361e0841a 100644 --- a/src/box/sql/vdbetrace.c +++ b/src/box/sql/vdbetrace.c @@ -158,6 +158,8 @@ sqlVdbeExpandSql(Vdbe * p, /* The prepared statement being evaluated */ sqlStrAccumAppend(&out, "NULL", 4); } else if (pVar->flags & MEM_Int) { sqlXPrintf(&out, "%lld", pVar->u.i); + } else if (pVar->flags & MEM_UInt) { + sqlXPrintf(&out, "%llu", pVar->u.u); } else if (pVar->flags & MEM_Real) { sqlXPrintf(&out, "%!.15g", pVar->u.r); } else if (pVar->flags & MEM_Str) { -- 2.17.1