[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