[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