[Tarantool-patches] [PATCH v5 51/52] sql: introduce mem_get_bytes_len()
Mergen Imeev
imeevma at tarantool.org
Wed Apr 14 04:55:48 MSK 2021
Thank you for the review! My answer, diff and new patch below.
On Wed, Apr 14, 2021 at 01:06:53AM +0200, Vladislav Shpilevoy wrote:
> Good job on the patch!
>
> > diff --git a/src/box/sql/func.c b/src/box/sql/func.c
> > index 2896a5c31..746bda0f4 100644
> > --- a/src/box/sql/func.c
> > +++ b/src/box/sql/func.c
> > @@ -65,6 +65,14 @@ mem_as_bin(struct Mem *mem)
> > return s;
> > }
> >
> > +static int
> > +mem_get_length(struct Mem *mem)
> > +{
> > + uint32_t len;
> > + mem_get_bytes_len(mem, &len);
>
> mem_get_bytes_len() is never used except here. I suggest you to
> rename it to mem_len(), drop mem_get_length(), and use mem_len()
> everywhere.
>
> Since you ignore the error always, it probably must has 'unsafe'
> suffix to emphasize it is broken.
I added new function mem_len_unsafe(). I decided to left mem_get_bytes_len()
since I think that there should be safe version of the function. In this case
we do not have to write a new function when we need it.
Diff:
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 0ea46f01c..9c28d5122 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -65,14 +65,6 @@ mem_as_bin(struct Mem *mem)
return s;
}
-static int
-mem_get_length(struct Mem *mem)
-{
- uint32_t len;
- mem_get_bytes_len(mem, &len);
- return len;
-}
-
/*
* Return the collating function associated with a function.
*/
@@ -196,14 +188,14 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv)
case MP_BOOL:
case MP_DOUBLE:{
mem_as_bin(argv[0]);
- sql_result_uint(context, mem_get_length(argv[0]));
+ sql_result_uint(context, mem_len_unsafe(argv[0]));
break;
}
case MP_STR:{
const unsigned char *z = mem_as_ustr(argv[0]);
if (z == 0)
return;
- len = sql_utf8_char_count(z, mem_get_length(argv[0]));
+ len = sql_utf8_char_count(z, mem_len_unsafe(argv[0]));
sql_result_uint(context, len);
break;
}
@@ -313,8 +305,8 @@ position_func(struct sql_context *context, int argc, struct Mem **argv)
return;
}
- int n_needle_bytes = mem_get_length(needle);
- int n_haystack_bytes = mem_get_length(haystack);
+ int n_needle_bytes = mem_len_unsafe(needle);
+ int n_haystack_bytes = mem_len_unsafe(haystack);
int position = 1;
if (n_needle_bytes > 0) {
const unsigned char *haystack_str;
@@ -460,17 +452,17 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
p1 = mem_get_int_unsafe(argv[1]);
if (p0type == MP_BIN) {
z = mem_as_bin(argv[0]);
- len = mem_get_length(argv[0]);
+ len = mem_len_unsafe(argv[0]);
if (z == 0)
return;
- assert(len == mem_get_length(argv[0]));
+ assert(len == mem_len_unsafe(argv[0]));
} else {
z = mem_as_ustr(argv[0]);
if (z == 0)
return;
len = 0;
if (p1 < 0)
- len = sql_utf8_char_count(z, mem_get_length(argv[0]));
+ len = sql_utf8_char_count(z, mem_len_unsafe(argv[0]));
}
if (argc == 3) {
p2 = mem_get_int_unsafe(argv[2]);
@@ -509,7 +501,7 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
* used because '\0' is not supposed to be
* end-of-string symbol.
*/
- int byte_size = mem_get_length(argv[0]);
+ int byte_size = mem_len_unsafe(argv[0]);
int n_chars = sql_utf8_char_count(z, byte_size);
int cnt = 0;
int i = 0;
@@ -628,7 +620,7 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv) \
return; \
} \
z2 = mem_as_str0(argv[0]); \
- n = mem_get_length(argv[0]); \
+ n = mem_len_unsafe(argv[0]); \
/* \
* Verify that the call to _bytes() \
* does not invalidate the _text() pointer. \
@@ -965,15 +957,15 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
}
const char *zB = mem_as_str0(argv[0]);
const char *zA = mem_as_str0(argv[1]);
- const char *zB_end = zB + mem_get_length(argv[0]);
- const char *zA_end = zA + mem_get_length(argv[1]);
+ const char *zB_end = zB + mem_len_unsafe(argv[0]);
+ const char *zA_end = zA + mem_len_unsafe(argv[1]);
/*
* Limit the length of the LIKE pattern to avoid problems
* of deep recursion and N*N behavior in
* sql_utf8_pattern_compare().
*/
- nPat = mem_get_length(argv[0]);
+ nPat = mem_len_unsafe(argv[0]);
testcase(nPat == db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH]);
testcase(nPat == db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH] + 1);
if (nPat > db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH]) {
@@ -994,7 +986,7 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
const unsigned char *zEsc = mem_as_ustr(argv[2]);
if (zEsc == 0)
return;
- if (sql_utf8_char_count(zEsc, mem_get_length(argv[2])) != 1) {
+ if (sql_utf8_char_count(zEsc, mem_len_unsafe(argv[2])) != 1) {
diag_set(ClientError, ER_SQL_EXECUTE, "ESCAPE "\
"expression must be a single character");
context->is_aborted = true;
@@ -1094,7 +1086,7 @@ quoteFunc(sql_context * context, int argc, sql_value ** argv)
case MP_MAP: {
char *zText = 0;
char const *zBlob = mem_as_bin(argv[0]);
- int nBlob = mem_get_length(argv[0]);
+ int nBlob = mem_len_unsafe(argv[0]);
assert(zBlob == mem_as_bin(argv[0])); /* No encoding change */
zText =
(char *)contextMalloc(context,
@@ -1229,7 +1221,7 @@ hexFunc(sql_context * context, int argc, sql_value ** argv)
assert(argc == 1);
UNUSED_PARAMETER(argc);
pBlob = mem_as_bin(argv[0]);
- n = mem_get_length(argv[0]);
+ n = mem_len_unsafe(argv[0]);
assert(pBlob == mem_as_bin(argv[0])); /* No encoding change */
z = zHex = contextMalloc(context, ((i64) n) * 2 + 1);
if (zHex) {
@@ -1287,7 +1279,7 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
zStr = mem_as_ustr(argv[0]);
if (zStr == 0)
return;
- nStr = mem_get_length(argv[0]);
+ nStr = mem_len_unsafe(argv[0]);
assert(zStr == mem_as_ustr(argv[0])); /* No encoding change */
zPattern = mem_as_ustr(argv[1]);
if (zPattern == 0) {
@@ -1295,7 +1287,7 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
|| sql_context_db_handle(context)->mallocFailed);
return;
}
- nPattern = mem_get_length(argv[1]);
+ nPattern = mem_len_unsafe(argv[1]);
if (nPattern == 0) {
assert(!mem_is_null(argv[1]));
sql_result_value(context, argv[0]);
@@ -1305,7 +1297,7 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
zRep = mem_as_ustr(argv[2]);
if (zRep == 0)
return;
- nRep = mem_get_length(argv[2]);
+ nRep = mem_len_unsafe(argv[2]);
assert(zRep == mem_as_ustr(argv[2]));
nOut = nStr + 1;
assert(nOut < SQL_MAX_LENGTH);
@@ -1467,7 +1459,7 @@ trim_func_one_arg(struct sql_context *context, sql_value *arg)
default_trim = (const unsigned char *) "\0";
else
default_trim = (const unsigned char *) " ";
- int input_str_sz = mem_get_length(arg);
+ int input_str_sz = mem_len_unsafe(arg);
const unsigned char *input_str = mem_as_ustr(arg);
uint8_t trim_char_len[1] = { 1 };
trim_procedure(context, TRIM_BOTH, default_trim, trim_char_len, 1,
@@ -1493,14 +1485,14 @@ trim_func_two_args(struct sql_context *context, sql_value *arg1,
if ((input_str = mem_as_ustr(arg2)) == NULL)
return;
- int input_str_sz = mem_get_length(arg2);
+ int input_str_sz = mem_len_unsafe(arg2);
if (sql_value_type(arg1) == MP_INT || sql_value_type(arg1) == MP_UINT) {
uint8_t len_one = 1;
trim_procedure(context, mem_get_int_unsafe(arg1),
(const unsigned char *) " ", &len_one, 1,
input_str, input_str_sz);
} else if ((trim_set = mem_as_ustr(arg1)) != NULL) {
- int trim_set_sz = mem_get_length(arg1);
+ int trim_set_sz = mem_len_unsafe(arg1);
uint8_t *char_len;
int char_cnt = trim_prepare_char_len(context, trim_set,
trim_set_sz, &char_len);
@@ -1529,8 +1521,8 @@ trim_func_three_args(struct sql_context *context, sql_value *arg1,
(trim_set = mem_as_ustr(arg2)) == NULL)
return;
- int trim_set_sz = mem_get_length(arg2);
- int input_str_sz = mem_get_length(arg3);
+ int trim_set_sz = mem_len_unsafe(arg2);
+ int input_str_sz = mem_len_unsafe(arg3);
uint8_t *char_len;
int char_cnt = trim_prepare_char_len(context, trim_set, trim_set_sz,
&char_len);
@@ -1844,7 +1836,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv)
if (!firstTerm) {
if (argc == 2) {
zSep = mem_as_str0(argv[1]);
- nSep = mem_get_length(argv[1]);
+ nSep = mem_len_unsafe(argv[1]);
} else {
zSep = ",";
nSep = 1;
@@ -1853,7 +1845,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv)
sqlStrAccumAppend(pAccum, zSep, nSep);
}
zVal = mem_as_str0(argv[0]);
- nVal = mem_get_length(argv[0]);
+ nVal = mem_len_unsafe(argv[0]);
if (zVal)
sqlStrAccumAppend(pAccum, zVal, nVal);
}
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index e7612fe7e..a67345fbd 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -870,6 +870,20 @@ mem_get_bin(const struct Mem *mem, const char **s);
int
mem_get_bytes_len(const struct Mem *mem, uint32_t *len);
+/**
+ * Return length of value for MEM of STRING or VARBINARY type. This function is
+ * not safe since there is no proper processing in case mem_get_bytes_len()
+ * return an error. In this case this function returns 0.
+ */
+static inline int
+mem_len_unsafe(const struct Mem *mem)
+{
+ uint32_t len;
+ if (mem_get_bytes_len(mem, &len) != 0)
+ return 0;
+ return len;
+}
+
/**
* Simple type to str convertor. It is used to simplify
* error reporting.
New patch:
commit 20f06a5f2c52149060938136273b173790b11b47
Author: Mergen Imeev <imeevma at gmail.com>
Date: Mon Mar 22 12:27:33 2021 +0300
sql: introduce mem_get_bytes_len()
This patch introduces mem_get_bytes_len(). This function is used to
receive length of string or binary value of MEM. If MEM is not
of STRING or VARBINARy type this function returns -1.
Part of #5818
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 8b4882b19..9c28d5122 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -187,14 +187,15 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv)
case MP_UINT:
case MP_BOOL:
case MP_DOUBLE:{
- sql_result_uint(context, sql_value_bytes(argv[0]));
+ mem_as_bin(argv[0]);
+ sql_result_uint(context, mem_len_unsafe(argv[0]));
break;
}
case MP_STR:{
const unsigned char *z = mem_as_ustr(argv[0]);
if (z == 0)
return;
- len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
+ len = sql_utf8_char_count(z, mem_len_unsafe(argv[0]));
sql_result_uint(context, len);
break;
}
@@ -304,8 +305,8 @@ position_func(struct sql_context *context, int argc, struct Mem **argv)
return;
}
- int n_needle_bytes = sql_value_bytes(needle);
- int n_haystack_bytes = sql_value_bytes(haystack);
+ int n_needle_bytes = mem_len_unsafe(needle);
+ int n_haystack_bytes = mem_len_unsafe(haystack);
int position = 1;
if (n_needle_bytes > 0) {
const unsigned char *haystack_str;
@@ -450,18 +451,18 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
p0type = sql_value_type(argv[0]);
p1 = mem_get_int_unsafe(argv[1]);
if (p0type == MP_BIN) {
- len = sql_value_bytes(argv[0]);
z = mem_as_bin(argv[0]);
+ len = mem_len_unsafe(argv[0]);
if (z == 0)
return;
- assert(len == sql_value_bytes(argv[0]));
+ assert(len == mem_len_unsafe(argv[0]));
} else {
z = mem_as_ustr(argv[0]);
if (z == 0)
return;
len = 0;
if (p1 < 0)
- len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
+ len = sql_utf8_char_count(z, mem_len_unsafe(argv[0]));
}
if (argc == 3) {
p2 = mem_get_int_unsafe(argv[2]);
@@ -500,7 +501,7 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
* used because '\0' is not supposed to be
* end-of-string symbol.
*/
- int byte_size = sql_value_bytes(argv[0]);
+ int byte_size = mem_len_unsafe(argv[0]);
int n_chars = sql_utf8_char_count(z, byte_size);
int cnt = 0;
int i = 0;
@@ -619,7 +620,7 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv) \
return; \
} \
z2 = mem_as_str0(argv[0]); \
- n = sql_value_bytes(argv[0]); \
+ n = mem_len_unsafe(argv[0]); \
/* \
* Verify that the call to _bytes() \
* does not invalidate the _text() pointer. \
@@ -956,15 +957,15 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
}
const char *zB = mem_as_str0(argv[0]);
const char *zA = mem_as_str0(argv[1]);
- const char *zB_end = zB + sql_value_bytes(argv[0]);
- const char *zA_end = zA + sql_value_bytes(argv[1]);
+ const char *zB_end = zB + mem_len_unsafe(argv[0]);
+ const char *zA_end = zA + mem_len_unsafe(argv[1]);
/*
* Limit the length of the LIKE pattern to avoid problems
* of deep recursion and N*N behavior in
* sql_utf8_pattern_compare().
*/
- nPat = sql_value_bytes(argv[0]);
+ nPat = mem_len_unsafe(argv[0]);
testcase(nPat == db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH]);
testcase(nPat == db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH] + 1);
if (nPat > db->aLimit[SQL_LIMIT_LIKE_PATTERN_LENGTH]) {
@@ -985,7 +986,7 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
const unsigned char *zEsc = mem_as_ustr(argv[2]);
if (zEsc == 0)
return;
- if (sql_utf8_char_count(zEsc, sql_value_bytes(argv[2])) != 1) {
+ if (sql_utf8_char_count(zEsc, mem_len_unsafe(argv[2])) != 1) {
diag_set(ClientError, ER_SQL_EXECUTE, "ESCAPE "\
"expression must be a single character");
context->is_aborted = true;
@@ -1085,7 +1086,7 @@ quoteFunc(sql_context * context, int argc, sql_value ** argv)
case MP_MAP: {
char *zText = 0;
char const *zBlob = mem_as_bin(argv[0]);
- int nBlob = sql_value_bytes(argv[0]);
+ int nBlob = mem_len_unsafe(argv[0]);
assert(zBlob == mem_as_bin(argv[0])); /* No encoding change */
zText =
(char *)contextMalloc(context,
@@ -1220,7 +1221,7 @@ hexFunc(sql_context * context, int argc, sql_value ** argv)
assert(argc == 1);
UNUSED_PARAMETER(argc);
pBlob = mem_as_bin(argv[0]);
- n = sql_value_bytes(argv[0]);
+ n = mem_len_unsafe(argv[0]);
assert(pBlob == mem_as_bin(argv[0])); /* No encoding change */
z = zHex = contextMalloc(context, ((i64) n) * 2 + 1);
if (zHex) {
@@ -1278,7 +1279,7 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
zStr = mem_as_ustr(argv[0]);
if (zStr == 0)
return;
- nStr = sql_value_bytes(argv[0]);
+ nStr = mem_len_unsafe(argv[0]);
assert(zStr == mem_as_ustr(argv[0])); /* No encoding change */
zPattern = mem_as_ustr(argv[1]);
if (zPattern == 0) {
@@ -1286,7 +1287,7 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
|| sql_context_db_handle(context)->mallocFailed);
return;
}
- nPattern = sql_value_bytes(argv[1]);
+ nPattern = mem_len_unsafe(argv[1]);
if (nPattern == 0) {
assert(!mem_is_null(argv[1]));
sql_result_value(context, argv[0]);
@@ -1296,7 +1297,7 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
zRep = mem_as_ustr(argv[2]);
if (zRep == 0)
return;
- nRep = sql_value_bytes(argv[2]);
+ nRep = mem_len_unsafe(argv[2]);
assert(zRep == mem_as_ustr(argv[2]));
nOut = nStr + 1;
assert(nOut < SQL_MAX_LENGTH);
@@ -1458,7 +1459,7 @@ trim_func_one_arg(struct sql_context *context, sql_value *arg)
default_trim = (const unsigned char *) "\0";
else
default_trim = (const unsigned char *) " ";
- int input_str_sz = sql_value_bytes(arg);
+ int input_str_sz = mem_len_unsafe(arg);
const unsigned char *input_str = mem_as_ustr(arg);
uint8_t trim_char_len[1] = { 1 };
trim_procedure(context, TRIM_BOTH, default_trim, trim_char_len, 1,
@@ -1484,14 +1485,14 @@ trim_func_two_args(struct sql_context *context, sql_value *arg1,
if ((input_str = mem_as_ustr(arg2)) == NULL)
return;
- int input_str_sz = sql_value_bytes(arg2);
+ int input_str_sz = mem_len_unsafe(arg2);
if (sql_value_type(arg1) == MP_INT || sql_value_type(arg1) == MP_UINT) {
uint8_t len_one = 1;
trim_procedure(context, mem_get_int_unsafe(arg1),
(const unsigned char *) " ", &len_one, 1,
input_str, input_str_sz);
} else if ((trim_set = mem_as_ustr(arg1)) != NULL) {
- int trim_set_sz = sql_value_bytes(arg1);
+ int trim_set_sz = mem_len_unsafe(arg1);
uint8_t *char_len;
int char_cnt = trim_prepare_char_len(context, trim_set,
trim_set_sz, &char_len);
@@ -1520,8 +1521,8 @@ trim_func_three_args(struct sql_context *context, sql_value *arg1,
(trim_set = mem_as_ustr(arg2)) == NULL)
return;
- int trim_set_sz = sql_value_bytes(arg2);
- int input_str_sz = sql_value_bytes(arg3);
+ int trim_set_sz = mem_len_unsafe(arg2);
+ int input_str_sz = mem_len_unsafe(arg3);
uint8_t *char_len;
int char_cnt = trim_prepare_char_len(context, trim_set, trim_set_sz,
&char_len);
@@ -1835,7 +1836,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv)
if (!firstTerm) {
if (argc == 2) {
zSep = mem_as_str0(argv[1]);
- nSep = sql_value_bytes(argv[1]);
+ nSep = mem_len_unsafe(argv[1]);
} else {
zSep = ",";
nSep = 1;
@@ -1844,7 +1845,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv)
sqlStrAccumAppend(pAccum, zSep, nSep);
}
zVal = mem_as_str0(argv[0]);
- nVal = sql_value_bytes(argv[0]);
+ nVal = mem_len_unsafe(argv[0]);
if (zVal)
sqlStrAccumAppend(pAccum, zVal, nVal);
}
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index 2ad853a40..0addff161 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -1156,6 +1156,18 @@ mem_get_bin(const struct Mem *mem, const char **s)
return 0;
}
+int
+mem_get_bytes_len(const struct Mem *mem, uint32_t *len)
+{
+ if ((mem->flags & (MEM_Str | MEM_Blob)) == 0)
+ return -1;
+ if ((mem->flags & MEM_Blob) !=0 && (mem->flags & MEM_Zero) != 0)
+ *len = mem->n + mem->u.nZero;
+ else
+ *len = mem->n;
+ return 0;
+}
+
int
mem_copy(struct Mem *to, const struct Mem *from)
{
@@ -1892,41 +1904,6 @@ sql_value_type(sql_value *pVal)
return mem_mp_type(mem);
}
-/*
- * The sqlValueBytes() routine returns the number of bytes in the
- * sql_value object assuming that it uses the encoding "enc".
- * The valueBytes() routine is a helper function.
- */
-static SQL_NOINLINE int
-valueBytes(sql_value * pVal)
-{
- if (mem_to_str(pVal) != 0)
- return 0;
- return pVal->n;
-}
-
-int
-sqlValueBytes(sql_value * pVal)
-{
- Mem *p = (Mem *) pVal;
- assert((p->flags & MEM_Null) == 0
- || (p->flags & (MEM_Str | MEM_Blob)) == 0);
- if ((p->flags & MEM_Str) != 0) {
- return p->n;
- }
- if ((p->flags & MEM_Blob) != 0) {
- if (p->flags & MEM_Zero) {
- return p->n + p->u.nZero;
- } else {
- return p->n;
- }
- }
- if (p->flags & MEM_Null)
- return 0;
- return valueBytes(pVal);
-}
-
-
#ifdef SQL_DEBUG
/*
* Check invariants on a Mem object.
@@ -2233,53 +2210,6 @@ releaseMemArray(Mem * p, int N)
}
}
-int
-sql_value_bytes(sql_value * pVal)
-{
- return sqlValueBytes(pVal);
-}
-
-/*
- * Return a pointer to static memory containing an SQL NULL value.
- */
-const Mem *
-columnNullValue(void)
-{
- /* Even though the Mem structure contains an element
- * of type i64, on certain architectures (x86) with certain compiler
- * switches (-Os), gcc may align this Mem object on a 4-byte boundary
- * instead of an 8-byte one. This all works fine, except that when
- * running with SQL_DEBUG defined the sql code sometimes assert()s
- * that a Mem structure is located on an 8-byte boundary. To prevent
- * these assert()s from failing, when building with SQL_DEBUG defined
- * using gcc, we force nullMem to be 8-byte aligned using the magical
- * __attribute__((aligned(8))) macro.
- */
- static const Mem nullMem
-#if defined(SQL_DEBUG) && defined(__GNUC__)
- __attribute__ ((aligned(8)))
-#endif
- = {
- /* .u = */ {
- 0},
- /* .flags = */ (u16) MEM_Null,
- /* .eSubtype = */ (u8) 0,
- /* .field_type = */ field_type_MAX,
- /* .n = */ (int)0,
- /* .z = */ (char *)0,
- /* .zMalloc = */ (char *)0,
- /* .szMalloc = */ (int)0,
- /* .uTemp = */ (u32) 0,
- /* .db = */ (sql *) 0,
- /* .xDel = */ (void (*)(void *))0,
-#ifdef SQL_DEBUG
- /* .pScopyFrom = */ (Mem *) 0,
- /* .pFiller = */ (void *)0,
-#endif
- };
- return &nullMem;
-}
-
/*
* Return true if the Mem object contains a TEXT or BLOB that is
* too large - whose size exceeds SQL_MAX_LENGTH.
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index 00c9bab36..a67345fbd 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -863,6 +863,27 @@ mem_as_str0(struct Mem *mem)
int
mem_get_bin(const struct Mem *mem, const char **s);
+/**
+ * Return length of value for MEM of STRING or VARBINARY type. Original MEM is
+ * not changed.
+ */
+int
+mem_get_bytes_len(const struct Mem *mem, uint32_t *len);
+
+/**
+ * Return length of value for MEM of STRING or VARBINARY type. This function is
+ * not safe since there is no proper processing in case mem_get_bytes_len()
+ * return an error. In this case this function returns 0.
+ */
+static inline int
+mem_len_unsafe(const struct Mem *mem)
+{
+ uint32_t len;
+ if (mem_get_bytes_len(mem, &len) != 0)
+ return 0;
+ return len;
+}
+
/**
* Simple type to str convertor. It is used to simplify
* error reporting.
@@ -881,8 +902,6 @@ mem_mp_type(struct Mem *mem);
enum mp_type
sql_value_type(struct Mem *);
-int sqlValueBytes(struct Mem *);
-
#ifdef SQL_DEBUG
int sqlVdbeCheckMemInvariants(struct Mem *);
void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
@@ -912,18 +931,8 @@ struct Mem *sqlValueNew(struct sql *);
void
releaseMemArray(Mem * p, int N);
-/** Getters. */
-
-int
-sql_value_bytes(struct Mem *);
-
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
-const Mem *
-columnNullValue(void);
-
-/** Checkers. */
-
int sqlVdbeMemTooBig(Mem *);
/* Return TRUE if Mem X contains dynamically allocated content - anything
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 8a7a87b49..8feb112f5 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -433,9 +433,6 @@ sql_stmt_compile(const char *sql, int bytes_count, struct Vdbe *re_prepared,
int
sql_step(sql_stmt *);
-int
-sql_column_bytes(sql_stmt *, int iCol);
-
int
sql_column_bytes16(sql_stmt *, int iCol);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 5bb02e541..2bec2b186 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -422,41 +422,6 @@ sql_data_count(sql_stmt * pStmt)
return pVm->nResColumn;
}
-/*
- * Check to see if column iCol of the given statement is valid. If
- * it is, return a pointer to the Mem for the value of that column.
- * If iCol is not valid, return a pointer to a Mem which has a value
- * of NULL.
- */
-static Mem *
-columnMem(sql_stmt * pStmt, int i)
-{
- Vdbe *pVm;
- Mem *pOut;
-
- pVm = (Vdbe *) pStmt;
- if (pVm == 0)
- return (Mem *) columnNullValue();
- assert(pVm->db);
- if (pVm->pResultSet != 0 && i < pVm->nResColumn && i >= 0) {
- pOut = &pVm->pResultSet[i];
- } else {
- pOut = (Mem *) columnNullValue();
- }
- return pOut;
-}
-
-/**************************** sql_column_ ******************************
- * The following routines are used to access elements of the current row
- * in the result set.
- */
-
-int
-sql_column_bytes(sql_stmt * pStmt, int i)
-{
- return sql_value_bytes(columnMem(pStmt, i));
-}
-
char *
sql_result_to_msgpack(struct sql_stmt *stmt, uint32_t *tuple_size,
struct region *region)
More information about the Tarantool-patches
mailing list