[Tarantool-patches] [PATCH v4 11/53] sql: introduce mem_is_*() functions()
imeevma at tarantool.org
imeevma at tarantool.org
Tue Mar 23 12:35:18 MSK 2021
This patch introduces mem_is_*() functions that allows to check current
MEM state.
Part of #5818
---
src/box/sql/func.c | 40 ++++---
src/box/sql/mem.c | 139 +++++++++++++++++++++++-
src/box/sql/mem.h | 69 ++++++++++--
src/box/sql/select.c | 2 +-
src/box/sql/vdbe.c | 228 +++++++++++++++++++---------------------
src/box/sql/vdbeInt.h | 11 --
src/box/sql/vdbeapi.c | 4 +-
src/box/sql/vdbeaux.c | 6 +-
src/box/sql/vdbesort.c | 2 +-
src/box/sql/whereexpr.c | 3 +-
10 files changed, 332 insertions(+), 172 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index e600a9800..81b537d9b 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -398,10 +398,10 @@ minmaxFunc(sql_context * context, int argc, sql_value ** argv)
pColl = sqlGetFuncCollSeq(context);
assert(mask == -1 || mask == 0);
iBest = 0;
- if (sql_value_is_null(argv[0]))
+ if (mem_is_null(argv[0]))
return;
for (i = 1; i < argc; i++) {
- if (sql_value_is_null(argv[i]))
+ if (mem_is_null(argv[i]))
return;
if ((sqlMemCompare(argv[iBest], argv[i], pColl) ^ mask) >=
0) {
@@ -736,8 +736,8 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
context->is_aborted = true;
return;
}
- if (sql_value_is_null(argv[1])
- || (argc == 3 && sql_value_is_null(argv[2]))
+ if (mem_is_null(argv[1])
+ || (argc == 3 && mem_is_null(argv[2]))
) {
return;
}
@@ -838,16 +838,15 @@ roundFunc(sql_context * context, int argc, sql_value ** argv)
return;
}
if (argc == 2) {
- if (sql_value_is_null(argv[1]))
+ if (mem_is_null(argv[1]))
return;
n = sql_value_int(argv[1]);
if (n < 0)
n = 0;
}
- if (sql_value_is_null(argv[0]))
+ if (mem_is_null(argv[0]))
return;
- enum mp_type mp_type = sql_value_type(argv[0]);
- if (mp_type_is_bloblike(mp_type)) {
+ if (mem_is_binary(argv[0])) {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
mem_str(argv[0]), "numeric");
context->is_aborted = true;
@@ -907,8 +906,7 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv) \
const char *z2; \
int n; \
UNUSED_PARAMETER(argc); \
- int arg_type = sql_value_type(argv[0]); \
- if (mp_type_is_bloblike(arg_type)) { \
+ if (mem_is_binary(argv[0])) { \
diag_set(ClientError, ER_INCONSISTENT_TYPES, "text", \
"varbinary"); \
context->is_aborted = true; \
@@ -989,7 +987,7 @@ randomBlob(sql_context * context, int argc, sql_value ** argv)
unsigned char *p;
assert(argc == 1);
UNUSED_PARAMETER(argc);
- if (mp_type_is_bloblike(sql_value_type(argv[0]))) {
+ if (mem_is_binary(argv[0])) {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
mem_str(argv[0]), "numeric");
context->is_aborted = true;
@@ -1439,7 +1437,7 @@ quoteFunc(sql_context * context, int argc, sql_value ** argv)
break;
}
default:{
- assert(sql_value_is_null(argv[0]));
+ assert(mem_is_null(argv[0]));
sql_result_text(context, "NULL", 4, SQL_STATIC);
break;
}
@@ -1578,13 +1576,13 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
assert(zStr == sql_value_text(argv[0])); /* No encoding change */
zPattern = sql_value_text(argv[1]);
if (zPattern == 0) {
- assert(sql_value_is_null(argv[1])
+ assert(mem_is_null(argv[1])
|| sql_context_db_handle(context)->mallocFailed);
return;
}
nPattern = sql_value_bytes(argv[1]);
if (nPattern == 0) {
- assert(! sql_value_is_null(argv[1]));
+ assert(! mem_is_null(argv[1]));
sql_result_value(context, argv[0]);
return;
}
@@ -1748,10 +1746,9 @@ trim_func_one_arg(struct sql_context *context, sql_value *arg)
{
/* In case of VARBINARY type default trim octet is X'00'. */
const unsigned char *default_trim;
- enum mp_type val_type = sql_value_type(arg);
- if (val_type == MP_NIL)
+ if (mem_is_null(arg))
return;
- if (mp_type_is_bloblike(val_type))
+ if (mem_is_binary(arg))
default_trim = (const unsigned char *) "\0";
else
default_trim = (const unsigned char *) " ";
@@ -1880,8 +1877,7 @@ soundexFunc(sql_context * context, int argc, sql_value ** argv)
1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
};
assert(argc == 1);
- enum mp_type mp_type = sql_value_type(argv[0]);
- if (mp_type_is_bloblike(mp_type)) {
+ if (mem_is_binary(argv[0])) {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
mem_str(argv[0]), "text");
context->is_aborted = true;
@@ -2039,7 +2035,7 @@ countStep(sql_context * context, int argc, sql_value ** argv)
return;
}
p = sql_aggregate_context(context, sizeof(*p));
- if ((argc == 0 || ! sql_value_is_null(argv[0])) && p) {
+ if ((argc == 0 || ! mem_is_null(argv[0])) && p) {
p->n++;
}
}
@@ -2068,7 +2064,7 @@ minmaxStep(sql_context * context, int NotUsed, sql_value ** argv)
if (!pBest)
return;
- if (sql_value_is_null(argv[0])) {
+ if (mem_is_null(argv[0])) {
if (pBest->flags)
sqlSkipAccumulatorLoad(context);
} else if (pBest->flags) {
@@ -2122,7 +2118,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv)
context->is_aborted = true;
return;
}
- if (sql_value_is_null(argv[0]))
+ if (mem_is_null(argv[0]))
return;
pAccum =
(StrAccum *) sql_aggregate_context(context, sizeof(*pAccum));
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index ec6aaab64..abc9291ef 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -37,6 +37,142 @@
#include "box/tuple.h"
#include "mpstream/mpstream.h"
+bool
+mem_is_null(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Null) != 0;
+}
+
+bool
+mem_is_unsigned(const struct Mem *mem)
+{
+ return (mem->flags & MEM_UInt) != 0;
+}
+
+bool
+mem_is_string(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Str) != 0;
+}
+
+bool
+mem_is_number(const struct Mem *mem)
+{
+ return (mem->flags & (MEM_Real | MEM_Int |MEM_UInt)) != 0;
+}
+
+bool
+mem_is_double(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Real) != 0;
+}
+
+bool
+mem_is_integer(const struct Mem *mem)
+{
+ return (mem->flags & (MEM_Int | MEM_UInt)) != 0;
+}
+
+bool
+mem_is_boolean(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Bool) != 0;
+}
+
+bool
+mem_is_binary(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Blob) != 0;
+}
+
+bool
+mem_is_map(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Blob) != 0 &&
+ (mem->flags & MEM_Subtype) != 0 &&
+ mem->subtype == SQL_SUBTYPE_MSGPACK &&
+ mp_typeof(*mem->z) == MP_MAP;
+}
+
+bool
+mem_is_array(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Blob) != 0 &&
+ (mem->flags & MEM_Subtype) != 0 &&
+ mem->subtype == SQL_SUBTYPE_MSGPACK &&
+ mp_typeof(*mem->z) == MP_ARRAY;
+}
+
+bool
+mem_is_aggregate(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Agg) != 0;
+}
+
+bool
+mem_is_varstring(const struct Mem *mem)
+{
+ return (mem->flags & (MEM_Blob | MEM_Str)) != 0;
+}
+
+bool
+mem_is_frame(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Frame) != 0;
+}
+
+bool
+mem_is_undefined(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Undefined) != 0;
+}
+
+bool
+mem_is_static(const struct Mem *mem)
+{
+ return (mem->flags & (MEM_Str | MEM_Blob)) != 0 &&
+ (mem->flags & MEM_Static) != 0;
+}
+
+bool
+mem_is_ephemeral(const struct Mem *mem)
+{
+ return (mem->flags & (MEM_Str | MEM_Blob)) != 0 &&
+ (mem->flags & MEM_Ephem) != 0;
+}
+
+bool
+mem_is_dynamic(const struct Mem *mem)
+{
+ return (mem->flags & (MEM_Str | MEM_Blob)) != 0 &&
+ (mem->flags & MEM_Dyn) != 0;
+}
+
+bool
+mem_is_allocated(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Blob) != 0 && mem->z == mem->zMalloc;
+}
+
+bool
+mem_is_cleared(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Null) != 0 && (mem->flags & MEM_Cleared) != 0;
+}
+
+bool
+mem_is_zeroblob(const struct Mem *mem)
+{
+ return (mem->flags & MEM_Blob) != 0 && (mem->flags & MEM_Zero) != 0;
+}
+
+bool
+mem_is_same_type(const struct Mem *mem1, const struct Mem *mem2)
+{
+ return (mem1->flags & MEM_PURE_TYPE_MASK) ==
+ (mem2->flags & MEM_PURE_TYPE_MASK);
+}
+
enum {
BUF_SIZE = 32,
};
@@ -1083,8 +1219,7 @@ mem_convert_to_integer(struct Mem *mem)
int
mem_convert_to_numeric(struct Mem *mem, enum field_type type)
{
- assert(mp_type_is_numeric(mem_mp_type(mem)) &&
- sql_type_is_numeric(type));
+ assert(mem_is_number(mem) && sql_type_is_numeric(type));
assert(type != FIELD_TYPE_NUMBER);
if (type == FIELD_TYPE_DOUBLE)
return mem_convert_to_double(mem);
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index 5ac02c002..19920af3a 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -87,6 +87,69 @@ struct Mem {
*/
#define MEMCELLSIZE offsetof(Mem,zMalloc)
+bool
+mem_is_null(const struct Mem *mem);
+
+bool
+mem_is_unsigned(const struct Mem *mem);
+
+bool
+mem_is_string(const struct Mem *mem);
+
+bool
+mem_is_number(const struct Mem *mem);
+
+bool
+mem_is_double(const struct Mem *mem);
+
+bool
+mem_is_integer(const struct Mem *mem);
+
+bool
+mem_is_boolean(const struct Mem *mem);
+
+bool
+mem_is_binary(const struct Mem *mem);
+
+bool
+mem_is_map(const struct Mem *mem);
+
+bool
+mem_is_array(const struct Mem *mem);
+
+bool
+mem_is_aggregate(const struct Mem *mem);
+
+bool
+mem_is_varstring(const struct Mem *mem);
+
+bool
+mem_is_frame(const struct Mem *mem);
+
+bool
+mem_is_undefined(const struct Mem *mem);
+
+bool
+mem_is_static(const struct Mem *mem);
+
+bool
+mem_is_ephemeral(const struct Mem *mem);
+
+bool
+mem_is_dynamic(const struct Mem *mem);
+
+bool
+mem_is_allocated(const struct Mem *mem);
+
+bool
+mem_is_cleared(const struct Mem *mem);
+
+bool
+mem_is_zeroblob(const struct Mem *mem);
+
+bool
+mem_is_same_type(const struct Mem *mem1, const struct Mem *mem2);
+
/**
* Return a string that represent content of MEM. String is either allocated
* using static_alloc() of just a static variable.
@@ -396,12 +459,6 @@ columnNullValue(void);
/** Checkers. */
-static inline bool
-sql_value_is_null(struct Mem *value)
-{
- return sql_value_type(value) == MP_NIL;
-}
-
int sqlVdbeMemTooBig(Mem *);
/* Return TRUE if Mem X contains dynamically allocated content - anything
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 0fa388ae9..b9107fccc 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1092,7 +1092,7 @@ selectInnerLoop(Parse * pParse, /* The parser context */
* re-use second for Null op-code.
*
* Change to an OP_Null sets the
- * MEM_Cleared bit on the first
+ * Cleared flag on the first
* register of the previous value.
* This will cause the OP_Ne below
* to always fail on the first
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 12712efb4..05e0f78c1 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -91,8 +91,8 @@ int sql_sort_count = 0;
#endif
/*
- * The next global variable records the size of the largest MEM_Blob
- * or MEM_Str that has been used by a VDBE opcode. The test procedures
+ * The next global variable records the size of the largest varbinary
+ * or string that has been used by a VDBE opcode. The test procedures
* use this information to make sure that the zero-blob functionality
* is working correctly. This variable has no function other than to
* help verify the correct operation of the library.
@@ -102,9 +102,8 @@ int sql_max_blobsize = 0;
static void
updateMaxBlobsize(Mem *p)
{
- if ((p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sql_max_blobsize) {
+ if (mem_is_varstring(p) && p->n > sql_max_blobsize)
sql_max_blobsize = p->n;
- }
}
#endif
@@ -396,8 +395,7 @@ vdbe_field_ref_fetch(struct vdbe_field_ref *field_ref, uint32_t fieldno,
* Add 0 termination (at most for strings)
* Not sure why do we check MEM_Ephem
*/
- if ((dest_mem->flags & (MEM_Ephem | MEM_Str)) ==
- (MEM_Ephem | MEM_Str)) {
+ if (mem_is_string(dest_mem) && mem_is_ephemeral(dest_mem)) {
int len = dest_mem->n;
if (dest_mem->szMalloc < len + 1) {
if (sqlVdbeMemGrow(dest_mem, len + 1, 1) != 0)
@@ -630,7 +628,7 @@ case OP_Gosub: { /* jump */
*/
case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
- assert(pIn1->flags==MEM_UInt);
+ assert(mem_is_unsigned(pIn1));
pOp = &aOp[pIn1->u.u];
pIn1->flags = MEM_Undefined;
break;
@@ -669,7 +667,7 @@ case OP_InitCoroutine: { /* jump */
case OP_EndCoroutine: { /* in1 */
VdbeOp *pCaller;
pIn1 = &aMem[pOp->p1];
- assert(pIn1->flags == MEM_UInt);
+ assert(mem_is_unsigned(pIn1));
assert(pIn1->u.u < (uint64_t) p->nOp);
pCaller = &aOp[pIn1->u.u];
assert(pCaller->opcode==OP_Yield);
@@ -1079,7 +1077,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
pIn2 = &aMem[pOp->p2];
pOut = vdbe_prepare_null_out(p, pOp->p3);
assert(pIn1!=pOut);
- if ((pIn1->flags | pIn2->flags) & MEM_Null) {
+ if (mem_is_null(pIn1) || mem_is_null(pIn2)) {
/* Force NULL be of type STRING. */
pOut->field_type = FIELD_TYPE_STRING;
break;
@@ -1088,10 +1086,10 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
* Concatenation operation can be applied only to
* strings and blobs.
*/
- uint32_t str_type_p1 = pIn1->flags & (MEM_Blob | MEM_Str);
- uint32_t str_type_p2 = pIn2->flags & (MEM_Blob | MEM_Str);
- if (str_type_p1 == 0 || str_type_p2 == 0) {
- char *inconsistent_type = str_type_p1 == 0 ?
+ bool str_type_p1 = mem_is_varstring(pIn1);
+ bool str_type_p2 = mem_is_varstring(pIn2);
+ if (!str_type_p1 || !str_type_p2) {
+ char *inconsistent_type = !str_type_p1 ?
mem_type_to_str(pIn1) :
mem_type_to_str(pIn2);
diag_set(ClientError, ER_INCONSISTENT_TYPES,
@@ -1100,7 +1098,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
}
/* Moreover, both operands must be of the same type. */
- if (str_type_p1 != str_type_p2) {
+ if (mem_is_string(pIn1) != mem_is_string(pIn2)) {
diag_set(ClientError, ER_INCONSISTENT_TYPES,
mem_type_to_str(pIn2), mem_type_to_str(pIn1));
goto abort_due_to_error;
@@ -1114,7 +1112,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if (sqlVdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2)) {
goto no_mem;
}
- if (pIn1->flags & MEM_Str)
+ if (mem_is_string(pIn1))
MemSetTypeFlag(pOut, MEM_Str);
else
MemSetTypeFlag(pOut, MEM_Blob);
@@ -1173,7 +1171,6 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
- u32 flags; /* Combined MEM_* flags from both inputs */
u16 type1; /* Numeric type of left operand */
u16 type2; /* Numeric type of right operand */
i64 iA; /* Integer value of left operand */
@@ -1186,14 +1183,16 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
pIn2 = &aMem[pOp->p2];
type2 = numericType(pIn2);
pOut = vdbe_prepare_null_out(p, pOp->p3);
- flags = pIn1->flags | pIn2->flags;
- if ((flags & MEM_Null)!=0) goto arithmetic_result_is_null;
+ if (mem_is_null(pIn1) || mem_is_null(pIn2))
+ goto arithmetic_result_is_null;
if ((type1 & (MEM_Int | MEM_UInt)) != 0 &&
(type2 & (MEM_Int | MEM_UInt)) != 0) {
iA = pIn1->u.i;
iB = pIn2->u.i;
- bool is_lhs_neg = pIn1->flags & MEM_Int;
- bool is_rhs_neg = pIn2->flags & MEM_Int;
+ bool is_lhs_neg = mem_is_integer(pIn1) &&
+ !mem_is_unsigned(pIn1);
+ bool is_rhs_neg = mem_is_integer(pIn2) &&
+ !mem_is_unsigned(pIn2);
bool is_res_neg;
switch( pOp->opcode) {
case OP_Add: {
@@ -1400,7 +1399,7 @@ case OP_BuiltinFunction: {
goto abort_due_to_error;
/* Copy the result of the function into register P3 */
- if (pOut->flags & (MEM_Str|MEM_Blob)) {
+ if (mem_is_varstring(pOut)) {
if (sqlVdbeMemTooBig(pCtx->pOut)) goto too_big;
}
@@ -1459,7 +1458,7 @@ case OP_FunctionByName: {
* Copy the result of the function invocation into
* register P3.
*/
- if ((pOut->flags & (MEM_Str | MEM_Blob)) != 0)
+ if (mem_is_varstring(pOut))
if (sqlVdbeMemTooBig(pOut)) goto too_big;
REGISTER_TRACE(p, pOp->p3, pOut);
@@ -1509,7 +1508,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
pOut = vdbe_prepare_null_out(p, pOp->p3);
- if ((pIn1->flags | pIn2->flags) & MEM_Null) {
+ if (mem_is_null(pIn1) || mem_is_null(pIn2)) {
/* Force NULL be of type INTEGER. */
pOut->field_type = FIELD_TYPE_INTEGER;
break;
@@ -1568,7 +1567,7 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
case OP_AddImm: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
- assert((pIn1->flags & MEM_UInt) != 0 && pOp->p2 >= 0);
+ assert(mem_is_unsigned(pIn1) && pOp->p2 >= 0);
pIn1->u.u += pOp->p2;
break;
}
@@ -1582,9 +1581,9 @@ case OP_AddImm: { /* in1 */
*/
case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
- if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
+ if (!mem_is_integer(pIn1)) {
mem_apply_type(pIn1, FIELD_TYPE_INTEGER);
- if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
+ if (!mem_is_integer(pIn1)) {
if (pOp->p2==0) {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
mem_str(pIn1), "integer");
@@ -1608,7 +1607,7 @@ case OP_MustBeInt: { /* jump, in1 */
*/
case OP_Realify: { /* in1 */
pIn1 = &aMem[pOp->p1];
- if ((pIn1->flags & (MEM_Int | MEM_UInt)) != 0) {
+ if (mem_is_integer(pIn1)) {
sqlVdbeMemRealify(pIn1);
}
break;
@@ -1749,7 +1748,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
flags3 = pIn3->flags;
enum field_type ft_p1 = pIn1->field_type;
enum field_type ft_p3 = pIn3->field_type;
- if ((flags1 | flags3)&MEM_Null) {
+ if (mem_is_null(pIn1) || mem_is_null(pIn3)) {
/* One or both operands are NULL */
if (pOp->p5 & SQL_NULLEQ) {
/* If SQL_NULLEQ is set (which will only happen if the operator is
@@ -1757,11 +1756,10 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
* or not both operands are null.
*/
assert(pOp->opcode==OP_Eq || pOp->opcode==OP_Ne);
- assert((flags1 & MEM_Cleared)==0);
+ assert(!mem_is_cleared(pIn1));
assert((pOp->p5 & SQL_JUMPIFNULL)==0);
- if ((flags1&flags3&MEM_Null)!=0
- && (flags3&MEM_Cleared)==0
- ) {
+ if (mem_is_null(pIn1) && mem_is_null(pIn3) &&
+ !mem_is_cleared(pIn3)) {
res = 0; /* Operands are equal */
} else {
res = 1; /* Operands are not equal */
@@ -1783,22 +1781,17 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}
break;
}
- } else if (((flags1 | flags3) & MEM_Bool) != 0 ||
- ((flags1 | flags3) & MEM_Blob) != 0) {
- /*
- * If one of values is of type BOOLEAN or VARBINARY,
- * then the second one must be of the same type as
- * well. Otherwise an error is raised.
- */
- int type_arg1 = flags1 & (MEM_Bool | MEM_Blob);
- int type_arg3 = flags3 & (MEM_Bool | MEM_Blob);
- if (type_arg1 != type_arg3) {
- char *inconsistent_type = type_arg1 != 0 ?
+ } else if (mem_is_boolean(pIn1) || mem_is_boolean(pIn3) ||
+ mem_is_binary(pIn1) || mem_is_binary(pIn3)) {
+ if (!mem_is_same_type(pIn1, pIn3)) {
+ char *inconsistent_type = mem_is_boolean(pIn1) ||
+ mem_is_binary(pIn1) ?
mem_type_to_str(pIn3) :
mem_type_to_str(pIn1);
- char *expected_type = type_arg1 != 0 ?
- mem_type_to_str(pIn1) :
- mem_type_to_str(pIn3);
+ char *expected_type = mem_is_boolean(pIn1) ||
+ mem_is_binary(pIn1) ?
+ mem_type_to_str(pIn1) :
+ mem_type_to_str(pIn3);
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
inconsistent_type, expected_type);
goto abort_due_to_error;
@@ -1807,28 +1800,25 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
} else {
enum field_type type = pOp->p5 & FIELD_TYPE_MASK;
if (sql_type_is_numeric(type)) {
- if ((flags1 | flags3)&MEM_Str) {
- if ((flags1 & MEM_Str) == MEM_Str) {
- mem_apply_numeric_type(pIn1);
- testcase( flags3!=pIn3->flags); /* Possible if pIn1==pIn3 */
- flags3 = pIn3->flags;
- }
- if ((flags3 & MEM_Str) == MEM_Str) {
- if (mem_apply_numeric_type(pIn3) != 0) {
- diag_set(ClientError,
- ER_SQL_TYPE_MISMATCH,
- mem_str(pIn3),
- "numeric");
- goto abort_due_to_error;
- }
-
+ if (mem_is_string(pIn1)) {
+ mem_apply_numeric_type(pIn1);
+ flags3 = pIn3->flags;
+ }
+ if (mem_is_string(pIn3)) {
+ if (mem_apply_numeric_type(pIn3) != 0) {
+ diag_set(ClientError,
+ ER_SQL_TYPE_MISMATCH,
+ mem_str(pIn3),
+ "numeric");
+ goto abort_due_to_error;
}
}
/* Handle the common case of integer comparison here, as an
* optimization, to avoid a call to sqlMemCompare()
*/
- if ((pIn1->flags & pIn3->flags & (MEM_Int | MEM_UInt)) != 0) {
- if ((pIn1->flags & pIn3->flags & MEM_Int) != 0) {
+ if (mem_is_integer(pIn1) && mem_is_integer(pIn3)) {
+ if (!mem_is_unsigned(pIn1) &&
+ !mem_is_unsigned(pIn3)) {
if (pIn3->u.i > pIn1->u.i)
res = +1;
else if (pIn3->u.i < pIn1->u.i)
@@ -1837,7 +1827,8 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
res = 0;
goto compare_op;
}
- if ((pIn1->flags & pIn3->flags & MEM_UInt) != 0) {
+ if (mem_is_unsigned(pIn1) &&
+ mem_is_unsigned(pIn3)) {
if (pIn3->u.u > pIn1->u.u)
res = +1;
else if (pIn3->u.u < pIn1->u.u)
@@ -1846,8 +1837,8 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
res = 0;
goto compare_op;
}
- if ((pIn1->flags & MEM_UInt) != 0 &&
- (pIn3->flags & MEM_Int) != 0) {
+ if (mem_is_unsigned(pIn1) &&
+ !mem_is_unsigned(pIn3)) {
res = -1;
goto compare_op;
}
@@ -1855,21 +1846,13 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
goto compare_op;
}
} else if (type == FIELD_TYPE_STRING) {
- if ((flags1 & MEM_Str) == 0 &&
- (flags1 & (MEM_Int | MEM_UInt | MEM_Real)) != 0) {
- testcase( pIn1->flags & MEM_Int);
- testcase( pIn1->flags & MEM_Real);
+ if (!mem_is_string(pIn1) && mem_is_number(pIn1)) {
sqlVdbeMemStringify(pIn1);
- 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_UInt | MEM_Real)) != 0) {
- testcase( pIn3->flags & MEM_Int);
- testcase( pIn3->flags & MEM_Real);
+ if (!mem_is_string(pIn3) && mem_is_number(pIn3)) {
sqlVdbeMemStringify(pIn3);
- testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn));
flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
}
}
@@ -2077,9 +2060,9 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
pIn1 = &aMem[pOp->p1];
- if (pIn1->flags & MEM_Null) {
+ if (mem_is_null(pIn1)) {
v1 = 2;
- } else if ((pIn1->flags & MEM_Bool) != 0) {
+ } else if (mem_is_boolean(pIn1)) {
v1 = pIn1->u.b;
} else {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
@@ -2087,9 +2070,9 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
goto abort_due_to_error;
}
pIn2 = &aMem[pOp->p2];
- if (pIn2->flags & MEM_Null) {
+ if (mem_is_null(pIn2)) {
v2 = 2;
- } else if ((pIn2->flags & MEM_Bool) != 0) {
+ } else if (mem_is_boolean(pIn2)) {
v2 = pIn2->u.b;
} else {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
@@ -2120,8 +2103,8 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */
pIn1 = &aMem[pOp->p1];
pOut = vdbe_prepare_null_out(p, pOp->p2);
pOut->field_type = FIELD_TYPE_BOOLEAN;
- if ((pIn1->flags & MEM_Null)==0) {
- if ((pIn1->flags & MEM_Bool) == 0) {
+ if (!mem_is_null(pIn1)) {
+ if (!mem_is_boolean(pIn1)) {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
mem_str(pIn1), "boolean");
goto abort_due_to_error;
@@ -2143,7 +2126,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
pOut = vdbe_prepare_null_out(p, pOp->p2);
/* Force NULL be of type INTEGER. */
pOut->field_type = FIELD_TYPE_INTEGER;
- if ((pIn1->flags & MEM_Null)==0) {
+ if (!mem_is_null(pIn1)) {
int64_t i;
bool is_neg;
if (sqlVdbeIntValue(pIn1, &i, &is_neg) != 0) {
@@ -2188,9 +2171,9 @@ case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
int c;
pIn1 = &aMem[pOp->p1];
- if (pIn1->flags & MEM_Null) {
+ if (mem_is_null(pIn1)) {
c = pOp->p3;
- } else if ((pIn1->flags & MEM_Bool) != 0) {
+ } else if (mem_is_boolean(pIn1)) {
c = pOp->opcode == OP_IfNot ? ! pIn1->u.b : pIn1->u.b;
} else {
diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
@@ -2211,8 +2194,8 @@ case OP_IfNot: { /* jump, in1 */
*/
case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
- VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
- if ((pIn1->flags & MEM_Null)!=0) {
+ VdbeBranchTaken(mem_is_null(pIn1), 2);
+ if (mem_is_null(pIn1)) {
goto jump_to_p2;
}
break;
@@ -2225,8 +2208,8 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
- VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
- if ((pIn1->flags & MEM_Null)==0) {
+ VdbeBranchTaken(!mem_is_null(pIn1), 2);
+ if (!mem_is_null(pIn1)) {
goto jump_to_p2;
}
break;
@@ -2280,7 +2263,7 @@ case OP_Column: {
if (pC->eCurType==CURTYPE_PSEUDO) {
assert(pC->uc.pseudoTableReg>0);
pReg = &aMem[pC->uc.pseudoTableReg];
- assert(pReg->flags & MEM_Blob);
+ assert(mem_is_binary(pReg));
assert(memIsValid(pReg));
vdbe_field_ref_prepare_data(&pC->field_ref,
pReg->z, pReg->n);
@@ -2309,7 +2292,7 @@ case OP_Column: {
if (vdbe_field_ref_fetch(&pC->field_ref, p2, pDest) != 0)
goto abort_due_to_error;
- if ((pDest->flags & MEM_Null) &&
+ if (mem_is_null(pDest) &&
(uint32_t) p2 >= pC->field_ref.field_count &&
default_val_mem != NULL) {
sqlVdbeMemShallowCopy(pDest, default_val_mem, MEM_Static);
@@ -2364,7 +2347,7 @@ case OP_ApplyType: {
if (!sql_type_is_numeric(type))
goto type_mismatch;
/* Implicit cast is allowed only from numeric type. */
- if (!mp_type_is_numeric(mem_mp_type(pIn1)))
+ if (!mem_is_number(pIn1))
goto type_mismatch;
/* Try to convert numeric-to-numeric. */
if (mem_convert_to_numeric(pIn1, type) != 0)
@@ -2982,18 +2965,18 @@ case OP_SeekGT: { /* jump, in3 */
* the seek, so convert it.
*/
pIn3 = &aMem[int_field];
- if ((pIn3->flags & MEM_Null) != 0)
+ if (mem_is_null(pIn3))
goto skip_truncate;
- if ((pIn3->flags & MEM_Str) != 0)
+ if (mem_is_string(pIn3))
mem_apply_numeric_type(pIn3);
int64_t i;
- if ((pIn3->flags & MEM_Int) == MEM_Int) {
+ if (mem_is_integer(pIn3) && !mem_is_unsigned(pIn3)) {
i = pIn3->u.i;
is_neg = true;
- } else if ((pIn3->flags & MEM_UInt) == MEM_UInt) {
+ } else if (mem_is_unsigned(pIn3)) {
i = pIn3->u.u;
is_neg = false;
- } else if ((pIn3->flags & MEM_Real) == MEM_Real) {
+ } else if (mem_is_double(pIn3)) {
if (pIn3->u.r > (double)INT64_MAX)
i = INT64_MAX;
else if (pIn3->u.r < (double)INT64_MIN)
@@ -3011,8 +2994,8 @@ 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 | MEM_UInt)) == 0) {
- if ((pIn3->flags & MEM_Real)==0) {
+ if (!mem_is_integer(pIn3)) {
+ if (!mem_is_double(pIn3)) {
/* If the P3 value cannot be converted into any kind of a number,
* then the seek is not possible, so jump to P2
*/
@@ -3218,7 +3201,8 @@ case OP_Found: { /* jump, in3 */
#ifdef SQL_DEBUG
for(ii=0; ii<r.nField; ii++) {
assert(memIsValid(&r.aMem[ii]));
- assert((r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0);
+ assert(!mem_is_zeroblob(&r.aMem[ii]) ||
+ r.aMem[ii].n == 0);
if (ii != 0)
REGISTER_TRACE(p, pOp->p3+ii, &r.aMem[ii]);
}
@@ -3228,7 +3212,7 @@ case OP_Found: { /* jump, in3 */
} else {
pFree = pIdxKey = sqlVdbeAllocUnpackedRecord(db, pC->key_def);
if (pIdxKey==0) goto no_mem;
- assert(pIn3->flags & MEM_Blob );
+ assert(mem_is_binary(pIn3));
(void)ExpandBlob(pIn3);
sqlVdbeRecordUnpackMsgpack(pC->key_def,
pIn3->z, pIdxKey);
@@ -3242,7 +3226,7 @@ case OP_Found: { /* jump, in3 */
* conflict
*/
for(ii=0; ii<pIdxKey->nField; ii++) {
- if (pIdxKey->aMem[ii].flags & MEM_Null) {
+ if (mem_is_null(&pIdxKey->aMem[ii])) {
takeJump = 1;
break;
}
@@ -3352,11 +3336,11 @@ case OP_FCopy: { /* out2 */
pIn1 = &aMem[pOp->p1];
}
- if ((pOp->p3 & OPFLAG_NOOP_IF_NULL) && (pIn1->flags & MEM_Null)) {
+ if ((pOp->p3 & OPFLAG_NOOP_IF_NULL) && mem_is_null(pIn1)) {
pOut = vdbe_prepare_null_out(p, pOp->p2);
} else {
assert(memIsValid(pIn1));
- assert((pIn1->flags & (MEM_Int | MEM_UInt)) != 0);
+ assert(mem_is_integer(pIn1));
pOut = vdbe_prepare_null_out(p, pOp->p2);
mem_set_int(pOut, pIn1->u.i, pIn1->flags == MEM_Int);
@@ -3491,7 +3475,7 @@ case OP_SorterData: {
assert(isSorter(pC));
if (sqlVdbeSorterRowkey(pC, pOut) != 0)
goto abort_due_to_error;
- assert(pOut->flags & MEM_Blob);
+ assert(mem_is_binary(pOut));
assert(pOp->p1>=0 && pOp->p1<p->nCursor);
p->apCsr[pOp->p3]->cacheStatus = CACHE_STALE;
break;
@@ -3849,7 +3833,7 @@ case OP_SorterInsert: { /* in2 */
assert(cursor != NULL);
assert(isSorter(cursor));
pIn2 = &aMem[pOp->p2];
- assert((pIn2->flags & MEM_Blob) != 0);
+ assert(mem_is_binary(pIn2));
if (ExpandBlob(pIn2) != 0 ||
sqlVdbeSorterWrite(cursor, pIn2) != 0)
goto abort_due_to_error;
@@ -3883,7 +3867,7 @@ case OP_SorterInsert: { /* in2 */
case OP_IdxReplace:
case OP_IdxInsert: {
pIn2 = &aMem[pOp->p1];
- assert((pIn2->flags & MEM_Blob) != 0);
+ assert(mem_is_binary(pIn2));
if (ExpandBlob(pIn2) != 0)
goto abort_due_to_error;
struct space *space;
@@ -3894,7 +3878,7 @@ case OP_IdxInsert: {
assert(space != NULL);
if (space->def->id != 0) {
/* Make sure that memory has been allocated on region. */
- assert(aMem[pOp->p1].flags & MEM_Ephem);
+ assert(mem_is_ephemeral(&aMem[pOp->p1]));
if (pOp->opcode == OP_IdxInsert) {
rc = tarantoolsqlInsert(space, pIn2->z,
pIn2->z + pIn2->n);
@@ -3928,7 +3912,7 @@ case OP_IdxInsert: {
}
if ((pOp->p5 & OPFLAG_NCHANGE) != 0)
p->nChange++;
- if (pOp->p3 > 0 && ((aMem[pOp->p3].flags) & MEM_Null) != 0) {
+ if (pOp->p3 > 0 && mem_is_null(&aMem[pOp->p3])) {
assert(space->sequence != NULL);
int64_t value;
if (sequence_get_value(space->sequence, &value) != 0)
@@ -3974,10 +3958,10 @@ case OP_Update: {
assert(pOp->p4type == P4_SPACEPTR);
struct Mem *key_mem = &aMem[pOp->p2];
- assert((key_mem->flags & MEM_Blob) != 0);
+ assert(mem_is_binary(key_mem));
struct Mem *upd_fields_mem = &aMem[pOp->p3];
- assert((upd_fields_mem->flags & MEM_Blob) != 0);
+ assert(mem_is_binary(upd_fields_mem));
uint32_t *upd_fields = (uint32_t *)upd_fields_mem->z;
uint32_t upd_fields_cnt = upd_fields_mem->n / sizeof(uint32_t);
@@ -4409,7 +4393,7 @@ case OP_Program: { /* jump */
* the trigger program. If this trigger has been fired before, then pRt
* is already allocated. Otherwise, it must be initialized.
*/
- if ((pRt->flags&MEM_Frame)==0) {
+ if (!mem_is_frame(pRt)) {
/* SubProgram.nMem is set to the number of memory cells used by the
* program stored in SubProgram.aOp. As well as these, one memory
* cell is required for each cursor used by the program. Set local
@@ -4549,8 +4533,8 @@ case OP_FkIfZero: { /* jump */
*/
case OP_IfPos: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
- assert((pIn1->flags & (MEM_Int | MEM_UInt)) != 0);
- if ((pIn1->flags & MEM_UInt) != 0 && pIn1->u.u != 0) {
+ assert(mem_is_integer(pIn1));
+ if (mem_is_unsigned(pIn1) && pIn1->u.u != 0) {
assert(pOp->p3 >= 0);
uint64_t res = pIn1->u.u - (uint64_t) pOp->p3;
/*
@@ -4584,8 +4568,8 @@ case OP_OffsetLimit: { /* in1, out2, in3 */
pIn3 = &aMem[pOp->p3];
pOut = vdbe_prepare_null_out(p, pOp->p2);
- assert((pIn1->flags & MEM_UInt) != 0);
- assert((pIn3->flags & MEM_UInt) != 0);
+ assert(mem_is_unsigned(pIn1));
+ assert(mem_is_unsigned(pIn3));
uint64_t x = pIn1->u.u;
uint64_t rhs = pIn3->u.u;
bool unused;
@@ -4608,7 +4592,7 @@ case OP_OffsetLimit: { /* in1, out2, in3 */
*/
case OP_IfNotZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
- assert((pIn1->flags & MEM_UInt) != 0);
+ assert(mem_is_unsigned(pIn1));
if (pIn1->u.u > 0) {
pIn1->u.u--;
goto jump_to_p2;
@@ -4624,7 +4608,7 @@ case OP_IfNotZero: { /* jump, in1 */
*/
case OP_DecrJumpZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
- assert((pIn1->flags & MEM_UInt) != 0);
+ assert(mem_is_unsigned(pIn1));
if (pIn1->u.u > 0)
pIn1->u.u--;
if (pIn1->u.u == 0) goto jump_to_p2;
@@ -4721,7 +4705,7 @@ case OP_AggStep: {
mem_destroy(&t);
goto abort_due_to_error;
}
- assert(t.flags==MEM_Null);
+ assert(mem_is_null(&t));
if (pCtx->skipFlag) {
assert(pOp[-1].opcode==OP_CollSeq);
i = pOp[-1].p1;
@@ -4747,7 +4731,7 @@ case OP_AggFinal: {
Mem *pMem;
assert(pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor));
pMem = &aMem[pOp->p1];
- assert((pMem->flags & ~(MEM_Null|MEM_Agg))==0);
+ assert(mem_is_null(pMem) || mem_is_aggregate(pMem));
if (sql_vdbemem_finalize(pMem, pOp->p4.func) != 0)
goto abort_due_to_error;
UPDATE_MAX_BLOBSIZE(pMem);
@@ -4874,7 +4858,7 @@ case OP_SetSession: {
struct session_setting *setting = &session_settings[sid];
switch (setting->field_type) {
case FIELD_TYPE_BOOLEAN: {
- if ((pIn1->flags & MEM_Bool) == 0)
+ if (!mem_is_boolean(pIn1))
goto invalid_type;
bool value = pIn1->u.b;
size_t size = mp_sizeof_bool(value);
@@ -4885,7 +4869,7 @@ case OP_SetSession: {
break;
}
case FIELD_TYPE_STRING: {
- if ((pIn1->flags & MEM_Str) == 0)
+ if (!mem_is_string(pIn1))
goto invalid_type;
const char *str = pIn1->z;
uint32_t size = mp_sizeof_str(pIn1->n);
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 338b8bc96..9615c36a6 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -333,17 +333,6 @@ int sqlVdbeList(Vdbe *);
int sqlVdbeHalt(Vdbe *);
-/**
- * In terms of VDBE memory cell type, _BIN, _ARRAY and _MAP
- * messagepacks are stored as binary string (i.e. featuring
- * MEM_Blob internal type).
- */
-#define mp_type_is_bloblike(X) ((X) == MP_BIN || (X) == MP_ARRAY || (X) == MP_MAP)
-
-/** Return TRUE if MP_type of X is numeric, FALSE otherwise. */
-#define mp_type_is_numeric(X) ((X) == MP_INT || (X) == MP_UINT ||\
- (X) == MP_DOUBLE)
-
const char *sqlOpcodeName(int);
int sqlVdbeCloseStatement(Vdbe *, int);
void sqlVdbeFrameDelete(VdbeFrame *);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index a195f8dfd..8a9573c57 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -380,7 +380,7 @@ static SQL_NOINLINE void *
createAggContext(sql_context * p, int nByte)
{
Mem *pMem = p->pMem;
- assert((pMem->flags & MEM_Agg) == 0);
+ assert(!mem_is_aggregate(pMem));
if (nByte <= 0) {
sqlVdbeMemSetNull(pMem);
pMem->z = 0;
@@ -407,7 +407,7 @@ sql_aggregate_context(sql_context * p, int nByte)
assert(p->func->def->language == FUNC_LANGUAGE_SQL_BUILTIN);
assert(p->func->def->aggregate == FUNC_AGGREGATE_GROUP);
testcase(nByte < 0);
- if ((p->pMem->flags & MEM_Agg) == 0) {
+ if (!mem_is_aggregate(p->pMem)) {
return createAggContext(p, nByte);
} else {
return (void *)p->pMem->z;
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 55d4fc14f..11304b5bc 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1253,7 +1253,7 @@ sqlVdbeList(Vdbe * p)
*/
assert(p->nMem > 9);
pSub = &p->aMem[9];
- if (pSub->flags & MEM_Blob) {
+ if (mem_is_binary(pSub)) {
/* On the first call to sql_step(), pSub will hold a NULL. It is
* initialized to a BLOB by the P4_SUBPROGRAM processing logic below
*/
@@ -1698,7 +1698,7 @@ Cleanup(Vdbe * p)
assert(p->apCsr[i] == 0);
if (p->aMem) {
for (i = 0; i < p->nMem; i++)
- assert(p->aMem[i].flags == MEM_Undefined);
+ assert(mem_is_undefined(&p->aMem[i]));
}
#endif
@@ -2306,7 +2306,7 @@ sqlVdbeGetBoundValue(Vdbe * v, int iVar, u8 aff)
assert(iVar > 0);
if (v) {
Mem *pMem = &v->aVar[iVar - 1];
- if (0 == (pMem->flags & MEM_Null)) {
+ if (!mem_is_null(pMem)) {
sql_value *pRet = sqlValueNew(v->db);
if (pRet) {
sqlVdbeMemCopy((Mem *) pRet, pMem);
diff --git a/src/box/sql/vdbesort.c b/src/box/sql/vdbesort.c
index 927f85559..a9a5f45af 100644
--- a/src/box/sql/vdbesort.c
+++ b/src/box/sql/vdbesort.c
@@ -2218,7 +2218,7 @@ sqlVdbeSorterCompare(const VdbeCursor * pCsr, /* Sorter cursor */
pKey = vdbeSorterRowkey(pSorter, &nKey);
sqlVdbeRecordUnpackMsgpack(pCsr->key_def, pKey, r2);
for (i = 0; i < nKeyCol; i++) {
- if (r2->aMem[i].flags & MEM_Null) {
+ if (mem_is_null(&r2->aMem[i])) {
*pRes = -1;
return 0;
}
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 0c002dbee..782e44734 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -312,9 +312,8 @@ like_optimization_is_valid(Parse *pParse, Expr *pExpr, Expr **ppPrefix,
pVal =
sqlVdbeGetBoundValue(pReprepare, iCol,
FIELD_TYPE_SCALAR);
- if (pVal && sql_value_type(pVal) == MP_STR) {
+ if (pVal != NULL && mem_is_string(pVal))
z = (char *)sql_value_text(pVal);
- }
assert(pRight->op == TK_VARIABLE || pRight->op == TK_REGISTER);
} else if (op == TK_STRING) {
z = pRight->u.zToken;
--
2.25.1
More information about the Tarantool-patches
mailing list