[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