better exception for function 'in' with invalid number of arguments

This commit is contained in:
Anton Popov 2020-07-15 17:22:54 +03:00
parent 00acf4173c
commit de7b0c2424
6 changed files with 29 additions and 4 deletions

View File

@ -368,7 +368,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
}
SetPtr prepared_set;
if (functionIsInOrGlobalInOperator(node.name))
if (checkFunctionIsInOrGlobalInOperator(node))
{
/// Let's find the type of the first argument (then getActionsImpl will be called again and will not affect anything).
visit(node.arguments->children.at(0), data);
@ -445,7 +445,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
/// Select the name in the next cycle.
argument_names.emplace_back();
}
else if (functionIsInOrGlobalInOperator(node.name) && arg == 1 && prepared_set)
else if (checkFunctionIsInOrGlobalInOperator(node) && arg == 1 && prepared_set)
{
ColumnWithTypeAndName column;
column.type = std::make_shared<DataTypeSet>();

View File

@ -180,7 +180,7 @@ void ExecuteScalarSubqueriesMatcher::visit(const ASTFunction & func, ASTPtr & as
/// But if an argument is not subquery, than deeper may be scalar subqueries and we need to descend in them.
std::vector<ASTPtr *> out;
if (functionIsInOrGlobalInOperator(func.name))
if (checkFunctionIsInOrGlobalInOperator(func))
{
for (auto & child : ast->children)
{

View File

@ -35,7 +35,7 @@ void MarkTableIdentifiersMatcher::visit(ASTTableExpression & table, ASTPtr &, Da
void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr &, Data & data)
{
/// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`.
if (functionIsInOrGlobalInOperator(func.name))
if (checkFunctionIsInOrGlobalInOperator(func))
{
auto & ast = func.arguments->children.at(1);
auto opt_name = tryGetIdentifierName(ast);

View File

@ -1,10 +1,16 @@
#pragma once
#include <Common/StringUtils/StringUtils.h>
#include <Parsers/ASTFunction.h>
namespace DB
{
namespace ErrorCodes
{
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
}
inline bool functionIsInOperator(const std::string & name)
{
return name == "in" || name == "notIn" || name == "nullIn" || name == "notNullIn";
@ -30,4 +36,19 @@ inline bool functionIsDictGet(const std::string & name)
return startsWith(name, "dictGet") || (name == "dictHas") || (name == "dictIsIn");
}
inline bool checkFunctionIsInOrGlobalInOperator(const ASTFunction & func)
{
if (functionIsInOrGlobalInOperator(func.name))
{
size_t num_arguments = func.arguments->children.size();
if (num_arguments != 2)
throw Exception("Wrong number of arguments passed to function in. Expected: 2, passed: " + std::to_string(num_arguments),
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
return true;
}
return false;
}
}

View File

@ -0,0 +1,4 @@
select in((1, 1, 1, 1)); -- { serverError 42 }
select in(1); -- { serverError 42 }
select in(); -- { serverError 42 }
select in(1, 2, 3); -- { serverError 42 }