[Tarantool-patches] [PATCH v2 2/5] sql: introduce SQL built-in functions to parser

imeevma at tarantool.org imeevma at tarantool.org
Wed Aug 18 17:34:59 MSK 2021


This patch moves SQL built-in functions to parser, so now names of these
functions are new keywords. Also, but to this the number of arguments
for functions with a variable number of arguments will be checked during
parsing. For functions with a constant number of arguments, it is always
checked during parsing.

Part of #6105
---
 extra/mkkeywordhash.c                    |  37 +-
 src/box/sql/parse.y                      | 507 ++++++++++++++++++++++-
 test/box/tx_man.result                   |   4 +-
 test/box/tx_man.test.lua                 |   4 +-
 test/sql-tap/autoindex5.test.lua         |   2 +-
 test/sql-tap/built-in-functions.test.lua | 109 +++++
 test/sql-tap/default.test.lua            |   2 +-
 test/sql-tap/func.test.lua               |  12 +-
 test/sql-tap/func2.test.lua              |  18 +-
 test/sql-tap/func5.test.lua              |   6 +-
 test/sql-tap/identifier_case.test.lua    |   9 +-
 test/sql-tap/keyword1.test.lua           |  41 +-
 test/sql-tap/misc5.test.lua              |   4 +-
 test/sql-tap/select1.test.lua            |  14 +-
 test/sql-tap/select6.test.lua            |  16 +-
 test/sql-tap/select8.test.lua            |   8 +-
 test/sql-tap/sql-errors.test.lua         |   8 +-
 test/sql-tap/tkt1449.test.lua            |   2 +-
 test/sql-tap/uuid.test.lua               |   2 +-
 test/sql-tap/where3.test.lua             |   8 +-
 test/sql/collation.result                |   6 +-
 test/sql/collation.test.lua              |   4 +-
 test/sql/message-func-indexes.result     |   6 +-
 test/sql/message-func-indexes.test.lua   |   6 +-
 24 files changed, 749 insertions(+), 86 deletions(-)
 create mode 100755 test/sql-tap/built-in-functions.test.lua

diff --git a/extra/mkkeywordhash.c b/extra/mkkeywordhash.c
index 0d998506c..369d9e1dd 100644
--- a/extra/mkkeywordhash.c
+++ b/extra/mkkeywordhash.c
@@ -184,7 +184,6 @@ static Keyword aKeywordTable[] = {
   { "BLOB",                   "TK_STANDARD",    true  },
   { "BINARY",                 "TK_ID",          true  },
   { "CALL",                   "TK_STANDARD",    true  },
-  { "CHAR",                   "TK_CHAR",        true  },
   { "CHARACTER",              "TK_ID",          true  },
   { "CONDITION",              "TK_STANDARD",    true  },
   { "CONNECT",                "TK_STANDARD",    true  },
@@ -251,6 +250,42 @@ static Keyword aKeywordTable[] = {
   { "LEADING",                "TK_LEADING",     true  },
   { "TRAILING",               "TK_TRAILING",    true  },
   { "BOTH",                   "TK_BOTH",        true  },
+  { "ABS",                    "TK_ABS",         true  },
+  { "AVG",                    "TK_AVG",         true  },
+  { "CHAR",                   "TK_CHAR",        true  },
+  { "CHAR_LENGTH",            "TK_CHAR_LEN",    true  },
+  { "CHARACTER_LENGTH",       "TK_CHAR_LEN",    true  },
+  { "COALESCE",               "TK_COALESCE",    true  },
+  { "COUNT",                  "TK_COUNT",       true  },
+  { "GREATEST",               "TK_GREATEST",    true  },
+  { "GROUP_CONCAT",           "TK_GROUP_CONCAT",true  },
+  { "HEX",                    "TK_HEX",         true  },
+  { "IFNULL",                 "TK_IFNULL",      true  },
+  { "LEAST",                  "TK_LEAST",       true  },
+  { "LENGTH",                 "TK_LENGTH",      true  },
+  { "LIKELIHOOD",             "TK_LIKELIHOOD",  true  },
+  { "LIKELY",                 "TK_LIKELY",      true  },
+  { "LOWER",                  "TK_LOWER",       true  },
+  { "MAX",                    "TK_MAX",         true  },
+  { "MIN",                    "TK_MIN",         true  },
+  { "NULLIF",                 "TK_NULLIF",      true  },
+  { "POSITION",               "TK_POSITION",    true  },
+  { "PRINTF",                 "TK_PRINTF",      true  },
+  { "QUOTE",                  "TK_QUOTE",       true  },
+  { "RANDOM",                 "TK_RANDOM",      true  },
+  { "RANDOMBLOB",             "TK_RANDOMBLOB",  true  },
+  { "ROUND",                  "TK_ROUND",       true  },
+  { "ROW_COUNT",              "TK_ROW_COUNT",   true  },
+  { "SOUNDEX",                "TK_SOUNDEX",     true  },
+  { "SUBSTR",                 "TK_SUBSTR",      true  },
+  { "SUM",                    "TK_SUM",         true  },
+  { "TOTAL",                  "TK_TOTAL",       true  },
+  { "TYPEOF",                 "TK_TYPEOF",      true  },
+  { "UNICODE",                "TK_UNICODE",     true  },
+  { "UNLIKELY",               "TK_UNLIKELY",    true  },
+  { "UPPER",                  "TK_UPPER",       true  },
+  { "VERSION",                "TK_VERSION",     true  },
+  { "ZEROBLOB",               "TK_ZEROBLOB",    true  },
 };
 
 /* Number of keywords */
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index bd041e862..cb2e627db 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1172,27 +1172,506 @@ trim_specification(A) ::= LEADING.  { A = TRIM_LEADING; }
 trim_specification(A) ::= TRAILING. { A = TRIM_TRAILING; }
 trim_specification(A) ::= BOTH.     { A = TRIM_BOTH; }
 
-expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
-  if( Y && Y->nExpr>pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG] ){
-    const char *err =
-      tt_sprintf("Number of arguments to function %.*s", X.n, X.z);
-    diag_set(ClientError, ER_SQL_PARSER_LIMIT, err, Y->nExpr,
-             pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]);
+expr(A) ::= ABS(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ABS", "1", n);
     pParse->is_aborted = true;
+    return;
   }
   A.pExpr = sqlExprFunction(pParse, Y, &X);
-  spanSet(&A,&X,&E);
-  if( D==SF_Distinct && A.pExpr ){
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
     A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= AVG(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "AVG", "1", n);
+    pParse->is_aborted = true;
+    return;
   }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
 }
 
-/*
- * type_func(A) ::= DATE(A) .
- * type_func(A) ::= DATETIME(A) .
- */
-type_func(A) ::= CHAR(A) .
-expr(A) ::= type_func(X) LP distinct(D) exprlist(Y) RP(E). {
+expr(A) ::= CHAR(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL && Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) {
+    const char *str = tt_sprintf("from %d to %d", 0,
+                                 pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "CHAR", str, Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= CHAR_LEN(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *name = X.n == strlen("CHAR_LENGTH") ? "CHAR_LENGTH" :
+                       "CHARACTER_LENGTH";
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, name, "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= COALESCE(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr < 2 ||
+      Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *str = tt_sprintf("from %d to %d", 2,
+                                 pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "COALESCE", str, n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= COUNT(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL && Y->nExpr > 1) {
+    const char *str = tt_sprintf("from %d to %d", 0, 1);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "COUNT", str, Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  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 = sqlExprFunction(pParse, NULL, &X);
+  spanSet(&A, &X, &E);
+}
+
+expr(A) ::= GREATEST(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr < 2 ||
+      Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *str = tt_sprintf("from %d to %d", 2,
+                                 pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "GREATEST", str, n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= GROUP_CONCAT(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr > 2) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *str = tt_sprintf("from %d to %d", 1, 2);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "GROUP_CONCAT", str, n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= HEX(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "HEX", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= IFNULL(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 2) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "IFNULL", "2", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= LEAST(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr < 2 ||
+      Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *str = tt_sprintf("from %d to %d", 2,
+                                 pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "LEAST", str, n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= LENGTH(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "LENGTH", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= LIKELIHOOD(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 2) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "LIKELIHOOD", "2", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= LIKELY(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "LIKELY", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= LOWER(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "LOWER", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= MAX(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "MAX", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= MIN(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "MIN", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= NULLIF(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 2) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "NULLIF", "2", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= POSITION(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 2) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "POSITION", "2", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= PRINTF(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL && Y->nExpr > pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]) {
+    const char *str = tt_sprintf("from %d to %d", 0,
+                                 pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG]);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "PRINTF", str, Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= QUOTE(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "QUOTE", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= RANDOM(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL) {
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "RANDOM", "0", Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= RANDOMBLOB(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "RANDOMBLOB", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= REPLACE(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 3) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "REPLACE", "3", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= ROUND(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr > 2) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *str = tt_sprintf("from %d to %d", 1, 2);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ROUND", str, n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= ROW_COUNT(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL) {
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ROW_COUNT", "0", Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= SOUNDEX(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "SOUNDEX", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= SUBSTR(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr < 2 || Y->nExpr > 3) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    const char *str = tt_sprintf("from %d to %d", 2, 3);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "SUBSTR", str, n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= SUM(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "SUM", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= TOTAL(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "TOTAL", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= TYPEOF(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "TYPEOF", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= UNICODE(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "UNICODE", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= UNLIKELY(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "UNLIKELY", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= UPPER(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "UPPER", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= UUID(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL && Y->nExpr > 1) {
+    const char *str = tt_sprintf("from %d to %d", 0, 1);
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "UUID", str, Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= VERSION(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y != NULL) {
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "VERSION", "0", Y->nExpr);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= ZEROBLOB(X) LP distinct(D) exprlist(Y) RP(E). {
+  if (Y == NULL || Y->nExpr != 1) {
+    int n = Y == NULL ? 0 : Y->nExpr;
+    diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ZEROBLOB", "1", n);
+    pParse->is_aborted = true;
+    return;
+  }
+  A.pExpr = sqlExprFunction(pParse, Y, &X);
+  spanSet(&A, &X, &E);
+  if(D == SF_Distinct && A.pExpr)
+    A.pExpr->flags |= EP_Distinct;
+}
+
+expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
   if( Y && Y->nExpr>pParse->db->aLimit[SQL_LIMIT_FUNCTION_ARG] ){
     const char *err =
       tt_sprintf("Number of arguments to function %.*s", X.n, X.z);
diff --git a/test/box/tx_man.result b/test/box/tx_man.result
index 786d7fc30..b99fbc2ca 100644
--- a/test/box/tx_man.result
+++ b/test/box/tx_man.result
@@ -2129,11 +2129,11 @@ tx1:rollback()
 
 -- gh-6095: SQL query may crash in MVCC mode if it involves ephemeral spaces.
 --
-box.execute([[ CREATE TABLE test (id INT NOT NULL PRIMARY KEY, count INT NOT NULL)]])
+box.execute([[ CREATE TABLE test (id INT NOT NULL PRIMARY KEY, "COUNT" INT NOT NULL)]])
  | ---
  | - row_count: 1
  | ...
-box.execute([[ UPDATE test SET count = count + 1 WHERE id = 0 ]])
+box.execute([[ UPDATE test SET "COUNT" = "COUNT" + 1 WHERE id = 0 ]])
  | ---
  | - row_count: 0
  | ...
diff --git a/test/box/tx_man.test.lua b/test/box/tx_man.test.lua
index ebb86dd13..1f32bd8dd 100644
--- a/test/box/tx_man.test.lua
+++ b/test/box/tx_man.test.lua
@@ -661,8 +661,8 @@ tx1:rollback()
 
 -- gh-6095: SQL query may crash in MVCC mode if it involves ephemeral spaces.
 --
-box.execute([[ CREATE TABLE test (id INT NOT NULL PRIMARY KEY, count INT NOT NULL)]])
-box.execute([[ UPDATE test SET count = count + 1 WHERE id = 0 ]])
+box.execute([[ CREATE TABLE test (id INT NOT NULL PRIMARY KEY, "COUNT" INT NOT NULL)]])
+box.execute([[ UPDATE test SET "COUNT" = "COUNT" + 1 WHERE id = 0 ]])
 box.execute([[ DROP TABLE test]])
 
 -- https://github.com/tarantool/tarantool/issues/5515
diff --git a/test/sql-tap/autoindex5.test.lua b/test/sql-tap/autoindex5.test.lua
index 488924b09..8d56971df 100755
--- a/test/sql-tap/autoindex5.test.lua
+++ b/test/sql-tap/autoindex5.test.lua
@@ -40,7 +40,7 @@ test:do_execsql_test(
                     release_t TEXT NOT NULL,
                     subrelease TEXT NOT NULL,
                     archive TEXT NOT NULL,
-                    version TEXT NOT NULL,
+                    version_txt TEXT NOT NULL,
                     version_id INTEGER NOT NULL DEFAULT 0,
                     PRIMARY KEY (name, release_t, subrelease, archive));
 
diff --git a/test/sql-tap/built-in-functions.test.lua b/test/sql-tap/built-in-functions.test.lua
new file mode 100755
index 000000000..3575062ae
--- /dev/null
+++ b/test/sql-tap/built-in-functions.test.lua
@@ -0,0 +1,109 @@
+#!/usr/bin/env tarantool
+local test = require("sqltester")
+test:plan(10)
+
+--
+-- Make sure that number of arguments check is checked properly for SQL built-in
+-- functions with variable number of arguments.
+--
+test:do_catchsql_test(
+    "builtins-1.1",
+    [[
+        SELECT COUNT(1, 2);
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to COUNT(): expected from 0 to 1, got 2]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.2",
+    [[
+        SELECT GREATEST();
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to GREATEST(): expected from 2 to 127, got 0]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.3",
+    [[
+        SELECT GROUP_CONCAT();
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to GROUP_CONCAT(): expected from 1 to 2, got 0]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.4",
+    [[
+        SELECT GROUP_CONCAT(1, 2, 3);
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to GROUP_CONCAT(): expected from 1 to 2, got 3]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.5",
+    [[
+        SELECT LEAST();
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to LEAST(): expected from 2 to 127, got 0]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.6",
+    [[
+        SELECT ROUND();
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to ROUND(): expected from 1 to 2, got 0]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.7",
+    [[
+        SELECT ROUND(1, 2, 3);
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to ROUND(): expected from 1 to 2, got 3]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.8",
+    [[
+        SELECT SUBSTR('1');
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 1]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.9",
+    [[
+        SELECT SUBSTR('1', '2', '3', '4');
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 4]]
+    }
+)
+
+test:do_catchsql_test(
+    "builtins-1.10",
+    [[
+        SELECT UUID(1, 2);
+    ]],
+    {
+        1, [[Wrong number of arguments is passed to UUID(): expected from 0 to 1, got 2]]
+    }
+)
+
+test:finish_test()
diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua
index 9c15220eb..41f23386c 100755
--- a/test/sql-tap/default.test.lua
+++ b/test/sql-tap/default.test.lua
@@ -62,7 +62,7 @@ test:do_catchsql_test(
 	CREATE TABLE t3(
 	rowid INTEGER PRIMARY KEY AUTOINCREMENT,
 	x INTEGER,
-	y INTEGER DEFAULT (max(x,5))
+	y INTEGER DEFAULT (greatest(x,5))
 	);
 	]], {
 	-- <default-1.3>
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index e7b35c9d9..7dd85025a 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -68,7 +68,7 @@ test:do_catchsql_test(
         SELECT length(*) FROM tbl1 ORDER BY t1
     ]], {
         -- <func-1.1>
-        1, "Wrong number of arguments is passed to LENGTH(): expected 1, got 0"
+        1, "Syntax error at line 1 near '*'"
         -- </func-1.1>
     })
 
@@ -427,7 +427,7 @@ test:do_catchsql_test(
         SELECT round(a,b,c) FROM t1
     ]], {
         -- <func-4.5>
-        1, "Wrong number of arguments is passed to ROUND(): expected 1 or 2, got 3"
+        1, "Wrong number of arguments is passed to ROUND(): expected from 1 to 2, got 3"
         -- </func-4.5>
     })
 
@@ -487,7 +487,7 @@ test:do_catchsql_test(
         SELECT round() FROM t1 ORDER BY a
     ]], {
         -- <func-4.11>
-        1, "Wrong number of arguments is passed to ROUND(): expected 1 or 2, got 0"
+        1, "Wrong number of arguments is passed to ROUND(): expected from 1 to 2, got 0"
         -- </func-4.11>
     })
 
@@ -777,7 +777,7 @@ test:do_catchsql_test(
         SELECT upper(*) FROM t2
     ]], {
         -- <func-5.5>
-        1, "Wrong number of arguments is passed to UPPER(): expected 1, got 0"
+        1, "Syntax error at line 1 near '*'"
         -- </func-5.5>
     })
 
@@ -2483,7 +2483,7 @@ test:do_catchsql_test(
         SELECT coalesce()
     ]], {
         -- <func-27.1>
-        1, "Wrong number of arguments is passed to COALESCE(): expected at least two, got 0"
+        1, "Wrong number of arguments is passed to COALESCE(): expected from 2 to 127, got 0"
         -- </func-27.1>
     })
 
@@ -2493,7 +2493,7 @@ test:do_catchsql_test(
         SELECT coalesce(1)
     ]], {
         -- <func-27.2>
-        1, "Wrong number of arguments is passed to COALESCE(): expected at least two, got 1"
+        1, "Wrong number of arguments is passed to COALESCE(): expected from 2 to 127, got 1"
         -- </func-27.2>
     })
 
diff --git a/test/sql-tap/func2.test.lua b/test/sql-tap/func2.test.lua
index 95b8a1f5f..792f020f1 100755
--- a/test/sql-tap/func2.test.lua
+++ b/test/sql-tap/func2.test.lua
@@ -50,7 +50,7 @@ test:do_catchsql_test(
         SELECT SUBSTR()
     ]], {
         -- <func2-1.2.1>
-        1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 0"
+        1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 0"
         -- </func2-1.2.1>
     })
 
@@ -60,7 +60,7 @@ test:do_catchsql_test(
         SELECT SUBSTR('Supercalifragilisticexpialidocious')
     ]], {
         -- <func2-1.2.2>
-        1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 1"
+        1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 1"
         -- </func2-1.2.2>
     })
 
@@ -70,7 +70,7 @@ test:do_catchsql_test(
         SELECT SUBSTR('Supercalifragilisticexpialidocious', 1,1,1)
     ]], {
         -- <func2-1.2.3>
-        1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 4"
+        1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 4"
         -- </func2-1.2.3>
     })
 
@@ -673,7 +673,7 @@ if ("ሴ" ~= "u1234")
             SELECT SUBSTR()
         ]], {
             -- <func2-2.1.2>
-            1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 0"
+            1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 0"
             -- </func2-2.1.2>
         })
 
@@ -683,7 +683,7 @@ if ("ሴ" ~= "u1234")
             SELECT SUBSTR('hiሴho')
         ]], {
             -- <func2-2.1.3>
-            1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 1"
+            1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 1"
             -- </func2-2.1.3>
         })
 
@@ -693,7 +693,7 @@ if ("ሴ" ~= "u1234")
             SELECT SUBSTR('hiሴho', 1,1,1)
         ]], {
             -- <func2-2.1.4>
-            1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 4"
+            1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 4"
             -- </func2-2.1.4>
         })
 
@@ -1038,7 +1038,7 @@ test:do_catchsql_test(
         SELECT SUBSTR()
     ]], {
         -- <func2-3.1.2>
-        1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 0"
+        1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 0"
         -- </func2-3.1.2>
     })
 
@@ -1048,7 +1048,7 @@ test:do_catchsql_test(
         SELECT SUBSTR(x'1234')
     ]], {
         -- <func2-3.1.3>
-        1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 1"
+        1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 1"
         -- </func2-3.1.3>
     })
 
@@ -1058,7 +1058,7 @@ test:do_catchsql_test(
         SELECT SUBSTR(x'1234', 1,1,1)
     ]], {
         -- <func2-3.1.4>
-        1, "Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 4"
+        1, "Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 4"
         -- </func2-3.1.4>
     })
 
diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua
index 44755b1f7..71c971fe4 100755
--- a/test/sql-tap/func5.test.lua
+++ b/test/sql-tap/func5.test.lua
@@ -276,19 +276,19 @@ test:do_catchsql_test(
     "func-5-5.1",
     [[
         SELECT LEAST(false);
-    ]], { 1, "Wrong number of arguments is passed to LEAST(): expected at least two, got 1" } )
+    ]], { 1, "Wrong number of arguments is passed to LEAST(): expected from 2 to 127, got 1" } )
 
 test:do_catchsql_test(
     "func-5-5.2",
     [[
         SELECT GREATEST('abc');
-    ]], { 1, "Wrong number of arguments is passed to GREATEST(): expected at least two, got 1" } )
+    ]], { 1, "Wrong number of arguments is passed to GREATEST(): expected from 2 to 127, got 1" } )
 
 test:do_catchsql_test(
     "func-5-5.3",
     [[
         SELECT LEAST();
-    ]], { 1, "Wrong number of arguments is passed to LEAST(): expected at least two, got 0" } )
+    ]], { 1, "Wrong number of arguments is passed to LEAST(): expected from 2 to 127, got 0" } )
 
 -- Make sure that ifnull() returns type of corresponding (i.e. first
 -- non-null) argument.
diff --git a/test/sql-tap/identifier_case.test.lua b/test/sql-tap/identifier_case.test.lua
index 097fa1b64..41668ddc5 100755
--- a/test/sql-tap/identifier_case.test.lua
+++ b/test/sql-tap/identifier_case.test.lua
@@ -200,7 +200,6 @@ for _, row in ipairs(data) do
         row[3])
 end
 
-
 -- Check that collaiton names work as identifiers
 data = {
     { 1,  [[ binary ]], {1, "Collation 'BINARY' does not exist"}},
@@ -208,7 +207,9 @@ data = {
     { 3,  [["binary"]], {0}},
     { 4,  [["bInaRy"]], {1, "Collation 'bInaRy' does not exist"}},
     { 5,  [["unicode"]], {0}},
-    { 6,  [[ unicode ]], {1,"Collation 'UNICODE' does not exist"}},
+    { 6,  [[ unicode ]], {1, [[At line 1 at or near position 51: keyword ]]..
+                             [['unicode' is reserved. Please use double ]]..
+                             [[quotes if 'unicode' is an identifier.]]}},
     { 7,  [["UNICODE"]], {1,"Collation 'UNICODE' does not exist"}},
     { 8,  [[NONE]], {1,"Collation 'NONE' does not exist"}},
     { 9,  [["none"]], {0}},
@@ -243,7 +244,9 @@ data = {
     { 3,  [[ 'a' < 'b' collate 'binary' ]], {1, [[Syntax error at line 1 near ''binary'']]}},
     { 4,  [[ 'a' < 'b' collate "unicode" ]], {0, {true}}},
     { 5,  [[ '5' < 'b' collate "unicode" ]], {0, {true}}},
-    { 6,  [[ '5' < 'b' collate unicode ]], {1,"Collation 'UNICODE' does not exist"}},
+    { 6,  [[ '5' < 'b' collate unicode ]], {1,
+        [[At line 1 at or near position 43: keyword 'unicode' is reserved. ]]..
+        [[Please use double quotes if 'unicode' is an identifier.]]}},
     { 7,  [[ '5' < 'b' collate "unicode_ci" ]], {0, {true}}},
     { 8,  [[ '5' < 'b' collate NONE ]], {1, "Collation 'NONE' does not exist"}},
     { 9,  [[ '5' < 'b' collate "none" ]], {0, {true}}},
diff --git a/test/sql-tap/keyword1.test.lua b/test/sql-tap/keyword1.test.lua
index f9a9c6865..a0461abfd 100755
--- a/test/sql-tap/keyword1.test.lua
+++ b/test/sql-tap/keyword1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 local test = require("sqltester")
-test:plan(184)
+test:plan(219)
 
 --!./tcltestrunner.lua
 -- 2009 January 29
@@ -138,7 +138,6 @@ local bannedkws = {
 	"asensitive",
 	"binary",
 	"call",
-	"char",
 	"character",
 	"condition",
 	"connect",
@@ -192,7 +191,43 @@ local bannedkws = {
 	"varchar",
 	"varbinary",
 	"whenever",
-	"while"
+	"while",
+	"abs",
+	"avg",
+	"char",
+	"char_length",
+	"character_length",
+	"coalesce",
+	"count",
+	"greatest",
+	"group_concat",
+	"hex",
+	"ifnull",
+	"least",
+	"length",
+	"likelihood",
+	"likely",
+	"lower",
+	"max",
+	"min",
+	"nullif",
+	"position",
+	"printf",
+	"quote",
+	"random",
+	"randomblob",
+	"round",
+	"row_count",
+	"soundex",
+	"substr",
+	"sum",
+	"total",
+	"typeof",
+	"unicode",
+	"unlikely",
+	"upper",
+	"version",
+	"zeroblob"
 }
 local exprkw = [[
     "cast",
diff --git a/test/sql-tap/misc5.test.lua b/test/sql-tap/misc5.test.lua
index 38eddfc64..55c8cef39 100755
--- a/test/sql-tap/misc5.test.lua
+++ b/test/sql-tap/misc5.test.lua
@@ -176,10 +176,10 @@ test:do_execsql_test(
               --     one      10
               --     three    5
               --
-              SELECT DISTINCT artist,sum(timesplayed) AS total
+              SELECT DISTINCT artist,sum(timesplayed) AS "TOTAL"
               FROM songs
               GROUP BY LOWER(artist)
-              ORDER BY total DESC
+              ORDER BY "TOTAL" DESC
               LIMIT 10
             )
             WHERE artist <> ''
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index 2bf7fd3a2..568b3ee2d 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -250,7 +250,7 @@ test:do_catchsql_test(
         SELECT count(f1,f2) FROM test1
     ]], {
         -- <select1-2.1>
-        1, "Wrong number of arguments is passed to COUNT(): expected 0 or 1, got 2"
+        1, "Wrong number of arguments is passed to COUNT(): expected from 0 to 1, got 2"
         -- </select1-2.1>
     })
 
@@ -330,7 +330,7 @@ test:do_catchsql_test(
         SELECT min(*) FROM test1
     ]], {
         -- <select1-2.6>
-        1, "Wrong number of arguments is passed to MIN(): expected 1, got 0"
+        1, "Syntax error at line 1 near '*'"
         -- </select1-2.6>
     })
 
@@ -395,7 +395,7 @@ test:do_catchsql_test(
         SELECT MAX(*) FROM test1
     ]], {
         -- <select1-2.9>
-        1, "Wrong number of arguments is passed to MAX(): expected 1, got 0"
+        1, "Syntax error at line 1 near '*'"
         -- </select1-2.9>
     })
 
@@ -475,7 +475,7 @@ test:do_catchsql_test(
         SELECT SUM(*) FROM test1
     ]], {
         -- <select1-2.14>
-        1, "Wrong number of arguments is passed to SUM(): expected 1, got 0"
+        1, "Syntax error at line 1 near '*'"
         -- </select1-2.14>
     })
 
@@ -697,7 +697,7 @@ test:do_catchsql_test(
         SELECT f1 FROM test1 WHERE count(f1,f2)!=11
     ]], {
         -- <select1-3.9>
-        1, "misuse of aggregate function COUNT()"
+        1, "Wrong number of arguments is passed to COUNT(): expected from 0 to 1, got 2"
         -- </select1-3.9>
     })
 
@@ -1982,8 +1982,8 @@ test:do_test(
         -- This used to seg-fault when the problem existed.
         return test:execsql [[
             SELECT count(
-              (SELECT a FROM abc WHERE a = NULL AND b >= upper.c)
-            ) FROM abc AS upper;
+              (SELECT a FROM abc WHERE a = NULL AND b >= "UPPER".c)
+            ) FROM abc AS "UPPER";
         ]]
     end, {
         -- <select1-13.1>
diff --git a/test/sql-tap/select6.test.lua b/test/sql-tap/select6.test.lua
index 031892112..2142aaf46 100755
--- a/test/sql-tap/select6.test.lua
+++ b/test/sql-tap/select6.test.lua
@@ -152,9 +152,9 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select6-1.9",
     [=[
-        SELECT q, p, r, min
+        SELECT q, p, r, m
         FROM (SELECT count(*) as p , y as q FROM t1 GROUP BY y) AS a,
-             (SELECT max(x) as r, y as s, min(x)+y AS min FROM t1 GROUP BY y) as b
+             (SELECT max(x) as r, y as s, min(x)+y AS m FROM t1 GROUP BY y) as b
         WHERE q=s ORDER BY s
     ]=], {
         -- <select6-1.9>
@@ -245,9 +245,9 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select6-2.7",
     [=[
-        SELECT a.b, a.count, max, count
-        FROM (SELECT count(*) AS count, b FROM t2 GROUP BY b) AS a,
-             (SELECT max(a) AS max, b FROM t2 GROUP BY b) as b
+        SELECT a.b, a.c, m, c
+        FROM (SELECT count(*) AS c, b FROM t2 GROUP BY b) AS a,
+             (SELECT max(a) AS m, b FROM t2 GROUP BY b) as b
         WHERE a.b=b.b ORDER BY a.b
     ]=], {
         -- <select6-2.7>
@@ -429,8 +429,8 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select6-3.14",
     [=[
-        SELECT count, y FROM (SELECT count(*) AS count, y FROM t1 GROUP BY y)
-        ORDER BY count
+        SELECT c, y FROM (SELECT count(*) AS c, y FROM t1 GROUP BY y)
+        ORDER BY c
     ]=], {
         -- <select6-3.14>
         1, 1, 2, 2, 4, 3, 5, 5, 8, 4
@@ -440,7 +440,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select6-3.15",
     [=[
-        SELECT count, y FROM (SELECT count(*) AS count, y FROM t1 GROUP BY y)
+        SELECT c, y FROM (SELECT count(*) AS c, y FROM t1 GROUP BY y)
         ORDER BY y
     ]=], {
         -- <select6-3.15>
diff --git a/test/sql-tap/select8.test.lua b/test/sql-tap/select8.test.lua
index 747dd9bca..336ea1c0b 100755
--- a/test/sql-tap/select8.test.lua
+++ b/test/sql-tap/select8.test.lua
@@ -32,7 +32,7 @@ test:execsql [[
     INSERT INTO songs VALUES(6,'two',11);
 ]]
 local result = test:execsql [[
-    SELECT DISTINCT artist,sum(timesplayed) AS total
+    SELECT DISTINCT artist,sum(timesplayed) AS "TOTAL"
     FROM songs
     GROUP BY LOWER(artist)
 ]]
@@ -48,7 +48,7 @@ end
 test:do_execsql_test(
     "select8-1.1",
     [[
-        SELECT DISTINCT artist,sum(timesplayed) AS total
+        SELECT DISTINCT artist,sum(timesplayed) AS "TOTAL"
         FROM songs
         GROUP BY LOWER(artist)
         LIMIT 1 OFFSET 1
@@ -57,7 +57,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select8-1.2",
     [[
-        SELECT DISTINCT artist,sum(timesplayed) AS total
+        SELECT DISTINCT artist,sum(timesplayed) AS "TOTAL"
         FROM songs
         GROUP BY LOWER(artist)
         LIMIT 2 OFFSET 1
@@ -66,7 +66,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "select8-1.3",
     [[
-        SELECT DISTINCT artist,sum(timesplayed) AS total
+        SELECT DISTINCT artist,sum(timesplayed) AS "TOTAL"
         FROM songs
         GROUP BY LOWER(artist)
         LIMIT 1000 OFFSET 2
diff --git a/test/sql-tap/sql-errors.test.lua b/test/sql-tap/sql-errors.test.lua
index daf0ee643..f85a31010 100755
--- a/test/sql-tap/sql-errors.test.lua
+++ b/test/sql-tap/sql-errors.test.lua
@@ -40,7 +40,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
 	"sql-errors-1.3",
 	[[
-		CREATE TABLE t3 (i INT PRIMARY KEY, a INT DEFAULT(MAX(i, 1)));
+		CREATE TABLE t3 (i INT PRIMARY KEY, a INT DEFAULT(GREATEST(i, 1)));
 	]], {
 		-- <sql-errors-1.3>
 		1,"Failed to create space 'T3': default value of column 'A' is not constant"
@@ -183,7 +183,8 @@ test:do_catchsql_test(
 	select_statement,
 	{
 		-- <sql-errors-1.16>
-		1,"Number of arguments to function CHAR 128 exceeds the limit (127)"
+		1, [[Wrong number of arguments is passed to CHAR(): ]]..
+		   [[expected from 0 to 127, got 128]]
 		-- </sql-errors-1.16>
 	})
 
@@ -198,7 +199,8 @@ test:do_catchsql_test(
 	select_statement,
 	{
 		-- <sql-errors-1.17>
-		1,"Number of arguments to function MAX 128 exceeds the limit (127)"
+		1, [[Wrong number of arguments is passed to MAX(): ]]..
+		   [[expected 1, got 128]]
 		-- </sql-errors-1.17>
 	})
 
diff --git a/test/sql-tap/tkt1449.test.lua b/test/sql-tap/tkt1449.test.lua
index ef69b09ac..085a333e5 100755
--- a/test/sql-tap/tkt1449.test.lua
+++ b/test/sql-tap/tkt1449.test.lua
@@ -40,7 +40,7 @@ test:do_execsql_test(
         CREATE TABLE ATTACHMENTS(TQUNID varchar(36) not null, OBJECTID varchar(50) null, ISSUEID varchar(50) null, DATASTREAM SCALAR not null, CONTENTENCODING varchar(50) null, CONTENTCHARSET varchar(50) null, CONTENTTYPE varchar(100) null, CONTENTID varchar(100) null, CONTENTLOCATION varchar(100) null, CONTENTNAME varchar(100) not null, constraint PK_ATTACHMENTS primary key (TQUNID));
         CREATE TABLE COMPLIANCEPOLICIES(CLASSID int null, SEQNO int not null, LASTMODONNODEID varchar(50) not null, PREVMODONNODEID varchar(50) null, ISSUEID varchar(50) not null, OBJECTID varchar(50) not null, REVISIONNUM int not null, CONTAINERID varchar(50) not null, AUTHORID varchar(50) not null, CREATIONDATE varchar(25) null, LASTMODIFIEDDATE varchar(25) null, UPDATENUMBER int null, PREVREVISIONNUM int null, LASTCMD int null, LASTCMDACLVERSION int null, USERDEFINEDFIELD varchar(300) null, LASTMODIFIEDBYID varchar(50) null, BODY text null, constraint PK_COMPLIANCEPOLICIES primary key (ISSUEID, OBJECTID));
         CREATE TABLE DBHISTORY(id INT primary key, "DATETIME" varchar(25) not null, OPERATION varchar(20) not null, KUBIVERSION varchar(100) not null, FROMVERSION int null, TOVERSION int null);
-        CREATE TABLE DBINFO(id INT primary key, FINGERPRINT varchar(32) not null, VERSION int not null);
+        CREATE TABLE DBINFO(id INT primary key, FINGERPRINT varchar(32) not null, "VERSION" int not null);
         CREATE TABLE DETACHEDATTACHMENTS (TQUNID varchar(36) not null, ISSUEID varchar(50) not null, OBJECTID varchar(50) not null, PATH varchar(300) not null, DETACHEDFILELASTMODTIMESTAMP varchar(25) null, CONTENTID varchar(100) not null, constraint PK_DETACHEDATTACHMENTS primary key (TQUNID));
         CREATE TABLE DOCREFERENCES(CLASSID int null, SEQNO int not null, LASTMODONNODEID varchar(50) not null, PREVMODONNODEID varchar(50) null, ISSUEID varchar(50) not null, OBJECTID varchar(50) not null, REVISIONNUM int not null, CONTAINERID varchar(50) not null, AUTHORID varchar(50) not null, CREATIONDATE varchar(25) null, LASTMODIFIEDDATE varchar(25) null, UPDATENUMBER int null, PREVREVISIONNUM int null, LASTCMD int null, LASTCMDACLVERSION int null, USERDEFINEDFIELD varchar(300) null, LASTMODIFIEDBYID varchar(50) null, REFERENCEDOCUMENTID varchar(50) null, constraint PK_DOCREFERENCES primary key (ISSUEID, OBJECTID));
         CREATE TABLE DQ (TQUNID varchar(36) not null, ISSUEID varchar(50) not null, DEPENDSID varchar(50) null, DEPENDSTYPE int null, DEPENDSCOMMANDSTREAM SCALAR null, DEPENDSNODEIDSEQNOKEY varchar(100) null, DEPENDSACLVERSION int null, constraint PK_DQ primary key (TQUNID));
diff --git a/test/sql-tap/uuid.test.lua b/test/sql-tap/uuid.test.lua
index ec5caab63..fd7c52351 100755
--- a/test/sql-tap/uuid.test.lua
+++ b/test/sql-tap/uuid.test.lua
@@ -1290,7 +1290,7 @@ test:do_catchsql_test(
     [[
         SELECT uuid(4, 5);
     ]], {
-        1, "Wrong number of arguments is passed to UUID(): expected one or zero, got 2"
+        1, "Wrong number of arguments is passed to UUID(): expected from 0 to 1, got 2"
     })
 
 -- Make sure the uuid() function generates a new UUID each time when called.
diff --git a/test/sql-tap/where3.test.lua b/test/sql-tap/where3.test.lua
index 9b2bc2e25..eda106f68 100755
--- a/test/sql-tap/where3.test.lua
+++ b/test/sql-tap/where3.test.lua
@@ -444,19 +444,19 @@ test:do_execsql_test(
     [[
         CREATE TABLE aaa (id INTEGER PRIMARY KEY, type INTEGER,
                           fk TEXT DEFAULT NULL, parent INTEGER,
-                          position INTEGER, title TEXT,
+                          "POSITION" INTEGER, title TEXT,
                           keyword_id INTEGER, folder_type TEXT,
                           dateAdded INTEGER, lastModified INTEGER);
         CREATE INDEX aaa_111 ON aaa (fk, type);
-        CREATE INDEX aaa_222 ON aaa (parent, position);
+        CREATE INDEX aaa_222 ON aaa (parent, "POSITION");
         CREATE INDEX aaa_333 ON aaa (fk, lastModified);
         CREATE TABLE bbb (id INTEGER PRIMARY KEY, type INTEGER,
                           fk TEXT DEFAULT NULL, parent INTEGER,
-                          position INTEGER, title TEXT,
+                          "POSITION" INTEGER, title TEXT,
                           keyword_id INTEGER, folder_type TEXT,
                           dateAdded INTEGER, lastModified INTEGER);
         CREATE INDEX bbb_111 ON bbb (fk, type);
-        CREATE INDEX bbb_222 ON bbb (parent, position);
+        CREATE INDEX bbb_222 ON bbb (parent, "POSITION");
         CREATE INDEX bbb_333 ON bbb (fk, lastModified);
 
          SELECT bbb.title AS tag_title
diff --git a/test/sql/collation.result b/test/sql/collation.result
index 1fcc212d8..a94a047dc 100644
--- a/test/sql/collation.result
+++ b/test/sql/collation.result
@@ -63,7 +63,7 @@ box.execute([[INSERT INTO tu VALUES ('Latin Small Letter Dotless I U+0131','ı')
 - row_count: 1
 ...
 -- Without collation
-box.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower FROM tu;]])
+box.execute([[SELECT descriptor, upper(letter) AS "UPPER",lower(letter) AS "LOWER" FROM tu;]])
 ---
 - metadata:
   - name: DESCRIPTOR
@@ -79,7 +79,7 @@ box.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower F
   - ['Latin Small Letter I U+0069', 'I', 'i']
 ...
 -- With collation
-box.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS upper,lower(letter COLLATE "TURKISH") AS lower FROM tu;]])
+box.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS "UPPER", lower(letter COLLATE "TURKISH") AS "LOWER" FROM tu;]])
 ---
 - metadata:
   - name: DESCRIPTOR
@@ -298,7 +298,7 @@ box.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = c COLLATE \"unicode\";
 box.execute("SELECT * FROM t WHERE a COLLATE \"binary\" = substr();")
 ---
 - null
-- 'Wrong number of arguments is passed to SUBSTR(): expected 1 or 2, got 0'
+- 'Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 0'
 ...
 -- Compound queries perform implicit comparisons between values.
 -- Hence, rules for collations compatibilities are the same.
diff --git a/test/sql/collation.test.lua b/test/sql/collation.test.lua
index 407fc19dc..6d0f4f30c 100644
--- a/test/sql/collation.test.lua
+++ b/test/sql/collation.test.lua
@@ -21,9 +21,9 @@ box.execute([[INSERT INTO tu VALUES ('Latin Small Letter I U+0069','i');]])
 box.execute([[INSERT INTO tu VALUES ('Latin Capital Letter I With Dot Above U+0130','İ');]])
 box.execute([[INSERT INTO tu VALUES ('Latin Small Letter Dotless I U+0131','ı');]])
 -- Without collation
-box.execute([[SELECT descriptor, upper(letter) AS upper,lower(letter) AS lower FROM tu;]])
+box.execute([[SELECT descriptor, upper(letter) AS "UPPER",lower(letter) AS "LOWER" FROM tu;]])
 -- With collation
-box.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS upper,lower(letter COLLATE "TURKISH") AS lower FROM tu;]])
+box.execute([[SELECT descriptor, upper(letter COLLATE "TURKISH") AS "UPPER", lower(letter COLLATE "TURKISH") AS "LOWER" FROM tu;]])
 box.internal.collation.drop('TURKISH')
 
 -- For de-DE result is actually the same
diff --git a/test/sql/message-func-indexes.result b/test/sql/message-func-indexes.result
index 002dbd883..def2528ee 100644
--- a/test/sql/message-func-indexes.result
+++ b/test/sql/message-func-indexes.result
@@ -12,7 +12,7 @@ box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER)")
 ---
 - row_count: 1
 ...
-box.execute("CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, count INTEGER)")
+box.execute([[CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, "COUNT" INTEGER)]])
 ---
 - row_count: 1
 ...
@@ -36,12 +36,12 @@ box.execute("CREATE INDEX i4 ON t2(price)")
 ---
 - row_count: 1
 ...
-box.execute("CREATE INDEX i5 ON t2(count + 1)")
+box.execute([[CREATE INDEX i5 ON t2("COUNT" + 1)]])
 ---
 - null
 - Tarantool does not support functional indexes
 ...
-box.execute("CREATE INDEX i6 ON t2(count * price)")
+box.execute([[CREATE INDEX i6 ON t2("COUNT" * price)]])
 ---
 - null
 - Tarantool does not support functional indexes
diff --git a/test/sql/message-func-indexes.test.lua b/test/sql/message-func-indexes.test.lua
index 3cbfe3e61..ca3e54731 100644
--- a/test/sql/message-func-indexes.test.lua
+++ b/test/sql/message-func-indexes.test.lua
@@ -4,7 +4,7 @@ _ = box.space._session_settings:update('sql_default_engine', {{'=', 2, engine}})
 
 -- Creating tables.
 box.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER)")
-box.execute("CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, count INTEGER)")
+box.execute([[CREATE TABLE t2(object INTEGER PRIMARY KEY, price INTEGER, "COUNT" INTEGER)]])
 
 -- Expressions that're supposed to create functional indexes
 -- should return certain message.
@@ -12,8 +12,8 @@ box.execute("CREATE INDEX i1 ON t1(a+1)")
 box.execute("CREATE INDEX i2 ON t1(a)")
 box.execute("CREATE INDEX i3 ON t2(price + 100)")
 box.execute("CREATE INDEX i4 ON t2(price)")
-box.execute("CREATE INDEX i5 ON t2(count + 1)")
-box.execute("CREATE INDEX i6 ON t2(count * price)")
+box.execute([[CREATE INDEX i5 ON t2("COUNT" + 1)]])
+box.execute([[CREATE INDEX i6 ON t2("COUNT" * price)]])
 
 -- Cleaning up.
 box.execute("DROP TABLE t1")
-- 
2.25.1



More information about the Tarantool-patches mailing list