[Tarantool-patches] [PATCH v2 06/10] sql: add overloaded versions of the functions
imeevma at tarantool.org
imeevma at tarantool.org
Fri Aug 14 18:05:02 MSK 2020
This patch adds overload function definitions for the length(),
substr(), trim(), and position() functions.
Part of #4159
---
src/box/sql/analyze.c | 6 ++---
src/box/sql/expr.c | 29 ++++++++++++++++++++---
src/box/sql/func.c | 54 ++++++++++++++++++++++++++++++++++++++++---
src/box/sql/sqlInt.h | 5 ++--
src/box/sql/vdbemem.c | 2 +-
5 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index f74f9b358..d304b266e 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -716,7 +716,7 @@ callStatGet(Vdbe * v, int regStat4, int iParam, int regOut)
{
assert(regOut != regStat4 && regOut != regStat4 + 1);
sqlVdbeAddOp2(v, OP_Integer, iParam, regStat4 + 1);
- struct func *func = sql_func_by_signature("_sql_stat_get", 2);
+ struct func *func = sql_func_by_signature("_sql_stat_get", false, 2);
assert(func != NULL);
sqlVdbeAddOp4(v, OP_BuiltinFunction0, 0, regStat4, regOut,
(char *)func, P4_FUNC);
@@ -856,7 +856,7 @@ vdbe_emit_analyze_space(struct Parse *parse, struct space *space)
sqlVdbeAddOp2(v, OP_Integer, part_count, stat4_reg + 1);
sqlVdbeAddOp2(v, OP_Integer, part_count, stat4_reg + 2);
struct func *init_func =
- sql_func_by_signature("_sql_stat_init", 3);
+ sql_func_by_signature("_sql_stat_init", false, 3);
assert(init_func != NULL);
sqlVdbeAddOp4(v, OP_BuiltinFunction0, 0, stat4_reg + 1,
stat4_reg, (char *)init_func, P4_FUNC);
@@ -957,7 +957,7 @@ vdbe_emit_analyze_space(struct Parse *parse, struct space *space)
pk_part_count, key_reg);
assert(chng_reg == (stat4_reg + 1));
struct func *push_func =
- sql_func_by_signature("_sql_stat_push", 3);
+ sql_func_by_signature("_sql_stat_push", false, 3);
assert(push_func != NULL);
sqlVdbeAddOp4(v, OP_BuiltinFunction0, 1, stat4_reg, tmp_reg,
(char *)push_func, P4_FUNC);
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index bc2182446..99ca91bba 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -328,8 +328,15 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t *coll_id,
if (op == TK_FUNCTION) {
uint32_t arg_count = p->x.pList == NULL ? 0 :
p->x.pList->nExpr;
+ bool has_blob_arg = false;
+ if (arg_count > 0) {
+ enum field_type type =
+ sql_expr_type(p->x.pList->a[0].pExpr);
+ has_blob_arg = type == FIELD_TYPE_VARBINARY;
+ }
struct func *func =
- sql_func_by_signature(p->u.zToken, arg_count);
+ sql_func_by_signature(p->u.zToken, has_blob_arg,
+ arg_count);
if (func == NULL)
break;
if (sql_func_flag_is_set(func, SQL_FUNC_DERIVEDCOLL) &&
@@ -3975,8 +3982,15 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
}
nFarg = pFarg ? pFarg->nExpr : 0;
assert(!ExprHasProperty(pExpr, EP_IntValue));
+ bool has_blob_arg = false;
+ if (nFarg > 0) {
+ enum field_type type =
+ sql_expr_type(pExpr->x.pList->a[0].pExpr);
+ has_blob_arg = type == FIELD_TYPE_VARBINARY;
+ }
zId = pExpr->u.zToken;
- struct func *func = sql_func_by_signature(zId, nFarg);
+ struct func *func =
+ sql_func_by_signature(zId, has_blob_arg, nFarg);
if (func == NULL) {
diag_set(ClientError, ER_NO_SUCH_FUNCTION,
zId);
@@ -5448,9 +5462,18 @@ analyzeAggregate(Walker * pWalker, Expr * pExpr)
uint32_t argc =
pExpr->x.pList != NULL ?
pExpr->x.pList->nExpr : 0;
+ bool has_blob_arg = false;
+ if (argc > 0) {
+ enum field_type type =
+ sql_expr_type(pExpr->x.pList->a[0].pExpr);
+ has_blob_arg =
+ type == FIELD_TYPE_VARBINARY;
+ }
pItem->func =
sql_func_by_signature(
- name, argc);
+ name,
+ has_blob_arg,
+ argc);
assert(pItem->func != NULL);
assert(pItem->func->def->
language ==
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 1afee4924..ae1842824 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -2169,19 +2169,27 @@ sql_is_like_func(struct Expr *expr)
expr->x.pList->nExpr != 2)
return 0;
assert(!ExprHasProperty(expr, EP_xIsSelect));
- struct func *func = sql_func_by_signature(expr->u.zToken, 2);
+ struct func *func = sql_func_by_signature(expr->u.zToken, false, 2);
if (func == NULL || !sql_func_flag_is_set(func, SQL_FUNC_LIKE))
return 0;
return 1;
}
struct func *
-sql_func_by_signature(const char *name, int argc)
+sql_func_by_signature(const char *name, bool has_blob_arg, int argc)
{
struct func *base = func_by_name(name, strlen(name));
- if (base == NULL || !base->def->exports.sql)
+ if (base == NULL || !base->def->exports.sql ||
+ base->def->opts.is_overloaded)
return NULL;
+ if (has_blob_arg && base->def->opts.has_overload) {
+ const char *overload_name = tt_sprintf("%s_VARBINARY", name);
+ base = func_by_name(overload_name, strlen(overload_name));
+ assert(base != NULL && base->def->exports.sql);
+ assert(base->def->opts.is_overloaded);
+ }
+
if (!base->def->opts.has_vararg && base->def->param_count != argc)
return NULL;
return base;
@@ -2497,6 +2505,16 @@ static struct {
.call = lengthFunc,
.finalize = NULL,
.export_to_sql = true,
+ }, {
+ .name = "LENGTH_VARBINARY",
+ .param_count = 1,
+ .returns = FIELD_TYPE_INTEGER,
+ .aggregate = FUNC_AGGREGATE_NONE,
+ .is_deterministic = true,
+ .flags = SQL_FUNC_LENGTH,
+ .call = lengthFunc,
+ .finalize = NULL,
+ .export_to_sql = true,
}, {
.name = "LESSER",
.call = sql_builtin_stub,
@@ -2617,6 +2635,16 @@ static struct {
.call = position_func,
.finalize = NULL,
.export_to_sql = true,
+ }, {
+ .name = "POSITION_VARBINARY",
+ .param_count = 2,
+ .returns = FIELD_TYPE_INTEGER,
+ .aggregate = FUNC_AGGREGATE_NONE,
+ .is_deterministic = true,
+ .flags = 0,
+ .call = position_func,
+ .finalize = NULL,
+ .export_to_sql = true,
}, {
.name = "POWER",
.call = sql_builtin_stub,
@@ -2747,6 +2775,16 @@ static struct {
.call = substrFunc,
.finalize = NULL,
.export_to_sql = true,
+ }, {
+ .name = "SUBSTR_VARBINARY",
+ .param_count = -1,
+ .returns = FIELD_TYPE_STRING,
+ .aggregate = FUNC_AGGREGATE_NONE,
+ .is_deterministic = true,
+ .flags = SQL_FUNC_DERIVEDCOLL,
+ .call = substrFunc,
+ .finalize = NULL,
+ .export_to_sql = true,
}, {
.name = "SUM",
.param_count = 1,
@@ -2787,6 +2825,16 @@ static struct {
.call = trim_func,
.finalize = NULL,
.export_to_sql = true,
+ }, {
+ .name = "TRIM_VARBINARY",
+ .param_count = -1,
+ .returns = FIELD_TYPE_STRING,
+ .aggregate = FUNC_AGGREGATE_NONE,
+ .is_deterministic = true,
+ .flags = SQL_FUNC_DERIVEDCOLL,
+ .call = trim_func,
+ .finalize = NULL,
+ .export_to_sql = true,
}, {
.name = "TYPEOF",
.param_count = 1,
diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h
index adf90d824..9ff1dd3ff 100644
--- a/src/box/sql/sqlInt.h
+++ b/src/box/sql/sqlInt.h
@@ -4441,13 +4441,14 @@ sql_func_flag_is_set(struct func *func, uint16_t flag)
* A SQL method to find a function in a hash by its name and
* count of arguments. Only functions that have 'SQL' engine
* export field set true and have exactly the same signature
- * are returned.
+ * are returned. If has_blob_arg is set to true, the varbinary
+ * version of the function is returned is the functions has one.
*
* Returns not NULL function pointer when a valid and exported
* to SQL engine function is found and NULL otherwise.
*/
struct func *
-sql_func_by_signature(const char *name, int argc);
+sql_func_by_signature(const char *name, bool has_blob_arg, int argc);
/**
* Generate VDBE code to halt execution with correct error if
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 8e9ebf7ab..3af96c37c 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -1327,7 +1327,7 @@ valueFromFunction(sql * db, /* The database connection */
pList = p->x.pList;
if (pList)
nVal = pList->nExpr;
- struct func *func = sql_func_by_signature(p->u.zToken, nVal);
+ struct func *func = sql_func_by_signature(p->u.zToken, false, nVal);
if (func == NULL || func->def->language != FUNC_LANGUAGE_SQL_BUILTIN ||
!func->def->is_deterministic ||
sql_func_flag_is_set(func, SQL_FUNC_NEEDCOLL))
--
2.25.1
More information about the Tarantool-patches
mailing list