diff --git a/changelogs/unreleased/gh-6483-default-type-for-builtins.md b/changelogs/unreleased/gh-6483-default-type-for-builtins.md new file mode 100644 index 0000000000000000000000000000000000000000..134c065f127ebd816e337b2a691941b6fb57bbc9 --- /dev/null +++ b/changelogs/unreleased/gh-6483-default-type-for-builtins.md @@ -0,0 +1,4 @@ +## feature/sql + +* A default type is now defined in case the argument type of a SQL built-in + function cannot be determined during parsing (gh-4415). diff --git a/src/box/sql/func.c b/src/box/sql/func.c index e3ce6c18e421fe5f11485d5f7ddf7e88f70aca10..721444c8c0cb5f161fa9ec1af9360d3570a9da0f 100644 --- a/src/box/sql/func.c +++ b/src/box/sql/func.c @@ -1703,15 +1703,15 @@ struct sql_func_definition { * function should be defined in succession. */ static struct sql_func_definition definitions[] = { + {"ABS", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DECIMAL, func_abs_dec, + NULL}, {"ABS", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, func_abs_int, NULL}, {"ABS", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, func_abs_double, NULL}, - {"ABS", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DECIMAL, func_abs_dec, - NULL}, + {"AVG", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DECIMAL, step_avg, fin_avg}, {"AVG", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, step_avg, fin_avg}, {"AVG", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, step_avg, fin_avg}, - {"AVG", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DECIMAL, step_avg, fin_avg}, {"CHAR", -1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_STRING, func_char, NULL}, {"CHAR_LENGTH", 1, {FIELD_TYPE_STRING}, FIELD_TYPE_INTEGER, func_char_length, NULL}, @@ -1836,15 +1836,15 @@ static struct sql_func_definition definitions[] = { {"SUBSTR", 3, {FIELD_TYPE_VARBINARY, FIELD_TYPE_INTEGER, FIELD_TYPE_INTEGER}, FIELD_TYPE_VARBINARY, func_substr_octets, NULL}, + {"SUM", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DECIMAL, step_sum, NULL}, {"SUM", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_INTEGER, step_sum, NULL}, {"SUM", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, step_sum, NULL}, - {"SUM", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DECIMAL, step_sum, NULL}, + {"TOTAL", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DOUBLE, step_total, + fin_total}, {"TOTAL", 1, {FIELD_TYPE_INTEGER}, FIELD_TYPE_DOUBLE, step_total, fin_total}, {"TOTAL", 1, {FIELD_TYPE_DOUBLE}, FIELD_TYPE_DOUBLE, step_total, fin_total}, - {"TOTAL", 1, {FIELD_TYPE_DECIMAL}, FIELD_TYPE_DOUBLE, step_total, - fin_total}, {"TRIM", 2, {FIELD_TYPE_STRING, FIELD_TYPE_INTEGER}, FIELD_TYPE_STRING, func_trim_str, NULL}, diff --git a/test/sql-tap/built-in-functions.test.lua b/test/sql-tap/built-in-functions.test.lua index 6fae811dcdecded1cc4fd69c17fb3a9963f9be45..e7b06cf869eef5d0a75f9a94074d6d5a41586fd8 100755 --- a/test/sql-tap/built-in-functions.test.lua +++ b/test/sql-tap/built-in-functions.test.lua @@ -1,6 +1,6 @@ #!/usr/bin/env tarantool local test = require("sqltester") -test:plan(52) +test:plan(66) -- -- Make sure that number of arguments check is checked properly for SQL built-in @@ -395,7 +395,7 @@ test:do_test( local res = {pcall(box.execute, [[SELECT ABS(?);]], {'1'})} return {tostring(res[3])} end, { - "Type mismatch: can not convert string('1') to integer" + "Type mismatch: can not convert string('1') to decimal" }) test:do_catchsql_test( @@ -455,7 +455,7 @@ test:do_test( local res = {pcall(box.execute, [[SELECT SUM(?);]], {'1'})} return {tostring(res[3])} end, { - "Type mismatch: can not convert string('1') to integer" + "Type mismatch: can not convert string('1') to decimal" }) test:do_catchsql_test( @@ -475,7 +475,7 @@ test:do_test( local res = {pcall(box.execute, [[SELECT AVG(?);]], {'1'})} return {tostring(res[3])} end, { - "Type mismatch: can not convert string('1') to integer" + "Type mismatch: can not convert string('1') to decimal" }) test:do_catchsql_test( @@ -495,7 +495,7 @@ test:do_test( local res = {pcall(box.execute, [[SELECT TOTAL(?);]], {'1'})} return {tostring(res[3])} end, { - "Type mismatch: can not convert string('1') to integer" + "Type mismatch: can not convert string('1') to decimal" }) -- @@ -545,4 +545,121 @@ test:do_test( {name = "COLUMN_2", type = "scalar"}, }) +-- gh-6483: Make sure functions have correct default type. +test:do_test( + "builtins-4.1", + function() + return box.execute([[SELECT ABS(?);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'decimal' + }) + +test:do_test( + "builtins-4.2", + function() + return box.execute([[SELECT AVG(?);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'decimal' + }) + +test:do_test( + "builtins-4.3", + function() + return box.execute([[SELECT GREATEST(?, 1);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'scalar' + }) + +test:do_test( + "builtins-4.4", + function() + return box.execute([[SELECT GROUP_CONCAT(?);]], {'a'}).metadata[1] + end, { + name = "COLUMN_1", type = 'string' + }) + +test:do_test( + "builtins-4.5", + function() + return box.execute([[SELECT LEAST(?, 1);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'scalar' + }) + +test:do_test( + "builtins-4.6", + function() + local res = {pcall(box.execute, [[SELECT LENGTH(?);]], {1})} + return {tostring(res[3])} + end, { + "Type mismatch: can not convert integer(1) to string" + }) + +test:do_test( + "builtins-4.7", + function() + return box.execute([[SELECT MAX(?);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'scalar' + }) + +test:do_test( + "builtins-4.8", + function() + return box.execute([[SELECT MIN(?);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'scalar' + }) + +test:do_test( + "builtins-4.9", + function() + local res = {pcall(box.execute, [[SELECT POSITION(?, ?);]], {1, 1})} + return {tostring(res[3])} + end, { + "Type mismatch: can not convert integer(1) to string" + }) + +test:do_test( + "builtins-4.10", + function() + return box.execute([[SELECT REPLACE(@1, @1, @1);]], {'a'}).metadata[1] + end, { + name = "COLUMN_1", type = 'string' + }) + +test:do_test( + "builtins-4.11", + function() + return box.execute([[SELECT SUBSTR(?, 1, 2);]], {'asd'}).metadata[1] + end, { + name = "COLUMN_1", type = 'string' + }) + +test:do_test( + "builtins-4.12", + function() + return box.execute([[SELECT SUM(?);]], {1}).metadata[1] + end, { + name = "COLUMN_1", type = 'decimal' + }) + +test:do_test( + "builtins-4.13", + function() + local res = {pcall(box.execute, [[SELECT TOTAL(?);]], {'a'})} + return {tostring(res[3])} + end, { + "Type mismatch: can not convert string('a') to decimal" + }) + +test:do_test( + "builtins-4.14", + function() + local res = {pcall(box.execute, [[SELECT TRIM(?);]], {1})} + return {tostring(res[3])} + end, { + "Type mismatch: can not convert integer(1) to string" + }) + test:finish_test() diff --git a/test/sql-tap/metatypes.test.lua b/test/sql-tap/metatypes.test.lua index 12c3ce06d0d98de3c67326a9481f22ec19f3d9b4..aa9ccb165b489caa1fb3c2bf485521e6e9c0c927 100755 --- a/test/sql-tap/metatypes.test.lua +++ b/test/sql-tap/metatypes.test.lua @@ -406,7 +406,7 @@ test:do_catchsql_test( [[ SELECT ABS(a) FROM t; ]], { - 1, "Type mismatch: can not convert any(1) to integer" + 1, "Type mismatch: can not convert any(1) to decimal" }) test:do_catchsql_test( @@ -414,7 +414,7 @@ test:do_catchsql_test( [[ SELECT AVG(a) FROM t; ]], { - 1, "Type mismatch: can not convert any(1) to integer" + 1, "Type mismatch: can not convert any(1) to decimal" }) test:do_catchsql_test( @@ -635,7 +635,7 @@ test:do_catchsql_test( [[ SELECT SUM(a) FROM t; ]], { - 1, "Type mismatch: can not convert any(1) to integer" + 1, "Type mismatch: can not convert any(1) to decimal" }) test:do_catchsql_test( @@ -643,7 +643,7 @@ test:do_catchsql_test( [[ SELECT TOTAL(a) FROM t; ]], { - 1, "Type mismatch: can not convert any(1) to integer" + 1, "Type mismatch: can not convert any(1) to decimal" }) test:do_catchsql_test(