From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpng2.m.smailru.net (smtpng2.m.smailru.net [94.100.179.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 9B956445321 for ; Mon, 13 Jul 2020 08:33:09 +0300 (MSK) From: imeevma@tarantool.org Date: Mon, 13 Jul 2020 08:33:08 +0300 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v4 3/5] sql: check number of arguments in sql_func_by_signature() List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: korablev@tarantool.org, tsafin@tarantool.org, tarantool-patches@dev.tarantool.org After this patch, the number of function arguments will always be checked in the sql_func_by_signature() function. This was not the case for some of the built-in functions. Part of #4159 --- src/box/sql/expr.c | 18 +- src/box/sql/func.c | 208 +++-- src/box/sql/sqlInt.h | 13 + test/sql-tap/func.test.lua | 8 +- test/sql-tap/func2.test.lua | 18 +- test/sql-tap/func5.test.lua | 6 +- test/sql-tap/select1.test.lua | 4 +- test/sql/collation.result | 2 +- test/sql/gh-4159-function-argumens.result | 821 ++++++++++++++++++++ test/sql/gh-4159-function-argumens.test.sql | 193 +++++ 10 files changed, 1212 insertions(+), 79 deletions(-) create mode 100644 test/sql/gh-4159-function-argumens.result create mode 100644 test/sql/gh-4159-function-argumens.test.sql diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c index d0620b98c..7aee240a3 100644 --- a/src/box/sql/expr.c +++ b/src/box/sql/expr.c @@ -3987,14 +3987,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) */ if (sql_func_flag_is_set(func, SQL_FUNC_COALESCE)) { int endCoalesce = sqlVdbeMakeLabel(v); - if (nFarg < 2) { - diag_set(ClientError, - ER_FUNC_WRONG_ARG_COUNT, - func->def->name, - "at least two", nFarg); - pParse->is_aborted = true; - break; - } + assert(nFarg >= 2); sqlExprCode(pParse, pFarg->a[0].pExpr, target); for (i = 1; i < nFarg; i++) { @@ -4017,14 +4010,7 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target) * of the first argument. */ if (sql_func_flag_is_set(func, SQL_FUNC_UNLIKELY)) { - if (nFarg < 1) { - diag_set(ClientError, - ER_FUNC_WRONG_ARG_COUNT, - func->def->name, - "at least one", nFarg); - pParse->is_aborted = true; - break; - } + assert(nFarg == 1 || nFarg == 2); return sqlExprCodeTarget(pParse, pFarg->a[0].pExpr, target); diff --git a/src/box/sql/func.c b/src/box/sql/func.c index 4bbe4d4b7..9d4c26081 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -383,17 +383,12 @@ error: static void minmaxFunc(sql_context * context, int argc, sql_value ** argv) { + assert(argc > 1); int i; int iBest; struct coll *pColl; struct func *func = context->func; int mask = sql_func_flag_is_set(func, SQL_FUNC_MAX) ? -1 : 0; - if (argc < 2) { - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - mask ? "GREATEST" : "LEAST", "at least two", argc); - context->is_aborted = true; - return; - } pColl = sqlGetFuncCollSeq(context); assert(mask == -1 || mask == 0); iBest = 0; @@ -722,6 +717,7 @@ printfFunc(sql_context * context, int argc, sql_value ** argv) static void substrFunc(sql_context * context, int argc, sql_value ** argv) { + assert(argc == 2 || argc == 3); const unsigned char *z; const unsigned char *z2; int len; @@ -729,12 +725,6 @@ substrFunc(sql_context * context, int argc, sql_value ** argv) i64 p1, p2; int negP2 = 0; - if (argc != 2 && argc != 3) { - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "SUBSTR", - "1 or 2", argc); - context->is_aborted = true; - return; - } if (sql_value_is_null(argv[1]) || (argc == 3 && sql_value_is_null(argv[2])) ) { @@ -828,14 +818,9 @@ substrFunc(sql_context * context, int argc, sql_value ** argv) static void roundFunc(sql_context * context, int argc, sql_value ** argv) { + assert(argc == 1 || argc == 2); int n = 0; double r; - if (argc != 1 && argc != 2) { - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "ROUND", - "1 or 2", argc); - context->is_aborted = true; - return; - } if (argc == 2) { if (sql_value_is_null(argv[1])) return; @@ -1226,14 +1211,9 @@ sql_utf8_pattern_compare(const char *pattern, static void likeFunc(sql_context *context, int argc, sql_value **argv) { + assert(argc == 2 || argc == 3); u32 escape = SQL_END_OF_STRING; int nPat; - if (argc != 2 && argc != 3) { - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - "LIKE", "2 or 3", argc); - context->is_aborted = true; - return; - } sql *db = sql_context_db_handle(context); int rhs_type = sql_value_type(argv[0]); int lhs_type = sql_value_type(argv[1]); @@ -1838,6 +1818,7 @@ trim_func_three_args(struct sql_context *context, sql_value *arg1, static void trim_func(struct sql_context *context, int argc, sql_value **argv) { + assert(argc == 1 || argc == 2 || argc == 3); switch (argc) { case 1: trim_func_one_arg(context, argv[0]); @@ -1849,9 +1830,7 @@ trim_func(struct sql_context *context, int argc, sql_value **argv) trim_func_three_args(context, argv[0], argv[1], argv[2]); break; default: - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, "TRIM", - "1 or 2 or 3", argc); - context->is_aborted = true; + unreachable(); } } @@ -2030,13 +2009,8 @@ struct CountCtx { static void countStep(sql_context * context, int argc, sql_value ** argv) { + assert(argc == 0 || argc == 1); CountCtx *p; - if (argc != 0 && argc != 1) { - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - "COUNT", "0 or 1", argc); - context->is_aborted = true; - return; - } p = sql_aggregate_context(context, sizeof(*p)); if ((argc == 0 || ! sql_value_is_null(argv[0])) && p) { p->n++; @@ -2111,16 +2085,11 @@ minMaxFinalize(sql_context * context) static void groupConcatStep(sql_context * context, int argc, sql_value ** argv) { + assert(argc == 1 || argc == 2); const char *zVal; StrAccum *pAccum; const char *zSep; int nVal, nSep; - if (argc != 1 && argc != 2) { - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - "GROUP_CONCAT", "1 or 2", argc); - context->is_aborted = true; - return; - } if (sql_value_is_null(argv[0])) return; pAccum = @@ -2195,11 +2164,28 @@ sql_func_by_signature(const char *name, int argc) name)); return NULL; } - int param_count = base->def->param_count; - if (param_count != -1 && param_count != argc) { - const char *err = tt_sprintf("%d", param_count); - diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, - base->def->name, err, argc); + if (base->def->language != FUNC_LANGUAGE_SQL_BUILTIN) { + int param_count = base->def->param_count; + if (param_count != -1 && param_count != argc) { + const char *err = tt_sprintf("%d", param_count); + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, + base->def->name, err, argc); + return NULL; + } + return base; + } + struct func_sql_builtin *func = (struct func_sql_builtin *)base; + uint32_t arg_c = (uint32_t)argc; + if (func->args.min_count > arg_c || func->args.max_count < arg_c) { + const char *err; + uint32_t min = func->args.min_count; + uint32_t max = func->args.max_count; + if (min != max) + err = tt_sprintf("from %d to %d", min, max); + else + err = tt_sprintf("%d", min); + diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT, base->def->name, + err, argc); return NULL; } return base; @@ -2242,12 +2228,16 @@ static struct { /** Members below are related to struct func_def. */ bool is_deterministic; int param_count; + uint32_t min_count; + uint32_t max_count; enum field_type returns; enum func_aggregate aggregate; bool export_to_sql; } sql_builtins[] = { {.name = "ABS", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_NUMBER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2258,6 +2248,8 @@ static struct { }, { .name = "AVG", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_NUMBER, .is_deterministic = false, .aggregate = FUNC_AGGREGATE_GROUP, @@ -2270,6 +2262,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2280,6 +2274,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2288,6 +2284,8 @@ static struct { }, { .name = "CHAR", .param_count = -1, + .min_count = 0, + .max_count = SQL_MAX_FUNCTION_ARG, .returns = FIELD_TYPE_STRING, .is_deterministic = true, .aggregate = FUNC_AGGREGATE_NONE, @@ -2298,6 +2296,8 @@ static struct { }, { .name = "CHARACTER_LENGTH", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2308,6 +2308,8 @@ static struct { }, { .name = "CHAR_LENGTH", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2318,6 +2320,8 @@ static struct { }, { .name = "COALESCE", .param_count = -1, + .min_count = 2, + .max_count = SQL_MAX_FUNCTION_ARG, .returns = FIELD_TYPE_SCALAR, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2328,6 +2332,8 @@ static struct { }, { .name = "COUNT", .param_count = -1, + .min_count = 0, + .max_count = 1, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_GROUP, .is_deterministic = false, @@ -2340,6 +2346,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2350,6 +2358,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2360,6 +2370,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2370,6 +2382,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2380,6 +2394,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2390,6 +2406,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2400,6 +2418,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2410,6 +2430,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2420,6 +2442,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2430,6 +2454,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2440,6 +2466,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2448,6 +2476,8 @@ static struct { }, { .name = "GREATEST", .param_count = -1, + .min_count = 2, + .max_count = SQL_MAX_FUNCTION_ARG, .returns = FIELD_TYPE_SCALAR, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2458,6 +2488,8 @@ static struct { }, { .name = "GROUP_CONCAT", .param_count = -1, + .min_count = 1, + .max_count = 2, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_GROUP, .is_deterministic = false, @@ -2468,6 +2500,8 @@ static struct { }, { .name = "HEX", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2478,6 +2512,8 @@ static struct { }, { .name = "IFNULL", .param_count = 2, + .min_count = 2, + .max_count = 2, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2490,6 +2526,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2498,6 +2536,8 @@ static struct { }, { .name = "LEAST", .param_count = -1, + .min_count = 2, + .max_count = SQL_MAX_FUNCTION_ARG, .returns = FIELD_TYPE_SCALAR, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2508,6 +2548,8 @@ static struct { }, { .name = "LENGTH", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2520,6 +2562,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2528,6 +2572,8 @@ static struct { }, { .name = "LIKE", .param_count = -1, + .min_count = 2, + .max_count = 3, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2538,6 +2584,8 @@ static struct { }, { .name = "LIKELIHOOD", .param_count = 2, + .min_count = 2, + .max_count = 2, .returns = FIELD_TYPE_BOOLEAN, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2548,6 +2596,8 @@ static struct { }, { .name = "LIKELY", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_BOOLEAN, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2560,6 +2610,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2568,6 +2620,8 @@ static struct { }, { .name = "LOWER", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2578,6 +2632,8 @@ static struct { }, { .name = "MAX", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_SCALAR, .aggregate = FUNC_AGGREGATE_GROUP, .is_deterministic = false, @@ -2588,6 +2644,8 @@ static struct { }, { .name = "MIN", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_SCALAR, .aggregate = FUNC_AGGREGATE_GROUP, .is_deterministic = false, @@ -2600,6 +2658,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2608,6 +2668,8 @@ static struct { }, { .name = "NULLIF", .param_count = 2, + .min_count = 2, + .max_count = 2, .returns = FIELD_TYPE_SCALAR, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2620,6 +2682,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2628,6 +2692,8 @@ static struct { }, { .name = "POSITION", .param_count = 2, + .min_count = 2, + .max_count = 2, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2640,6 +2706,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2648,6 +2716,8 @@ static struct { }, { .name = "PRINTF", .param_count = -1, + .min_count = 0, + .max_count = SQL_MAX_FUNCTION_ARG, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2658,6 +2728,8 @@ static struct { }, { .name = "QUOTE", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2668,6 +2740,8 @@ static struct { }, { .name = "RANDOM", .param_count = 0, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2678,6 +2752,8 @@ static struct { }, { .name = "RANDOMBLOB", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_VARBINARY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2688,6 +2764,8 @@ static struct { }, { .name = "REPLACE", .param_count = 3, + .min_count = 3, + .max_count = 3, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2698,6 +2776,8 @@ static struct { }, { .name = "ROUND", .param_count = -1, + .min_count = 1, + .max_count = 2, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2708,6 +2788,8 @@ static struct { }, { .name = "ROW_COUNT", .param_count = 0, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_INTEGER, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2720,6 +2802,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2728,6 +2812,8 @@ static struct { }, { .name = "SOUNDEX", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2740,6 +2826,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2750,6 +2838,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2758,6 +2848,8 @@ static struct { }, { .name = "SUBSTR", .param_count = -1, + .min_count = 2, + .max_count = 3, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2768,6 +2860,8 @@ static struct { }, { .name = "SUM", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_NUMBER, .aggregate = FUNC_AGGREGATE_GROUP, .is_deterministic = false, @@ -2780,6 +2874,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2788,6 +2884,8 @@ static struct { }, { .name = "TOTAL", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_NUMBER, .aggregate = FUNC_AGGREGATE_GROUP, .is_deterministic = false, @@ -2798,6 +2896,8 @@ static struct { }, { .name = "TRIM", .param_count = -1, + .min_count = 1, + .max_count = 3, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2808,6 +2908,8 @@ static struct { }, { .name = "TYPEOF", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2818,6 +2920,8 @@ static struct { }, { .name = "UNICODE", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2828,6 +2932,8 @@ static struct { }, { .name = "UNLIKELY", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_BOOLEAN, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2838,6 +2944,8 @@ static struct { }, { .name = "UPPER", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2848,6 +2956,8 @@ static struct { }, { .name = "VERSION", .param_count = 0, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_STRING, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2858,6 +2968,8 @@ static struct { }, { .name = "ZEROBLOB", .param_count = 1, + .min_count = 1, + .max_count = 1, .returns = FIELD_TYPE_VARBINARY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = true, @@ -2870,6 +2982,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2880,6 +2994,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2890,6 +3006,8 @@ static struct { .call = sql_builtin_stub, .export_to_sql = false, .param_count = -1, + .min_count = 0, + .max_count = 0, .returns = FIELD_TYPE_ANY, .aggregate = FUNC_AGGREGATE_NONE, .is_deterministic = false, @@ -2941,6 +3059,8 @@ func_sql_builtin_new(struct func_def *def) func->flags = sql_builtins[idx].flags; func->call = sql_builtins[idx].call; func->finalize = sql_builtins[idx].finalize; + func->args.min_count = sql_builtins[idx].min_count; + func->args.max_count = sql_builtins[idx].max_count; def->param_count = sql_builtins[idx].param_count; def->is_deterministic = sql_builtins[idx].is_deterministic; def->returns = sql_builtins[idx].returns; diff --git a/src/box/sql/sqlInt.h b/src/box/sql/sqlInt.h index 58a65acc1..6af9d7473 100644 --- a/src/box/sql/sqlInt.h +++ b/src/box/sql/sqlInt.h @@ -4397,11 +4397,24 @@ Expr *sqlExprForVectorField(Parse *, Expr *, int); */ extern int sqlSubProgramsRemaining; +/** + * A structure that contains additional information about + * arguments to built-in SQL functions. + */ +struct sql_builtin_func_args { + /** Min number of arguments. */ + uint32_t min_count; + /** Max number of arguments. */ + uint32_t max_count; +}; + struct func_sql_builtin { /** Function object base class. */ struct func base; /** A bitmask of SQL flags. */ uint16_t flags; + /** Information about arguments to built-in functions. */ + struct sql_builtin_func_args args; /** * A VDBE-memory-compatible call method. * SQL built-ins don't use func base class "call" diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua index 3c088920f..1d3ef9e2a 100755 --- a/test/sql-tap/func.test.lua +++ b/test/sql-tap/func.test.lua @@ -428,7 +428,7 @@ test:do_catchsql_test( SELECT round(a,b,c) FROM t1 ]], { -- - 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" -- }) @@ -488,7 +488,7 @@ test:do_catchsql_test( SELECT round() FROM t1 ORDER BY a ]], { -- - 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" -- }) @@ -2540,7 +2540,7 @@ test:do_catchsql_test( SELECT coalesce() ]], { -- - 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" -- }) @@ -2550,7 +2550,7 @@ test:do_catchsql_test( SELECT coalesce(1) ]], { -- - 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" -- }) diff --git a/test/sql-tap/func2.test.lua b/test/sql-tap/func2.test.lua index c9bd3665f..4bfee7150 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() ]], { -- - 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" -- }) @@ -60,7 +60,7 @@ test:do_catchsql_test( SELECT SUBSTR('Supercalifragilisticexpialidocious') ]], { -- - 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" -- }) @@ -70,7 +70,7 @@ test:do_catchsql_test( SELECT SUBSTR('Supercalifragilisticexpialidocious', 1,1,1) ]], { -- - 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" -- }) @@ -673,7 +673,7 @@ if ("ሴ" ~= "u1234") SELECT SUBSTR() ]], { -- - 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" -- }) @@ -683,7 +683,7 @@ if ("ሴ" ~= "u1234") SELECT SUBSTR('hiሴho') ]], { -- - 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" -- }) @@ -693,7 +693,7 @@ if ("ሴ" ~= "u1234") SELECT SUBSTR('hiሴho', 1,1,1) ]], { -- - 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" -- }) @@ -1038,7 +1038,7 @@ test:do_catchsql_test( SELECT SUBSTR() ]], { -- - 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" -- }) @@ -1048,7 +1048,7 @@ test:do_catchsql_test( SELECT SUBSTR(x'1234') ]], { -- - 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" -- }) @@ -1058,7 +1058,7 @@ test:do_catchsql_test( SELECT SUBSTR(x'1234', 1,1,1) ]], { -- - 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" -- }) diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua index 8329e1735..08c40fd02 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" } ) box.func.COUNTER1:drop() box.func.COUNTER2:drop() diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua index fbebfab37..6248abb65 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 ]], { -- - 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" -- }) @@ -697,7 +697,7 @@ test:do_catchsql_test( SELECT f1 FROM test1 WHERE count(f1,f2)!=11 ]], { -- - 1, "misuse of aggregate function COUNT()" + 1, "Wrong number of arguments is passed to COUNT(): expected from 0 to 1, got 2" -- }) diff --git a/test/sql/collation.result b/test/sql/collation.result index 4e4c27ef0..9c22c7191 100644 --- a/test/sql/collation.result +++ b/test/sql/collation.result @@ -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/gh-4159-function-argumens.result b/test/sql/gh-4159-function-argumens.result new file mode 100644 index 000000000..48bd550a4 --- /dev/null +++ b/test/sql/gh-4159-function-argumens.result @@ -0,0 +1,821 @@ +-- test-run result file version 2 +-- Function abs(). +SELECT abs(); + | --- + | - null + | - 'Wrong number of arguments is passed to ABS(): expected 1, got 0' + | ... +SELECT abs(1); + | --- + | - metadata: + | - name: abs(1) + | type: number + | rows: + | - [1] + | ... +SELECT abs(1, 2); + | --- + | - null + | - 'Wrong number of arguments is passed to ABS(): expected 1, got 2' + | ... + +-- Function char(). +SELECT char(); + | --- + | - metadata: + | - name: char() + | type: string + | rows: + | - [''] + | ... +SELECT char(1); + | --- + | - metadata: + | - name: char(1) + | type: string + | rows: + | - ["\x01"] + | ... +SELECT char(1, 2); + | --- + | - metadata: + | - name: char(1, 2) + | type: string + | rows: + | - ["\x01\x02"] + | ... + +-- Function character_length(). +SELECT character_length(); + | --- + | - null + | - 'Wrong number of arguments is passed to CHARACTER_LENGTH(): expected 1, got 0' + | ... +SELECT character_length('1'); + | --- + | - metadata: + | - name: character_length('1') + | type: integer + | rows: + | - [1] + | ... +SELECT character_length('1', '2'); + | --- + | - null + | - 'Wrong number of arguments is passed to CHARACTER_LENGTH(): expected 1, got 2' + | ... + +-- Function char_length(). +SELECT char_length(); + | --- + | - null + | - 'Wrong number of arguments is passed to CHAR_LENGTH(): expected 1, got 0' + | ... +SELECT char_length('1'); + | --- + | - metadata: + | - name: char_length('1') + | type: integer + | rows: + | - [1] + | ... +SELECT char_length('1', '2'); + | --- + | - null + | - 'Wrong number of arguments is passed to CHAR_LENGTH(): expected 1, got 2' + | ... + +-- Function coalesce(). +SELECT coalesce(); + | --- + | - null + | - 'Wrong number of arguments is passed to COALESCE(): expected from 2 to 127, got + | 0' + | ... +SELECT coalesce('1'); + | --- + | - null + | - 'Wrong number of arguments is passed to COALESCE(): expected from 2 to 127, got + | 1' + | ... +SELECT coalesce('1', '2'); + | --- + | - metadata: + | - name: coalesce('1', '2') + | type: scalar + | rows: + | - ['1'] + | ... +SELECT coalesce('1', '2', '3'); + | --- + | - metadata: + | - name: coalesce('1', '2', '3') + | type: scalar + | rows: + | - ['1'] + | ... + +-- Function greatest(). +SELECT greatest(); + | --- + | - null + | - 'Wrong number of arguments is passed to GREATEST(): expected from 2 to 127, got + | 0' + | ... +SELECT greatest('1'); + | --- + | - null + | - 'Wrong number of arguments is passed to GREATEST(): expected from 2 to 127, got + | 1' + | ... +SELECT greatest('1', '2'); + | --- + | - metadata: + | - name: greatest('1', '2') + | type: scalar + | rows: + | - ['2'] + | ... + +-- Function hex(). +SELECT hex(); + | --- + | - null + | - 'Wrong number of arguments is passed to HEX(): expected 1, got 0' + | ... +SELECT hex(X'33'); + | --- + | - metadata: + | - name: hex(X'33') + | type: string + | rows: + | - ['33'] + | ... +SELECT hex(X'33', X'33'); + | --- + | - null + | - 'Wrong number of arguments is passed to HEX(): expected 1, got 2' + | ... + +-- Function ifnull +SELECT ifnull(); + | --- + | - null + | - 'Wrong number of arguments is passed to IFNULL(): expected 2, got 0' + | ... +SELECT ifnull(1); + | --- + | - null + | - 'Wrong number of arguments is passed to IFNULL(): expected 2, got 1' + | ... +SELECT ifnull(1, 2); + | --- + | - metadata: + | - name: ifnull(1, 2) + | type: integer + | rows: + | - [1] + | ... +SELECT ifnull(1, 2, 3); + | --- + | - null + | - 'Wrong number of arguments is passed to IFNULL(): expected 2, got 3' + | ... + +-- Function least(). +SELECT least(); + | --- + | - null + | - 'Wrong number of arguments is passed to LEAST(): expected from 2 to 127, got 0' + | ... +SELECT least('1'); + | --- + | - null + | - 'Wrong number of arguments is passed to LEAST(): expected from 2 to 127, got 1' + | ... +SELECT least('1', '2'); + | --- + | - metadata: + | - name: least('1', '2') + | type: scalar + | rows: + | - ['1'] + | ... + +-- Function length(). +SELECT length(); + | --- + | - null + | - 'Wrong number of arguments is passed to LENGTH(): expected 1, got 0' + | ... +SELECT length('1'); + | --- + | - metadata: + | - name: length('1') + | type: integer + | rows: + | - [1] + | ... +SELECT length('1', '2'); + | --- + | - null + | - 'Wrong number of arguments is passed to LENGTH(): expected 1, got 2' + | ... + +-- Function likelihood +SELECT likelihood(); + | --- + | - null + | - 'Wrong number of arguments is passed to LIKELIHOOD(): expected 2, got 0' + | ... +SELECT likelihood(1); + | --- + | - null + | - 'Wrong number of arguments is passed to LIKELIHOOD(): expected 2, got 1' + | ... +SELECT likelihood(1, 0.5); + | --- + | - metadata: + | - name: likelihood(1, 0.5) + | type: integer + | rows: + | - [1] + | ... +SELECT likelihood(1, 0.5, 3); + | --- + | - null + | - 'Wrong number of arguments is passed to LIKELIHOOD(): expected 2, got 3' + | ... + +-- Function likely +SELECT likely(); + | --- + | - null + | - 'Wrong number of arguments is passed to LIKELY(): expected 1, got 0' + | ... +SELECT likely(1); + | --- + | - metadata: + | - name: likely(1) + | type: integer + | rows: + | - [1] + | ... +SELECT likely(1, 2); + | --- + | - null + | - 'Wrong number of arguments is passed to LIKELY(): expected 1, got 2' + | ... + +-- Function lower +SELECT lower(); + | --- + | - null + | - 'Wrong number of arguments is passed to LOWER(): expected 1, got 0' + | ... +SELECT lower('a'); + | --- + | - metadata: + | - name: lower('a') + | type: string + | rows: + | - ['a'] + | ... +SELECT lower('a', 2); + | --- + | - null + | - 'Wrong number of arguments is passed to LOWER(): expected 1, got 2' + | ... + +-- Function nullif +SELECT nullif(); + | --- + | - null + | - 'Wrong number of arguments is passed to NULLIF(): expected 2, got 0' + | ... +SELECT nullif(1); + | --- + | - null + | - 'Wrong number of arguments is passed to NULLIF(): expected 2, got 1' + | ... +SELECT nullif(1, 2); + | --- + | - metadata: + | - name: nullif(1, 2) + | type: scalar + | rows: + | - [1] + | ... +SELECT nullif(1, 2, 3); + | --- + | - null + | - 'Wrong number of arguments is passed to NULLIF(): expected 2, got 3' + | ... + +-- Function position +SELECT position(); + | --- + | - null + | - 'Wrong number of arguments is passed to POSITION(): expected 2, got 0' + | ... +SELECT position('12345'); + | --- + | - null + | - 'Wrong number of arguments is passed to POSITION(): expected 2, got 1' + | ... +SELECT position('12345', '2'); + | --- + | - metadata: + | - name: position('12345', '2') + | type: integer + | rows: + | - [0] + | ... +SELECT position('12345', '2', 3); + | --- + | - null + | - 'Wrong number of arguments is passed to POSITION(): expected 2, got 3' + | ... + +-- Function printf +SELECT printf(); + | --- + | - metadata: + | - name: printf() + | type: string + | rows: + | - [null] + | ... +SELECT printf('1'); + | --- + | - metadata: + | - name: printf('1') + | type: string + | rows: + | - ['1'] + | ... +SELECT printf('1', 2); + | --- + | - metadata: + | - name: printf('1', 2) + | type: string + | rows: + | - ['1'] + | ... +SELECT printf('1', 2, 3); + | --- + | - metadata: + | - name: printf('1', 2, 3) + | type: string + | rows: + | - ['1'] + | ... + +-- Function quote +SELECT quote(); + | --- + | - null + | - 'Wrong number of arguments is passed to QUOTE(): expected 1, got 0' + | ... +SELECT quote('1'); + | --- + | - metadata: + | - name: quote('1') + | type: string + | rows: + | - ['''1'''] + | ... +SELECT quote('1', 2); + | --- + | - null + | - 'Wrong number of arguments is passed to QUOTE(): expected 1, got 2' + | ... + +-- Function random +SELECT typeof(random()); + | --- + | - metadata: + | - name: typeof(random()) + | type: string + | rows: + | - ['integer'] + | ... +SELECT typeof(random(1)); + | --- + | - null + | - 'Wrong number of arguments is passed to RANDOM(): expected 0, got 1' + | ... + +-- Function randomblob +SELECT typeof(randomblob()); + | --- + | - null + | - 'Wrong number of arguments is passed to RANDOMBLOB(): expected 1, got 0' + | ... +SELECT typeof(randomblob(1)); + | --- + | - metadata: + | - name: typeof(randomblob(1)) + | type: string + | rows: + | - ['varbinary'] + | ... +SELECT typeof(randomblob(1, 2)); + | --- + | - null + | - 'Wrong number of arguments is passed to RANDOMBLOB(): expected 1, got 2' + | ... + +-- Function replace +SELECT replace(); + | --- + | - null + | - 'Wrong number of arguments is passed to REPLACE(): expected 3, got 0' + | ... +SELECT replace('12345'); + | --- + | - null + | - 'Wrong number of arguments is passed to REPLACE(): expected 3, got 1' + | ... +SELECT replace('12345', '2'); + | --- + | - null + | - 'Wrong number of arguments is passed to REPLACE(): expected 3, got 2' + | ... +SELECT replace('12345', '2', '3'); + | --- + | - metadata: + | - name: replace('12345', '2', '3') + | type: string + | rows: + | - ['13345'] + | ... +SELECT replace('12345', '2', '3', 4); + | --- + | - null + | - 'Wrong number of arguments is passed to REPLACE(): expected 3, got 4' + | ... + +-- Function round +SELECT round(); + | --- + | - null + | - 'Wrong number of arguments is passed to ROUND(): expected from 1 to 2, got 0' + | ... +SELECT round(1.1245); + | --- + | - metadata: + | - name: round(1.1245) + | type: integer + | rows: + | - [1] + | ... +SELECT round(1.1245, 2); + | --- + | - metadata: + | - name: round(1.1245, 2) + | type: integer + | rows: + | - [1.12] + | ... +SELECT round(1.1245, 2, 3); + | --- + | - null + | - 'Wrong number of arguments is passed to ROUND(): expected from 1 to 2, got 3' + | ... + +-- Function row_count +SELECT row_count(); + | --- + | - metadata: + | - name: row_count() + | type: integer + | rows: + | - [0] + | ... +SELECT row_count(1); + | --- + | - null + | - 'Wrong number of arguments is passed to ROW_COUNT(): expected 0, got 1' + | ... + +-- Function soundex +SELECT soundex(); + | --- + | - null + | - 'Wrong number of arguments is passed to SOUNDEX(): expected 1, got 0' + | ... +SELECT soundex(1); + | --- + | - metadata: + | - name: soundex(1) + | type: string + | rows: + | - ['?000'] + | ... +SELECT soundex(1, 2); + | --- + | - null + | - 'Wrong number of arguments is passed to SOUNDEX(): expected 1, got 2' + | ... + +-- Function substr +SELECT substr(); + | --- + | - null + | - 'Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 0' + | ... +SELECT substr('12345'); + | --- + | - null + | - 'Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 1' + | ... +SELECT substr('12345', 2); + | --- + | - metadata: + | - name: substr('12345', 2) + | type: string + | rows: + | - ['2345'] + | ... +SELECT substr('12345', 2, 3); + | --- + | - metadata: + | - name: substr('12345', 2, 3) + | type: string + | rows: + | - ['234'] + | ... +SELECT substr('12345', 2, 3, 4); + | --- + | - null + | - 'Wrong number of arguments is passed to SUBSTR(): expected from 2 to 3, got 4' + | ... + +-- Function typeof +SELECT typeof(); + | --- + | - null + | - 'Wrong number of arguments is passed to TYPEOF(): expected 1, got 0' + | ... +SELECT typeof(1); + | --- + | - metadata: + | - name: typeof(1) + | type: string + | rows: + | - ['integer'] + | ... +SELECT typeof(1, 2); + | --- + | - null + | - 'Wrong number of arguments is passed to TYPEOF(): expected 1, got 2' + | ... + +-- Function unicode +SELECT unicode(); + | --- + | - null + | - 'Wrong number of arguments is passed to UNICODE(): expected 1, got 0' + | ... +SELECT unicode('1'); + | --- + | - metadata: + | - name: unicode('1') + | type: string + | rows: + | - [49] + | ... +SELECT unicode('1', '2'); + | --- + | - null + | - 'Wrong number of arguments is passed to UNICODE(): expected 1, got 2' + | ... + +-- Function unlikely +SELECT unlikely(); + | --- + | - null + | - 'Wrong number of arguments is passed to UNLIKELY(): expected 1, got 0' + | ... +SELECT unlikely(1); + | --- + | - metadata: + | - name: unlikely(1) + | type: integer + | rows: + | - [1] + | ... +SELECT unlikely(1, 2); + | --- + | - null + | - 'Wrong number of arguments is passed to UNLIKELY(): expected 1, got 2' + | ... + +-- Function upper +SELECT upper(); + | --- + | - null + | - 'Wrong number of arguments is passed to UPPER(): expected 1, got 0' + | ... +SELECT upper('a'); + | --- + | - metadata: + | - name: upper('a') + | type: string + | rows: + | - ['A'] + | ... +SELECT upper('a', 2); + | --- + | - null + | - 'Wrong number of arguments is passed to UPPER(): expected 1, got 2' + | ... + +-- Function version +SELECT typeof(version()); + | --- + | - metadata: + | - name: typeof(version()) + | type: string + | rows: + | - ['string'] + | ... +SELECT typeof(version(1)); + | --- + | - null + | - 'Wrong number of arguments is passed to VERSION(): expected 0, got 1' + | ... + +-- Function zeroblob +SELECT zeroblob(); + | --- + | - null + | - 'Wrong number of arguments is passed to ZEROBLOB(): expected 1, got 0' + | ... +SELECT zeroblob(1); + | --- + | - metadata: + | - name: zeroblob(1) + | type: varbinary + | rows: + | - ["\0"] + | ... +SELECT zeroblob(1, 2); + | --- + | - null + | - 'Wrong number of arguments is passed to ZEROBLOB(): expected 1, got 2' + | ... + +-- Function avg +SELECT avg() FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to AVG(): expected 1, got 0' + | ... +SELECT avg("_auto_field_") FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: avg("_auto_field_") + | type: number + | rows: + | - [2] + | ... +SELECT avg("_auto_field_", 2) FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to AVG(): expected 1, got 2' + | ... + +-- Function count +SELECT count() FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: count() + | type: integer + | rows: + | - [3] + | ... +SELECT count("_auto_field_") FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: count("_auto_field_") + | type: integer + | rows: + | - [3] + | ... +SELECT count("_auto_field_", 2) FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to COUNT(): expected from 0 to 1, got 2' + | ... + +-- Function group_concat +SELECT group_concat() FROM (values('1'), ('2'), ('3')); + | --- + | - null + | - 'Wrong number of arguments is passed to GROUP_CONCAT(): expected from 1 to 2, got + | 0' + | ... +SELECT group_concat("_auto_field_") FROM (values('1'), ('2'), ('3')); + | --- + | - metadata: + | - name: group_concat("_auto_field_") + | type: string + | rows: + | - ['1,2,3'] + | ... +SELECT group_concat("_auto_field_", '2') FROM (values('1'), ('2'), ('3')); + | --- + | - metadata: + | - name: group_concat("_auto_field_", '2') + | type: string + | rows: + | - ['12223'] + | ... +SELECT group_concat("_auto_field_", '2', '3') FROM (values('1'), ('2'), ('3')); + | --- + | - null + | - 'Wrong number of arguments is passed to GROUP_CONCAT(): expected from 1 to 2, got + | 3' + | ... + +-- Function max +SELECT max() FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to MAX(): expected 1, got 0' + | ... +SELECT max("_auto_field_") FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: max("_auto_field_") + | type: scalar + | rows: + | - [3] + | ... +SELECT max("_auto_field_", 2) FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to MAX(): expected 1, got 2' + | ... + +-- Function min +SELECT min() FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to MIN(): expected 1, got 0' + | ... +SELECT min("_auto_field_") FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: min("_auto_field_") + | type: scalar + | rows: + | - [1] + | ... +SELECT min("_auto_field_", 2) FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to MIN(): expected 1, got 2' + | ... + +-- Function sum +SELECT sum() FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to SUM(): expected 1, got 0' + | ... +SELECT sum("_auto_field_") FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: sum("_auto_field_") + | type: number + | rows: + | - [6] + | ... +SELECT sum("_auto_field_", 2) FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to SUM(): expected 1, got 2' + | ... + +-- Function total +SELECT total() FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to TOTAL(): expected 1, got 0' + | ... +SELECT total("_auto_field_") FROM (values(1), (2), (3)); + | --- + | - metadata: + | - name: total("_auto_field_") + | type: number + | rows: + | - [6] + | ... +SELECT total("_auto_field_", 2) FROM (values(1), (2), (3)); + | --- + | - null + | - 'Wrong number of arguments is passed to TOTAL(): expected 1, got 2' + | ... diff --git a/test/sql/gh-4159-function-argumens.test.sql b/test/sql/gh-4159-function-argumens.test.sql new file mode 100644 index 000000000..7578768cb --- /dev/null +++ b/test/sql/gh-4159-function-argumens.test.sql @@ -0,0 +1,193 @@ +-- Function abs(). +SELECT abs(); +SELECT abs(1); +SELECT abs(1, 2); + +-- Function char(). +SELECT char(); +SELECT char(1); +SELECT char(1, 2); + +-- Function character_length(). +SELECT character_length(); +SELECT character_length('1'); +SELECT character_length('1', '2'); + +-- Function char_length(). +SELECT char_length(); +SELECT char_length('1'); +SELECT char_length('1', '2'); + +-- Function coalesce(). +SELECT coalesce(); +SELECT coalesce('1'); +SELECT coalesce('1', '2'); +SELECT coalesce('1', '2', '3'); + +-- Function greatest(). +SELECT greatest(); +SELECT greatest('1'); +SELECT greatest('1', '2'); + +-- Function hex(). +SELECT hex(); +SELECT hex(X'33'); +SELECT hex(X'33', X'33'); + +-- Function ifnull +SELECT ifnull(); +SELECT ifnull(1); +SELECT ifnull(1, 2); +SELECT ifnull(1, 2, 3); + +-- Function least(). +SELECT least(); +SELECT least('1'); +SELECT least('1', '2'); + +-- Function length(). +SELECT length(); +SELECT length('1'); +SELECT length('1', '2'); + +-- Function likelihood +SELECT likelihood(); +SELECT likelihood(1); +SELECT likelihood(1, 0.5); +SELECT likelihood(1, 0.5, 3); + +-- Function likely +SELECT likely(); +SELECT likely(1); +SELECT likely(1, 2); + +-- Function lower +SELECT lower(); +SELECT lower('a'); +SELECT lower('a', 2); + +-- Function nullif +SELECT nullif(); +SELECT nullif(1); +SELECT nullif(1, 2); +SELECT nullif(1, 2, 3); + +-- Function position +SELECT position(); +SELECT position('12345'); +SELECT position('12345', '2'); +SELECT position('12345', '2', 3); + +-- Function printf +SELECT printf(); +SELECT printf('1'); +SELECT printf('1', 2); +SELECT printf('1', 2, 3); + +-- Function quote +SELECT quote(); +SELECT quote('1'); +SELECT quote('1', 2); + +-- Function random +SELECT typeof(random()); +SELECT typeof(random(1)); + +-- Function randomblob +SELECT typeof(randomblob()); +SELECT typeof(randomblob(1)); +SELECT typeof(randomblob(1, 2)); + +-- Function replace +SELECT replace(); +SELECT replace('12345'); +SELECT replace('12345', '2'); +SELECT replace('12345', '2', '3'); +SELECT replace('12345', '2', '3', 4); + +-- Function round +SELECT round(); +SELECT round(1.1245); +SELECT round(1.1245, 2); +SELECT round(1.1245, 2, 3); + +-- Function row_count +SELECT row_count(); +SELECT row_count(1); + +-- Function soundex +SELECT soundex(); +SELECT soundex(1); +SELECT soundex(1, 2); + +-- Function substr +SELECT substr(); +SELECT substr('12345'); +SELECT substr('12345', 2); +SELECT substr('12345', 2, 3); +SELECT substr('12345', 2, 3, 4); + +-- Function typeof +SELECT typeof(); +SELECT typeof(1); +SELECT typeof(1, 2); + +-- Function unicode +SELECT unicode(); +SELECT unicode('1'); +SELECT unicode('1', '2'); + +-- Function unlikely +SELECT unlikely(); +SELECT unlikely(1); +SELECT unlikely(1, 2); + +-- Function upper +SELECT upper(); +SELECT upper('a'); +SELECT upper('a', 2); + +-- Function version +SELECT typeof(version()); +SELECT typeof(version(1)); + +-- Function zeroblob +SELECT zeroblob(); +SELECT zeroblob(1); +SELECT zeroblob(1, 2); + +-- Function avg +SELECT avg() FROM (values(1), (2), (3)); +SELECT avg("_auto_field_") FROM (values(1), (2), (3)); +SELECT avg("_auto_field_", 2) FROM (values(1), (2), (3)); + +-- Function count +SELECT count() FROM (values(1), (2), (3)); +SELECT count("_auto_field_") FROM (values(1), (2), (3)); +SELECT count("_auto_field_", 2) FROM (values(1), (2), (3)); + +-- Function group_concat +SELECT group_concat() FROM (values('1'), ('2'), ('3')); +SELECT group_concat("_auto_field_") FROM (values('1'), ('2'), ('3')); +SELECT group_concat("_auto_field_", '2') FROM (values('1'), ('2'), ('3')); +SELECT group_concat("_auto_field_", '2', '3') FROM (values('1'), ('2'), ('3')); + +-- Function max +SELECT max() FROM (values(1), (2), (3)); +SELECT max("_auto_field_") FROM (values(1), (2), (3)); +SELECT max("_auto_field_", 2) FROM (values(1), (2), (3)); + +-- Function min +SELECT min() FROM (values(1), (2), (3)); +SELECT min("_auto_field_") FROM (values(1), (2), (3)); +SELECT min("_auto_field_", 2) FROM (values(1), (2), (3)); + +-- Function sum +SELECT sum() FROM (values(1), (2), (3)); +SELECT sum("_auto_field_") FROM (values(1), (2), (3)); +SELECT sum("_auto_field_", 2) FROM (values(1), (2), (3)); + +-- Function total +SELECT total() FROM (values(1), (2), (3)); +SELECT total("_auto_field_") FROM (values(1), (2), (3)); +SELECT total("_auto_field_", 2) FROM (values(1), (2), (3)); -- 2.25.1