From d882d9f4483341645f477bae185d1a30dacc4cdf Mon Sep 17 00:00:00 2001 From: Mergen Imeev <imeevma@tarantool.org> Date: Tue, 16 Aug 2022 15:56:29 +0300 Subject: [PATCH] sql: introduce new parsing rule This commit introduces a new parse rule for compiling an unresolved single expression. This simplifies the current implementation of sql_expr_compile() and is useful for generating SQL expressions that can be used in the core check constraint. This rule is for internal use only. Part of #6986 NO_DOC=will be added later NO_TEST=refactoring NO_CHANGELOG=will be added later --- extra/mkkeywordhash.c | 2 +- src/box/sql.h | 8 -------- src/box/sql/parse.y | 21 +++++++++++++++++---- src/box/sql/select.c | 16 ---------------- src/box/sql/sqlInt.h | 2 ++ src/box/sql/tokenize.c | 7 ++++--- 6 files changed, 24 insertions(+), 32 deletions(-) diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c index fd1cc83f3d..6d961d9de7 100644 --- a/extra/mkkeywordhash.c +++ b/extra/mkkeywordhash.c @@ -210,7 +210,7 @@ static Keyword aKeywordTable[] = { { "ENABLE", "TK_ENABLE", false }, { "FETCH", "TK_STANDARD", true }, { "FLOAT", "TK_STANDARD", true }, - { "FUNCTION", "TK_STANDARD", true }, + { "FUNCTION", "TK_FUNCTION_KW", true }, { "GET", "TK_STANDARD", true }, { "GRANT", "TK_STANDARD", true }, { "INT", "TK_INT", true }, diff --git a/src/box/sql.h b/src/box/sql.h index fe7cb2f51f..bf8d7b7c5b 100644 --- a/src/box/sql.h +++ b/src/box/sql.h @@ -157,14 +157,6 @@ sql_trigger_name(struct sql_trigger *trigger); uint32_t sql_trigger_space_id(struct sql_trigger *trigger); -/** - * Store duplicate of a parsed expression into @a parser. - * @param parser Parser context. - * @param select Select to extract from. - */ -void -sql_expr_extract_select(struct Parse *parser, struct Select *select); - /** * Given space_id and field number, return default value * for the field. diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 40297cd03a..2046dc19ed 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -458,10 +458,13 @@ cmd ::= createkw(X) VIEW ifnotexists(E) nm(Y) eidlist_opt(C) // cmd ::= select(X). { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0}; - if(!pParse->parse_only) - sqlSelect(pParse, X, &dest); - else - sql_expr_extract_select(pParse, X); + if(pParse->parse_only) { + diag_set(ClientError, ER_SQL_PARSER_GENERIC, + "Failed to parse SQL expression"); + pParse->is_aborted = true; + return; + } + sqlSelect(pParse, X, &dest); sql_select_delete(pParse->db, X); } @@ -1611,6 +1614,16 @@ cmd ::= PRAGMA nm(X) LP nm(Y) RP. { cmd ::= PRAGMA nm(X) LP nm(Z) DOT nm(Y) RP. { sqlPragma(pParse,&X,&Y,&Z); } +cmd ::= FUNCTION_KW(T) expr(E). { + if (!pParse->is_expr) { + diag_set(ClientError, ER_SQL_SYNTAX_NEAR_TOKEN, pParse->line_count, T.n, + T.z); + pParse->is_aborted = true; + return; + } + pParse->parsed_ast_type = AST_TYPE_EXPR; + pParse->parsed_ast.expr = sqlExprDup(pParse->db, E.pExpr, 0); +} //////////////////////////// The CREATE TRIGGER command ///////////////////// cmd ::= createkw trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). { diff --git a/src/box/sql/select.c b/src/box/sql/select.c index 3ae7a709bd..a4b0c3c72e 100644 --- a/src/box/sql/select.c +++ b/src/box/sql/select.c @@ -6714,22 +6714,6 @@ sqlSelect(Parse * pParse, /* The parser context */ return rc; } -void -sql_expr_extract_select(struct Parse *parser, struct Select *select) -{ - struct ExprList *expr_list = select->pEList; - assert(expr_list->nExpr == 1); - parser->parsed_ast_type = AST_TYPE_EXPR; - /* - * Extract a copy of parsed expression. - * We cannot use EXPRDUP_REDUCE flag in sqlExprDup call - * because some compiled Expr (like Checks expressions) - * may require further resolve with sqlResolveExprNames. - */ - parser->parsed_ast.expr = - sqlExprDup(parser->db, expr_list->a->pExpr, 0); -} - struct sql_context * sql_context_new(struct func *func, struct coll *coll) { diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index a629024557..4b95045d79 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -2090,6 +2090,8 @@ struct Parse { bool initiateTTrans; /* Initiate Tarantool transaction */ /** If set - do not emit byte code at all, just parse. */ bool parse_only; + /** If true, then parsed_ast_type should be EXPR after parsing. */ + bool is_expr; /** Type of parsed_ast member. */ enum ast_type parsed_ast_type; /** SQL options which were used to compile this VDBE. */ diff --git a/src/box/sql/tokenize.c b/src/box/sql/tokenize.c index 5b6eef4d97..8b5cac26d0 100644 --- a/src/box/sql/tokenize.c +++ b/src/box/sql/tokenize.c @@ -570,7 +570,7 @@ sqlRunParser(Parse * pParse, const char *zSql) struct Expr * sql_expr_compile(sql *db, const char *expr, int expr_len) { - const char *outer = "SELECT "; + const char *outer = "FUNCTION "; int len = strlen(outer) + expr_len; struct Parse parser; @@ -582,6 +582,7 @@ sql_expr_compile(sql *db, const char *expr, int expr_len) */ parser.line_pos -= strlen(outer); parser.parse_only = true; + parser.is_expr = true; struct Expr *expression = NULL; char *stmt = (char *)region_alloc(&parser.region, len + 1); @@ -591,8 +592,8 @@ sql_expr_compile(sql *db, const char *expr, int expr_len) } snprintf(stmt, len + 1, "%s%.*s", outer, expr_len, expr); - if (sqlRunParser(&parser, stmt) == 0 && - parser.parsed_ast_type == AST_TYPE_EXPR) { + if (sqlRunParser(&parser, stmt) == 0) { + assert(parser.parsed_ast_type == AST_TYPE_EXPR); expression = parser.parsed_ast.expr; parser.parsed_ast.expr = NULL; } -- GitLab