From 2b164f6240d37036dc36721c195813de995ea929 Mon Sep 17 00:00:00 2001 From: Mergen Imeev <imeevma@tarantool.org> Date: Tue, 10 Oct 2023 17:17:48 +0300 Subject: [PATCH] sql: second lookup for collation names Part of #4467 NO_DOC=will be added later NO_CHANGELOG=will be added later --- src/box/sql.c | 8 ++++++++ src/box/sql/expr.c | 10 ++++++++++ src/box/sql/parse.y | 2 ++ src/box/sql/sqlInt.h | 14 ++++++++++---- ...gh_4467_sql_id_backwards_compatibility_test.lua | 13 +++++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/box/sql.c b/src/box/sql.c index 9bfabb2ea6..783f9c497e 100644 --- a/src/box/sql.c +++ b/src/box/sql.c @@ -1696,6 +1696,14 @@ sql_coll_id_by_token(const struct Token *name) char *name_str = sql_name_from_token(name); struct coll_id *coll_id = coll_by_name(name_str, strlen(name_str)); sql_xfree(name_str); + if (coll_id != NULL) + return coll_id->id; + if (name->z[0] == '"') + return UINT32_MAX; + + char *old_name_str = sql_legacy_name_new(name->z, name->n); + coll_id = coll_by_name(old_name_str, strlen(old_name_str)); + sql_xfree(old_name_str); if (coll_id != NULL) return coll_id->id; return UINT32_MAX; diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index aed97cad5b..2d62ffae2d 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -1056,6 +1056,8 @@ sql_expr_new_dequoted(int op, const struct Token *token) memcpy(e->u.zToken, token->z, token->n); e->u.zToken[token->n] = '\0'; sqlDequote(e->u.zToken); + if (op == TK_ID || op == TK_COLLATE || op == TK_FUNCTION) + e->flags |= token->z[0] != '"' ? EP_Lookup2 : 0; return e; } @@ -5451,6 +5453,14 @@ sql_coll_id_by_expr(const struct Expr *expr) assert(expr->op == TK_COLLATE); const char *name = expr->u.zToken; struct coll_id *coll_id = coll_by_name(name, strlen(name)); + if (coll_id != NULL) + return coll_id->id; + if ((expr->flags & EP_Lookup2) == 0) + return UINT32_MAX; + + char *old_name_str = sql_legacy_name_new0(expr->u.zToken); + coll_id = coll_by_name(old_name_str, strlen(old_name_str)); + sql_xfree(old_name_str); if (coll_id != NULL) return coll_id->id; return UINT32_MAX; diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y index 6a8c6c4a11..22df60beb7 100644 --- a/src/box/sql/parse.y +++ b/src/box/sql/parse.y @@ -940,6 +940,8 @@ idlist(A) ::= nm(Y). { memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = '\0'; sqlDequote(p->u.zToken); + if (op == TK_ID || op == TK_COLLATE || op == TK_FUNCTION) + p->flags |= t.z[0] != '"' ? EP_Lookup2 : 0; #if SQL_MAX_EXPR_DEPTH>0 p->nHeight = 1; #endif diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 1a527297c6..5beaf11a70 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -1415,6 +1415,8 @@ struct Expr { #define EP_Error 0x000008 /* Expression contains one or more errors */ #define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ +/** Second lookup could be performed for the ID. */ +#define EP_Lookup2 0x000040 #define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ #define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ @@ -3152,15 +3154,19 @@ uint32_t sql_fieldno_by_item(const struct space *space, const struct ExprList_item *it); /** - * Return the ID of the collation with the name defined by the token. Return - * UINT32_MAX if the field was not found. + * Return the ID of the collation with the name defined by the token. A second + * lookup will be performed if the collation is not found on the first try and + * token is not start with double quote. Return UINT32_MAX if the field was not + * found. */ uint32_t sql_coll_id_by_token(const struct Token *name); /** - * Return the ID of the collation with the name defined by the expression. - * Return UINT32_MAX if the field was not found. + * Return the ID of the collation with the name defined by the expression. A + * second lookup will be performed if the collation is not found on the first + * try and EP_Lookup2 flag is set. Return UINT32_MAX if the collation was not + * found. */ uint32_t sql_coll_id_by_expr(const struct Expr *expr); diff --git a/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua b/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua index 40433c9ef2..3c917b3171 100644 --- a/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua +++ b/test/sql-luatest/gh_4467_sql_id_backwards_compatibility_test.lua @@ -87,6 +87,19 @@ g.test_collation_name = function() local sql = [[SELECT UPPER('asd' COLLATE qwE);]] t.assert_equals(box.execute(sql).rows, {{'ASD'}}) box.space._collation:delete({coll.id}) + + coll_def = {'ZXC', 1, 'BINARY', '', map} + coll = box.space._collation:auto_increment(coll_def) + t.assert(coll ~= nil) + t.assert_equals(coll.name, 'ZXC') + sql = [[SELECT UPPER('asd' COLLATE zXc);]] + t.assert_equals(box.execute(sql).rows, {{'ASD'}}) + + sql = [[CREATE TABLE t(s STRING PRIMARY KEY COLLATE Zxc);]] + t.assert_equals(box.execute(sql), {row_count = 1}) + t.assert_equals(box.space.t:format()[1].collation, coll.id) + box.space.t:drop() + box.space._collation:delete({coll.id}) end) end -- GitLab