* [Tarantool-patches] [PATCH v1 01/21] sql: rework CHAR() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:48 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 02/21] sql: refactor GREATEST() and LEAST() functions Mergen Imeev via Tarantool-patches
` (20 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:48 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
The CHAR() function now uses the ICU macro to get characters.
Part of #4145
---
src/box/sql/func.c | 100 +++++++++++++++++++++++++--------------------
1 file changed, 55 insertions(+), 45 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 868d51145..0cd8f8f69 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -728,6 +728,60 @@ func_substr_characters(struct sql_context *ctx, int argc, struct Mem *argv)
ctx->is_aborted = true;
}
+/**
+ * Implementation of the CHAR() function.
+ *
+ * This function takes zero or more arguments, each of which is an integer. It
+ * constructs a string where each character of the string is the unicode
+ * character for the corresponding integer argument.
+ *
+ * If an argument is negative or greater than 0x10ffff, the symbol "�" is used.
+ * Symbol '\0' used instead of NULL argument.
+ */
+static void
+func_char(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ if (argc == 0)
+ return mem_set_str_static(ctx->pOut, "", 0);
+ struct region *region = &fiber()->gc;
+ size_t svp = region_used(region);
+ uint32_t size;
+ UChar32 *buf = region_alloc_array(region, typeof(*buf), argc, &size);
+ if (buf == NULL) {
+ ctx->is_aborted = true;
+ diag_set(OutOfMemory, size, "region_alloc_array", "buf");
+ return;
+ }
+ int len = 0;
+ for (int i = 0; i < argc; ++i) {
+ if (mem_is_null(&argv[i]))
+ buf[i] = 0;
+ else if (!mem_is_uint(&argv[i]) || argv[i].u.u > 0x10ffff)
+ buf[i] = 0xfffd;
+ else
+ buf[i] = argv[i].u.u;
+ len += U8_LENGTH(buf[i]);
+ }
+
+ char *str = sqlDbMallocRawNN(sql_get(), len);
+ if (str == NULL) {
+ region_truncate(region, svp);
+ ctx->is_aborted = true;
+ return;
+ }
+ int pos = 0;
+ for (int i = 0; i < argc; ++i) {
+ UBool is_error = false;
+ U8_APPEND((uint8_t *)str, pos, len, buf[i], is_error);
+ assert(!is_error);
+ (void)is_error;
+ }
+ region_truncate(region, svp);
+ assert(pos == len);
+ (void)pos;
+ mem_set_str_allocated(ctx->pOut, str, len);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1461,50 +1515,6 @@ unicodeFunc(struct sql_context *context, int argc, struct Mem *argv)
sql_result_uint(context, sqlUtf8Read(&z));
}
-/*
- * The char() function takes zero or more arguments, each of which is
- * an integer. It constructs a string where each character of the string
- * is the unicode character for the corresponding integer argument.
- */
-static void
-charFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- unsigned char *z, *zOut;
- int i;
- zOut = z = sql_malloc64(argc * 4 + 1);
- if (z == NULL) {
- context->is_aborted = true;
- return;
- }
- for (i = 0; i < argc; i++) {
- uint64_t x;
- unsigned c;
- if (sql_value_type(&argv[i]) == MP_INT)
- x = 0xfffd;
- else
- x = mem_get_uint_unsafe(&argv[i]);
- if (x > 0x10ffff)
- x = 0xfffd;
- c = (unsigned)(x & 0x1fffff);
- if (c < 0x00080) {
- *zOut++ = (u8) (c & 0xFF);
- } else if (c < 0x00800) {
- *zOut++ = 0xC0 + (u8) ((c >> 6) & 0x1F);
- *zOut++ = 0x80 + (u8) (c & 0x3F);
- } else if (c < 0x10000) {
- *zOut++ = 0xE0 + (u8) ((c >> 12) & 0x0F);
- *zOut++ = 0x80 + (u8) ((c >> 6) & 0x3F);
- *zOut++ = 0x80 + (u8) (c & 0x3F);
- } else {
- *zOut++ = 0xF0 + (u8) ((c >> 18) & 0x07);
- *zOut++ = 0x80 + (u8) ((c >> 12) & 0x3F);
- *zOut++ = 0x80 + (u8) ((c >> 6) & 0x3F);
- *zOut++ = 0x80 + (u8) (c & 0x3F);
- }
- }
- sql_result_text64(context, (char *)z, zOut - z, sql_free);
-}
-
/*
* The hex() function. Interpret the argument as a blob. Return
* a hexadecimal rendering as text.
@@ -1857,7 +1867,7 @@ static struct sql_func_definition definitions[] = {
NULL},
{"AVG", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, step_avg, fin_avg},
{"AVG", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, step_avg, fin_avg},
- {"CHAR", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_STRING, charFunc, NULL},
+ {"CHAR", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_STRING, func_char, NULL},
{"CHAR_LENGTH", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER,
func_char_length, NULL},
{"COALESCE", -1, {FIELD_TYPE_ANY}, FIELD_TYPE_SCALAR, sql_builtin_stub,
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 02/21] sql: refactor GREATEST() and LEAST() functions
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 01/21] sql: rework CHAR() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:48 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 03/21] sql: refactor HEX() function Mergen Imeev via Tarantool-patches
` (19 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:48 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 113 +++++++++++++++++++++++----------------------
1 file changed, 57 insertions(+), 56 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 0cd8f8f69..40bdbf739 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -782,6 +782,34 @@ func_char(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_str_allocated(ctx->pOut, str, len);
}
+/**
+ * Implementation of the GREATEST() and LEAST() functions.
+ *
+ * The GREATEST() function returns the largest of the given arguments.
+ * The LEAST() function returns the smallest of the given arguments.
+ */
+static void
+func_greatest_least(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc > 1);
+ int mask = ctx->func->def->name[0] == 'G' ? -1 : 0;
+ assert(ctx->func->def->name[0] == 'G' ||
+ ctx->func->def->name[0] == 'L');
+
+ if (mem_is_null(&argv[0]))
+ return;
+ int best = 0;
+ for (int i = 1; i < argc; ++i) {
+ if (mem_is_null(&argv[i]))
+ return;
+ int cmp = mem_cmp_scalar(&argv[best], &argv[i], ctx->coll);
+ if ((cmp ^ mask) >= 0)
+ best = i;
+ }
+ if (mem_copy(ctx->pOut, &argv[best]) != 0)
+ ctx->is_aborted = true;
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -829,37 +857,6 @@ sql_func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_uuid(ctx->pOut, &uuid);
}
-/*
- * Implementation of the non-aggregate min() and max() functions
- */
-static void
-minmaxFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- int i;
- int iBest;
- struct coll *pColl;
- struct func *func = context->func;
- int mask = sql_func_flag_is_set(func, SQL_FUNC_MAX) ? -1 : 0;
- if (argc < 2) {
- diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT,
- mask ? "GREATEST" : "LEAST", "at least two", argc);
- context->is_aborted = true;
- return;
- }
- pColl = context->coll;
- assert(mask == -1 || mask == 0);
- iBest = 0;
- if (mem_is_null(&argv[0]))
- return;
- for (i = 1; i < argc; i++) {
- if (mem_is_null(&argv[i]))
- return;
- if ((mem_cmp_scalar(&argv[iBest], &argv[i], pColl) ^ mask) >= 0)
- iBest = i;
- }
- sql_result_value(context, &argv[iBest]);
-}
-
/*
* Return the type of the argument.
*/
@@ -1788,13 +1785,11 @@ static struct sql_func_dictionary dictionaries[] = {
{"CHAR_LENGTH", 1, 1, 0, true, 0, NULL},
{"COALESCE", 2, SQL_MAX_FUNCTION_ARG, SQL_FUNC_COALESCE, true, 0, NULL},
{"COUNT", 0, 1, SQL_FUNC_AGG, false, 0, NULL},
- {"GREATEST", 2, SQL_MAX_FUNCTION_ARG, SQL_FUNC_MAX | SQL_FUNC_NEEDCOLL,
- true, 0, NULL},
+ {"GREATEST", 2, SQL_MAX_FUNCTION_ARG, SQL_FUNC_NEEDCOLL, true, 0, NULL},
{"GROUP_CONCAT", 1, 2, SQL_FUNC_AGG, false, 0, NULL},
{"HEX", 1, 1, 0, true, 0, NULL},
{"IFNULL", 2, 2, SQL_FUNC_COALESCE, true, 0, NULL},
- {"LEAST", 2, SQL_MAX_FUNCTION_ARG, SQL_FUNC_MIN | SQL_FUNC_NEEDCOLL,
- true, 0, NULL},
+ {"LEAST", 2, SQL_MAX_FUNCTION_ARG, SQL_FUNC_NEEDCOLL, true, 0, NULL},
{"LENGTH", 1, 1, SQL_FUNC_LENGTH, true, 0, NULL},
{"LIKE", 2, 3, SQL_FUNC_LIKE | SQL_FUNC_NEEDCOLL, true, 0, NULL},
{"LIKELIHOOD", 2, 2, SQL_FUNC_UNLIKELY, true, 0, NULL},
@@ -1876,19 +1871,20 @@ static struct sql_func_definition definitions[] = {
{"COUNT", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_INTEGER, step_count,
fin_count},
- {"GREATEST", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, minmaxFunc,
- NULL},
- {"GREATEST", -1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, minmaxFunc,
- NULL},
- {"GREATEST", -1, {FIELD_TYPE_NUMBER}, FIELD_TYPE_NUMBER, minmaxFunc,
- NULL},
+ {"GREATEST", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER,
+ func_greatest_least, NULL},
+ {"GREATEST", -1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE,
+ func_greatest_least, NULL},
+ {"GREATEST", -1, {FIELD_TYPE_NUMBER}, FIELD_TYPE_NUMBER,
+ func_greatest_least, NULL},
{"GREATEST", -1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_VARBINARY,
- minmaxFunc, NULL},
- {"GREATEST", -1, {FIELD_TYPE_UUID}, FIELD_TYPE_UUID, minmaxFunc, NULL},
- {"GREATEST", -1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING, minmaxFunc,
- NULL},
- {"GREATEST", -1, {FIELD_TYPE_SCALAR}, FIELD_TYPE_SCALAR, minmaxFunc,
- NULL},
+ func_greatest_least, NULL},
+ {"GREATEST", -1, {FIELD_TYPE_UUID}, FIELD_TYPE_UUID,
+ func_greatest_least, NULL},
+ {"GREATEST", -1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING,
+ func_greatest_least, NULL},
+ {"GREATEST", -1, {FIELD_TYPE_SCALAR}, FIELD_TYPE_SCALAR,
+ func_greatest_least, NULL},
{"GROUP_CONCAT", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING,
step_group_concat, NULL},
@@ -1903,15 +1899,20 @@ static struct sql_func_definition definitions[] = {
{"IFNULL", 2, {FIELD_TYPE_ANY, FIELD_TYPE_ANY}, FIELD_TYPE_SCALAR,
sql_builtin_stub, NULL},
- {"LEAST", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, minmaxFunc,
- NULL},
- {"LEAST", -1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, minmaxFunc, NULL},
- {"LEAST", -1, {FIELD_TYPE_NUMBER}, FIELD_TYPE_NUMBER, minmaxFunc, NULL},
- {"LEAST", -1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_VARBINARY, minmaxFunc,
- NULL},
- {"LEAST", -1, {FIELD_TYPE_UUID}, FIELD_TYPE_UUID, minmaxFunc, NULL},
- {"LEAST", -1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING, minmaxFunc, NULL},
- {"LEAST", -1, {FIELD_TYPE_SCALAR}, FIELD_TYPE_SCALAR, minmaxFunc, NULL},
+ {"LEAST", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER,
+ func_greatest_least, NULL},
+ {"LEAST", -1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE,
+ func_greatest_least, NULL},
+ {"LEAST", -1, {FIELD_TYPE_NUMBER}, FIELD_TYPE_NUMBER,
+ func_greatest_least, NULL},
+ {"LEAST", -1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_VARBINARY,
+ func_greatest_least, NULL},
+ {"LEAST", -1, {FIELD_TYPE_UUID}, FIELD_TYPE_UUID,
+ func_greatest_least, NULL},
+ {"LEAST", -1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING,
+ func_greatest_least, NULL},
+ {"LEAST", -1, {FIELD_TYPE_SCALAR}, FIELD_TYPE_SCALAR,
+ func_greatest_least, NULL},
{"LENGTH", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, func_char_length,
NULL},
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 03/21] sql: refactor HEX() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 01/21] sql: rework CHAR() function Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 02/21] sql: refactor GREATEST() and LEAST() functions Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:48 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 04/21] sql: refactor LENGTH() function Mergen Imeev via Tarantool-patches
` (18 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:48 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 74 ++++++++++++++++++++++++----------------------
1 file changed, 38 insertions(+), 36 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 40bdbf739..e4372de86 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -810,6 +810,43 @@ func_greatest_least(struct sql_context *ctx, int argc, struct Mem *argv)
ctx->is_aborted = true;
}
+/**
+ * Implementation of the HEX() function.
+ *
+ * The HEX() function returns the hexadecimal representation of the argument.
+ */
+static const char hexdigits[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+static void
+func_hex(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1);
+ (void)argc;
+ struct Mem *arg = &argv[0];
+ if (mem_is_null(arg))
+ return;
+
+ assert(mem_is_bin(arg) && arg->n >= 0);
+ if (arg->n == 0)
+ return mem_set_str0_static(ctx->pOut, "");
+
+ uint32_t size = 2 * arg->n;
+ char *str = sqlDbMallocRawNN(sql_get(), size);
+ if (str == NULL) {
+ ctx->is_aborted = true;
+ return;
+ }
+ for (int i = 0; i < arg->n; ++i) {
+ char c = arg->z[i];
+ str[2 * i] = hexdigits[(c >> 4) & 0xf];
+ str[2 * i + 1] = hexdigits[c & 0xf];
+ }
+ mem_set_str_allocated(ctx->pOut, str, size);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1395,14 +1432,6 @@ sql_func_version(struct sql_context *context, int argc, struct Mem *argv)
sql_result_text(context, tarantool_version(), -1, SQL_STATIC);
}
-/* Array for converting from half-bytes (nybbles) into ASCII hex
- * digits.
- */
-static const char hexdigits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
/*
* Implementation of the QUOTE() function. This function takes a single
* argument. If the argument is numeric, the return value is the same as
@@ -1512,33 +1541,6 @@ unicodeFunc(struct sql_context *context, int argc, struct Mem *argv)
sql_result_uint(context, sqlUtf8Read(&z));
}
-/*
- * The hex() function. Interpret the argument as a blob. Return
- * a hexadecimal rendering as text.
- */
-static void
-hexFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- int i, n;
- const unsigned char *pBlob;
- char *zHex, *z;
- assert(argc == 1);
- UNUSED_PARAMETER(argc);
- pBlob = mem_as_bin(&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) {
- for (i = 0; i < n; i++, pBlob++) {
- unsigned char c = *pBlob;
- *(z++) = hexdigits[(c >> 4) & 0xf];
- *(z++) = hexdigits[c & 0xf];
- }
- *z = 0;
- sql_result_text(context, zHex, n * 2, sql_free);
- }
-}
-
/*
* The zeroblob(N) function returns a zero-filled blob of size N bytes.
*/
@@ -1895,7 +1897,7 @@ static struct sql_func_definition definitions[] = {
{"GROUP_CONCAT", 2, {FIELD_TYPE_VARBINARY, FIELD_TYPE_VARBINARY},
FIELD_TYPE_VARBINARY, step_group_concat, NULL},
- {"HEX", 1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_STRING, hexFunc, NULL},
+ {"HEX", 1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_STRING, func_hex, NULL},
{"IFNULL", 2, {FIELD_TYPE_ANY, FIELD_TYPE_ANY}, FIELD_TYPE_SCALAR,
sql_builtin_stub, NULL},
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 04/21] sql: refactor LENGTH() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (2 preceding siblings ...)
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 03/21] sql: refactor HEX() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:48 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 05/21] sql: refactor PRINTF() function Mergen Imeev via Tarantool-patches
` (17 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:48 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 55 +++++++++++++---------------------------------
1 file changed, 15 insertions(+), 40 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index e4372de86..c0e8c4416 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -847,6 +847,19 @@ func_hex(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_str_allocated(ctx->pOut, str, size);
}
+/** Implementation of the OCTET_LENGTH() function. */
+static void
+func_octet_length(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1);
+ (void)argc;
+ struct Mem *arg = &argv[0];
+ if (mem_is_null(arg))
+ return;
+ assert(mem_is_bytes(arg) && arg->n >= 0);
+ mem_set_uint(ctx->pOut, arg->n);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -941,44 +954,6 @@ typeofFunc(struct sql_context *context, int argc, struct Mem *argv)
sql_result_text(context, z, -1, SQL_STATIC);
}
-/*
- * Implementation of the length() function
- */
-static void
-lengthFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- int len;
-
- assert(argc == 1);
- UNUSED_PARAMETER(argc);
- switch (sql_value_type(&argv[0])) {
- case MP_BIN:
- case MP_ARRAY:
- case MP_MAP:
- case MP_INT:
- case MP_UINT:
- case MP_BOOL:
- case MP_DOUBLE:{
- mem_as_bin(&argv[0]);
- sql_result_uint(context, mem_len_unsafe(&argv[0]));
- break;
- }
- case MP_EXT:
- case MP_STR:{
- const unsigned char *z = mem_as_ustr(&argv[0]);
- if (z == 0)
- return;
- len = sql_utf8_char_count(z, mem_len_unsafe(&argv[0]));
- sql_result_uint(context, len);
- break;
- }
- default:{
- sql_result_null(context);
- break;
- }
- }
-}
-
/*
* Implementation of the printf() function.
*/
@@ -1918,8 +1893,8 @@ static struct sql_func_definition definitions[] = {
{"LENGTH", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, func_char_length,
NULL},
- {"LENGTH", 1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_INTEGER, lengthFunc,
- NULL},
+ {"LENGTH", 1, {FIELD_TYPE_VARBINARY}, FIELD_TYPE_INTEGER,
+ func_octet_length, NULL},
{"LIKE", 2, {FIELD_TYPE_STRING, FIELD_TYPE_STRING},
FIELD_TYPE_BOOLEAN, likeFunc, NULL},
{"LIKE", 3, {FIELD_TYPE_STRING, FIELD_TYPE_STRING, FIELD_TYPE_STRING},
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 05/21] sql: refactor PRINTF() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (3 preceding siblings ...)
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 04/21] sql: refactor LENGTH() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:48 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 06/21] sql: refactor RANDOM() function Mergen Imeev via Tarantool-patches
` (16 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:48 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 62 +++++++++++++++++++-------------------------
src/box/sql/printf.c | 6 ++---
src/box/sql/sqlInt.h | 3 ++-
3 files changed, 31 insertions(+), 40 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index c0e8c4416..603deb44e 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -860,6 +860,31 @@ func_octet_length(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_uint(ctx->pOut, arg->n);
}
+/** Implementation of the PRINTF() function. */
+static void
+func_printf(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ if (argc < 1 || mem_is_null(&argv[0]))
+ return;
+ if (argc == 1 || !mem_is_str(&argv[0])) {
+ struct Mem *mem = ctx->pOut;
+ if (mem_copy(mem, &argv[0]) != 0 || mem_to_str(mem) != 0)
+ ctx->is_aborted = true;
+ return;
+ }
+ struct PrintfArguments pargs;
+ struct StrAccum acc;
+ char *format = argv[0].z;
+ pargs.nArg = argc - 1;
+ pargs.nUsed = 0;
+ pargs.apArg = argv + 1;
+ struct sql *db = sql_get();
+ sqlStrAccumInit(&acc, db, 0, 0, db->aLimit[SQL_LIMIT_LENGTH]);
+ acc.printfFlags = SQL_PRINTF_SQLFUNC;
+ sqlXPrintf(&acc, format, &pargs);
+ mem_set_str_allocated(ctx->pOut, sqlStrAccumFinish(&acc), acc.nChar);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -954,40 +979,6 @@ typeofFunc(struct sql_context *context, int argc, struct Mem *argv)
sql_result_text(context, z, -1, SQL_STATIC);
}
-/*
- * Implementation of the printf() function.
- */
-static void
-printfFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- PrintfArguments x;
- StrAccum str;
- const char *zFormat;
- int n;
- sql *db = sql_context_db_handle(context);
-
- if (argc >= 1 && (zFormat = mem_as_str0(&argv[0])) != NULL) {
- x.nArg = argc - 1;
- x.nUsed = 0;
- x.apArg = sqlDbMallocRawNN(sql_get(),
- (argc - 1) * sizeof(*x.apArg));
- if (x.apArg == NULL) {
- context->is_aborted = true;
- return;
- }
- for (int i = 1; i < argc; ++i)
- x.apArg[i - 1] = &argv[i];
- sqlStrAccumInit(&str, db, 0, 0,
- db->aLimit[SQL_LIMIT_LENGTH]);
- str.printfFlags = SQL_PRINTF_SQLFUNC;
- sqlXPrintf(&str, zFormat, &x);
- sqlDbFree(sql_get(), x.apArg);
- n = str.nChar;
- sql_result_text(context, sqlStrAccumFinish(&str), n,
- SQL_DYNAMIC);
- }
-}
-
/*
* Implementation of the round() function
*/
@@ -1930,8 +1921,7 @@ static struct sql_func_definition definitions[] = {
FIELD_TYPE_INTEGER, func_position_characters, NULL},
{"POSITION", 2, {FIELD_TYPE_VARBINARY, FIELD_TYPE_VARBINARY},
FIELD_TYPE_INTEGER, func_position_octets, NULL},
- {"PRINTF", -1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, printfFunc,
- NULL},
+ {"PRINTF", -1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, func_printf, NULL},
{"QUOTE", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, quoteFunc, NULL},
{"RANDOM", 0, {}, FIELD_TYPE_INTEGER, randomFunc, NULL},
{"RANDOMBLOB", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY,
diff --git a/src/box/sql/printf.c b/src/box/sql/printf.c
index b4ab0d0f9..5b61646e3 100644
--- a/src/box/sql/printf.c
+++ b/src/box/sql/printf.c
@@ -144,7 +144,7 @@ getIntArg(PrintfArguments * p)
{
if (p->nArg <= p->nUsed)
return 0;
- return mem_get_int_unsafe(p->apArg[p->nUsed++]);
+ return mem_get_int_unsafe(&p->apArg[p->nUsed++]);
}
static double
@@ -152,7 +152,7 @@ getDoubleArg(PrintfArguments * p)
{
if (p->nArg <= p->nUsed)
return 0.0;
- return mem_get_double_unsafe(p->apArg[p->nUsed++]);
+ return mem_get_double_unsafe(&p->apArg[p->nUsed++]);
}
static char *
@@ -160,7 +160,7 @@ getTextArg(PrintfArguments * p)
{
if (p->nArg <= p->nUsed)
return 0;
- struct Mem *mem = p->apArg[p->nUsed++];
+ struct Mem *mem = &p->apArg[p->nUsed++];
return (char *)mem_as_str0(mem);
}
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index cfdf71f1f..9361775b1 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2511,7 +2511,8 @@ int sqlIsNaN(double);
struct PrintfArguments {
int nArg; /* Total number of arguments */
int nUsed; /* Number of arguments used so far */
- sql_value **apArg; /* The argument values */
+ /** The argument values. */
+ struct Mem *apArg;
};
void sqlVXPrintf(StrAccum *, const char *, va_list);
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 06/21] sql: refactor RANDOM() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (4 preceding siblings ...)
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 05/21] sql: refactor PRINTF() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:48 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 07/21] sql: rework RANDOMBLOB() function Mergen Imeev via Tarantool-patches
` (15 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:48 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 40 ++++++++++++++++------------------------
1 file changed, 16 insertions(+), 24 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 603deb44e..2d83d52f8 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -885,6 +885,21 @@ func_printf(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_str_allocated(ctx->pOut, sqlStrAccumFinish(&acc), acc.nChar);
}
+/**
+ * Implementation of the RANDOM() function.
+ *
+ * This function returns a random INT64 value.
+ */
+static void
+func_random(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ (void)argc;
+ (void)argv;
+ int64_t r;
+ sql_randomness(sizeof(r), &r);
+ mem_set_int(ctx->pOut, r, r < 0);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1050,29 +1065,6 @@ contextMalloc(struct sql_context *context, i64 nByte)
return z;
}
-/*
- * Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented
- * as VDBE code so that unused argument values do not have to be computed.
- * However, we still need some kind of function implementation for this
- * routines in the function table. The noopFunc macro provides this.
- * noopFunc will never be called so it doesn't matter what the implementation
- * is. We might as well use the "version()" function as a substitute.
- */
-#define noopFunc sql_func_version /* Substitute function - never called */
-
-/*
- * Implementation of random(). Return a random integer.
- */
-static void
-randomFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- (void)argc;
- (void)argv;
- int64_t r;
- sql_randomness(sizeof(r), &r);
- sql_result_int(context, r);
-}
-
/*
* Implementation of randomblob(N). Return a random blob
* that is N bytes long.
@@ -1923,7 +1915,7 @@ static struct sql_func_definition definitions[] = {
FIELD_TYPE_INTEGER, func_position_octets, NULL},
{"PRINTF", -1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, func_printf, NULL},
{"QUOTE", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, quoteFunc, NULL},
- {"RANDOM", 0, {}, FIELD_TYPE_INTEGER, randomFunc, NULL},
+ {"RANDOM", 0, {}, FIELD_TYPE_INTEGER, func_random, NULL},
{"RANDOMBLOB", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY,
randomBlob, NULL},
{"REPLACE", 3,
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 07/21] sql: rework RANDOMBLOB() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (5 preceding siblings ...)
2021-11-11 10:48 ` [Tarantool-patches] [PATCH v1 06/21] sql: refactor RANDOM() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 08/21] sql: refactor ZEROBLOB() function Mergen Imeev via Tarantool-patches
` (14 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
This patch refactors RANDOMBLOB() function. Also, RANDOMBLOB(0) now
returns empty string.
part of #4145
---
src/box/sql/func.c | 57 +++++++++++++++++++-------------------
test/sql-tap/func.test.lua | 4 +--
2 files changed, 30 insertions(+), 31 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 2d83d52f8..408c56e45 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -900,6 +900,33 @@ func_random(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_int(ctx->pOut, r, r < 0);
}
+/**
+ * Implementation of the RANDOMBLOB() function.
+ *
+ * This function returns a random VARBINARY value. The size of this value is
+ * specified as an argument of the function.
+ */
+static void
+func_randomblob(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1);
+ (void)argc;
+ struct Mem *arg = &argv[0];
+ assert(mem_is_null(arg) || mem_is_int(arg));
+ if (mem_is_null(arg) || !mem_is_uint(arg))
+ return;
+ if (arg->u.u == 0)
+ return mem_set_bin_static(ctx->pOut, "", 0);
+ uint64_t len = arg->u.u;
+ char *res = sqlDbMallocRawNN(sql_get(), len);
+ if (res == NULL) {
+ ctx->is_aborted = true;
+ return;
+ }
+ sql_randomness(len, res);
+ mem_set_bin_allocated(ctx->pOut, res, len);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1065,34 +1092,6 @@ contextMalloc(struct sql_context *context, i64 nByte)
return z;
}
-/*
- * Implementation of randomblob(N). Return a random blob
- * that is N bytes long.
- */
-static void
-randomBlob(struct sql_context *context, int argc, struct Mem *argv)
-{
- int64_t n;
- unsigned char *p;
- assert(argc == 1);
- UNUSED_PARAMETER(argc);
- if (mem_is_bin(&argv[0]) || mem_is_map(&argv[0]) ||
- mem_is_array(&argv[0])) {
- diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
- mem_str(&argv[0]), "number");
- context->is_aborted = true;
- return;
- }
- n = mem_get_int_unsafe(&argv[0]);
- if (n < 1)
- return;
- p = contextMalloc(context, n);
- if (p) {
- sql_randomness(n, p);
- sql_result_blob(context, (char *)p, n, sql_free);
- }
-}
-
#define Utf8Read(s, e) \
ucnv_getNextUChar(icu_utf8_conv, &(s), (e), &status)
@@ -1917,7 +1916,7 @@ static struct sql_func_definition definitions[] = {
{"QUOTE", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, quoteFunc, NULL},
{"RANDOM", 0, {}, FIELD_TYPE_INTEGER, func_random, NULL},
{"RANDOMBLOB", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY,
- randomBlob, NULL},
+ func_randomblob, NULL},
{"REPLACE", 3,
{FIELD_TYPE_STRING, FIELD_TYPE_STRING, FIELD_TYPE_STRING},
FIELD_TYPE_STRING, replaceFunc, NULL},
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index b52d5bd4c..e2e905907 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -2545,8 +2545,8 @@ test:do_execsql_test(
test:do_execsql_test(
"func-36",
- [[VALUES (LENGTH(RANDOMBLOB(0)))]],
- {""})
+ [[VALUES (RANDOMBLOB(0))]],
+ {''})
-- gh-3542
-- In SQL '\0' is NOT a end-of-string signal. Tests below ensures
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 08/21] sql: refactor ZEROBLOB() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (6 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 07/21] sql: rework RANDOMBLOB() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 09/21] sql: refactor TYPEOF() function Mergen Imeev via Tarantool-patches
` (13 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 54 +++++++++++++++++++++++-----------------------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 408c56e45..842e4e766 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -927,6 +927,32 @@ func_randomblob(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_bin_allocated(ctx->pOut, res, len);
}
+/**
+ * Implementation of the ZEROBLOB() function.
+ *
+ * This function returns a zero-filled VARBINARY value. The size of this value
+ * is specified as an argument of the function.
+ */
+static void
+func_zeroblob(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1);
+ (void)argc;
+ struct Mem *arg = &argv[0];
+ assert(mem_is_null(arg) || mem_is_int(arg));
+ if (mem_is_null(arg) || !mem_is_uint(arg))
+ return;
+ if (arg->u.u == 0)
+ return mem_set_bin_static(ctx->pOut, "", 0);
+ uint64_t len = arg->u.u;
+ char *res = sqlDbMallocZero(sql_get(), len);
+ if (res == NULL) {
+ ctx->is_aborted = true;
+ return;
+ }
+ mem_set_bin_allocated(ctx->pOut, res, len);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1498,32 +1524,6 @@ unicodeFunc(struct sql_context *context, int argc, struct Mem *argv)
sql_result_uint(context, sqlUtf8Read(&z));
}
-/*
- * The zeroblob(N) function returns a zero-filled blob of size N bytes.
- */
-static void
-zeroblobFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- int64_t n;
- assert(argc == 1);
- UNUSED_PARAMETER(argc);
- n = mem_get_int_unsafe(&argv[0]);
- if (n < 0)
- n = 0;
- if (n > sql_get()->aLimit[SQL_LIMIT_LENGTH]) {
- diag_set(ClientError, ER_SQL_EXECUTE, "string or binary string"\
- "is too big");
- context->is_aborted = true;
- return;
- }
- char *str = sqlDbMallocZero(sql_get(), n);
- if (str == NULL) {
- context->is_aborted = true;
- return;
- }
- mem_set_bin_allocated(context->pOut, str, n);
-}
-
/*
* The replace() function. Three arguments are all strings: call
* them A, B, and C. The result is also a string which is derived
@@ -1967,7 +1967,7 @@ static struct sql_func_definition definitions[] = {
{"UUID", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_UUID, sql_func_uuid, NULL},
{"VERSION", 0, {}, FIELD_TYPE_STRING, sql_func_version, NULL},
{"ZEROBLOB", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY,
- zeroblobFunc, NULL},
+ func_zeroblob, NULL},
};
static struct sql_func_dictionary *
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 09/21] sql: refactor TYPEOF() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (7 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 08/21] sql: refactor ZEROBLOB() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 10/21] sql: refactor ROUND() function Mergen Imeev via Tarantool-patches
` (12 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 58 ++++++++--------------------------------------
1 file changed, 10 insertions(+), 48 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 842e4e766..3a788b450 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -953,6 +953,15 @@ func_zeroblob(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_bin_allocated(ctx->pOut, res, len);
}
+/** Implementation of the TYPEOF() function. */
+static void
+func_typeof(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1);
+ (void)argc;
+ return mem_set_str0_static(ctx->pOut, mem_type_to_str(&argv[0]));
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1000,53 +1009,6 @@ sql_func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_uuid(ctx->pOut, &uuid);
}
-/*
- * Return the type of the argument.
- */
-static void
-typeofFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- (void)argc;
- const char *z = 0;
- if ((argv[0].flags & MEM_Number) != 0)
- return mem_set_str0_static(context->pOut, "number");
- if ((argv[0].flags & MEM_Scalar) != 0)
- return mem_set_str0_static(context->pOut, "scalar");
- switch (argv[0].type) {
- case MEM_TYPE_INT:
- case MEM_TYPE_UINT:
- z = "integer";
- break;
- case MEM_TYPE_DEC:
- z = "decimal";
- break;
- case MEM_TYPE_STR:
- z = "string";
- break;
- case MEM_TYPE_DOUBLE:
- z = "double";
- break;
- case MEM_TYPE_BIN:
- case MEM_TYPE_ARRAY:
- case MEM_TYPE_MAP:
- z = "varbinary";
- break;
- case MEM_TYPE_BOOL:
- z = "boolean";
- break;
- case MEM_TYPE_NULL:
- z = "NULL";
- break;
- case MEM_TYPE_UUID:
- z = "uuid";
- break;
- default:
- unreachable();
- break;
- }
- sql_result_text(context, z, -1, SQL_STATIC);
-}
-
/*
* Implementation of the round() function
*/
@@ -1956,7 +1918,7 @@ static struct sql_func_definition definitions[] = {
{FIELD_TYPE_VARBINARY, FIELD_TYPE_INTEGER, FIELD_TYPE_VARBINARY},
FIELD_TYPE_VARBINARY, func_trim_bin, NULL},
- {"TYPEOF", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, typeofFunc, NULL},
+ {"TYPEOF", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, func_typeof, NULL},
{"UNICODE", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, unicodeFunc,
NULL},
{"UNLIKELY", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_BOOLEAN, sql_builtin_stub,
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 10/21] sql: refactor ROUND() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (8 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 09/21] sql: refactor TYPEOF() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 11/21] sql: refactor ROW_COUNT() function Mergen Imeev via Tarantool-patches
` (11 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 75 +++++++++++++++++-----------------------------
1 file changed, 28 insertions(+), 47 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 3a788b450..c5428d87b 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -962,6 +962,32 @@ func_typeof(struct sql_context *ctx, int argc, struct Mem *argv)
return mem_set_str0_static(ctx->pOut, mem_type_to_str(&argv[0]));
}
+/** Implementation of the ROUND() function. */
+static void
+func_round(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1 || argc == 2);
+ if (mem_is_null(&argv[0]) || (argc == 2 && mem_is_null(&argv[1])))
+ return;
+ assert(mem_is_double(&argv[0]));
+ assert(argc == 1 || mem_is_int(&argv[1]));
+ uint64_t n = (argc == 2 && mem_is_uint(&argv[1])) ? argv[1].u.u : 0;
+
+ double d = argv[0].u.r;
+ struct Mem *res = ctx->pOut;
+ if (n != 0)
+ return mem_set_double(res, atof(tt_sprintf("%.*f", n, d)));
+ /*
+ * DOUBLE values greater than 2^53 or less than -2^53 have no digits
+ * after the decimal point.
+ */
+ assert(9007199254740992 == (int64_t)1 << 53);
+ if (d <= -9007199254740992.0 || d >= 9007199254740992.0)
+ return mem_set_double(res, d);
+ double delta = d < 0 ? -0.5 : 0.5;
+ return mem_set_double(res, (double)(int64_t)(d + delta));
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1009,51 +1035,6 @@ sql_func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_uuid(ctx->pOut, &uuid);
}
-/*
- * Implementation of the round() function
- */
-static void
-roundFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- int64_t n = 0;
- double r;
- if (argc != 1 && argc != 2) {
- diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ROUND",
- "1 or 2", argc);
- context->is_aborted = true;
- return;
- }
- if (argc == 2) {
- if (mem_is_null(&argv[1]))
- return;
- n = mem_get_int_unsafe(&argv[1]);
- if (n < 0)
- n = 0;
- }
- if (mem_is_null(&argv[0]))
- return;
- if (!mem_is_num(&argv[0]) && !mem_is_str(&argv[0])) {
- diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
- mem_str(&argv[0]), "number");
- context->is_aborted = true;
- return;
- }
- r = mem_get_double_unsafe(&argv[0]);
- /* If Y==0 and X will fit in a 64-bit int,
- * handle the rounding directly,
- * otherwise use printf.
- */
- if (n == 0 && r >= 0 && r < (double)(LARGEST_INT64 - 1)) {
- r = (double)((sql_int64) (r + 0.5));
- } else if (n == 0 && r < 0 && (-r) < (double)(LARGEST_INT64 - 1)) {
- r = -(double)((sql_int64) ((-r) + 0.5));
- } else {
- const char *rounded_value = tt_sprintf("%.*f", n, r);
- sqlAtoF(rounded_value, &r, sqlStrlen30(rounded_value));
- }
- sql_result_double(context, r);
-}
-
/*
* Allocate nByte bytes of space using sqlMalloc(). If the
* allocation fails, return NULL. If nByte is larger than the
@@ -1885,9 +1866,9 @@ static struct sql_func_definition definitions[] = {
{"REPLACE", 3,
{FIELD_TYPE_VARBINARY, FIELD_TYPE_VARBINARY, FIELD_TYPE_VARBINARY},
FIELD_TYPE_VARBINARY, replaceFunc, NULL},
- {"ROUND", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, roundFunc, NULL},
+ {"ROUND", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, func_round, NULL},
{"ROUND", 2, {FIELD_TYPE_DOUBLE, FIELD_TYPE_INTEGER}, FIELD_TYPE_DOUBLE,
- roundFunc, NULL},
+ func_round, NULL},
{"ROW_COUNT", 0, {}, FIELD_TYPE_INTEGER, sql_row_count, NULL},
{"SOUNDEX", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING, soundexFunc,
NULL},
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 11/21] sql: refactor ROW_COUNT() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (9 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 10/21] sql: refactor ROUND() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 12/21] sql: rework UUID() function Mergen Imeev via Tarantool-patches
` (10 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 12 +++++++++++-
src/box/sql/main.c | 10 ----------
src/box/sql/sqlInt.h | 8 +-------
3 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index c5428d87b..014fd9af2 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -988,6 +988,16 @@ func_round(struct sql_context *ctx, int argc, struct Mem *argv)
return mem_set_double(res, (double)(int64_t)(d + delta));
}
+/** Implementation of the ROW_COUNT() function. */
+static void
+func_row_count(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ (void)argc;
+ (void)argv;
+ assert(sql_get()->nChange >= 0);
+ return mem_set_uint(ctx->pOut, sql_get()->nChange);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1869,7 +1879,7 @@ static struct sql_func_definition definitions[] = {
{"ROUND", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, func_round, NULL},
{"ROUND", 2, {FIELD_TYPE_DOUBLE, FIELD_TYPE_INTEGER}, FIELD_TYPE_DOUBLE,
func_round, NULL},
- {"ROW_COUNT", 0, {}, FIELD_TYPE_INTEGER, sql_row_count, NULL},
+ {"ROW_COUNT", 0, {}, FIELD_TYPE_INTEGER, func_row_count, NULL},
{"SOUNDEX", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING, soundexFunc,
NULL},
{"SUBSTR", 2, {FIELD_TYPE_STRING, FIELD_TYPE_INTEGER},
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index a4247c760..ae872aaa1 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -220,16 +220,6 @@ setupLookaside(sql * db, void *pBuf, int sz, int cnt)
return 0;
}
-void
-sql_row_count(struct sql_context *context, int argc, struct Mem *argv)
-{
- (void)argc;
- (void)argv;
- sql *db = sql_context_db_handle(context);
- assert(db->nChange >= 0);
- sql_result_uint(context, db->nChange);
-}
-
/*
* Close all open savepoints.
* This procedure is trivial as savepoints are allocated on the "region" and
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 9361775b1..c8f711ed2 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -470,12 +470,6 @@ enum sql_subtype {
void
sql_randomness(int N, void *P);
-/**
- * Return the number of affected rows in the last SQL statement.
- */
-void
-sql_row_count(struct sql_context *context, int argc, struct Mem *argv);
-
int
sql_column_count(sql_stmt * pStmt);
@@ -1065,7 +1059,7 @@ struct sql {
u8 dfltLockMode; /* Default locking-mode for attached dbs */
u8 mTrace; /* zero or more sql_TRACE flags */
u32 magic; /* Magic number for detect library misuse */
- /** Value returned by sql_row_count(). */
+ /** Value returned by ROW_COUNT(). */
int nChange;
int aLimit[SQL_N_LIMIT]; /* Limits */
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 12/21] sql: rework UUID() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (10 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 11/21] sql: refactor ROW_COUNT() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 13/21] sql: refactor VERSION() function Mergen Imeev via Tarantool-patches
` (9 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
This patch refactors UUID() function. Also, UUID(NULL) now returns NULL.
Part of #4145
---
src/box/sql/func.c | 56 +++++++++++++++++---------------------
test/sql-tap/uuid.test.lua | 11 +++++++-
2 files changed, 35 insertions(+), 32 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 014fd9af2..dcd0157d0 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -998,6 +998,29 @@ func_row_count(struct sql_context *ctx, int argc, struct Mem *argv)
return mem_set_uint(ctx->pOut, sql_get()->nChange);
}
+/**
+ * Implementation of the UUID() function.
+ *
+ * Returns a randomly generated UUID value.
+ */
+static void
+func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ if (argc == 1) {
+ if (mem_is_null(&argv[0]))
+ return;
+ if (!mem_is_uint(&argv[0]) || argv[0].u.u != 4) {
+ diag_set(ClientError, ER_UNSUPPORTED, "Function UUID",
+ "versions other than 4");
+ ctx->is_aborted = true;
+ return;
+ }
+ }
+ struct tt_uuid uuid;
+ tt_uuid_create(&uuid);
+ mem_set_uuid(ctx->pOut, &uuid);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1016,35 +1039,6 @@ mem_as_bin(struct Mem *mem)
return s;
}
-static void
-sql_func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
-{
- if (argc > 1) {
- diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "UUID",
- "one or zero", argc);
- ctx->is_aborted = true;
- return;
- }
- if (argc == 1) {
- uint64_t version;
- if (mem_get_uint(&argv[0], &version) != 0) {
- diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
- mem_str(&argv[0]), "integer");
- ctx->is_aborted = true;
- return;
- }
- if (version != 4) {
- diag_set(ClientError, ER_UNSUPPORTED, "Function UUID",
- "versions other than 4");
- ctx->is_aborted = true;
- return;
- }
- }
- struct tt_uuid uuid;
- tt_uuid_create(&uuid);
- mem_set_uuid(ctx->pOut, &uuid);
-}
-
/*
* Allocate nByte bytes of space using sqlMalloc(). If the
* allocation fails, return NULL. If nByte is larger than the
@@ -1916,8 +1910,8 @@ static struct sql_func_definition definitions[] = {
NULL},
{"UPPER", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_STRING, func_lower_upper,
NULL},
- {"UUID", 0, {}, FIELD_TYPE_UUID, sql_func_uuid, NULL},
- {"UUID", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_UUID, sql_func_uuid, NULL},
+ {"UUID", 0, {}, FIELD_TYPE_UUID, func_uuid, NULL},
+ {"UUID", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_UUID, func_uuid, NULL},
{"VERSION", 0, {}, FIELD_TYPE_STRING, sql_func_version, NULL},
{"ZEROBLOB", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY,
func_zeroblob, NULL},
diff --git a/test/sql-tap/uuid.test.lua b/test/sql-tap/uuid.test.lua
index d6c53d123..884b1daf9 100755
--- a/test/sql-tap/uuid.test.lua
+++ b/test/sql-tap/uuid.test.lua
@@ -3,7 +3,7 @@ local build_path = os.getenv("BUILDDIR")
package.cpath = build_path..'/test/sql-tap/?.so;'..build_path..'/test/sql-tap/?.dylib;'..package.cpath
local test = require("sqltester")
-test:plan(146)
+test:plan(147)
local uuid = require("uuid")
local uuid1 = uuid.fromstr("11111111-1111-1111-1111-111111111111")
@@ -1290,6 +1290,15 @@ test:do_execsql_test(
true
})
+-- Make sure the uuid(NULL) returns NULL.
+test:do_execsql_test(
+ "uuid-16.7",
+ [[
+ SELECT uuid(NULL) IS NULL;
+ ]], {
+ true
+ })
+
-- Make sure STRING of wrong length cannot be cast to UUID.
test:do_catchsql_test(
"uuid-17.1",
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 13/21] sql: refactor VERSION() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (11 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 12/21] sql: rework UUID() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 14/21] sql: refactor UNICODE() function Mergen Imeev via Tarantool-patches
` (8 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 27 ++++++++++-----------------
1 file changed, 10 insertions(+), 17 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index dcd0157d0..59447df56 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1021,6 +1021,15 @@ func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_uuid(ctx->pOut, &uuid);
}
+/** Implementation of the VERSION() function. */
+static void
+func_version(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ (void)argc;
+ (void)argv;
+ return mem_set_str0_static(ctx->pOut, (char *)tarantool_version());
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1346,22 +1355,6 @@ likeFunc(sql_context *context, int argc, struct Mem *argv)
mem_set_bool(context->pOut, res == MATCH);
}
-/**
- * Implementation of the version() function. The result is the
- * version of the Tarantool that is running.
- *
- * @param context Context being used.
- * @param unused1 Unused.
- * @param unused2 Unused.
- */
-static void
-sql_func_version(struct sql_context *context, int argc, struct Mem *argv)
-{
- (void)argc;
- (void)argv;
- sql_result_text(context, tarantool_version(), -1, SQL_STATIC);
-}
-
/*
* Implementation of the QUOTE() function. This function takes a single
* argument. If the argument is numeric, the return value is the same as
@@ -1912,7 +1905,7 @@ static struct sql_func_definition definitions[] = {
NULL},
{"UUID", 0, {}, FIELD_TYPE_UUID, func_uuid, NULL},
{"UUID", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_UUID, func_uuid, NULL},
- {"VERSION", 0, {}, FIELD_TYPE_STRING, sql_func_version, NULL},
+ {"VERSION", 0, {}, FIELD_TYPE_STRING, func_version, NULL},
{"ZEROBLOB", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY,
func_zeroblob, NULL},
};
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 14/21] sql: refactor UNICODE() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (12 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 13/21] sql: refactor VERSION() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 15/21] sql: refactor SOUNDEX() function Mergen Imeev via Tarantool-patches
` (7 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 59447df56..69d4e7347 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1030,6 +1030,30 @@ func_version(struct sql_context *ctx, int argc, struct Mem *argv)
return mem_set_str0_static(ctx->pOut, (char *)tarantool_version());
}
+/**
+ * Implementation of the UNICODE() function.
+ *
+ * Return the Unicode code point value for the first character of the input
+ * string.
+ */
+static void
+func_unicode(struct sql_context *ctx, int argc, struct Mem *argv)
+{
+ assert(argc == 1);
+ (void)argc;
+ struct Mem *arg = &argv[0];
+ if (mem_is_null(arg))
+ return;
+ assert(mem_is_str(arg));
+ if (arg->n == 0)
+ return mem_set_uint(ctx->pOut, 0);
+ int pos = 0;
+ UChar32 c;
+ U8_NEXT((uint8_t *)arg->z, pos, arg->n, c);
+ (void)pos;
+ mem_set_uint(ctx->pOut, (uint64_t)c);
+}
+
static const unsigned char *
mem_as_ustr(struct Mem *mem)
{
@@ -1451,19 +1475,6 @@ quoteFunc(struct sql_context *context, int argc, struct Mem *argv)
}
}
-/*
- * The unicode() function. Return the integer unicode code-point value
- * for the first character of the input string.
- */
-static void
-unicodeFunc(struct sql_context *context, int argc, struct Mem *argv)
-{
- const unsigned char *z = mem_as_ustr(&argv[0]);
- (void)argc;
- if (z && z[0])
- sql_result_uint(context, sqlUtf8Read(&z));
-}
-
/*
* The replace() function. Three arguments are all strings: call
* them A, B, and C. The result is also a string which is derived
@@ -1897,7 +1908,7 @@ static struct sql_func_definition definitions[] = {
FIELD_TYPE_VARBINARY, func_trim_bin, NULL},
{"TYPEOF", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_STRING, func_typeof, NULL},
- {"UNICODE", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, unicodeFunc,
+ {"UNICODE", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, func_unicode,
NULL},
{"UNLIKELY", 1, {FIELD_TYPE_ANY}, FIELD_TYPE_BOOLEAN, sql_builtin_stub,
NULL},
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 15/21] sql: refactor SOUNDEX() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (13 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 14/21] sql: refactor UNICODE() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 16/21] sql: refactor REPLACE() function Mergen Imeev via Tarantool-patches
` (6 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 69d4e7347..ed4d681fc 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1591,16 +1591,11 @@ soundexFunc(struct sql_context *context, int argc, struct Mem *argv)
1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
};
assert(argc == 1);
- if (mem_is_bin(&argv[0]) || mem_is_map(&argv[0]) ||
- mem_is_array(&argv[0])) {
- diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
- mem_str(&argv[0]), "string");
- context->is_aborted = true;
- return;
- }
- zIn = (u8 *) mem_as_ustr(&argv[0]);
- if (zIn == 0)
+ assert(mem_is_null(&argv[0]) || mem_is_str(&argv[0]));
+ if (mem_is_null(&argv[0]) || argv[0].n == 0)
zIn = (u8 *) "";
+ else
+ zIn = (unsigned char *)argv[0].z;
for (i = 0; zIn[i] && !sqlIsalpha(zIn[i]); i++) {
}
if (zIn[i]) {
@@ -1621,12 +1616,10 @@ soundexFunc(struct sql_context *context, int argc, struct Mem *argv)
zResult[j++] = '0';
}
zResult[j] = 0;
- sql_result_text(context, zResult, 4, SQL_TRANSIENT);
+ if (mem_copy_str(context->pOut, zResult, 4) != 0)
+ context->is_aborted = true;
} else {
- /* IMP: R-64894-50321 The string "?000" is returned if the argument
- * is NULL or contains no ASCII alphabetic characters.
- */
- sql_result_text(context, "?000", 4, SQL_STATIC);
+ mem_set_str_static(context->pOut, "?000", 4);
}
}
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 16/21] sql: refactor REPLACE() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (14 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 15/21] sql: refactor SOUNDEX() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 17/21] sql: refactor QUOTE() function Mergen Imeev via Tarantool-patches
` (5 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Part of #4145
---
src/box/sql/func.c | 59 +++++++++++++++++-----------------------------
1 file changed, 21 insertions(+), 38 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index ed4d681fc..3b1e62ebf 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1496,34 +1496,27 @@ replaceFunc(struct sql_context *context, int argc, struct Mem *argv)
int i, j; /* Loop counters */
assert(argc == 3);
- UNUSED_PARAMETER(argc);
- zStr = mem_as_ustr(&argv[0]);
- if (zStr == 0)
- return;
- 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) {
- assert(mem_is_null(&argv[1])
- || sql_context_db_handle(context)->mallocFailed);
+ (void)argc;
+ if (mem_is_any_null(&argv[0], &argv[1]) || mem_is_null(&argv[2]))
return;
- }
- nPattern = mem_len_unsafe(&argv[1]);
+ assert(mem_is_bytes(&argv[0]) && mem_is_bytes(&argv[1]) &&
+ mem_is_bytes(&argv[2]));
+ zStr = (const unsigned char *)argv[0].z;
+ nStr = argv[0].n;
+ zPattern = (const unsigned char *)argv[1].z;
+ nPattern = argv[1].n;
if (nPattern == 0) {
- assert(!mem_is_null(&argv[1]));
- sql_result_value(context, &argv[0]);
+ if (mem_copy(context->pOut, &argv[0]) != 0)
+ context->is_aborted = true;
return;
}
- assert(zPattern == mem_as_ustr(&argv[1])); /* No encoding change */
- zRep = mem_as_ustr(&argv[2]);
- if (zRep == 0)
- return;
- nRep = mem_len_unsafe(&argv[2]);
- assert(zRep == mem_as_ustr(&argv[2]));
+ zRep = (const unsigned char *)argv[2].z;
+ nRep = argv[2].n;
nOut = nStr + 1;
- assert(nOut < SQL_MAX_LENGTH);
- zOut = contextMalloc(context, (i64) nOut);
- if (zOut == 0) {
+ struct sql *db = sql_get();
+ zOut = sqlDbMallocRawNN(db, nOut);
+ if (zOut == NULL) {
+ context->is_aborted = true;
return;
}
loopLimit = nStr - nPattern;
@@ -1533,22 +1526,12 @@ replaceFunc(struct sql_context *context, int argc, struct Mem *argv)
zOut[j++] = zStr[i];
} else {
u8 *zOld;
- sql *db = sql_context_db_handle(context);
nOut += nRep - nPattern;
- testcase(nOut - 1 == db->aLimit[SQL_LIMIT_LENGTH]);
- testcase(nOut - 2 == db->aLimit[SQL_LIMIT_LENGTH]);
- if (nOut - 1 > db->aLimit[SQL_LIMIT_LENGTH]) {
- diag_set(ClientError, ER_SQL_EXECUTE, "string "\
- "or binary string is too big");
- context->is_aborted = true;
- sql_free(zOut);
- return;
- }
zOld = zOut;
- zOut = sql_realloc64(zOut, (int)nOut);
- if (zOut == 0) {
+ zOut = sqlDbRealloc(db, zOut, nOut);
+ if (zOut == NULL) {
context->is_aborted = true;
- sql_free(zOld);
+ sqlDbFree(db, zOld);
return;
}
memcpy(&zOut[j], zRep, nRep);
@@ -1562,9 +1545,9 @@ replaceFunc(struct sql_context *context, int argc, struct Mem *argv)
assert(j <= nOut);
zOut[j] = 0;
if (context->func->def->returns == FIELD_TYPE_STRING)
- mem_set_str_dynamic(context->pOut, (char *)zOut, j);
+ mem_set_str_allocated(context->pOut, (char *)zOut, j);
else
- mem_set_bin_dynamic(context->pOut, (char *)zOut, j);
+ mem_set_bin_allocated(context->pOut, (char *)zOut, j);
}
/*
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 17/21] sql: refactor QUOTE() function
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (15 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 16/21] sql: refactor REPLACE() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 18/21] sql: remove unused code Mergen Imeev via Tarantool-patches
` (4 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
---
src/box/sql/func.c | 154 +++++++++++++++------------------------------
1 file changed, 50 insertions(+), 104 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 3b1e62ebf..a0e599b5e 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -1054,50 +1054,6 @@ func_unicode(struct sql_context *ctx, int argc, struct Mem *argv)
mem_set_uint(ctx->pOut, (uint64_t)c);
}
-static const unsigned char *
-mem_as_ustr(struct Mem *mem)
-{
- return (const unsigned char *)mem_as_str0(mem);
-}
-
-static const void *
-mem_as_bin(struct Mem *mem)
-{
- const char *s;
- if (mem_cast_explicit(mem, FIELD_TYPE_VARBINARY) != 0 &&
- mem_to_str(mem) != 0)
- return NULL;
- if (mem_get_bin(mem, &s) != 0)
- return NULL;
- return s;
-}
-
-/*
- * Allocate nByte bytes of space using sqlMalloc(). If the
- * allocation fails, return NULL. If nByte is larger than the
- * maximum string or blob length, then raise an error and return
- * NULL.
- */
-static void *
-contextMalloc(struct sql_context *context, i64 nByte)
-{
- char *z;
- sql *db = sql_context_db_handle(context);
- assert(nByte > 0);
- testcase(nByte == db->aLimit[SQL_LIMIT_LENGTH]);
- testcase(nByte == db->aLimit[SQL_LIMIT_LENGTH] + 1);
- if (nByte > db->aLimit[SQL_LIMIT_LENGTH]) {
- diag_set(ClientError, ER_SQL_EXECUTE, "string or blob too big");
- context->is_aborted = true;
- z = 0;
- } else {
- z = sqlMalloc(nByte);
- if (z == NULL)
- context->is_aborted = true;
- }
- return z;
-}
-
#define Utf8Read(s, e) \
ucnv_getNextUChar(icu_utf8_conv, &(s), (e), &status)
@@ -1395,83 +1351,73 @@ quoteFunc(struct sql_context *context, int argc, struct Mem *argv)
case MEM_TYPE_UUID: {
char buf[UUID_STR_LEN + 1];
tt_uuid_to_string(&argv[0].u.uuid, &buf[0]);
- sql_result_text(context, buf, UUID_STR_LEN, SQL_TRANSIENT);
+ if (mem_copy_str(context->pOut, buf, UUID_STR_LEN) != 0)
+ context->is_aborted = true;
break;
}
case MEM_TYPE_DOUBLE:
case MEM_TYPE_DEC:
case MEM_TYPE_UINT:
case MEM_TYPE_INT: {
- sql_result_value(context, &argv[0]);
- break;
- }
+ if (mem_copy(context->pOut, &argv[0]) != 0)
+ context->is_aborted = true;
+ break;
+ }
case MEM_TYPE_BIN:
case MEM_TYPE_ARRAY:
case MEM_TYPE_MAP: {
- char *zText = 0;
- char const *zBlob = mem_as_bin(&argv[0]);
- int nBlob = mem_len_unsafe(&argv[0]);
- assert(zBlob == mem_as_bin(&argv[0])); /* No encoding change */
- zText =
- (char *)contextMalloc(context,
- (2 * (i64) nBlob) + 4);
- if (zText) {
- int i;
- for (i = 0; i < nBlob; i++) {
- zText[(i * 2) + 2] =
- hexdigits[(zBlob[i] >> 4) & 0x0F];
- zText[(i * 2) + 3] =
- hexdigits[(zBlob[i]) & 0x0F];
- }
- zText[(nBlob * 2) + 2] = '\'';
- zText[(nBlob * 2) + 3] = '\0';
- zText[0] = 'X';
- zText[1] = '\'';
- sql_result_text(context, zText, -1,
- SQL_TRANSIENT);
- sql_free(zText);
- }
- break;
+ const char *zBlob = argv[0].z;
+ int nBlob = argv[0].n;
+ uint32_t size = 2 * nBlob + 3;
+ char *zText = zText = sqlDbMallocRawNN(sql_get(), size);
+ if (zText == NULL) {
+ context->is_aborted = true;
+ return;
}
+ for (int i = 0; i < nBlob; i++) {
+ zText[(i * 2) + 2] = hexdigits[(zBlob[i] >> 4) & 0x0F];
+ zText[(i * 2) + 3] = hexdigits[(zBlob[i]) & 0x0F];
+ }
+ zText[(nBlob * 2) + 2] = '\'';
+ zText[0] = 'X';
+ zText[1] = '\'';
+ mem_set_str_allocated(context->pOut, zText, size);
+ break;
+ }
case MEM_TYPE_STR: {
- int i, j;
- u64 n;
- const unsigned char *zArg = mem_as_ustr(&argv[0]);
- char *z;
+ const char *str = argv[0].z;
+ uint32_t len = argv[0].n;
+ uint32_t count = 0;
+ for (uint32_t i = 0; i < len; ++i) {
+ if (str[i] == '\'')
+ ++count;
+ }
+ uint32_t size = len + count + 2;
- if (zArg == 0)
- return;
- for (i = 0, n = 0; zArg[i]; i++) {
- if (zArg[i] == '\'')
- n++;
- }
- z = contextMalloc(context, ((i64) i) + ((i64) n) + 3);
- if (z) {
- z[0] = '\'';
- for (i = 0, j = 1; zArg[i]; i++) {
- z[j++] = zArg[i];
- if (zArg[i] == '\'') {
- z[j++] = '\'';
- }
- }
- z[j++] = '\'';
- z[j] = 0;
- sql_result_text(context, z, j,
- sql_free);
- }
- break;
+ char *res = sqlDbMallocRawNN(sql_get(), size);
+ if (res == NULL) {
+ context->is_aborted = true;
+ return;
+ }
+ res[0] = '\'';
+ for (uint32_t i = 0, j = 1; i < len; ++i) {
+ res[j++] = str[i];
+ if (str[i] == '\'')
+ res[j++] = '\'';
}
+ res[size - 1] = '\'';
+ mem_set_str_allocated(context->pOut, res, size);
+ break;
+ }
case MEM_TYPE_BOOL: {
- sql_result_text(context,
- SQL_TOKEN_BOOLEAN(argv[0].u.b),
- -1, SQL_TRANSIENT);
+ mem_set_str0_static(context->pOut,
+ SQL_TOKEN_BOOLEAN(argv[0].u.b));
break;
}
default:{
- assert(mem_is_null(&argv[0]));
- sql_result_text(context, "NULL", 4, SQL_STATIC);
- break;
- }
+ assert(mem_is_null(&argv[0]));
+ mem_set_str0_static(context->pOut, "NULL");
+ }
}
}
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 18/21] sql: remove unused code
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (16 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 17/21] sql: refactor QUOTE() function Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 19/21] sql: remove MEM_Dyn flag Mergen Imeev via Tarantool-patches
` (3 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
Some of the code is no longer used after changes in the SQL built-in
functions. This patch removes part of the unused code.
Needed for #4145
---
src/box/CMakeLists.txt | 1 -
src/box/bind.c | 5 +-
src/box/sql/mem.c | 11 --
src/box/sql/mem.h | 78 --------------
src/box/sql/sqlInt.h | 73 +------------
src/box/sql/trigger.c | 7 +-
src/box/sql/utf.c | 95 ----------------
src/box/sql/vdbe.h | 5 +-
src/box/sql/vdbeInt.h | 1 -
src/box/sql/vdbeapi.c | 238 +++--------------------------------------
src/box/sql/vdbeaux.c | 26 ++---
11 files changed, 33 insertions(+), 507 deletions(-)
delete mode 100644 src/box/sql/utf.c
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 957290bdd..17f1e60ba 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -55,7 +55,6 @@ set(sql_sources
sql/tokenize.c
sql/treeview.c
sql/trigger.c
- sql/utf.c
sql/update.c
sql/util.c
sql/vdbe.c
diff --git a/src/box/bind.c b/src/box/bind.c
index 58fff0b98..e75e36283 100644
--- a/src/box/bind.c
+++ b/src/box/bind.c
@@ -185,12 +185,11 @@ sql_bind_column(struct sql_stmt *stmt, const struct sql_bind *p,
* there is no need to copy the packet and we can
* use SQL_STATIC.
*/
- return sql_bind_text64(stmt, pos, p->s, p->bytes, SQL_STATIC);
+ return sql_bind_str_static(stmt, pos, p->s, p->bytes);
case MP_NIL:
return sql_bind_null(stmt, pos);
case MP_BIN:
- return sql_bind_blob64(stmt, pos, (const void *) p->s, p->bytes,
- SQL_STATIC);
+ return sql_bind_bin_static(stmt, pos, p->s, p->bytes);
case MP_EXT:
assert(p->ext_type == MP_UUID || p->ext_type == MP_DECIMAL);
if (p->ext_type == MP_UUID)
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index dc629aee3..70ca9e1b2 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -2638,17 +2638,6 @@ mem_mp_type(const struct Mem *mem)
return MP_NIL;
}
-/* EVIDENCE-OF: R-12793-43283 Every value in sql has one of five
- * fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
- * point number string BLOB NULL
- */
-enum mp_type
-sql_value_type(sql_value *pVal)
-{
- struct Mem *mem = (struct Mem *) pVal;
- return mem_mp_type(mem);
-}
-
#ifdef SQL_DEBUG
/*
* Check invariants on a Mem object.
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index 242f910db..9533833f2 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -359,54 +359,6 @@ mem_set_str0_dynamic(struct Mem *mem, char *value);
void
mem_set_str0_allocated(struct Mem *mem, char *value);
-static inline void
-mem_set_strl_ephemeral(struct Mem *mem, char *value, int len_hint)
-{
- if (len_hint < 0)
- mem_set_str0_ephemeral(mem, value);
- else
- mem_set_str_ephemeral(mem, value, len_hint);
-}
-
-static inline void
-mem_set_strl_static(struct Mem *mem, char *value, int len_hint)
-{
- if (len_hint < 0)
- mem_set_str0_static(mem, value);
- else
- mem_set_str_static(mem, value, len_hint);
-}
-
-static inline void
-mem_set_strl_dynamic(struct Mem *mem, char *value, int len_hint)
-{
- if (len_hint < 0)
- mem_set_str0_dynamic(mem, value);
- else
- mem_set_str_dynamic(mem, value, len_hint);
-}
-
-static inline void
-mem_set_strl_allocated(struct Mem *mem, char *value, int len_hint)
-{
- if (len_hint < 0)
- mem_set_str0_allocated(mem, value);
- else
- mem_set_str_allocated(mem, value, len_hint);
-}
-
-static inline void
-mem_set_strl(struct Mem *mem, char *value, int len_hint,
- void (*custom_free)(void *))
-{
- if (custom_free == SQL_STATIC)
- return mem_set_strl_static(mem, value, len_hint);
- if (custom_free == SQL_DYNAMIC)
- return mem_set_strl_allocated(mem, value, len_hint);
- if (custom_free != SQL_TRANSIENT)
- return mem_set_strl_dynamic(mem, value, len_hint);
-}
-
/** Copy string to a newly allocated memory. The MEM type becomes STRING. */
int
mem_copy_str(struct Mem *mem, const char *value, uint32_t len);
@@ -418,14 +370,6 @@ mem_copy_str(struct Mem *mem, const char *value, uint32_t len);
int
mem_copy_str0(struct Mem *mem, const char *value);
-static inline int
-mem_copy_strl(struct Mem *mem, const char *value, int len_hint)
-{
- if (len_hint < 0)
- return mem_copy_str0(mem, value);
- return mem_copy_str(mem, value, len_hint);
-}
-
/**
* Clear MEM and set it to VARBINARY. The binary value belongs to another
* object.
@@ -454,18 +398,6 @@ mem_set_bin_dynamic(struct Mem *mem, char *value, uint32_t size);
void
mem_set_bin_allocated(struct Mem *mem, char *value, uint32_t size);
-static inline void
-mem_set_binl(struct Mem *mem, char *value, uint32_t size,
- void (*custom_free)(void *))
-{
- if (custom_free == SQL_STATIC)
- return mem_set_bin_static(mem, value, size);
- if (custom_free == SQL_DYNAMIC)
- return mem_set_bin_allocated(mem, value, size);
- if (custom_free != SQL_TRANSIENT)
- return mem_set_bin_dynamic(mem, value, size);
-}
-
/**
* Copy binary value to a newly allocated memory. The MEM type becomes
* VARBINARY.
@@ -891,13 +823,6 @@ mem_len_unsafe(const struct Mem *mem)
return len;
}
-/**
- * Return address of memory allocated for accumulation structure of the
- * aggregate function.
- */
-int
-mem_get_agg(const struct Mem *mem, void **accum);
-
/**
* Simple type to str convertor. It is used to simplify
* error reporting.
@@ -913,9 +838,6 @@ mem_type_to_str(const struct Mem *p);
enum mp_type
mem_mp_type(const struct Mem *mem);
-enum mp_type
-sql_value_type(struct Mem *);
-
#ifdef SQL_DEBUG
int sqlVdbeCheckMemInvariants(struct Mem *);
void sqlVdbeMemPrettyPrint(Mem * pMem, char *zBuf);
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index c8f711ed2..22a4aa5cd 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -355,45 +355,6 @@ sql_stricmp(const char *, const char *);
int
sql_strnicmp(const char *, const char *, int);
-sql *
-sql_context_db_handle(sql_context *);
-
-
-void
-sql_result_blob(sql_context *, const void *,
- int, void (*)(void *));
-
-void
-sql_result_blob64(sql_context *, const void *,
- sql_uint64, void (*)(void *));
-
-void
-sql_result_double(sql_context *, double);
-
-void
-sql_result_uint(sql_context *ctx, uint64_t u_val);
-
-void
-sql_result_int(sql_context *ctx, int64_t val);
-
-void
-sql_result_bool(struct sql_context *ctx, bool value);
-
-void
-sql_result_null(sql_context *);
-
-void
-sql_result_text(sql_context *, const char *,
- int, void (*)(void *));
-
-void
-sql_result_text64(sql_context *, const char *,
- sql_uint64, void (*)(void *));
-
-void
-sql_result_value(sql_context *,
- sql_value *);
-
char *
sql_mprintf(const char *, ...);
char *
@@ -567,14 +528,6 @@ sql_vfs_register(sql_vfs *, int makeDflt);
void
sql_unbind(struct sql_stmt *stmt);
-int
-sql_bind_blob(sql_stmt *, int, const void *,
- int n, void (*)(void *));
-
-int
-sql_bind_blob64(sql_stmt *, int, const void *,
- sql_uint64, void (*)(void *));
-
int
sql_bind_double(sql_stmt *, int, double);
@@ -602,8 +555,10 @@ int
sql_bind_null(sql_stmt *, int);
int
-sql_bind_text64(sql_stmt *, int, const char *,
- sql_uint64, void (*)(void *));
+sql_bind_str_static(sql_stmt *stmt, int i, const char *str, uint32_t len);
+
+int
+sql_bind_bin_static(sql_stmt *stmt, int i, const char *str, uint32_t size);
int
sql_bind_uuid(struct sql_stmt *stmt, int i, const struct tt_uuid *uuid);
@@ -3697,26 +3652,6 @@ void sqlDetach(Parse *, Expr *);
int sqlAtoF(const char *z, double *, int);
int sqlGetInt32(const char *, int *);
-/**
- * Return number of symbols in the given string.
- *
- * Number of symbols != byte size of string because some symbols
- * are encoded with more than one byte. Also note that all
- * symbols from 'str' to 'str + byte_len' would be counted,
- * even if there is a '\0' somewhere between them.
- *
- * This function is implemented to be fast and indifferent to
- * correctness of string being processed. If input string has
- * even one invalid utf-8 sequence, then the resulting length
- * could be arbitary in these boundaries (0 < len < byte_len).
- * @param str String to be counted.
- * @param byte_len Byte length of given string.
- * @return number of symbols in the given string.
- */
-int
-sql_utf8_char_count(const unsigned char *str, int byte_len);
-
-u32 sqlUtf8Read(const u8 **);
LogEst sqlLogEst(u64);
LogEst sqlLogEstAdd(LogEst, LogEst);
u64 sqlLogEstToInt(LogEst);
diff --git a/src/box/sql/trigger.c b/src/box/sql/trigger.c
index 7c983fea5..fbd159126 100644
--- a/src/box/sql/trigger.c
+++ b/src/box/sql/trigger.c
@@ -805,11 +805,8 @@ sql_row_trigger_program(struct Parse *parser, struct sql_trigger *trigger,
if (!parser->is_aborted)
parser->is_aborted = pSubParse->is_aborted;
- if (db->mallocFailed == 0) {
- pProgram->aOp =
- sqlVdbeTakeOpArray(v, &pProgram->nOp,
- &pTop->nMaxArg);
- }
+ if (db->mallocFailed == 0)
+ pProgram->aOp = sqlVdbeTakeOpArray(v, &pProgram->nOp);
pProgram->nMem = pSubParse->nMem;
pProgram->nCsr = pSubParse->nTab;
pProgram->token = (void *)trigger;
diff --git a/src/box/sql/utf.c b/src/box/sql/utf.c
deleted file mode 100644
index 2d9a12806..000000000
--- a/src/box/sql/utf.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2010-2017, Tarantool AUTHORS, please see AUTHORS file.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * This file contains routines used to translate between UTF-8.
- *
- * Notes on UTF-8:
- *
- * Byte-0 Byte-1 Byte-2 Byte-3 Value
- * 0xxxxxxx 00000000 00000000 0xxxxxxx
- * 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
- * 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
- * 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
- *
- *
- */
-#include "sqlInt.h"
-
-/*
- * This lookup table is used to help decode the first byte of
- * a multi-byte UTF8 character.
- */
-static const unsigned char sqlUtf8Trans1[] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
-};
-
-u32
-sqlUtf8Read(const unsigned char **pz /* Pointer to string from which to read char */
- )
-{
- unsigned int c;
-
- /* Same as READ_UTF8() above but without the zTerm parameter.
- * For this routine, we assume the UTF8 string is always zero-terminated.
- */
- c = *((*pz)++);
- if (c >= 0xc0) {
- c = sqlUtf8Trans1[c - 0xc0];
- while ((*(*pz) & 0xc0) == 0x80) {
- c = (c << 6) + (0x3f & *((*pz)++));
- }
- if (c < 0x80
- || (c & 0xFFFFF800) == 0xD800
- || (c & 0xFFFFFFFE) == 0xFFFE) {
- c = 0xFFFD;
- }
- }
- return c;
-}
-
-int
-sql_utf8_char_count(const unsigned char *str, int byte_len)
-{
- int symbol_count = 0;
- for (int i = 0; i < byte_len;) {
- SQL_UTF8_FWD_1(str, i, byte_len);
- symbol_count++;
- }
- return symbol_count;
-}
diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h
index 121b86029..106555bb1 100644
--- a/src/box/sql/vdbe.h
+++ b/src/box/sql/vdbe.h
@@ -264,7 +264,10 @@ void sqlVdbeCountChanges(Vdbe *);
sql *sqlVdbeDb(Vdbe *);
void sqlVdbeSetSql(Vdbe *, const char *z, int n);
void sqlVdbeSwap(Vdbe *, Vdbe *);
-VdbeOp *sqlVdbeTakeOpArray(Vdbe *, int *, int *);
+
+struct VdbeOp *
+sqlVdbeTakeOpArray(struct Vdbe *p, int *pnOp);
+
sql_value *sqlVdbeGetBoundValue(Vdbe *, int);
char *sqlVdbeExpandSql(Vdbe *, const char *);
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 8dbba4908..c45cc9301 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -262,7 +262,6 @@ struct Vdbe {
Op *aOp; /* Space to hold the virtual machine's program */
Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
/** SQL metadata for DML/DQL queries. */
struct sql_column_metadata *metadata;
Mem *pResultSet; /* Pointer to an array of results */
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index 486f797fb..3894bb943 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -107,135 +107,6 @@ sql_metadata_is_full()
return current_session()->sql_flags & SQL_FullMetadata;
}
-/**************************** sql_result_ ******************************
- * The following routines are used by user-defined functions to specify
- * the function result.
- *
- * The setStrOrError() function sets the result as a string or blob but
- * if the string or blob is too large, it then sets the error code.
- *
- * The invokeValueDestructor(P,X) routine invokes destructor function X()
- * on value P is not going to be used and need to be destroyed.
- */
-static void
-setResultStrOrError(sql_context * pCtx, /* Function context */
- const char *z, /* String pointer */
- int n, /* Bytes in string, or negative */
- void (*xDel) (void *) /* Destructor function */
- )
-{
- if (xDel != SQL_TRANSIENT)
- return mem_set_strl(pCtx->pOut, (char *)z, n, xDel);
- if (mem_copy_strl(pCtx->pOut, z, n) != 0)
- pCtx->is_aborted = true;
-}
-
-static int
-invokeValueDestructor(const void *p, /* Value to destroy */
- void (*xDel) (void *), /* The destructor */
- sql_context *pCtx /* Set an error if no NULL */
- )
-{
- assert(xDel != SQL_DYNAMIC);
- if (xDel == 0) {
- /* noop */
- } else if (xDel == SQL_TRANSIENT) {
- /* noop */
- } else {
- xDel((void *)p);
- }
- if (pCtx) {
- diag_set(ClientError, ER_SQL_EXECUTE, "string or binary string"\
- "is too big");
- pCtx->is_aborted = true;
- }
- return -1;
-}
-
-void
-sql_result_blob(sql_context * pCtx,
- const void *z, int n, void (*xDel) (void *)
- )
-{
- assert(n >= 0);
- if (xDel != SQL_TRANSIENT)
- mem_set_binl(pCtx->pOut, (char *)z, n, xDel);
- else if (mem_copy_bin(pCtx->pOut, z, n) != 0)
- pCtx->is_aborted = true;
-}
-
-void
-sql_result_blob64(sql_context * pCtx,
- const void *z, sql_uint64 n, void (*xDel) (void *)
- )
-{
- assert(xDel != SQL_DYNAMIC);
- if (n > 0x7fffffff) {
- (void)invokeValueDestructor(z, xDel, pCtx);
- } else {
- setResultStrOrError(pCtx, z, (int)n, xDel);
- }
-}
-
-void
-sql_result_double(sql_context * pCtx, double rVal)
-{
- mem_set_double(pCtx->pOut, rVal);
-}
-
-void
-sql_result_uint(sql_context *ctx, uint64_t u_val)
-{
- mem_set_uint(ctx->pOut, u_val);
-}
-
-void
-sql_result_int(sql_context *ctx, int64_t val)
-{
- mem_set_int(ctx->pOut, val, val < 0);
-}
-
-void
-sql_result_bool(struct sql_context *ctx, bool value)
-{
- mem_set_bool(ctx->pOut, value);
-}
-
-void
-sql_result_null(sql_context * pCtx)
-{
- mem_set_null(pCtx->pOut);
-}
-
-void
-sql_result_text(sql_context * pCtx,
- const char *z, int n, void (*xDel) (void *)
- )
-{
- setResultStrOrError(pCtx, z, n, xDel);
-}
-
-void
-sql_result_text64(sql_context * pCtx,
- const char *z,
- sql_uint64 n,
- void (*xDel) (void *))
-{
- assert(xDel != SQL_DYNAMIC);
- if (n > 0x7fffffff) {
- (void)invokeValueDestructor(z, xDel, pCtx);
- } else {
- setResultStrOrError(pCtx, z, (int)n, xDel);
- }
-}
-
-void
-sql_result_value(sql_context * pCtx, sql_value * pValue)
-{
- if (mem_copy(pCtx->pOut, pValue) != 0)
- pCtx->is_aborted = true;
-}
-
/*
* Execute the statement pStmt, either until a row of data is ready, the
* statement is completely executed or an error occurs.
@@ -313,23 +184,6 @@ sql_step(sql_stmt * pStmt)
return sqlStep(v);
}
-/*
- * Extract the user data from a sql_context structure and return a
- * pointer to it.
- *
- * IMPLEMENTATION-OF: R-46798-50301 The sql_context_db_handle() interface
- * returns a copy of the pointer to the database connection (the 1st
- * parameter) of the sql_create_function() and
- * sql_create_function16() routines that originally registered the
- * application defined function.
- */
-sql *
-sql_context_db_handle(sql_context * p)
-{
- assert(p && p->pOut);
- return p->pOut->db;
-}
-
/*
* Return the number of columns in the result set for the statement pStmt.
*/
@@ -582,73 +436,6 @@ sql_unbind(struct sql_stmt *stmt)
}
}
-/*
- * Bind a text or BLOB value.
- */
-static int
-bindText(sql_stmt * pStmt, /* The statement to bind against */
- int i, /* Index of the parameter to bind */
- const void *zData, /* Pointer to the data to be bound */
- int nData, /* Number of bytes of data to be bound */
- void (*xDel) (void *) /* Destructor for the data */
- )
-{
- Vdbe *p = (Vdbe *) pStmt;
- Mem *pVar;
- if (vdbeUnbind(p, i) != 0) {
- if (xDel != SQL_STATIC && xDel != SQL_TRANSIENT)
- xDel((void *)zData);
- return -1;
- }
- if (zData == NULL)
- return 0;
- pVar = &p->aVar[i - 1];
- if (xDel != SQL_TRANSIENT)
- mem_set_strl(pVar, (char *)zData, nData, xDel);
- else if (mem_copy_strl(pVar, zData, nData) != 0)
- return -1;
- return sql_bind_type(p, i, "text");
-}
-
-/*
- * Bind a blob value to an SQL statement variable.
- */
-int
-sql_bind_blob(sql_stmt * pStmt,
- int i, const void *zData, int nData, void (*xDel) (void *)
- )
-{
- struct Vdbe *p = (Vdbe *) pStmt;
- if (vdbeUnbind(p, i) != 0) {
- if (xDel != SQL_STATIC && xDel != SQL_TRANSIENT)
- xDel((void *)zData);
- return -1;
- }
- if (zData == NULL)
- return 0;
- struct Mem *var = &p->aVar[i - 1];
- if (xDel != SQL_TRANSIENT)
- mem_set_binl(var, (char *)zData, nData, xDel);
- else if (mem_copy_bin(var, zData, nData) != 0)
- return -1;
- return sql_bind_type(p, i, "varbinary");
-}
-
-int
-sql_bind_blob64(sql_stmt * pStmt,
- int i,
- const void *zData,
- sql_uint64 nData, void (*xDel) (void *)
- )
-{
- assert(xDel != SQL_DYNAMIC);
- if (nData > 0x7fffffff) {
- return invokeValueDestructor(zData, xDel, 0);
- } else {
- return sql_bind_blob(pStmt, i, zData, (int)nData, xDel);
- }
-}
-
int
sql_bind_double(sql_stmt * pStmt, int i, double rValue)
{
@@ -722,18 +509,19 @@ sql_bind_ptr(struct sql_stmt *stmt, int i, void *ptr)
}
int
-sql_bind_text64(sql_stmt * pStmt,
- int i,
- const char *zData,
- sql_uint64 nData,
- void (*xDel) (void *))
-{
- assert(xDel != SQL_DYNAMIC);
- if (nData > 0x7fffffff) {
- return invokeValueDestructor(zData, xDel, 0);
- } else {
- return bindText(pStmt, i, zData, (int)nData, xDel);
- }
+sql_bind_str_static(sql_stmt *stmt, int i, const char *str, uint32_t len)
+{
+ struct Vdbe *vdbe = (struct Vdbe *)stmt;
+ mem_set_str_static(&vdbe->aVar[i - 1], (char *)str, len);
+ return sql_bind_type(vdbe, i, "text");
+}
+
+int
+sql_bind_bin_static(sql_stmt *stmt, int i, const char *str, uint32_t size)
+{
+ struct Vdbe *vdbe = (struct Vdbe *)stmt;
+ mem_set_bin_static(&vdbe->aVar[i - 1], (char *)str, size);
+ return sql_bind_type(vdbe, i, "text");
}
int
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 1a429e7f1..b71f65966 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -447,21 +447,17 @@ sqlVdbeRunOnlyOnce(Vdbe * p)
* (1) For each jump instruction with a negative P2 value (a label)
* resolve the P2 value to an actual address.
*
- * (2) Compute the maximum number of arguments used by any SQL function
- * and store that value in *pMaxFuncArgs.
+ * (2) Initialize the p4.xAdvance pointer on opcodes that use it.
*
- * (3) Initialize the p4.xAdvance pointer on opcodes that use it.
- *
- * (4) Reclaim the memory allocated for storing labels.
+ * (3) Reclaim the memory allocated for storing labels.
*
* This routine will only function correctly if the mkopcodeh.sh generator
* script numbers the opcodes correctly. Changes to this routine must be
* coordinated with changes to mkopcodeh.sh.
*/
static void
-resolveP2Values(Vdbe * p, int *pMaxFuncArgs)
+resolveP2Values(Vdbe * p)
{
- int nMaxArgs = *pMaxFuncArgs;
Op *pOp;
Parse *pParse = p->pParse;
int *aLabel = pParse->aLabel;
@@ -506,7 +502,6 @@ resolveP2Values(Vdbe * p, int *pMaxFuncArgs)
sqlDbFree(p->db, pParse->aLabel);
pParse->aLabel = 0;
pParse->nLabel = 0;
- *pMaxFuncArgs = nMaxArgs;
}
/*
@@ -526,17 +521,15 @@ sqlVdbeCurrentAddr(Vdbe * p)
* vdbeFreeOpArray() function.
*
* Before returning, *pnOp is set to the number of entries in the returned
- * array. Also, *pnMaxArg is set to the larger of its current value and
- * the number of entries in the Vdbe.apArg[] array required to execute the
- * returned program.
+ * array.
*/
-VdbeOp *
-sqlVdbeTakeOpArray(Vdbe * p, int *pnOp, int *pnMaxArg)
+struct VdbeOp *
+sqlVdbeTakeOpArray(struct Vdbe *p, int *pnOp)
{
VdbeOp *aOp = p->aOp;
assert(aOp && !p->db->mallocFailed);
- resolveP2Values(p, pnMaxArg);
+ resolveP2Values(p);
*pnOp = p->nOp;
p->aOp = 0;
return aOp;
@@ -1490,7 +1483,6 @@ sqlVdbeMakeReady(Vdbe * p, /* The VDBE */
int nVar; /* Number of parameters */
int nMem; /* Number of VM memory registers */
int nCursor; /* Number of cursors required */
- int nArg; /* Number of arguments in subprograms */
int n; /* Loop counter */
struct ReusableSpace x; /* Reusable bulk memory */
@@ -1504,7 +1496,6 @@ sqlVdbeMakeReady(Vdbe * p, /* The VDBE */
nVar = pParse->nVar;
nMem = pParse->nMem;
nCursor = pParse->nTab;
- nArg = pParse->nMaxArg;
/* Each cursor uses a memory cell. The first cursor (cursor 0) can
* use aMem[0] which is not otherwise used by the VDBE program. Allocate
@@ -1526,7 +1517,7 @@ sqlVdbeMakeReady(Vdbe * p, /* The VDBE */
assert(x.nFree >= 0);
assert(EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]));
- resolveP2Values(p, &nArg);
+ resolveP2Values(p);
if (pParse->explain && nMem < 10) {
nMem = 10;
}
@@ -1546,7 +1537,6 @@ sqlVdbeMakeReady(Vdbe * p, /* The VDBE */
x.nNeeded = 0;
p->aMem = allocSpace(&x, p->aMem, nMem * sizeof(Mem));
p->aVar = allocSpace(&x, p->aVar, nVar * sizeof(Mem));
- p->apArg = allocSpace(&x, p->apArg, nArg * sizeof(Mem *));
p->apCsr =
allocSpace(&x, p->apCsr, nCursor * sizeof(VdbeCursor *));
if (x.nNeeded == 0)
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 19/21] sql: remove MEM_Dyn flag
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (17 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 18/21] sql: remove unused code Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 20/21] sql: remove MEM_Term flag Mergen Imeev via Tarantool-patches
` (2 subsequent siblings)
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
This patch removes the MEM_Dyn flag, because after changes in the SQL
built-in functions, this flag is no longer used.
Needed for #4145
---
src/box/sql/mem.c | 110 +++++++------------------------------------
src/box/sql/mem.h | 56 +---------------------
src/box/sql/sqlInt.h | 14 ------
3 files changed, 18 insertions(+), 162 deletions(-)
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index 70ca9e1b2..4150a24f0 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -207,7 +207,6 @@ mem_create(struct Mem *mem)
mem->szMalloc = 0;
mem->uTemp = 0;
mem->db = sql_get();
- mem->xDel = NULL;
#ifdef SQL_DEBUG
mem->pScopyFrom = NULL;
mem->pFiller = NULL;
@@ -217,15 +216,10 @@ mem_create(struct Mem *mem)
static inline void
mem_clear(struct Mem *mem)
{
- if (mem->type == MEM_TYPE_FRAME || (mem->flags & MEM_Dyn) != 0) {
- if ((mem->flags & MEM_Dyn) != 0) {
- assert(mem->xDel != SQL_DYNAMIC && mem->xDel != NULL);
- mem->xDel((void *)mem->z);
- } else {
- struct VdbeFrame *frame = mem->u.pFrame;
- frame->pParent = frame->v->pDelFrame;
- frame->v->pDelFrame = frame;
- }
+ if (mem->type == MEM_TYPE_FRAME) {
+ struct VdbeFrame *frame = mem->u.pFrame;
+ frame->pParent = frame->v->pDelFrame;
+ frame->v->pDelFrame = frame;
}
mem->type = MEM_TYPE_NULL;
mem->flags = 0;
@@ -320,21 +314,14 @@ set_str_const(struct Mem *mem, char *value, uint32_t len, int alloc_type)
static inline void
set_str_dynamic(struct Mem *mem, char *value, uint32_t len, int alloc_type)
{
- assert((mem->flags & MEM_Dyn) == 0 || value != mem->z);
assert(mem->szMalloc == 0 || value != mem->zMalloc);
- assert(alloc_type == MEM_Dyn || alloc_type == 0);
mem_destroy(mem);
mem->z = value;
mem->n = len;
mem->type = MEM_TYPE_STR;
mem->flags = alloc_type;
- if (alloc_type == MEM_Dyn) {
- mem->xDel = sql_free;
- } else {
- mem->xDel = NULL;
- mem->zMalloc = mem->z;
- mem->szMalloc = sqlDbMallocSize(mem->db, mem->zMalloc);
- }
+ mem->zMalloc = mem->z;
+ mem->szMalloc = sqlDbMallocSize(mem->db, mem->zMalloc);
}
void
@@ -349,12 +336,6 @@ mem_set_str_static(struct Mem *mem, char *value, uint32_t len)
set_str_const(mem, value, len, MEM_Static);
}
-void
-mem_set_str_dynamic(struct Mem *mem, char *value, uint32_t len)
-{
- set_str_dynamic(mem, value, len, MEM_Dyn);
-}
-
void
mem_set_str_allocated(struct Mem *mem, char *value, uint32_t len)
{
@@ -375,13 +356,6 @@ mem_set_str0_static(struct Mem *mem, char *value)
mem->flags |= MEM_Term;
}
-void
-mem_set_str0_dynamic(struct Mem *mem, char *value)
-{
- set_str_dynamic(mem, value, strlen(value), MEM_Dyn);
- mem->flags |= MEM_Term;
-}
-
void
mem_set_str0_allocated(struct Mem *mem, char *value)
{
@@ -436,21 +410,14 @@ set_bin_const(struct Mem *mem, char *value, uint32_t size, int alloc_type)
static inline void
set_bin_dynamic(struct Mem *mem, char *value, uint32_t size, int alloc_type)
{
- assert((mem->flags & MEM_Dyn) == 0 || value != mem->z);
assert(mem->szMalloc == 0 || value != mem->zMalloc);
- assert(alloc_type == MEM_Dyn || alloc_type == 0);
mem_destroy(mem);
mem->z = value;
mem->n = size;
mem->type = MEM_TYPE_BIN;
mem->flags = alloc_type;
- if (alloc_type == MEM_Dyn) {
- mem->xDel = sql_free;
- } else {
- mem->xDel = NULL;
- mem->zMalloc = mem->z;
- mem->szMalloc = sqlDbMallocSize(mem->db, mem->zMalloc);
- }
+ mem->zMalloc = mem->z;
+ mem->szMalloc = sqlDbMallocSize(mem->db, mem->zMalloc);
}
void
@@ -465,12 +432,6 @@ mem_set_bin_static(struct Mem *mem, char *value, uint32_t size)
set_bin_const(mem, value, size, MEM_Static);
}
-void
-mem_set_bin_dynamic(struct Mem *mem, char *value, uint32_t size)
-{
- set_bin_dynamic(mem, value, size, MEM_Dyn);
-}
-
void
mem_set_bin_allocated(struct Mem *mem, char *value, uint32_t size)
{
@@ -524,13 +485,6 @@ mem_set_map_static(struct Mem *mem, char *value, uint32_t size)
set_msgpack_value(mem, value, size, MEM_Static, MEM_TYPE_MAP);
}
-void
-mem_set_map_dynamic(struct Mem *mem, char *value, uint32_t size)
-{
- assert(mp_typeof(*value) == MP_MAP);
- set_msgpack_value(mem, value, size, MEM_Dyn, MEM_TYPE_MAP);
-}
-
void
mem_set_map_allocated(struct Mem *mem, char *value, uint32_t size)
{
@@ -552,13 +506,6 @@ mem_set_array_static(struct Mem *mem, char *value, uint32_t size)
set_msgpack_value(mem, value, size, MEM_Static, MEM_TYPE_ARRAY);
}
-void
-mem_set_array_dynamic(struct Mem *mem, char *value, uint32_t size)
-{
- assert(mp_typeof(*value) == MP_ARRAY);
- set_msgpack_value(mem, value, size, MEM_Dyn, MEM_TYPE_ARRAY);
-}
-
void
mem_set_array_allocated(struct Mem *mem, char *value, uint32_t size)
{
@@ -1907,7 +1854,7 @@ mem_append(struct Mem *mem, const char *value, uint32_t len)
if (len == 0)
return 0;
int new_size = mem->n + len;
- if (((mem->flags & (MEM_Static | MEM_Dyn | MEM_Ephem)) != 0) ||
+ if (((mem->flags & (MEM_Static | MEM_Ephem)) != 0) ||
mem->szMalloc < new_size) {
/*
* Force exponential buffer size growth to avoid having to call
@@ -2648,18 +2595,6 @@ mem_mp_type(const struct Mem *mem)
int
sqlVdbeCheckMemInvariants(Mem * p)
{
- /* If MEM_Dyn is set then Mem.xDel!=0.
- * Mem.xDel is might not be initialized if MEM_Dyn is clear.
- */
- assert((p->flags & MEM_Dyn) == 0 || p->xDel != 0);
-
- /* MEM_Dyn may only be set if Mem.szMalloc==0. In this way we
- * ensure that if Mem.szMalloc>0 then it is safe to do
- * Mem.z = Mem.zMalloc without having to check Mem.flags&MEM_Dyn.
- * That saves a few cycles in inner loops.
- */
- assert((p->flags & MEM_Dyn) == 0 || p->szMalloc == 0);
-
/* The szMalloc field holds the correct memory allocation size */
assert(p->szMalloc == 0 ||
p->szMalloc == sqlDbMallocSize(p->db, p->zMalloc));
@@ -2674,7 +2609,6 @@ sqlVdbeCheckMemInvariants(Mem * p)
*/
if ((p->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) != 0 && p->n > 0) {
assert(((p->szMalloc > 0 && p->z == p->zMalloc) ? 1 : 0) +
- ((p->flags & MEM_Dyn) != 0 ? 1 : 0) +
((p->flags & MEM_Ephem) != 0 ? 1 : 0) +
((p->flags & MEM_Static) != 0 ? 1 : 0) == 1);
}
@@ -2694,15 +2628,12 @@ sqlVdbeMemPrettyPrint(Mem *pMem, char *zBuf)
if (pMem->type == MEM_TYPE_BIN) {
int i;
char c;
- if (f & MEM_Dyn) {
- c = 'z';
- assert((f & (MEM_Static|MEM_Ephem))==0);
- } else if (f & MEM_Static) {
+ if ((f & MEM_Static) != 0) {
c = 't';
- assert((f & (MEM_Dyn|MEM_Ephem))==0);
+ assert((f & MEM_Ephem) == 0);
} else if (f & MEM_Ephem) {
c = 'e';
- assert((f & (MEM_Static|MEM_Dyn))==0);
+ assert((f & MEM_Static) == 0);
} else {
c = 's';
}
@@ -2726,15 +2657,12 @@ sqlVdbeMemPrettyPrint(Mem *pMem, char *zBuf)
} else if (pMem->type == MEM_TYPE_STR) {
int j, k;
zBuf[0] = ' ';
- if (f & MEM_Dyn) {
- zBuf[1] = 'z';
- assert((f & (MEM_Static|MEM_Ephem))==0);
- } else if (f & MEM_Static) {
+ if ((f & MEM_Static) != 0) {
zBuf[1] = 't';
- assert((f & (MEM_Dyn|MEM_Ephem))==0);
+ assert((f & MEM_Ephem) == 0);
} else if (f & MEM_Ephem) {
zBuf[1] = 'e';
- assert((f & (MEM_Static|MEM_Dyn))==0);
+ assert((f & MEM_Static) == 0);
} else {
zBuf[1] = 's';
}
@@ -2847,13 +2775,9 @@ sqlVdbeMemGrow(struct Mem *pMem, int n, int bPreserve)
if (bPreserve && pMem->z && pMem->z != pMem->zMalloc) {
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
- if ((pMem->flags & MEM_Dyn) != 0) {
- assert(pMem->xDel != 0 && pMem->xDel != SQL_DYNAMIC);
- pMem->xDel((void *)(pMem->z));
- }
pMem->z = pMem->zMalloc;
- pMem->flags &= ~(MEM_Dyn | MEM_Ephem | MEM_Static);
+ pMem->flags &= ~(MEM_Ephem | MEM_Static);
return 0;
}
@@ -2872,11 +2796,9 @@ int
sqlVdbeMemClearAndResize(Mem * pMem, int szNew)
{
assert(szNew > 0);
- assert((pMem->flags & MEM_Dyn) == 0 || pMem->szMalloc == 0);
if (pMem->szMalloc < szNew) {
return sqlVdbeMemGrow(pMem, szNew, 0);
}
- assert((pMem->flags & MEM_Dyn) == 0);
pMem->z = pMem->zMalloc;
return 0;
}
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index 9533833f2..d2e9cc135 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -87,7 +87,6 @@ struct Mem {
int szMalloc; /* Size of the zMalloc allocation */
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
sql *db; /* The associated database connection */
- void (*xDel) (void *); /* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQL_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
void *pFiller; /* So that sizeof(Mem) is a multiple of 8 */
@@ -106,7 +105,6 @@ struct Mem {
* string is \000 or \u0000 terminated
*/
#define MEM_Term 0x0400 /* String rep is nul terminated */
-#define MEM_Dyn 0x0800 /* Need to call Mem.xDel() on Mem.z */
#define MEM_Static 0x1000 /* Mem.z points to a static string */
#define MEM_Ephem 0x2000 /* Mem.z points to an ephemeral string */
@@ -217,13 +215,6 @@ mem_is_ephemeral(const struct Mem *mem)
return (mem->flags & MEM_Ephem) != 0;
}
-static inline bool
-mem_is_dynamic(const struct Mem *mem)
-{
- assert(mem_is_bytes(mem));
- return (mem->flags & MEM_Dyn) != 0;
-}
-
static inline bool
mem_is_allocated(const struct Mem *mem)
{
@@ -234,8 +225,7 @@ mem_is_allocated(const struct Mem *mem)
static inline bool
mem_is_trivial(const struct Mem *mem)
{
- return mem->szMalloc == 0 && (mem->flags & MEM_Dyn) == 0 &&
- mem->type != MEM_TYPE_FRAME;
+ return mem->szMalloc == 0 && mem->type != MEM_TYPE_FRAME;
}
static inline bool
@@ -314,14 +304,6 @@ mem_set_str_ephemeral(struct Mem *mem, char *value, uint32_t len);
void
mem_set_str_static(struct Mem *mem, char *value, uint32_t len);
-/**
- * Clear MEM and set it to STRING. The string was allocated by another object
- * and passed to MEM. MEMs with this allocation type must free given memory
- * whenever the MEM changes.
- */
-void
-mem_set_str_dynamic(struct Mem *mem, char *value, uint32_t len);
-
/**
* Clear MEM and set it to STRING. The string was allocated by another object
* and passed to MEM. MEMs with this allocation type only deallocate the string
@@ -342,14 +324,6 @@ mem_set_str0_ephemeral(struct Mem *mem, char *value);
void
mem_set_str0_static(struct Mem *mem, char *value);
-/**
- * Clear MEM and set it to NULL-terminated STRING. The string was allocated by
- * another object and passed to MEM. MEMs with this allocation type must free
- * given memory whenever the MEM changes.
- */
-void
-mem_set_str0_dynamic(struct Mem *mem, char *value);
-
/**
* Clear MEM and set it to NULL-terminated STRING. The string was allocated by
* another object and passed to MEM. MEMs with this allocation type only
@@ -381,14 +355,6 @@ mem_set_bin_ephemeral(struct Mem *mem, char *value, uint32_t size);
void
mem_set_bin_static(struct Mem *mem, char *value, uint32_t size);
-/**
- * Clear MEM and set it to VARBINARY. The binary value was allocated by another
- * object and passed to MEM. MEMs with this allocation type must free given
- * memory whenever the MEM changes.
- */
-void
-mem_set_bin_dynamic(struct Mem *mem, char *value, uint32_t size);
-
/**
* Clear MEM and set it to VARBINARY. The binary value was allocated by another
* object and passed to MEM. MEMs with this allocation type only deallocate the
@@ -419,14 +385,6 @@ mem_set_map_ephemeral(struct Mem *mem, char *value, uint32_t size);
void
mem_set_map_static(struct Mem *mem, char *value, uint32_t size);
-/**
- * Clear MEM and set it to MAP. The binary value was allocated by another object
- * and passed to MEM. The binary value must be msgpack of MAP type. MEMs with
- * this allocation type must free given memory whenever the MEM changes.
- */
-void
-mem_set_map_dynamic(struct Mem *mem, char *value, uint32_t size);
-
/**
* Clear MEM and set it to MAP. The binary value was allocated by another object
* and passed to MEM. The binary value must be msgpack of MAP type. MEMs with
@@ -451,15 +409,6 @@ mem_set_array_ephemeral(struct Mem *mem, char *value, uint32_t size);
void
mem_set_array_static(struct Mem *mem, char *value, uint32_t size);
-/**
- * Clear MEM and set it to ARRAY. The binary value was allocated by another
- * object and passed to MEM. The binary value must be msgpack of ARRAY type.
- * MEMs with this allocation type must free given memory whenever the MEM
- * changes.
- */
-void
-mem_set_array_dynamic(struct Mem *mem, char *value, uint32_t size);
-
/**
* Clear MEM and set it to ARRAY. The binary value was allocated by another
* object and passed to MEM. The binary value must be msgpack of ARRAY type.
@@ -869,8 +818,7 @@ int sqlVdbeMemTooBig(Mem *);
/* Return TRUE if Mem X contains dynamically allocated content - anything
* that needs to be deallocated to avoid a leak.
*/
-#define VdbeMemDynamic(X) (((X)->flags & MEM_Dyn) != 0 ||\
- ((X)->type & MEM_TYPE_FRAME) != 0)
+#define VdbeMemDynamic(X) (((X)->type & MEM_TYPE_FRAME) != 0)
/**
* Perform comparison of two tuples: unpacked (key1) and packed (key2)
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 22a4aa5cd..148350d05 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -370,10 +370,6 @@ sql_vsnprintf(int, char *, const char *, va_list);
#define MATCH_ONE_WILDCARD '_'
#define MATCH_ALL_WILDCARD '%'
-typedef void (*sql_destructor_type) (void *);
-#define SQL_STATIC ((sql_destructor_type)0)
-#define SQL_TRANSIENT ((sql_destructor_type)-1)
-
/**
* Compile the UTF-8 encoded SQL statement into
* a statement handle (struct Vdbe).
@@ -873,16 +869,6 @@ typedef u64 uptr;
*/
#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
-/*
- * The following value as a destructor means to use sqlDbFree().
- * The sqlDbFree() routine requires two parameters instead of the
- * one parameter that destructors normally want. So we have to introduce
- * this magic value that the code knows to handle differently. Any
- * pointer will work here as long as it is distinct from sql_STATIC
- * and sql_TRANSIENT.
- */
-#define SQL_DYNAMIC ((sql_destructor_type)sqlMallocSize)
-
/*
* The usual case where Writable Static Data (WSD) is supported,
* the sql_WSD and GLOBAL macros become no-ops and have zero
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 20/21] sql: remove MEM_Term flag
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (18 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 19/21] sql: remove MEM_Dyn flag Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 21/21] sql: make arguments to be const Mergen Imeev via Tarantool-patches
2021-11-11 11:00 ` [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Kirill Yukhin via Tarantool-patches
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
This patch removes the MEM_Term flag, because after changes in the SQL
built-in functions, this flag is no longer used.
Needed for #4145
---
src/box/sql/mem.c | 78 +++--------------------------------------
src/box/sql/mem.h | 36 -------------------
src/box/sql/printf.c | 20 +++++++++--
src/box/sql/vdbe.h | 4 ++-
src/box/sql/vdbeaux.c | 31 ++++------------
src/box/sql/whereexpr.c | 18 +++++++---
6 files changed, 43 insertions(+), 144 deletions(-)
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index 4150a24f0..1f5df3332 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -346,21 +346,18 @@ void
mem_set_str0_ephemeral(struct Mem *mem, char *value)
{
set_str_const(mem, value, strlen(value), MEM_Ephem);
- mem->flags |= MEM_Term;
}
void
mem_set_str0_static(struct Mem *mem, char *value)
{
set_str_const(mem, value, strlen(value), MEM_Static);
- mem->flags |= MEM_Term;
}
void
mem_set_str0_allocated(struct Mem *mem, char *value)
{
set_str_dynamic(mem, value, strlen(value), 0);
- mem->flags |= MEM_Term;
}
int
@@ -392,7 +389,6 @@ mem_copy_str0(struct Mem *mem, const char *value)
if (mem_copy_str(mem, value, len + 1) != 0)
return -1;
mem->n = len;
- mem->flags |= MEM_Term;
return 0;
}
@@ -657,24 +653,12 @@ int_to_str0(struct Mem *mem)
return mem_copy_str0(mem, str);
}
-static inline int
-str_to_str0(struct Mem *mem)
-{
- assert(mem->type == MEM_TYPE_STR);
- if (sqlVdbeMemGrow(mem, mem->n + 1, 1) != 0)
- return -1;
- mem->z[mem->n] = '\0';
- mem->flags |= MEM_Term;
- mem->flags &= ~MEM_Scalar;
- return 0;
-}
-
static inline int
str_to_bin(struct Mem *mem)
{
assert(mem->type == MEM_TYPE_STR);
mem->type = MEM_TYPE_BIN;
- mem->flags &= ~(MEM_Term | MEM_Scalar);
+ mem->flags &= ~MEM_Scalar;
return 0;
}
@@ -725,18 +709,6 @@ bin_to_str(struct Mem *mem)
return 0;
}
-static inline int
-bin_to_str0(struct Mem *mem)
-{
- assert(mem->type == MEM_TYPE_BIN);
- if (sqlVdbeMemGrow(mem, mem->n + 1, 1) != 0)
- return -1;
- mem->z[mem->n] = '\0';
- mem->type = MEM_TYPE_STR;
- mem->flags = MEM_Term;
- return 0;
-}
-
static inline int
bin_to_uuid(struct Mem *mem)
{
@@ -1002,7 +974,7 @@ double_to_str0(struct Mem *mem)
sql_snprintf(BUF_SIZE, mem->z, "%!.15g", mem->u.r);
mem->n = strlen(mem->z);
mem->type = MEM_TYPE_STR;
- mem->flags = MEM_Term;
+ mem->flags = 0;
return 0;
}
@@ -1284,39 +1256,6 @@ mem_to_number(struct Mem *mem)
return -1;
}
-int
-mem_to_str0(struct Mem *mem)
-{
- assert(mem->type < MEM_TYPE_INVALID);
- switch (mem->type) {
- case MEM_TYPE_STR:
- if ((mem->flags & MEM_Term) != 0) {
- mem->flags &= ~MEM_Scalar;
- return 0;
- }
- return str_to_str0(mem);
- case MEM_TYPE_INT:
- case MEM_TYPE_UINT:
- return int_to_str0(mem);
- case MEM_TYPE_DOUBLE:
- return double_to_str0(mem);
- case MEM_TYPE_BOOL:
- return bool_to_str0(mem);
- case MEM_TYPE_BIN:
- return bin_to_str0(mem);
- case MEM_TYPE_MAP:
- return map_to_str0(mem);
- case MEM_TYPE_ARRAY:
- return array_to_str0(mem);
- case MEM_TYPE_UUID:
- return uuid_to_str0(mem);
- case MEM_TYPE_DEC:
- return dec_to_str0(mem);
- default:
- return -1;
- }
-}
-
int
mem_to_str(struct Mem *mem)
{
@@ -1763,15 +1702,6 @@ mem_get_bool(const struct Mem *mem, bool *b)
return -1;
}
-int
-mem_get_str0(const struct Mem *mem, const char **s)
-{
- if (mem->type != MEM_TYPE_STR || (mem->flags & MEM_Term) == 0)
- return -1;
- *s = mem->z;
- return 0;
-}
-
int
mem_get_bin(const struct Mem *mem, const char **s)
{
@@ -1814,7 +1744,7 @@ mem_copy(struct Mem *to, const struct Mem *from)
to->szMalloc = sqlDbMallocSize(to->db, to->zMalloc);
memcpy(to->zMalloc, to->z, to->n);
to->z = to->zMalloc;
- to->flags &= MEM_Term;
+ to->flags = 0;
return 0;
}
@@ -1831,7 +1761,7 @@ mem_copy_as_ephemeral(struct Mem *to, const struct Mem *from)
return;
if ((to->flags & (MEM_Static | MEM_Ephem)) != 0)
return;
- to->flags &= MEM_Term;
+ to->flags = 0;
to->flags |= MEM_Ephem;
return;
}
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index d2e9cc135..1ef8a945b 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -98,13 +98,6 @@ struct Mem {
/** MEM is of SCALAR meta-type. */
#define MEM_Scalar 0x0002
#define MEM_Cleared 0x0200 /* NULL set by OP_Null, not from data */
-
-/* Whenever Mem contains a valid string or blob representation, one of
- * the following flags must be set to determine the memory management
- * policy for Mem.z. The MEM_Term flag tells us whether or not the
- * string is \000 or \u0000 terminated
- */
-#define MEM_Term 0x0400 /* String rep is nul terminated */
#define MEM_Static 0x1000 /* Mem.z points to a static string */
#define MEM_Ephem 0x2000 /* Mem.z points to an ephemeral string */
@@ -610,14 +603,6 @@ mem_to_number(struct Mem *mem);
int
mem_to_str(struct Mem *mem);
-/**
- * Convert the given MEM to STRING. This function and the function above define
- * the rules that are used to convert values of all other types to STRING. In
- * this function, the string received after convertion is NULL-terminated.
- */
-int
-mem_to_str0(struct Mem *mem);
-
/** Convert the given MEM to given type according to explicit cast rules. */
int
mem_cast_explicit(struct Mem *mem, enum field_type type);
@@ -722,27 +707,6 @@ mem_get_bool_unsafe(const struct Mem *mem)
return b;
}
-/**
- * Return value for MEM of STRING type if MEM contains a NULL-terminated string.
- * Otherwise convert value of the MEM to NULL-terminated string if possible and
- * return converted value. Original MEM is not changed.
- */
-int
-mem_get_str0(const struct Mem *mem, const char **s);
-
-/**
- * Return value for MEM of STRING type if MEM contains NULL-terminated string.
- * Otherwise convert MEM to MEM of string type that contains NULL-terminated
- * string and return its value. Return NULL if conversion is impossible.
- */
-static inline const char *
-mem_as_str0(struct Mem *mem)
-{
- if (mem_to_str0(mem) != 0)
- return NULL;
- return mem->z;
-}
-
/**
* Return value for MEM of VARBINARY type. For MEM of all other types convert
* value of the MEM to VARBINARY if possible and return converted value.
diff --git a/src/box/sql/printf.c b/src/box/sql/printf.c
index 5b61646e3..8da7c9878 100644
--- a/src/box/sql/printf.c
+++ b/src/box/sql/printf.c
@@ -160,8 +160,20 @@ getTextArg(PrintfArguments * p)
{
if (p->nArg <= p->nUsed)
return 0;
- struct Mem *mem = &p->apArg[p->nUsed++];
- return (char *)mem_as_str0(mem);
+ struct Mem mem;
+ mem_create(&mem);
+ mem_copy_as_ephemeral(&mem, &p->apArg[p->nUsed++]);
+ if (mem_to_str(&mem) != 0) {
+ mem_destroy(&mem);
+ return NULL;
+ }
+ char *str = sqlDbMallocRawNN(sql_get(), mem.n + 1);
+ if (str == NULL)
+ return NULL;
+ memcpy(str, mem.z, mem.n);
+ str[mem.n] = '\0';
+ mem_destroy(&mem);
+ return str;
}
/*
@@ -677,6 +689,7 @@ sqlVXPrintf(StrAccum * pAccum, /* Accumulate results here */
if (bArgList) {
bufpt = getTextArg(pArgList);
c = bufpt ? bufpt[0] : 0;
+ zExtra = bufpt;
} else {
c = va_arg(ap, int);
}
@@ -697,7 +710,7 @@ sqlVXPrintf(StrAccum * pAccum, /* Accumulate results here */
case etDYNSTRING:
if (bArgList) {
bufpt = getTextArg(pArgList);
- xtype = etSTRING;
+ xtype = etDYNSTRING;
} else {
bufpt = va_arg(ap, char *);
}
@@ -727,6 +740,7 @@ sqlVXPrintf(StrAccum * pAccum, /* Accumulate results here */
if (bArgList) {
escarg = getTextArg(pArgList);
+ zExtra = escarg;
} else {
escarg = va_arg(ap, char *);
}
diff --git a/src/box/sql/vdbe.h b/src/box/sql/vdbe.h
index 106555bb1..48e687d49 100644
--- a/src/box/sql/vdbe.h
+++ b/src/box/sql/vdbe.h
@@ -260,6 +260,9 @@ vdbe_metadata_set_col_autoincrement(struct Vdbe *p, int idx);
int
vdbe_metadata_set_col_span(struct Vdbe *p, int idx, const char *span);
+const struct Mem *
+vdbe_get_bound_value(struct Vdbe *vdbe, int id);
+
void sqlVdbeCountChanges(Vdbe *);
sql *sqlVdbeDb(Vdbe *);
void sqlVdbeSetSql(Vdbe *, const char *z, int n);
@@ -268,7 +271,6 @@ void sqlVdbeSwap(Vdbe *, Vdbe *);
struct VdbeOp *
sqlVdbeTakeOpArray(struct Vdbe *p, int *pnOp);
-sql_value *sqlVdbeGetBoundValue(Vdbe *, int);
char *sqlVdbeExpandSql(Vdbe *, const char *);
/**
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index b71f65966..109ab1446 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -2285,31 +2285,12 @@ sqlVdbeDb(Vdbe * v)
return v->db;
}
-/*
- * Return a pointer to an sql_value structure containing the value bound
- * parameter iVar of VM v. Except, if the value is an SQL NULL, return
- * 0 instead. Unless it is NULL, apply type to the value before returning it.
- *
- * The returned value must be freed by the caller using sqlValueFree().
- */
-sql_value *
-sqlVdbeGetBoundValue(struct Vdbe *v, int iVar)
-{
- assert(iVar > 0);
- if (v) {
- Mem *pMem = &v->aVar[iVar - 1];
- if (!mem_is_null(pMem)) {
- sql_value *pRet = sqlValueNew(v->db);
- if (pRet == NULL)
- return NULL;
- if (mem_copy(pRet, pMem) != 0) {
- sqlValueFree(pRet);
- return NULL;
- }
- return pRet;
- }
- }
- return 0;
+const struct Mem *
+vdbe_get_bound_value(struct Vdbe *vdbe, int id)
+{
+ if (vdbe == NULL || id < 0 || id >= vdbe->nVar)
+ return NULL;
+ return &vdbe->aVar[id];
}
void
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index 6849f13ec..08a1b4e3a 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -268,7 +268,6 @@ like_optimization_is_valid(Parse *pParse, Expr *pExpr, Expr **ppPrefix,
int cnt;
/* Database connection. */
sql *db = pParse->db;
- sql_value *pVal = 0;
/* Opcode of pRight. */
int op;
/* Result code to return. */
@@ -306,13 +305,22 @@ like_optimization_is_valid(Parse *pParse, Expr *pExpr, Expr **ppPrefix,
return 0;
op = pRight->op;
+ struct region *region = &pParse->region;
+ size_t svp = region_used(region);
if (op == TK_VARIABLE) {
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
- pVal = sqlVdbeGetBoundValue(pReprepare, iCol);
- if (pVal != NULL && mem_is_str(pVal)) {
- if (mem_as_str0(pVal) == NULL)
+ const struct Mem *var = vdbe_get_bound_value(pReprepare, iCol);
+ if (var != NULL && mem_is_str(var)) {
+ uint32_t size = var->n + 1;
+ char *str = region_alloc(region, size);
+ if (str == NULL) {
+ diag_set(OutOfMemory, size, "region", "str");
return -1;
+ }
+ memcpy(str, var->z, var->n);
+ str[var->n] = '\0';
+ z = str;
}
assert(pRight->op == TK_VARIABLE || pRight->op == TK_REGISTER);
} else if (op == TK_STRING) {
@@ -356,8 +364,8 @@ like_optimization_is_valid(Parse *pParse, Expr *pExpr, Expr **ppPrefix,
}
}
+ region_truncate(region, svp);
rc = (z != 0);
- sqlValueFree(pVal);
return rc;
}
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* [Tarantool-patches] [PATCH v1 21/21] sql: make arguments to be const
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (19 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 20/21] sql: remove MEM_Term flag Mergen Imeev via Tarantool-patches
@ 2021-11-11 10:49 ` Mergen Imeev via Tarantool-patches
2021-11-11 11:00 ` [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Kirill Yukhin via Tarantool-patches
21 siblings, 0 replies; 25+ messages in thread
From: Mergen Imeev via Tarantool-patches @ 2021-11-11 10:49 UTC (permalink / raw)
To: kyukhin; +Cc: tarantool-patches
This patch forces SQL built-in function implementations to accept
'const struct Mem *' instead of just 'struct Mem *'.
Needed for #4145
---
src/box/sql/func.c | 94 ++++++++++++++++++++++----------------------
src/box/sql/sqlInt.h | 4 +-
2 files changed, 50 insertions(+), 48 deletions(-)
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index a0e599b5e..8fb225c0c 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -55,7 +55,7 @@ static struct func_sql_builtin **functions;
/** Implementation of the SUM() function. */
static void
-step_sum(struct sql_context *ctx, int argc, struct Mem *argv)
+step_sum(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
@@ -70,7 +70,7 @@ step_sum(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the TOTAL() function. */
static void
-step_total(struct sql_context *ctx, int argc, struct Mem *argv)
+step_total(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
@@ -95,7 +95,7 @@ fin_total(struct Mem *mem)
/** Implementation of the AVG() function. */
static void
-step_avg(struct sql_context *ctx, int argc, struct Mem *argv)
+step_avg(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
@@ -143,7 +143,7 @@ fin_avg(struct Mem *mem)
/** Implementation of the COUNT() function. */
static void
-step_count(struct sql_context *ctx, int argc, struct Mem *argv)
+step_count(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 0 || argc == 1);
if (mem_is_null(ctx->pOut))
@@ -166,7 +166,7 @@ fin_count(struct Mem *mem)
/** Implementation of the MIN() and MAX() functions. */
static void
-step_minmax(struct sql_context *ctx, int argc, struct Mem *argv)
+step_minmax(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
@@ -199,7 +199,7 @@ step_minmax(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the GROUP_CONCAT() function. */
static void
-step_group_concat(struct sql_context *ctx, int argc, struct Mem *argv)
+step_group_concat(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1 || argc == 2);
(void)argc;
@@ -234,11 +234,11 @@ step_group_concat(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementations of the ABS() function. */
static void
-func_abs_int(struct sql_context *ctx, int argc, struct Mem *argv)
+func_abs_int(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
assert(mem_is_int(arg));
@@ -247,11 +247,11 @@ func_abs_int(struct sql_context *ctx, int argc, struct Mem *argv)
}
static void
-func_abs_double(struct sql_context *ctx, int argc, struct Mem *argv)
+func_abs_double(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
assert(mem_is_double(arg));
@@ -260,11 +260,11 @@ func_abs_double(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the CHAR_LENGTH() function. */
static void
-func_char_length(struct sql_context *ctx, int argc, struct Mem *argv)
+func_char_length(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
assert(mem_is_str(arg) && arg->n >= 0);
@@ -280,11 +280,11 @@ func_char_length(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the UPPER() and LOWER() functions. */
static void
-func_lower_upper(struct sql_context *ctx, int argc, struct Mem *argv)
+func_lower_upper(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
assert(mem_is_str(arg) && arg->n >= 0);
@@ -333,7 +333,7 @@ func_lower_upper(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the NULLIF() function. */
static void
-func_nullif(struct sql_context *ctx, int argc, struct Mem *argv)
+func_nullif(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 2);
(void)argc;
@@ -382,7 +382,7 @@ trim_bin_start(const char *str, int end, const char *octets, int octets_size,
}
static void
-func_trim_bin(struct sql_context *ctx, int argc, struct Mem *argv)
+func_trim_bin(struct sql_context *ctx, int argc, const struct Mem *argv)
{
if (mem_is_null(&argv[0]) || (argc == 3 && mem_is_null(&argv[2])))
return;
@@ -461,7 +461,7 @@ trim_str_start(const char *str, int end, const char *chars, uint8_t *chars_len,
}
static void
-func_trim_str(struct sql_context *ctx, int argc, struct Mem *argv)
+func_trim_str(struct sql_context *ctx, int argc, const struct Mem *argv)
{
if (mem_is_null(&argv[0]) || (argc == 3 && mem_is_null(&argv[2])))
return;
@@ -511,7 +511,7 @@ func_trim_str(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the POSITION() function. */
static void
-func_position_octets(struct sql_context *ctx, int argc, struct Mem *argv)
+func_position_octets(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 2);
(void)argc;
@@ -530,7 +530,8 @@ func_position_octets(struct sql_context *ctx, int argc, struct Mem *argv)
}
static void
-func_position_characters(struct sql_context *ctx, int argc, struct Mem *argv)
+func_position_characters(struct sql_context *ctx, int argc,
+ const struct Mem *argv)
{
assert(argc == 2);
(void)argc;
@@ -610,7 +611,7 @@ substr_normalize(int64_t base_start, bool is_start_neg, uint64_t base_length,
}
static void
-func_substr_octets(struct sql_context *ctx, int argc, struct Mem *argv)
+func_substr_octets(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 2 || argc == 3);
if (mem_is_any_null(&argv[0], &argv[1]))
@@ -666,7 +667,8 @@ func_substr_octets(struct sql_context *ctx, int argc, struct Mem *argv)
}
static void
-func_substr_characters(struct sql_context *ctx, int argc, struct Mem *argv)
+func_substr_characters(struct sql_context *ctx, int argc, const
+ struct Mem *argv)
{
assert(argc == 2 || argc == 3);
(void)argc;
@@ -739,7 +741,7 @@ func_substr_characters(struct sql_context *ctx, int argc, struct Mem *argv)
* Symbol '\0' used instead of NULL argument.
*/
static void
-func_char(struct sql_context *ctx, int argc, struct Mem *argv)
+func_char(struct sql_context *ctx, int argc, const struct Mem *argv)
{
if (argc == 0)
return mem_set_str_static(ctx->pOut, "", 0);
@@ -789,7 +791,7 @@ func_char(struct sql_context *ctx, int argc, struct Mem *argv)
* The LEAST() function returns the smallest of the given arguments.
*/
static void
-func_greatest_least(struct sql_context *ctx, int argc, struct Mem *argv)
+func_greatest_least(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc > 1);
int mask = ctx->func->def->name[0] == 'G' ? -1 : 0;
@@ -821,11 +823,11 @@ static const char hexdigits[] = {
};
static void
-func_hex(struct sql_context *ctx, int argc, struct Mem *argv)
+func_hex(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
@@ -849,11 +851,11 @@ func_hex(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the OCTET_LENGTH() function. */
static void
-func_octet_length(struct sql_context *ctx, int argc, struct Mem *argv)
+func_octet_length(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
assert(mem_is_bytes(arg) && arg->n >= 0);
@@ -862,7 +864,7 @@ func_octet_length(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the PRINTF() function. */
static void
-func_printf(struct sql_context *ctx, int argc, struct Mem *argv)
+func_printf(struct sql_context *ctx, int argc, const struct Mem *argv)
{
if (argc < 1 || mem_is_null(&argv[0]))
return;
@@ -891,7 +893,7 @@ func_printf(struct sql_context *ctx, int argc, struct Mem *argv)
* This function returns a random INT64 value.
*/
static void
-func_random(struct sql_context *ctx, int argc, struct Mem *argv)
+func_random(struct sql_context *ctx, int argc, const struct Mem *argv)
{
(void)argc;
(void)argv;
@@ -907,11 +909,11 @@ func_random(struct sql_context *ctx, int argc, struct Mem *argv)
* specified as an argument of the function.
*/
static void
-func_randomblob(struct sql_context *ctx, int argc, struct Mem *argv)
+func_randomblob(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
assert(mem_is_null(arg) || mem_is_int(arg));
if (mem_is_null(arg) || !mem_is_uint(arg))
return;
@@ -934,11 +936,11 @@ func_randomblob(struct sql_context *ctx, int argc, struct Mem *argv)
* is specified as an argument of the function.
*/
static void
-func_zeroblob(struct sql_context *ctx, int argc, struct Mem *argv)
+func_zeroblob(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
assert(mem_is_null(arg) || mem_is_int(arg));
if (mem_is_null(arg) || !mem_is_uint(arg))
return;
@@ -955,7 +957,7 @@ func_zeroblob(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the TYPEOF() function. */
static void
-func_typeof(struct sql_context *ctx, int argc, struct Mem *argv)
+func_typeof(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
@@ -964,7 +966,7 @@ func_typeof(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the ROUND() function. */
static void
-func_round(struct sql_context *ctx, int argc, struct Mem *argv)
+func_round(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1 || argc == 2);
if (mem_is_null(&argv[0]) || (argc == 2 && mem_is_null(&argv[1])))
@@ -990,7 +992,7 @@ func_round(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the ROW_COUNT() function. */
static void
-func_row_count(struct sql_context *ctx, int argc, struct Mem *argv)
+func_row_count(struct sql_context *ctx, int argc, const struct Mem *argv)
{
(void)argc;
(void)argv;
@@ -1004,7 +1006,7 @@ func_row_count(struct sql_context *ctx, int argc, struct Mem *argv)
* Returns a randomly generated UUID value.
*/
static void
-func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
+func_uuid(struct sql_context *ctx, int argc, const struct Mem *argv)
{
if (argc == 1) {
if (mem_is_null(&argv[0]))
@@ -1023,7 +1025,7 @@ func_uuid(struct sql_context *ctx, int argc, struct Mem *argv)
/** Implementation of the VERSION() function. */
static void
-func_version(struct sql_context *ctx, int argc, struct Mem *argv)
+func_version(struct sql_context *ctx, int argc, const struct Mem *argv)
{
(void)argc;
(void)argv;
@@ -1037,11 +1039,11 @@ func_version(struct sql_context *ctx, int argc, struct Mem *argv)
* string.
*/
static void
-func_unicode(struct sql_context *ctx, int argc, struct Mem *argv)
+func_unicode(struct sql_context *ctx, int argc, const struct Mem *argv)
{
assert(argc == 1);
(void)argc;
- struct Mem *arg = &argv[0];
+ const struct Mem *arg = &argv[0];
if (mem_is_null(arg))
return;
assert(mem_is_str(arg));
@@ -1274,7 +1276,7 @@ sql_utf8_pattern_compare(const char *pattern,
* is NULL then result is NULL as well.
*/
static void
-likeFunc(sql_context *context, int argc, struct Mem *argv)
+likeFunc(sql_context *context, int argc, const struct Mem *argv)
{
u32 escape = SQL_END_OF_STRING;
int nPat;
@@ -1343,7 +1345,7 @@ likeFunc(sql_context *context, int argc, struct Mem *argv)
* single-quote escapes.
*/
static void
-quoteFunc(struct sql_context *context, int argc, struct Mem *argv)
+quoteFunc(struct sql_context *context, int argc, const struct Mem *argv)
{
assert(argc == 1);
UNUSED_PARAMETER(argc);
@@ -1428,7 +1430,7 @@ quoteFunc(struct sql_context *context, int argc, struct Mem *argv)
* must be exact. Collating sequences are not used.
*/
static void
-replaceFunc(struct sql_context *context, int argc, struct Mem *argv)
+replaceFunc(struct sql_context *context, int argc, const struct Mem *argv)
{
const unsigned char *zStr; /* The input string A */
const unsigned char *zPattern; /* The pattern string B */
@@ -1503,7 +1505,7 @@ replaceFunc(struct sql_context *context, int argc, struct Mem *argv)
* soundex encoding of the string X.
*/
static void
-soundexFunc(struct sql_context *context, int argc, struct Mem *argv)
+soundexFunc(struct sql_context *context, int argc, const struct Mem *argv)
{
(void) argc;
char zResult[8];
@@ -1576,7 +1578,7 @@ func_sql_builtin_call_stub(struct func *func, struct port *args,
}
static void
-sql_builtin_stub(sql_context *ctx, int argc, struct Mem *argv)
+sql_builtin_stub(sql_context *ctx, int argc, const struct Mem *argv)
{
(void) argc; (void) argv;
diag_set(ClientError, ER_SQL_EXECUTE,
@@ -1678,7 +1680,7 @@ struct sql_func_definition {
/** Type of the result of the implementation. */
enum field_type result;
/** Call implementation with given arguments. */
- void (*call)(sql_context *ctx, int argc, struct Mem *argv);
+ void (*call)(sql_context *ctx, int argc, const struct Mem *argv);
/** Call finalization function for this implementation. */
int (*finalize)(struct Mem *mem);
};
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index 148350d05..dcd71e5bd 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -2447,7 +2447,7 @@ struct PrintfArguments {
int nArg; /* Total number of arguments */
int nUsed; /* Number of arguments used so far */
/** The argument values. */
- struct Mem *apArg;
+ const struct Mem *apArg;
};
void sqlVXPrintf(StrAccum *, const char *, va_list);
@@ -4270,7 +4270,7 @@ struct func_sql_builtin {
* Access checks are redundant, because all SQL built-ins
* are predefined and are executed on SQL privilege level.
*/
- void (*call)(struct sql_context *ctx, int argc, struct Mem *argv);
+ void (*call)(struct sql_context *ctx, int argc, const struct Mem *argv);
/**
* A VDBE-memory-compatible finalize method
* (is valid only for aggregate function).
--
2.25.1
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions
2021-11-11 10:48 [Tarantool-patches] [PATCH v1 00/21] Refactor non-standard and non-aggragate functions Mergen Imeev via Tarantool-patches
` (20 preceding siblings ...)
2021-11-11 10:49 ` [Tarantool-patches] [PATCH v1 21/21] sql: make arguments to be const Mergen Imeev via Tarantool-patches
@ 2021-11-11 11:00 ` Kirill Yukhin via Tarantool-patches
21 siblings, 0 replies; 25+ messages in thread
From: Kirill Yukhin via Tarantool-patches @ 2021-11-11 11:00 UTC (permalink / raw)
To: imeevma; +Cc: tarantool-patches
Hello,
On 11 ноя 13:48, imeevma@tarantool.org wrote:
> This patch-set refactor the built-in SQL functions that were not refactored in
> the previous two patch-sets. It also simplifies struct Mem.
>
> https://github.com/tarantool/tarantool/issues/4145
> https://github.com/tarantool/tarantool/tree/imeevma/gh-4145-row-sql-builtin-funcs
LGTM. I've checked your patchset into master.
--
Regards, Kirill Yukhin
^ permalink raw reply [flat|nested] 25+ messages in thread