[Tarantool-patches] [PATCH v4 08/53] sql: introduce mem_str()

imeevma at tarantool.org imeevma at tarantool.org
Tue Mar 23 12:35:11 MSK 2021


This patch introduces mem_str() which allows to receive value of MEM as
a string.

Part of #5818
---
 src/box/sql/func.c      |  8 ++++----
 src/box/sql/mem.c       | 45 ++++++++++++++++++++++++++++++-----------
 src/box/sql/mem.h       | 16 +++++++--------
 src/box/sql/vdbe.c      | 28 ++++++++++++-------------
 src/box/sql/vdbeaux.c   | 19 ++++-------------
 src/box/sql/vdbetrace.c | 33 ++++--------------------------
 6 files changed, 66 insertions(+), 83 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 074d41260..5ece28d6d 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -849,7 +849,7 @@ roundFunc(sql_context * context, int argc, sql_value ** argv)
 	enum mp_type mp_type = sql_value_type(argv[0]);
 	if (mp_type_is_bloblike(mp_type)) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(argv[0]), "numeric");
+			 mem_str(argv[0]), "numeric");
 		context->is_aborted = true;
 		return;
 	}
@@ -991,7 +991,7 @@ randomBlob(sql_context * context, int argc, sql_value ** argv)
 	UNUSED_PARAMETER(argc);
 	if (mp_type_is_bloblike(sql_value_type(argv[0]))) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(argv[0]), "numeric");
+			 mem_str(argv[0]), "numeric");
 		context->is_aborted = true;
 		return;
 	}
@@ -1883,7 +1883,7 @@ soundexFunc(sql_context * context, int argc, sql_value ** argv)
 	enum mp_type mp_type = sql_value_type(argv[0]);
 	if (mp_type_is_bloblike(mp_type)) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(argv[0]), "text");
+			 mem_str(argv[0]), "text");
 		context->is_aborted = true;
 		return;
 	}
@@ -1956,7 +1956,7 @@ sum_step(struct sql_context *context, int argc, sql_value **argv)
 	if (type != MP_DOUBLE && type != MP_INT && type != MP_UINT) {
 		if (mem_apply_numeric_type(argv[0]) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(argv[0]), "number");
+				 mem_str(argv[0]), "number");
 			context->is_aborted = true;
 			return;
 		}
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index 62338e1db..0ed5e38d4 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -37,6 +37,39 @@
 #include "box/tuple.h"
 #include "mpstream/mpstream.h"
 
+enum {
+	BUF_SIZE = 32,
+};
+
+const char *
+mem_str(const struct Mem *mem)
+{
+	char buf[BUF_SIZE];
+	switch (mem->flags & MEM_PURE_TYPE_MASK) {
+	case MEM_Null:
+		return "NULL";
+	case MEM_Str:
+		return tt_sprintf("%.*s", mem->n, mem->z);
+	case MEM_Int:
+		return tt_sprintf("%lld", mem->u.i);
+	case MEM_UInt:
+		return tt_sprintf("%llu", mem->u.u);
+	case MEM_Real:
+		sql_snprintf(BUF_SIZE, &buf[0], "%!.15g", mem->u.r);
+		return tt_sprintf("%s", buf);
+	case MEM_Blob:
+		if ((mem->flags & MEM_Subtype) == 0)
+			return "varbinary";
+		assert(mem->subtype == SQL_SUBTYPE_MSGPACK);
+		return mp_str(mem->z);
+	case MEM_Bool:
+		return mem->u.b ? "TRUE" : "FALSE";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
 static inline bool
 mem_has_msgpack_subtype(struct Mem *mem)
 {
@@ -1632,18 +1665,6 @@ sqlValueText(sql_value * pVal)
 	return valueToText(pVal);
 }
 
-const char *
-sql_value_to_diag_str(sql_value *value)
-{
-	enum mp_type mp_type = sql_value_type(value);
-	if (mp_type_is_bloblike(mp_type)) {
-		if (mem_has_msgpack_subtype(value))
-			return sqlValueText(value);
-		return "varbinary";
-	}
-	return sqlValueText(value);
-}
-
 enum sql_subtype
 sql_value_subtype(sql_value * pVal)
 {
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index e78ebbe47..740c7dfba 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -87,6 +87,13 @@ struct Mem {
  */
 #define MEMCELLSIZE offsetof(Mem,zMalloc)
 
+/**
+ * Return a string that represent content of MEM. String is either allocated
+ * using static_alloc() of just a static variable.
+ */
+const char *
+mem_str(const struct Mem *mem);
+
 /* One or more of the following flags are set to indicate the validOK
  * representations of the value stored in the Mem struct.
  *
@@ -375,15 +382,6 @@ sql_value_text(struct Mem *);
 
 const void *sqlValueText(struct Mem *);
 
-/**
- * Return pointer to a string with the data type in the case of
- * binary data stored in @a value. Otherwise, return the result
- * of sql_value_text(). It is used due to the fact that not all
- * binary strings can be displayed correctly (e.g. contain
- * unprintable symbols).
- */
-const char *
-sql_value_to_diag_str(struct Mem *value);
 #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
 
 enum sql_subtype
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index dbbcc1013..9b392f9cb 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1236,12 +1236,12 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
 	} else {
 		if (sqlVdbeRealValue(pIn1, &rA) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1), "numeric");
+				 mem_str(pIn1), "numeric");
 			goto abort_due_to_error;
 		}
 		if (sqlVdbeRealValue(pIn2, &rB) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn2), "numeric");
+				 mem_str(pIn2), "numeric");
 			goto abort_due_to_error;
 		}
 		assert(((type1 | type2) & MEM_Real) != 0);
@@ -1517,12 +1517,12 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 	bool unused;
 	if (sqlVdbeIntValue(pIn2, (int64_t *) &iA, &unused) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn2), "integer");
+			 mem_str(pIn2), "integer");
 		goto abort_due_to_error;
 	}
 	if (sqlVdbeIntValue(pIn1, (int64_t *) &iB, &unused) != 0) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), "integer");
+			 mem_str(pIn1), "integer");
 		goto abort_due_to_error;
 	}
 	op = pOp->opcode;
@@ -1587,7 +1587,7 @@ case OP_MustBeInt: {            /* jump, in1 */
 		if ((pIn1->flags & (MEM_Int | MEM_UInt)) == 0) {
 			if (pOp->p2==0) {
 				diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-					 sql_value_to_diag_str(pIn1), "integer");
+					 mem_str(pIn1), "integer");
 				goto abort_due_to_error;
 			} else {
 				goto jump_to_p2;
@@ -1644,7 +1644,7 @@ case OP_Cast: {                  /* in1 */
 	UPDATE_MAX_BLOBSIZE(pIn1);
 	if (rc == 0)
 		break;
-	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sql_value_to_diag_str(pIn1),
+	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, mem_str(pIn1),
 		 field_type_strs[pOp->p2]);
 	goto abort_due_to_error;
 }
@@ -1817,7 +1817,7 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 					if (mem_apply_numeric_type(pIn3) != 0) {
 						diag_set(ClientError,
 							 ER_SQL_TYPE_MISMATCH,
-							 sql_value_to_diag_str(pIn3),
+							 mem_str(pIn3),
 							 "numeric");
 						goto abort_due_to_error;
 					}
@@ -2083,7 +2083,7 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 		v1 = pIn1->u.b;
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), "boolean");
+			 mem_str(pIn1), "boolean");
 		goto abort_due_to_error;
 	}
 	pIn2 = &aMem[pOp->p2];
@@ -2093,7 +2093,7 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 		v2 = pIn2->u.b;
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn2), "boolean");
+			 mem_str(pIn2), "boolean");
 		goto abort_due_to_error;
 	}
 	if (pOp->opcode==OP_And) {
@@ -2123,7 +2123,7 @@ case OP_Not: {                /* same as TK_NOT, in1, out2 */
 	if ((pIn1->flags & MEM_Null)==0) {
 		if ((pIn1->flags & MEM_Bool) == 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1), "boolean");
+				 mem_str(pIn1), "boolean");
 			goto abort_due_to_error;
 		}
 		mem_set_bool(pOut, ! pIn1->u.b);
@@ -2148,7 +2148,7 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 		bool is_neg;
 		if (sqlVdbeIntValue(pIn1, &i, &is_neg) != 0) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn1), "integer");
+				 mem_str(pIn1), "integer");
 			goto abort_due_to_error;
 		}
 		mem_set_i64(pOut, ~i);
@@ -2194,7 +2194,7 @@ case OP_IfNot: {            /* jump, in1 */
 		c = pOp->opcode == OP_IfNot ? ! pIn1->u.b : pIn1->u.b;
 	} else {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), "boolean");
+			 mem_str(pIn1), "boolean");
 		goto abort_due_to_error;
 	}
 	VdbeBranchTaken(c!=0, 2);
@@ -2374,7 +2374,7 @@ case OP_ApplyType: {
 		continue;
 type_mismatch:
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(pIn1), field_type_strs[type]);
+			 mem_str(pIn1), field_type_strs[type]);
 		goto abort_due_to_error;
 	}
 	break;
@@ -3003,7 +3003,7 @@ case OP_SeekGT: {       /* jump, in3 */
 			is_neg = i < 0;
 		} else {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(pIn3), "integer");
+				 mem_str(pIn3), "integer");
 			goto abort_due_to_error;
 		}
 		iKey = i;
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 9153df1df..f270b0ed1 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1108,21 +1108,10 @@ displayP4(Op * pOp, char *zTemp, int nTemp)
 			break;
 		}
 	case P4_MEM:{
-			Mem *pMem = pOp->p4.pMem;
-			if (pMem->flags & MEM_Str) {
-				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) {
-				zP4 = "NULL";
-			} else {
-				assert(pMem->flags & MEM_Blob);
-				zP4 = "(binary string)";
-			}
+			const char *value = mem_str(pOp->p4.pMem);
+			uint32_t size = MIN((int)strlen(value), nTemp - 1);
+			memcpy(zP4, value, size);
+			zP4[size] = '\0';
 			break;
 		}
 	case P4_INTARRAY:{
diff --git a/src/box/sql/vdbetrace.c b/src/box/sql/vdbetrace.c
index e84bb3192..eceaa953b 100644
--- a/src/box/sql/vdbetrace.c
+++ b/src/box/sql/vdbetrace.c
@@ -97,8 +97,6 @@ sqlVdbeExpandSql(Vdbe * p,	/* The prepared statement being evaluated */
 	int nextIndex = 1;	/* Index of next ? host parameter */
 	int n;			/* Length of a token prefix */
 	int nToken;		/* Length of the parameter token */
-	int i;			/* Loop counter */
-	Mem *pVar;		/* Value of a host parameter */
 	StrAccum out;		/* Accumulate the output here */
 	char zBase[100];	/* Initial working space */
 
@@ -147,33 +145,10 @@ sqlVdbeExpandSql(Vdbe * p,	/* The prepared statement being evaluated */
 			zRawSql += nToken;
 			nextIndex = idx + 1;
 			assert(idx > 0 && idx <= p->nVar);
-			pVar = &p->aVar[idx - 1];
-			if (pVar->flags & MEM_Null) {
-				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) {
-				int nOut;	/* Number of bytes of the string text to include in output */
-				nOut = pVar->n;
-				sqlXPrintf(&out, "'%.*q'", nOut, pVar->z);
-			} else if (pVar->flags & MEM_Zero) {
-				sqlXPrintf(&out, "zeroblob(%d)",
-					       pVar->u.nZero);
-			} else {
-				int nOut;	/* Number of bytes of the blob to include in output */
-				assert(pVar->flags & MEM_Blob);
-				sqlStrAccumAppend(&out, "x'", 2);
-				nOut = pVar->n;
-				for (i = 0; i < nOut; i++) {
-					sqlXPrintf(&out, "%02x",
-						       pVar->z[i] & 0xff);
-				}
-				sqlStrAccumAppend(&out, "'", 1);
-			}
+			const char *value = mem_str(&p->aVar[idx - 1]);
+			uint32_t size = MIN(strlen(value), sizeof(zBase) - 1);
+			memcpy(zBase, value, size);
+			zBase[size] = '\0';
 		}
 	}
 	if (out.accError)
-- 
2.25.1



More information about the Tarantool-patches mailing list