From: Mergen Imeev via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: vdavydov@tarantool.org Cc: tarantool-patches@dev.tarantool.org Subject: [Tarantool-patches] [PATCH v2 4/5] sql: separate function flags from functions Date: Wed, 18 Aug 2021 17:35:03 +0300 [thread overview] Message-ID: <4d7ba8434f561a54bddbff576e1b0acab4089ff2.1629297142.git.imeevma@gmail.com> (raw) In-Reply-To: <cover.1629297142.git.imeevma@gmail.com> This patch separates function flags from function definition. This allows us not to look for a function where we need its flags, but not the function itself. It also allows us to search for a function after the function arguments have been properly initialized, which will help us to check the types of those arguments. Part of #6105 --- src/box/sql/expr.c | 49 +++++++-------- src/box/sql/func.c | 137 +++++++++++++++++++++++++++++++++++++----- src/box/sql/parse.y | 82 ++++++++++++------------- src/box/sql/resolve.c | 33 ++++------ src/box/sql/select.c | 12 ++-- src/box/sql/sqlInt.h | 20 +++--- 6 files changed, 214 insertions(+), 119 deletions(-) diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index 6c24dc09a..0544539d2 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -351,7 +351,7 @@ sql_expr_coll(Parse *parse, Expr *p, bool *is_explicit_coll, uint32_t *coll_id, if (op == TK_BUILT_IN_FUNC) { uint32_t arg_count = p->x.pList == NULL ? 0 : p->x.pList->nExpr; - uint32_t flags = sql_func_flags(p->u.zToken); + uint32_t flags = sql_func_flags(p->func_id); if (((flags & SQL_FUNC_DERIVEDCOLL) != 0) && arg_count > 0) { /* @@ -1219,7 +1219,7 @@ sqlExprFunction(Parse * pParse, ExprList * pList, Token * pToken) struct Expr * sql_expr_new_built_in(struct Parse *parser, struct ExprList *list, - struct Token *token) + struct Token *token, uint8_t id) { struct sql *db = parser->db; assert(token != NULL); @@ -1231,6 +1231,7 @@ sql_expr_new_built_in(struct Parse *parser, struct ExprList *list, return NULL; } new_expr->x.pList = list; + new_expr->func_id = id; assert(!ExprHasProperty(new_expr, EP_xIsSelect)); sqlExprSetHeightAndFlags(parser, new_expr); return new_expr; @@ -1513,6 +1514,8 @@ sql_expr_dup(struct sql *db, struct Expr *p, int flags, char **buffer) nToken = sqlStrlen30(p->u.zToken) + 1; else nToken = 0; + if (p->op == TK_BUILT_IN_FUNC) + pNew->func_id = p->func_id; if (flags) { assert(ExprHasProperty(p, EP_Reduced) == 0); memcpy(zAlloc, p, nNewSize); @@ -1549,7 +1552,6 @@ sql_expr_dup(struct sql *db, struct Expr *p, int flags, char **buffer) sql_expr_list_dup(db, p->x.pList, flags); } } - /* Fill in pNew->pLeft and pNew->pRight. */ if (ExprHasProperty(pNew, EP_Reduced | EP_TokenOnly)) { zAlloc += dupedExprNodeSize(p, flags); @@ -4022,21 +4024,17 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) } nFarg = pFarg ? pFarg->nExpr : 0; assert(!ExprHasProperty(pExpr, EP_IntValue)); - struct func *func = sql_func_find(pExpr); - if (func == NULL) { - pParse->is_aborted = true; - break; - } + uint32_t flags = sql_func_flags(pExpr->func_id); /* Attempt a direct implementation of the built-in COALESCE() and * IFNULL() functions. This avoids unnecessary evaluation of * arguments past the first non-NULL argument. */ - if (sql_func_flag_is_set(func, SQL_FUNC_COALESCE)) { + if ((flags & SQL_FUNC_COALESCE) != 0) { int endCoalesce = sqlVdbeMakeLabel(v); if (nFarg < 2) { diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - func->def->name, + pExpr->u.zToken, "at least two", nFarg); pParse->is_aborted = true; break; @@ -4062,11 +4060,11 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) /* The UNLIKELY() function is a no-op. The result is the value * of the first argument. */ - if (sql_func_flag_is_set(func, SQL_FUNC_UNLIKELY)) { + if ((flags & SQL_FUNC_UNLIKELY) != 0) { if (nFarg < 1) { diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - func->def->name, + pExpr->u.zToken, "at least one", nFarg); pParse->is_aborted = true; break; @@ -4092,8 +4090,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) * is done using ANSI rules from * collations_check_compatibility(). */ - if (sql_func_flag_is_set(func, SQL_FUNC_NEEDCOLL) && - nFarg > 0) { + if ((flags & SQL_FUNC_NEEDCOLL) != 0 && nFarg > 0) { struct coll *unused = NULL; uint32_t curr_id = COLL_NONE; bool is_curr_forced = false; @@ -4140,8 +4137,8 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) * or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data * loading. */ - if (sql_func_flag_is_set(func, SQL_FUNC_LENGTH | - SQL_FUNC_TYPEOF)) { + if ((flags & (SQL_FUNC_LENGTH | + SQL_FUNC_TYPEOF)) != 0) { u8 exprOp; assert(nFarg == 1); assert(pFarg->a[0].pExpr != 0); @@ -4164,10 +4161,15 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) } else { r1 = 0; } - if (sql_func_flag_is_set(func, SQL_FUNC_NEEDCOLL)) { + if ((flags & SQL_FUNC_NEEDCOLL) != 0) { sqlVdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)coll, P4_COLLSEQ); } + struct func *func = sql_func_find(pExpr); + if (func == NULL) { + pParse->is_aborted = true; + break; + } sqlVdbeAddOp4(v, OP_BuiltinFunction0, constMask, r1, target, (char *)func, P4_FUNC); sqlVdbeChangeP5(v, (u8) nFarg); @@ -5470,15 +5472,10 @@ analyzeAggregate(Walker * pWalker, Expr * pExpr) pItem->iMem = ++pParse->nMem; assert(!ExprHasProperty (pExpr, EP_IntValue)); - pItem->func = - sql_func_find(pExpr); - assert(pItem->func != NULL); - assert(pItem->func->def-> - language == - FUNC_LANGUAGE_SQL_BUILTIN && - pItem->func->def-> - aggregate == - FUNC_AGGREGATE_GROUP); + pItem->flags = + sql_func_flags(pExpr->func_id); + assert((pItem->flags & + SQL_FUNC_AGG) != 0); if (pExpr->flags & EP_Distinct) { pItem->iDistinct = pParse->nTab++; diff --git a/src/box/sql/func.c b/src/box/sql/func.c index 492960443..29235ed62 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -1907,8 +1907,7 @@ sql_is_like_func(struct Expr *expr) expr->x.pList->nExpr != 2) return 0; assert(!ExprHasProperty(expr, EP_xIsSelect)); - struct func *func = sql_func_find(expr); - if (func == NULL || !sql_func_flag_is_set(func, SQL_FUNC_LIKE)) + if ((sql_func_flags(expr->func_id) & SQL_FUNC_LIKE) == 0) return 0; return 1; } @@ -2677,19 +2676,6 @@ sql_func_find(struct Expr *expr) return func; } -uint32_t -sql_func_flags(const char *name) -{ - struct func *func = built_in_func_get(name); - if (func == NULL) - return 0; - assert(func->def->language == FUNC_LANGUAGE_SQL_BUILTIN); - uint32_t flags = ((struct func_sql_builtin *)func)->flags; - if (func->def->aggregate == FUNC_AGGREGATE_GROUP) - flags |= SQL_FUNC_AGG; - return flags; -} - static struct func_vtab func_sql_builtin_vtab; void @@ -2770,3 +2756,124 @@ static struct func_vtab func_sql_builtin_vtab = { .call = func_sql_builtin_call_stub, .destroy = func_sql_builtin_destroy, }; + +uint32_t +sql_func_flags(uint8_t id) +{ + switch(id) { + case TK_ABS: + case TK_CHAR: + case TK_CHAR_LEN: + case TK_HEX: + case TK_PRINTF: + case TK_QUOTE: + case TK_ROUND: + case TK_ROW_COUNT: + case TK_SOUNDEX: + case TK_UNICODE: + case TK_VERSION: + case TK_ZEROBLOB: + return SQL_FUNC_DETERM; + case TK_AVG: + case TK_COUNT: + case TK_GROUP_CONCAT: + case TK_SUM: + case TK_TOTAL: + return SQL_FUNC_AGG; + case TK_COALESCE: + case TK_IFNULL: + return SQL_FUNC_COALESCE | SQL_FUNC_DETERM; + case TK_GREATEST: + return SQL_FUNC_MAX | SQL_FUNC_NEEDCOLL | SQL_FUNC_DETERM; + case TK_LEAST: + return SQL_FUNC_MIN | SQL_FUNC_NEEDCOLL | SQL_FUNC_DETERM; + case TK_LENGTH: + return SQL_FUNC_LENGTH | SQL_FUNC_DETERM; + case TK_LIKE_KW: + return SQL_FUNC_LIKE | SQL_FUNC_NEEDCOLL | SQL_FUNC_DETERM; + case TK_LIKELIHOOD: + case TK_LIKELY: + case TK_UNLIKELY: + return SQL_FUNC_UNLIKELY | SQL_FUNC_DETERM; + case TK_LOWER: + case TK_UPPER: + return SQL_FUNC_DERIVEDCOLL | SQL_FUNC_NEEDCOLL | + SQL_FUNC_DETERM; + case TK_MAX: + return SQL_FUNC_MAX | SQL_FUNC_AGG | SQL_FUNC_NEEDCOLL; + case TK_MIN: + return SQL_FUNC_MIN | SQL_FUNC_AGG | SQL_FUNC_NEEDCOLL; + case TK_NULLIF: + case TK_POSITION: + return SQL_FUNC_NEEDCOLL | SQL_FUNC_DETERM; + case TK_RANDOM: + case TK_RANDOMBLOB: + case TK_UUID: + return 0; + case TK_REPLACE: + case TK_SUBSTR: + case TK_TRIM: + return SQL_FUNC_DERIVEDCOLL | SQL_FUNC_DETERM; + case TK_TYPEOF: + return SQL_FUNC_TYPEOF | SQL_FUNC_DETERM; + default: + unreachable(); + } + return 0; +} + +enum field_type +sql_func_result(struct Expr *expr) +{ + switch(expr->func_id) { + case TK_ABS: + case TK_AVG: + case TK_SUM: + case TK_TOTAL: + return FIELD_TYPE_NUMBER; + case TK_CHAR: + case TK_GROUP_CONCAT: + case TK_HEX: + case TK_LOWER: + case TK_PRINTF: + case TK_QUOTE: + case TK_REPLACE: + case TK_SOUNDEX: + case TK_SUBSTR: + case TK_TRIM: + case TK_TYPEOF: + case TK_UNICODE: + case TK_UPPER: + case TK_VERSION: + return FIELD_TYPE_STRING; + case TK_CHAR_LEN: + case TK_COUNT: + case TK_LENGTH: + case TK_LIKE_KW: + case TK_POSITION: + case TK_RANDOM: + case TK_ROUND: + case TK_ROW_COUNT: + return FIELD_TYPE_INTEGER; + case TK_COALESCE: + case TK_GREATEST: + case TK_IFNULL: + case TK_LEAST: + case TK_MAX: + case TK_MIN: + case TK_NULLIF: + return FIELD_TYPE_SCALAR; + case TK_LIKELIHOOD: + case TK_LIKELY: + case TK_UNLIKELY: + return FIELD_TYPE_BOOLEAN; + case TK_RANDOMBLOB: + case TK_ZEROBLOB: + return FIELD_TYPE_VARBINARY; + case TK_UUID: + return FIELD_TYPE_UUID; + default: + unreachable(); + } + return field_type_MAX; +} diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 2327482ec..4a4ca96c3 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -1125,7 +1125,7 @@ expr(A) ::= CAST(X) LP expr(E) AS typedef(T) RP(Y). { } expr(A) ::= TRIM(X) LP trim_operands(Y) RP(E). { - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_TRIM); spanSet(&A, &X, &E); } @@ -1179,7 +1179,7 @@ expr(A) ::= ABS(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_ABS); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1192,7 +1192,7 @@ expr(A) ::= AVG(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_AVG); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1206,7 +1206,7 @@ expr(A) ::= CHAR(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_CHAR); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1221,7 +1221,7 @@ expr(A) ::= CHAR_LEN(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_CHAR_LEN); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1237,7 +1237,7 @@ expr(A) ::= COALESCE(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_COALESCE); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1250,14 +1250,14 @@ expr(A) ::= COUNT(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_COUNT); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; } expr(A) ::= COUNT(X) LP STAR RP(E). { - A.pExpr = sql_expr_new_built_in(pParse, NULL, &X); + A.pExpr = sql_expr_new_built_in(pParse, NULL, &X, TK_COUNT); spanSet(&A, &X, &E); } @@ -1271,7 +1271,7 @@ expr(A) ::= GREATEST(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_GREATEST); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1285,7 +1285,7 @@ expr(A) ::= GROUP_CONCAT(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_GROUP_CONCAT); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1298,7 +1298,7 @@ expr(A) ::= HEX(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_HEX); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1311,7 +1311,7 @@ expr(A) ::= IFNULL(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_IFNULL); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1327,7 +1327,7 @@ expr(A) ::= LEAST(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_LEAST); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1340,7 +1340,7 @@ expr(A) ::= LENGTH(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_LENGTH); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1353,7 +1353,7 @@ expr(A) ::= LIKELIHOOD(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_LIKELIHOOD); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1366,7 +1366,7 @@ expr(A) ::= LIKELY(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_LIKELY); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1379,7 +1379,7 @@ expr(A) ::= LOWER(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_LOWER); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1392,7 +1392,7 @@ expr(A) ::= MAX(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_MAX); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1405,7 +1405,7 @@ expr(A) ::= MIN(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_MIN); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1418,7 +1418,7 @@ expr(A) ::= NULLIF(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_NULLIF); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1431,7 +1431,7 @@ expr(A) ::= POSITION(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_POSITION); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1445,7 +1445,7 @@ expr(A) ::= PRINTF(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_PRINTF); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1458,7 +1458,7 @@ expr(A) ::= QUOTE(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_QUOTE); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1470,7 +1470,7 @@ expr(A) ::= RANDOM(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_RANDOM); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1483,7 +1483,7 @@ expr(A) ::= RANDOMBLOB(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_RANDOMBLOB); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1496,7 +1496,7 @@ expr(A) ::= REPLACE(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_REPLACE); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1510,7 +1510,7 @@ expr(A) ::= ROUND(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_ROUND); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1522,7 +1522,7 @@ expr(A) ::= ROW_COUNT(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_ROW_COUNT); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1535,7 +1535,7 @@ expr(A) ::= SOUNDEX(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_SOUNDEX); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1549,7 +1549,7 @@ expr(A) ::= SUBSTR(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_SUBSTR); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1562,7 +1562,7 @@ expr(A) ::= SUM(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_SUM); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1575,7 +1575,7 @@ expr(A) ::= TOTAL(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_TOTAL); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1588,7 +1588,7 @@ expr(A) ::= TYPEOF(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_TYPEOF); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1601,7 +1601,7 @@ expr(A) ::= UNICODE(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_UNICODE); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1614,7 +1614,7 @@ expr(A) ::= UNLIKELY(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_UNLIKELY); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1627,7 +1627,7 @@ expr(A) ::= UPPER(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_UPPER); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1640,7 +1640,7 @@ expr(A) ::= UUID(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_UUID); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1652,7 +1652,7 @@ expr(A) ::= VERSION(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_VERSION); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1665,7 +1665,7 @@ expr(A) ::= ZEROBLOB(X) LP distinct(D) exprlist(Y) RP(E). { pParse->is_aborted = true; return; } - A.pExpr = sql_expr_new_built_in(pParse, Y, &X); + A.pExpr = sql_expr_new_built_in(pParse, Y, &X, TK_ZEROBLOB); spanSet(&A, &X, &E); if(D == SF_Distinct && A.pExpr) A.pExpr->flags |= EP_Distinct; @@ -1753,7 +1753,7 @@ expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] { OP.n &= 0x7fffffff; pList = sql_expr_list_append(pParse->db,NULL, Y.pExpr); pList = sql_expr_list_append(pParse->db,pList, A.pExpr); - A.pExpr = sql_expr_new_built_in(pParse, pList, &OP); + A.pExpr = sql_expr_new_built_in(pParse, pList, &OP, TK_LIKE_KW); exprNot(pParse, bNot, &A); A.zEnd = Y.zEnd; if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; @@ -1765,7 +1765,7 @@ expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { pList = sql_expr_list_append(pParse->db,NULL, Y.pExpr); pList = sql_expr_list_append(pParse->db,pList, A.pExpr); pList = sql_expr_list_append(pParse->db,pList, E.pExpr); - A.pExpr = sql_expr_new_built_in(pParse, pList, &OP); + A.pExpr = sql_expr_new_built_in(pParse, pList, &OP, TK_LIKE_KW); exprNot(pParse, bNot, &A); A.zEnd = E.zEnd; if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; diff --git a/src/box/sql/resolve.c b/src/box/sql/resolve.c index 32ab1ac68..833ccbc83 100644 --- a/src/box/sql/resolve.c +++ b/src/box/sql/resolve.c @@ -618,19 +618,9 @@ resolveExprStep(Walker * pWalker, Expr * pExpr) assert(!ExprHasProperty(pExpr, EP_xIsSelect)); zId = pExpr->u.zToken; nId = sqlStrlen30(zId); - struct func *func = sql_func_find(pExpr); - if (func == NULL) { - pParse->is_aborted = true; - pNC->nErr++; - return WRC_Abort; - } - bool is_agg = func->def->aggregate == - FUNC_AGGREGATE_GROUP; - assert(!is_agg || func->def->language == - FUNC_LANGUAGE_SQL_BUILTIN); - pExpr->type = func->def->returns; - if (sql_func_flag_is_set(func, SQL_FUNC_UNLIKELY) && - n == 2) { + uint32_t flags = sql_func_flags(pExpr->func_id); + bool is_agg = (flags & SQL_FUNC_AGG) != 0; + if ((flags & SQL_FUNC_UNLIKELY) != 0 && n == 2) { ExprSetProperty(pExpr, EP_Unlikely | EP_Skip); pExpr->iTable = exprProbability(pList->a[1].pExpr); @@ -643,19 +633,18 @@ resolveExprStep(Walker * pWalker, Expr * pExpr) pNC->nErr++; return WRC_Abort; } - } else if (sql_func_flag_is_set(func, - SQL_FUNC_UNLIKELY)) { + } else if ((flags & SQL_FUNC_UNLIKELY) != 0) { ExprSetProperty(pExpr, EP_Unlikely | EP_Skip); /* * unlikely() probability is * 0.0625, likely() is 0.9375 */ - pExpr->iTable = func->def->name[0] == 'u' ? + pExpr->iTable = zId[0] == 'u' ? 8388608 : 125829120; } - assert(!func->def->is_deterministic || + assert(((flags & SQL_FUNC_DETERM) == 0) || (pNC->ncFlags & NC_IdxExpr) == 0); - if (func->def->is_deterministic) + if ((flags & SQL_FUNC_DETERM) != 0) ExprSetProperty(pExpr, EP_ConstFunc); if (is_agg && (pNC->ncFlags & NC_AllowAgg) == 0) { const char *err = @@ -681,16 +670,16 @@ resolveExprStep(Walker * pWalker, Expr * pExpr) pExpr->op2++; pNC2 = pNC2->pNext; } - assert(func != NULL); if (pNC2) { pNC2->ncFlags |= NC_HasAgg; - if (sql_func_flag_is_set(func, - SQL_FUNC_MIN | - SQL_FUNC_MAX)) + if ((flags & (SQL_FUNC_MIN | + SQL_FUNC_MAX)) != 0) pNC2->ncFlags |= NC_MinMaxAgg; } pNC->ncFlags |= NC_AllowAgg; } + pExpr->type = sql_func_result(pExpr); + assert(pExpr->type != field_type_MAX); return WRC_Prune; } case TK_SELECT: diff --git a/src/box/sql/select.c b/src/box/sql/select.c index 8003703a1..2f8a7a031 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -4647,9 +4647,7 @@ is_simple_count(struct Select *select, struct AggInfo *agg_info) return NULL; if (NEVER(agg_info->nFunc == 0)) return NULL; - assert(agg_info->aFunc->func->def->language == - FUNC_LANGUAGE_SQL_BUILTIN); - if (sql_func_flag_is_set(agg_info->aFunc->func, SQL_FUNC_COUNT) || + if ((agg_info->aFunc->flags & SQL_FUNC_COUNT) != 0 || (agg_info->aFunc->pExpr->x.pList != NULL && agg_info->aFunc->pExpr->x.pList->nExpr > 0)) return NULL; @@ -5576,7 +5574,8 @@ finalizeAggFunctions(Parse * pParse, AggInfo * pAggInfo) assert(!ExprHasProperty(pF->pExpr, EP_xIsSelect)); sqlVdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0); - sqlVdbeAppendP4(v, pF->func, P4_FUNC); + struct func *func = sql_func_find(pF->pExpr); + sqlVdbeAppendP4(v, func, P4_FUNC); } } @@ -5617,7 +5616,7 @@ updateAccumulator(Parse * pParse, AggInfo * pAggInfo) vdbe_insert_distinct(pParse, pF->iDistinct, pF->reg_eph, addrNext, 1, regAgg); } - if (sql_func_flag_is_set(pF->func, SQL_FUNC_NEEDCOLL)) { + if ((pF->flags & SQL_FUNC_NEEDCOLL) != 0) { struct coll *coll = NULL; struct ExprList_item *pItem; int j; @@ -5636,7 +5635,8 @@ updateAccumulator(Parse * pParse, AggInfo * pAggInfo) (char *)coll, P4_COLLSEQ); } sqlVdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem); - sqlVdbeAppendP4(v, pF->func, P4_FUNC); + struct func *func = sql_func_find(pF->pExpr); + sqlVdbeAppendP4(v, func, P4_FUNC); sqlVdbeChangeP5(v, (u8) nArg); sql_expr_type_cache_change(pParse, regAgg, nArg); sqlReleaseTempRange(pParse, regAgg, nArg); diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 1fd9d2bbf..01701e271 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -1188,6 +1188,8 @@ struct type_def { */ /** Function is one of aggregate functions. */ #define SQL_FUNC_AGG 0x0001 +/** Function is deterministic. */ +#define SQL_FUNC_DETERM 0x0002 #define SQL_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */ #define SQL_FUNC_NEEDCOLL 0x0020 /* sqlGetFuncCollSeq() might be called. * The flag is set when the collation @@ -1398,8 +1400,7 @@ struct AggInfo { */ struct AggInfo_func { /* For each aggregate function */ Expr *pExpr; /* Expression encoding the function */ - /** The aggregate function implementation. */ - struct func *func; + uint32_t flags; int iMem; /* Memory location that acts as accumulator */ int iDistinct; /* Ephemeral table used to enforce DISTINCT */ /** @@ -1494,6 +1495,9 @@ struct Expr { * access them will result in a segfault or malfunction. ********************************************************************/ + /** SQL Built-in function id. */ + uint8_t func_id; + Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { @@ -2705,7 +2709,7 @@ ExprList *sqlExprListAppendVector(Parse *, ExprList *, IdList *, Expr *); /** Construct a new expression node for a built-in function. */ struct Expr * sql_expr_new_built_in(struct Parse *parser, struct ExprList *list, - struct Token *token); + struct Token *token, uint8_t id); /** * Set the sort order for the last element on the given ExprList. @@ -4400,13 +4404,11 @@ sql_func_find(struct Expr *expr); struct func * sql_func_by_signature(const char *name, uint32_t argc); -/** - * Return the parameters of the function with the given name. If the function - * with the given name does not exist, or the function is not a built-in SQL - * function, 0 is returned, which means no parameters have been set. - */ uint32_t -sql_func_flags(const char *name); +sql_func_flags(uint8_t id); + +enum field_type +sql_func_result(struct Expr *expr); /** * Generate VDBE code to halt execution with correct error if -- 2.25.1
next prev parent reply other threads:[~2021-08-18 14:36 UTC|newest] Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-08-18 14:34 [Tarantool-patches] [PATCH v2 0/5] Prepare for static arguments type check Mergen Imeev via Tarantool-patches 2021-08-18 14:34 ` [Tarantool-patches] [PATCH v2 1/5] sql: modify arithmetic aggregate functions Mergen Imeev via Tarantool-patches 2021-08-18 14:34 ` [Tarantool-patches] [PATCH v2 2/5] sql: introduce SQL built-in functions to parser Mergen Imeev via Tarantool-patches 2021-08-19 8:35 ` Vladimir Davydov via Tarantool-patches 2021-08-21 0:27 ` Safin Timur via Tarantool-patches 2021-08-18 14:35 ` [Tarantool-patches] [PATCH v2 3/5] sql: separate functions in parser Mergen Imeev via Tarantool-patches 2021-08-18 14:35 ` Mergen Imeev via Tarantool-patches [this message] 2021-08-18 14:35 ` [Tarantool-patches] [PATCH v2 5/5] sql: encapsulate SQL built-in functions opcodes Mergen Imeev via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=4d7ba8434f561a54bddbff576e1b0acab4089ff2.1629297142.git.imeevma@gmail.com \ --to=tarantool-patches@dev.tarantool.org \ --cc=imeevma@tarantool.org \ --cc=vdavydov@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v2 4/5] sql: separate function flags from functions' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox