[Tarantool-patches] [PATCH v2 3/5] sql: remove struct func from struct sql_context

imeevma at tarantool.org imeevma at tarantool.org
Thu Aug 19 08:31:30 MSK 2021


This patch removes struct func from struct sql_context since we don't
need the functionality of struct func here. Without this structure, we
can make it easier to work with SQL built-in functions.

Part of #6105
---
 src/box/sql/func.c    | 123 +++++++++++++++++++++++++++++++++++++-----
 src/box/sql/vdbe.c    |   8 +--
 src/box/sql/vdbeInt.h |   6 ++-
 src/box/sql/vdbeaux.c |   5 +-
 4 files changed, 119 insertions(+), 23 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 4a0d2d097..adbc6d5a4 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -132,8 +132,7 @@ minmaxFunc(sql_context * context, int argc, sql_value ** 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;
+	int mask = (context->flags & SQL_FUNC_MAX) != 0 ? -1 : 0;
 	if (argc < 2) {
 		diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT,
 		mask ? "GREATEST" : "LEAST", "at least two", argc);
@@ -1799,8 +1798,6 @@ minmaxStep(sql_context * context, int NotUsed, sql_value ** argv)
 	Mem *pBest;
 	UNUSED_PARAMETER(NotUsed);
 
-	struct func_sql_builtin *func =
-		(struct func_sql_builtin *)context->func;
 	pBest = sql_context_agg_mem(context);
 	if (!pBest)
 		return;
@@ -1816,7 +1813,7 @@ minmaxStep(sql_context * context, int NotUsed, sql_value ** argv)
 		 * between the two being that the sense of the
 		 * comparison is inverted.
 		 */
-		bool is_max = (func->flags & SQL_FUNC_MAX) != 0;
+		bool is_max = (context->flags & SQL_FUNC_MAX) != 0;
 		int cmp = mem_cmp_scalar(pBest, pArg, pColl);
 		if ((is_max && cmp < 0) || (!is_max && cmp > 0)) {
 			mem_copy(pBest, pArg);
@@ -1930,9 +1927,7 @@ static void
 sql_builtin_stub(sql_context *ctx, int argc, sql_value **argv)
 {
 	(void) argc; (void) argv;
-	diag_set(ClientError, ER_SQL_EXECUTE,
-		 tt_sprintf("function '%s' is not implemented",
-			    ctx->func->def->name));
+	diag_set(ClientError, ER_SQL_EXECUTE, "function is not implemented");
 	ctx->is_aborted = true;
 }
 
@@ -2886,20 +2881,124 @@ int
 sql_emit_func_call(struct Vdbe *vdbe, struct Expr *expr, int op, int mask,
 		   int r1, int r2, uint8_t argc)
 {
-	struct func *func = sql_func_find(expr);
-	if (func == NULL)
-		return -1;
 	uint32_t size = sizeof(struct sql_context);
 	if (argc > 1)
 		size += (argc - 1) * sizeof(struct Mem);
 	struct sql_context *ctx = sqlDbMallocRawNN(sql_get(), size);
 	if (ctx == NULL)
 		return -1;
+	switch(expr->func_id) {
+	case TK_ABS:
+		ctx->call = absFunc;
+		break;
+	case TK_AVG:
+	case TK_SUM:
+		ctx->call = sum_step;
+		break;
+	case TK_CHAR:
+		ctx->call = charFunc;
+		break;
+	case TK_CHAR_LEN:
+	case TK_LENGTH:
+		ctx->call = lengthFunc;
+		break;
+	case TK_COALESCE:
+	case TK_IFNULL:
+	case TK_LIKELIHOOD:
+	case TK_LIKELY:
+	case TK_UNLIKELY:
+		ctx->call = sql_builtin_stub;
+		break;
+	case TK_COUNT:
+		ctx->call = countStep;
+		break;
+	case TK_GREATEST:
+	case TK_LEAST:
+		ctx->call = minmaxFunc;
+		break;
+	case TK_GROUP_CONCAT:
+		ctx->call = groupConcatStep;
+		break;
+	case TK_HEX:
+		ctx->call = hexFunc;
+		break;
+	case TK_LIKE_KW:
+		ctx->call = likeFunc;
+		break;
+	case TK_LOWER:
+		ctx->call = LowerICUFunc;
+		break;
+	case TK_MAX:
+	case TK_MIN:
+		ctx->call = minmaxStep;
+		break;
+	case TK_NULLIF:
+		ctx->call = nullifFunc;
+		break;
+	case TK_POSITION:
+		ctx->call = position_func;
+		break;
+	case TK_PRINTF:
+		ctx->call = printfFunc;
+		break;
+	case TK_QUOTE:
+		ctx->call = quoteFunc;
+		break;
+	case TK_RANDOM:
+		ctx->call = randomFunc;
+		break;
+	case TK_RANDOMBLOB:
+		ctx->call = randomBlob;
+		break;
+	case TK_REPLACE:
+		ctx->call = replaceFunc;
+		break;
+	case TK_ROUND:
+		ctx->call = roundFunc;
+		break;
+	case TK_ROW_COUNT:
+		ctx->call = sql_row_count;
+		break;
+	case TK_SOUNDEX:
+		ctx->call = soundexFunc;
+		break;
+	case TK_SUBSTR:
+		ctx->call = substrFunc;
+		break;
+	case TK_TOTAL:
+		ctx->call = total_step;
+		break;
+	case TK_TRIM:
+		ctx->call = trim_func;
+		break;
+	case TK_TYPEOF:
+		ctx->call = typeofFunc;
+		break;
+	case TK_UNICODE:
+		ctx->call = unicodeFunc;
+		break;
+	case TK_UPPER:
+		ctx->call = UpperICUFunc;
+		break;
+	case TK_UUID:
+		ctx->call = sql_func_uuid;
+		break;
+	case TK_VERSION:
+		ctx->call = sql_func_version;
+		break;
+	case TK_ZEROBLOB:
+		ctx->call = zeroblobFunc;
+		break;
+	default:
+		unreachable();
+	}
+	assert(strlen(expr->u.zToken) < 24);
+	strcpy(ctx->name, expr->u.zToken);
 	ctx->pOut = NULL;
-	ctx->func = func;
 	ctx->iOp = 0;
 	ctx->pVdbe = vdbe;
 	ctx->argc = argc;
+	ctx->flags = sql_func_flags(expr->func_id);
 	sqlVdbeAddOp4(vdbe, op, mask, r1, r2, (char *)ctx, P4_FUNCCTX);
 	sqlVdbeChangeP5(vdbe, argc);
 	return 0;
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 9fb103e82..c63dbaa5a 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -1221,9 +1221,7 @@ case OP_BuiltinFunction: {
 	}
 #endif
 	pCtx->is_aborted = false;
-	assert(pCtx->func->def->language == FUNC_LANGUAGE_SQL_BUILTIN);
-	struct func_sql_builtin *func = (struct func_sql_builtin *)pCtx->func;
-	func->call(pCtx, pCtx->argc, pCtx->argv);
+	pCtx->call(pCtx, pCtx->argc, pCtx->argv);
 
 	/* If the function returned an error, throw an exception */
 	if (pCtx->is_aborted)
@@ -4185,9 +4183,7 @@ case OP_AggStep: {
 	pCtx->pOut = &t;
 	pCtx->is_aborted = false;
 	pCtx->skipFlag = 0;
-	assert(pCtx->func->def->language == FUNC_LANGUAGE_SQL_BUILTIN);
-	struct func_sql_builtin *func = (struct func_sql_builtin *)pCtx->func;
-	func->call(pCtx, pCtx->argc, pCtx->argv);
+	pCtx->call(pCtx, pCtx->argc, pCtx->argv);
 	if (pCtx->is_aborted) {
 		mem_destroy(&t);
 		goto abort_due_to_error;
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index 073ac0b97..0a0e6cc97 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -169,9 +169,8 @@ struct VdbeFrame {
  * (Mem) which are only defined there.
  */
 struct sql_context {
+	char name[24];
 	Mem *pOut;		/* The return value is stored here */
-	/* A pointer to function implementation. */
-	struct func *func;
 	Mem *pMem;		/* Memory cell used to store aggregate context */
 	Vdbe *pVdbe;		/* The VM that owns this context */
 	/** Instruction number of OP_BuiltinFunction or OP_AggStep. */
@@ -183,6 +182,9 @@ struct sql_context {
 	bool is_aborted;
 	u8 skipFlag;		/* Skip accumulator loading if true */
 	u8 argc;		/* Number of arguments */
+	uint32_t flags;
+	/* Implementation of SQL built-in function. */
+	void (*call)(struct sql_context *ctx, int argc, struct Mem **argv);
 	sql_value *argv[1];	/* Argument set */
 };
 
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index 662fbbf81..3913dc637 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -1070,9 +1070,8 @@ displayP4(Op * pOp, char *zTemp, int nTemp)
 		}
 #if defined(SQL_DEBUG) || defined(VDBE_PROFILE)
 	case P4_FUNCCTX:{
-			struct func *func = pOp->p4.pCtx->func;
-			sqlXPrintf(&x, "%s(%d)", func->def->name,
-				   func->def->param_count);
+			sqlXPrintf(&x, "%s(%d)", pOp->p4.pCtx->name,
+				   pOp->p4.pCtx->argc);
 			break;
 		}
 #endif
-- 
2.25.1



More information about the Tarantool-patches mailing list