From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 83CF368F4B; Tue, 23 Mar 2021 13:00:20 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 83CF368F4B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1616493620; bh=EtwrwOOInqF30HXDqfG3FmuvqVKhnYOPphb89eiTQ8Y=; h=To:Cc:Date:In-Reply-To:References:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=hPcd4Ha+rSeJsRxUs9isjegxPOXODXo2PCsC9++mL5NUDdWcBIqaofAhGDUecwpQc Brw3hAuUar7G90uLaxasFRwRrLOuVXSepqqirYG8pPiPJd6584NzSH/i1+lWGXd3Qm QvQ/h7T1yrzrY9kvlvfP07yAQ0fh5kV1o4USzGzI= Received: from smtp60.i.mail.ru (smtp60.i.mail.ru [217.69.128.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id A540568F69 for ; Tue, 23 Mar 2021 12:36:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org A540568F69 Received: by smtp60.i.mail.ru with esmtpa (envelope-from ) id 1lOdT0-0004yT-OE; Tue, 23 Mar 2021 12:36:51 +0300 To: v.shpilevoy@tarantool.org, tsafin@tarantool.org Cc: tarantool-patches@dev.tarantool.org Date: Tue, 23 Mar 2021 12:36:50 +0300 Message-Id: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: 78E4E2B564C1792B X-77F55803: 4F1203BC0FB41BD95D6E7CC48CB1F5F19D4B90E2C0E110A6B701D7D268243E19182A05F538085040D6F1EAC6577C2A0C2FB82CDC122D12AD2906B7D6D3B4485FB8A57197A40A5271 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7011EB7026DD4A9BAEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637CD86AAD37E7767A88638F802B75D45FF914D58D5BE9E6BC131B5C99E7648C95C686AF563A045C75E70B466C270E75B10394F802A3A0AF02DA471835C12D1D9774AD6D5ED66289B5259CC434672EE6371117882F4460429724CE54428C33FAD30A8DF7F3B2552694AC26CFBAC0749D213D2E47CDBA5A9658359CC434672EE6371117882F4460429728AD0CFFFB425014E868A13BD56FB6657D81D268191BDAD3DC09775C1D3CA48CFF4AF32A017141CDEBA3038C0950A5D36C8A9BA7A39EFB766EC990983EF5C0329BA3038C0950A5D36D5E8D9A59859A8B6E2B2DC65147354B476E601842F6C81A1F004C906525384307823802FF610243DF43C7A68FF6260569E8FC8737B5C2249EC8D19AE6D49635B3BBE47FD9DD3FB59A8DF7F3B2552694A57739F23D657EF2B13377AFFFEAFD26923F8577A6DFFEA7C7D149460FF1CF91893EC92FD9297F6715571747095F342E857739F23D657EF2BD5E8D9A59859A8B6EC71F829093BE88A089D37D7C0E48F6C5571747095F342E857739F23D657EF2B6825BDBE14D8E7024847893F9AA87235E5BFE6E7EFDEDCD789D4C264860C145E X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A24A6D60772A99906F8E1CD14B953EB46D99E93BC45261B22E355D89D7DBCDD132 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C686AF563A045C75E70B466C270E75B10394F802A3A0AF02D9C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF0417BEADF48D1460699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34B3611847B8BC2D0BC8176E80BF1033D5AF56A9F109E88A378556B366922140AEDC73540DF431A5DA1D7E09C32AA3244CEEAC0FFD1F7FFD0CD17BA2947F94000FF522A1CF68F4BE05FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojWJZv20R+6UiHvqC6G58Fcg== X-Mailru-Sender: 5C3750E245F362008BC1685FEC6306ED927517479144683B2FB82CDC122D12AD52685D71546B8E9E5105BD0848736F9966FEC6BF5C9C28D97E07721503EA2E00ED97202A5A4E92BF7402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v4 51/53] sql: introduce mem_get_string0() X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Mergen Imeev via Tarantool-patches Reply-To: imeevma@tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" This patch introduces mem_get_string0() which is used to receive NULL-terminated string from MEM. Part of #5818 --- src/box/sql/func.c | 77 ++++++++++++++++++------------ src/box/sql/mem.c | 101 ++++++---------------------------------- src/box/sql/mem.h | 9 ++-- src/box/sql/printf.c | 6 ++- src/box/sql/sqlInt.h | 4 -- src/box/sql/vdbeapi.c | 6 --- src/box/sql/whereexpr.c | 7 ++- 7 files changed, 75 insertions(+), 135 deletions(-) diff --git a/src/box/sql/func.c b/src/box/sql/func.c index d033dae86..78f4ec3b5 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -54,6 +54,24 @@ #include "lua/utils.h" #include "mpstream/mpstream.h" +static const char * +mem_get_str(struct Mem *mem) +{ + const char *str; + if (mem_convert_to_string0(mem) != 0 || mem_get_string0(mem, &str) != 0) + return NULL; + return str; +} + +static const unsigned char * +mem_get_ustr(struct Mem *mem) +{ + const char *str; + if (mem_convert_to_string0(mem) != 0 || mem_get_string0(mem, &str) != 0) + return NULL; + return (const unsigned char *)str; +} + /* * Return the collating function associated with a function. */ @@ -131,7 +149,7 @@ port_vdbemem_dump_lua(struct port *base, struct lua_State *L, bool is_flat) break; } case MP_STR: - lua_pushstring(L, (const char *) sql_value_text(param)); + lua_pushstring(L, mem_get_str(param)); break; case MP_BIN: case MP_ARRAY: @@ -192,7 +210,7 @@ port_vdbemem_get_msgpack(struct port *base, uint32_t *size) break; } case MP_STR: { - const char *str = (const char *) sql_value_text(param); + const char *str = mem_get_str(param); mpstream_encode_str(&stream, str); break; } @@ -497,7 +515,7 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv) break; } case MP_STR:{ - const unsigned char *z = sql_value_text(argv[0]); + const unsigned char *z = mem_get_ustr(argv[0]); if (z == 0) return; len = sql_utf8_char_count(z, sql_value_bytes(argv[0])); @@ -652,8 +670,8 @@ position_func(struct sql_context *context, int argc, struct Mem **argv) * Character size is equal to * needle char size. */ - haystack_str = sql_value_text(haystack); - needle_str = sql_value_text(needle); + haystack_str = mem_get_ustr(haystack); + needle_str = mem_get_ustr(needle); int n_needle_chars = sql_utf8_char_count(needle_str, n_needle_bytes); @@ -715,8 +733,7 @@ printfFunc(sql_context * context, int argc, sql_value ** argv) int n; sql *db = sql_context_db_handle(context); - if (argc >= 1 - && (zFormat = (const char *)sql_value_text(argv[0])) != 0) { + if (argc >= 1 && (zFormat = mem_get_str(argv[0])) != NULL) { x.nArg = argc - 1; x.nUsed = 0; x.apArg = argv + 1; @@ -773,7 +790,7 @@ substrFunc(sql_context * context, int argc, sql_value ** argv) return; assert(len == sql_value_bytes(argv[0])); } else { - z = sql_value_text(argv[0]); + z = mem_get_ustr(argv[0]); if (z == 0) return; len = 0; @@ -936,13 +953,13 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv) \ context->is_aborted = true; \ return; \ } \ - z2 = (char *)sql_value_text(argv[0]); \ + z2 = mem_get_str(argv[0]); \ n = sql_value_bytes(argv[0]); \ /* \ * Verify that the call to _bytes() \ * does not invalidate the _text() pointer. \ */ \ - assert(z2 == (char *)sql_value_text(argv[0])); \ + assert(z2 == mem_get_str(argv[0])); \ if (!z2) \ return; \ z1 = contextMalloc(context, ((i64) n) + 1); \ @@ -1273,8 +1290,8 @@ likeFunc(sql_context *context, int argc, sql_value **argv) context->is_aborted = true; return; } - const char *zB = (const char *) sql_value_text(argv[0]); - const char *zA = (const char *) sql_value_text(argv[1]); + const char *zB = mem_get_str(argv[0]); + const char *zA = mem_get_str(argv[1]); const char *zB_end = zB + sql_value_bytes(argv[0]); const char *zA_end = zA + sql_value_bytes(argv[1]); @@ -1293,7 +1310,7 @@ likeFunc(sql_context *context, int argc, sql_value **argv) return; } /* Encoding did not change */ - assert(zB == (const char *) sql_value_text(argv[0])); + assert(zB == mem_get_str(argv[0])); if (argc == 3) { /* @@ -1301,7 +1318,7 @@ likeFunc(sql_context *context, int argc, sql_value **argv) * single UTF-8 character. Otherwise, return an * error. */ - const unsigned char *zEsc = sql_value_text(argv[2]); + const unsigned char *zEsc = mem_get_ustr(argv[2]); if (zEsc == 0) return; if (sql_utf8_char_count(zEsc, sql_value_bytes(argv[2])) != 1) { @@ -1430,7 +1447,7 @@ quoteFunc(sql_context * context, int argc, sql_value ** argv) case MP_STR:{ int i, j; u64 n; - const unsigned char *zArg = sql_value_text(argv[0]); + const unsigned char *zArg = mem_get_ustr(argv[0]); char *z; if (zArg == 0) @@ -1477,7 +1494,7 @@ quoteFunc(sql_context * context, int argc, sql_value ** argv) static void unicodeFunc(sql_context * context, int argc, sql_value ** argv) { - const unsigned char *z = sql_value_text(argv[0]); + const unsigned char *z = mem_get_ustr(argv[0]); (void)argc; if (z && z[0]) sql_result_uint(context, sqlUtf8Read(&z)); @@ -1596,12 +1613,12 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv) assert(argc == 3); UNUSED_PARAMETER(argc); - zStr = sql_value_text(argv[0]); + zStr = mem_get_ustr(argv[0]); if (zStr == 0) return; nStr = sql_value_bytes(argv[0]); - assert(zStr == sql_value_text(argv[0])); /* No encoding change */ - zPattern = sql_value_text(argv[1]); + assert(zStr == mem_get_ustr(argv[0])); /* No encoding change */ + zPattern = mem_get_ustr(argv[1]); if (zPattern == 0) { assert(mem_is_null(argv[1]) || sql_context_db_handle(context)->mallocFailed); @@ -1613,12 +1630,12 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv) sql_result_value(context, argv[0]); return; } - assert(zPattern == sql_value_text(argv[1])); /* No encoding change */ - zRep = sql_value_text(argv[2]); + assert(zPattern == mem_get_ustr(argv[1])); /* No encoding change */ + zRep = mem_get_ustr(argv[2]); if (zRep == 0) return; nRep = sql_value_bytes(argv[2]); - assert(zRep == sql_value_text(argv[2])); + assert(zRep == mem_get_ustr(argv[2])); nOut = nStr + 1; assert(nOut < SQL_MAX_LENGTH); zOut = contextMalloc(context, (i64) nOut); @@ -1780,7 +1797,7 @@ trim_func_one_arg(struct sql_context *context, sql_value *arg) else default_trim = (const unsigned char *) " "; int input_str_sz = sql_value_bytes(arg); - const unsigned char *input_str = sql_value_text(arg); + const unsigned char *input_str = mem_get_ustr(arg); uint8_t trim_char_len[1] = { 1 }; trim_procedure(context, TRIM_BOTH, default_trim, trim_char_len, 1, input_str, input_str_sz); @@ -1802,7 +1819,7 @@ trim_func_two_args(struct sql_context *context, sql_value *arg1, sql_value *arg2) { const unsigned char *input_str, *trim_set; - if ((input_str = sql_value_text(arg2)) == NULL) + if ((input_str = mem_get_ustr(arg2)) == NULL) return; int input_str_sz = sql_value_bytes(arg2); @@ -1813,7 +1830,7 @@ trim_func_two_args(struct sql_context *context, sql_value *arg1, mem_get_integer(arg1, &n, &unused); trim_procedure(context, n, (const unsigned char *) " ", &len_one, 1, input_str, input_str_sz); - } else if ((trim_set = sql_value_text(arg1)) != NULL) { + } else if ((trim_set = mem_get_ustr(arg1)) != NULL) { int trim_set_sz = sql_value_bytes(arg1); uint8_t *char_len; int char_cnt = trim_prepare_char_len(context, trim_set, @@ -1839,8 +1856,8 @@ trim_func_three_args(struct sql_context *context, sql_value *arg1, { assert(sql_value_type(arg1) == MP_INT || sql_value_type(arg1) == MP_UINT); const unsigned char *input_str, *trim_set; - if ((input_str = sql_value_text(arg3)) == NULL || - (trim_set = sql_value_text(arg2)) == NULL) + if ((input_str = mem_get_ustr(arg3)) == NULL || + (trim_set = mem_get_ustr(arg2)) == NULL) return; int trim_set_sz = sql_value_bytes(arg2); @@ -1915,7 +1932,7 @@ soundexFunc(sql_context * context, int argc, sql_value ** argv) context->is_aborted = true; return; } - zIn = (u8 *) sql_value_text(argv[0]); + zIn = (u8 *) mem_get_ustr(argv[0]); if (zIn == 0) zIn = (u8 *) ""; for (i = 0; zIn[i] && !sqlIsalpha(zIn[i]); i++) { @@ -2165,7 +2182,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv) pAccum->mxAlloc = db->aLimit[SQL_LIMIT_LENGTH]; if (!firstTerm) { if (argc == 2) { - zSep = (char *)sql_value_text(argv[1]); + zSep = mem_get_str(argv[1]); nSep = sql_value_bytes(argv[1]); } else { zSep = ","; @@ -2174,7 +2191,7 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv) if (zSep) sqlStrAccumAppend(pAccum, zSep, nSep); } - zVal = (char *)sql_value_text(argv[0]); + zVal = mem_get_str(argv[0]); nVal = sql_value_bytes(argv[0]); if (zVal) sqlStrAccumAppend(pAccum, zVal, nVal); diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c index 90c6ee526..efd3e4677 100644 --- a/src/box/sql/mem.c +++ b/src/box/sql/mem.c @@ -1319,6 +1319,15 @@ mem_get_boolean(const struct Mem *mem, bool *b) return -1; } +int +mem_get_string0(const struct Mem *mem, const char **s) +{ + if ((mem->flags & MEM_Str) == 0 || (mem->flags & MEM_Term) == 0) + return -1; + *s = mem->z; + return 0; +} + int mem_copy(struct Mem *to, const struct Mem *from) { @@ -1936,45 +1945,6 @@ mem_has_msgpack_subtype(struct Mem *mem) mem->subtype == SQL_SUBTYPE_MSGPACK; } -/* - * The pVal argument is known to be a value other than NULL. - * Convert it into a string with encoding enc and return a pointer - * to a zero-terminated version of that string. - */ -static SQL_NOINLINE const void * -valueToText(sql_value * pVal) -{ - assert(pVal != 0); - assert((pVal->flags & (MEM_Null)) == 0); - if ((pVal->flags & (MEM_Blob | MEM_Str)) && - !mem_has_msgpack_subtype(pVal)) { - if (ExpandBlob(pVal)) - return 0; - pVal->flags |= MEM_Str; - sqlVdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */ - } else { - mem_convert_to_string(pVal); - assert(0 == (1 & SQL_PTR_TO_INT(pVal->z))); - } - return pVal->z; -} - -/* - * It is already known that pMem contains an unterminated string. - * Add the zero terminator. - */ -static SQL_NOINLINE int -vdbeMemAddTerminator(Mem * pMem) -{ - if (sqlVdbeMemGrow(pMem, pMem->n + 2, 1)) { - return -1; - } - pMem->z[pMem->n] = 0; - pMem->z[pMem->n + 1] = 0; - pMem->flags |= MEM_Term; - return 0; -} - /* * Both *pMem1 and *pMem2 contain string values. Compare the two values * using the collation sequence pColl. As usual, return a negative , zero @@ -2076,7 +2046,9 @@ sql_value_type(sql_value *pVal) static SQL_NOINLINE int valueBytes(sql_value * pVal) { - return valueToText(pVal) != 0 ? pVal->n : 0; + if (mem_convert_to_string(pVal) != 0) + return 0; + return pVal->n; } int @@ -2311,21 +2283,6 @@ registerTrace(int iReg, Mem *p) { } #endif -/* - * Make sure the given Mem is \u0000 terminated. - */ -int -sqlVdbeMemNulTerminate(Mem * pMem) -{ - testcase((pMem->flags & (MEM_Term | MEM_Str)) == (MEM_Term | MEM_Str)); - testcase((pMem->flags & (MEM_Term | MEM_Str)) == 0); - if ((pMem->flags & (MEM_Term | MEM_Str)) != MEM_Str) { - return 0; /* Nothing to do */ - } else { - return vdbeMemAddTerminator(pMem); - } -} - /* * If the given Mem* has a zero-filled tail, turn it into an ordinary * blob stored in dynamically allocated space. @@ -2493,7 +2450,9 @@ sql_value_blob(sql_value * pVal) p->flags |= MEM_Blob; return p->n ? p->z : 0; } else { - return sql_value_text(pVal); + if (mem_convert_to_string(pVal) != 0) + return NULL; + return pVal->z; } } @@ -2503,36 +2462,6 @@ sql_value_bytes(sql_value * pVal) return sqlValueBytes(pVal); } -const unsigned char * -sql_value_text(sql_value * pVal) -{ - return (const unsigned char *)sqlValueText(pVal); -} - -/* This function is only available internally, it is not part of the - * external API. It works in a similar way to sql_value_text(), - * except the data returned is in the encoding specified by the second - * parameter, which must be one of SQL_UTF16BE, SQL_UTF16LE or - * SQL_UTF8. - * - * (2006-02-16:) The enc value can be or-ed with SQL_UTF16_ALIGNED. - * If that is the case, then the result must be aligned on an even byte - * boundary. - */ -const void * -sqlValueText(sql_value * pVal) -{ - if (!pVal) - return 0; - if ((pVal->flags & (MEM_Str | MEM_Term)) == (MEM_Str | MEM_Term)) { - return pVal->z; - } - if (pVal->flags & MEM_Null) { - return 0; - } - return valueToText(pVal); -} - /* * Return a pointer to static memory containing an SQL NULL value. */ diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h index 8015608fa..fb2385541 100644 --- a/src/box/sql/mem.h +++ b/src/box/sql/mem.h @@ -357,6 +357,9 @@ mem_get_double(const struct Mem *mem, double *d); int mem_get_boolean(const struct Mem *mem, bool *b); +int +mem_get_string0(const struct Mem *mem, const char **s); + /** * Simple type to str convertor. It is used to simplify * error reporting. @@ -407,7 +410,6 @@ registerTrace(int iReg, Mem *p); # define memAboutToChange(P,M) #endif -int sqlVdbeMemNulTerminate(struct Mem *); int sqlVdbeMemExpandBlob(struct Mem *); #define ExpandBlob(P) (mem_is_zeroblob(P)? sqlVdbeMemExpandBlob(P) : 0) @@ -439,11 +441,6 @@ sql_value_blob(struct Mem *); int sql_value_bytes(struct Mem *); -const unsigned char * -sql_value_text(struct Mem *); - -const void *sqlValueText(struct Mem *); - #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))]) const Mem * diff --git a/src/box/sql/printf.c b/src/box/sql/printf.c index 0790a52a7..85cfe8802 100644 --- a/src/box/sql/printf.c +++ b/src/box/sql/printf.c @@ -165,7 +165,11 @@ getTextArg(PrintfArguments * p) { if (p->nArg <= p->nUsed) return 0; - return (char *)sql_value_text(p->apArg[p->nUsed++]); + const char *str; + struct Mem *mem = p->apArg[p->nUsed++]; + if (mem_convert_to_string0(mem) != 0 || mem_get_string0(mem, &str) != 0) + return NULL; + return (char *)str; } /* diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 9b4afc3f2..2f995ffc6 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -442,10 +442,6 @@ sql_column_bytes(sql_stmt *, int iCol); int sql_column_bytes16(sql_stmt *, int iCol); -const unsigned char * -sql_column_text(sql_stmt *, - int iCol); - char * sql_result_to_msgpack(struct sql_stmt *stmt, uint32_t *tuple_size, struct region *region); diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c index 532677b05..465284567 100644 --- a/src/box/sql/vdbeapi.c +++ b/src/box/sql/vdbeapi.c @@ -485,12 +485,6 @@ sql_column_bytes(sql_stmt * pStmt, int i) return sql_value_bytes(columnMem(pStmt, i)); } -const unsigned char * -sql_column_text(sql_stmt * pStmt, int i) -{ - return sql_value_text(columnMem(pStmt, i)); -} - char * sql_result_to_msgpack(struct sql_stmt *stmt, uint32_t *tuple_size, struct region *region) diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c index 782e44734..51681b008 100644 --- a/src/box/sql/whereexpr.c +++ b/src/box/sql/whereexpr.c @@ -312,8 +312,11 @@ like_optimization_is_valid(Parse *pParse, Expr *pExpr, Expr **ppPrefix, pVal = sqlVdbeGetBoundValue(pReprepare, iCol, FIELD_TYPE_SCALAR); - if (pVal != NULL && mem_is_string(pVal)) - z = (char *)sql_value_text(pVal); + if (pVal != NULL && mem_is_string(pVal)) { + if (mem_convert_to_string0(pVal) != 0 || + mem_get_string0(pVal, &z) != 0) + return -1; + } assert(pRight->op == TK_VARIABLE || pRight->op == TK_REGISTER); } else if (op == TK_STRING) { z = pRight->u.zToken; -- 2.25.1