[tarantool-patches] [PATCH v2 15/15] sql: support -2^63 .. 2^64-1 integer type
Stanislav Zudin
szudin at tarantool.org
Mon Apr 1 23:44:53 MSK 2019
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
More information about the Tarantool-patches
mailing list