mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 16:12:01 +00:00
Fix assert in IN with tuple literals and functions
This commit is contained in:
parent
d17284e7bc
commit
af14418fc1
@ -161,6 +161,8 @@ static Block createBlockFromAST(const ASTPtr & node, const DataTypes & types, co
|
|||||||
{
|
{
|
||||||
if (num_columns == 1)
|
if (num_columns == 1)
|
||||||
{
|
{
|
||||||
|
/// One column at the left of IN.
|
||||||
|
|
||||||
Field value = extractValueFromNode(elem, *types[0], context);
|
Field value = extractValueFromNode(elem, *types[0], context);
|
||||||
|
|
||||||
if (!value.isNull() || context.getSettingsRef().transform_null_in)
|
if (!value.isNull() || context.getSettingsRef().transform_null_in)
|
||||||
@ -168,15 +170,20 @@ static Block createBlockFromAST(const ASTPtr & node, const DataTypes & types, co
|
|||||||
}
|
}
|
||||||
else if (elem->as<ASTFunction>() || elem->as<ASTLiteral>())
|
else if (elem->as<ASTFunction>() || elem->as<ASTLiteral>())
|
||||||
{
|
{
|
||||||
|
/// Multiple columns at the left of IN.
|
||||||
|
/// The right hand side of in should be a set of tuples.
|
||||||
|
|
||||||
Field function_result;
|
Field function_result;
|
||||||
const Tuple * tuple = nullptr;
|
const Tuple * tuple = nullptr;
|
||||||
|
|
||||||
|
/// Tuple can be represented as a function in AST.
|
||||||
auto * func = elem->as<ASTFunction>();
|
auto * func = elem->as<ASTFunction>();
|
||||||
if (func && func->name != "tuple")
|
if (func && func->name != "tuple")
|
||||||
{
|
{
|
||||||
if (!tuple_type)
|
if (!tuple_type)
|
||||||
tuple_type = std::make_shared<DataTypeTuple>(types);
|
tuple_type = std::make_shared<DataTypeTuple>(types);
|
||||||
|
|
||||||
|
/// If the function is not a tuple, treat it as a constant expression that returns tuple and extract it.
|
||||||
function_result = extractValueFromNode(elem, *tuple_type, context);
|
function_result = extractValueFromNode(elem, *tuple_type, context);
|
||||||
if (function_result.getType() != Field::Types::Tuple)
|
if (function_result.getType() != Field::Types::Tuple)
|
||||||
throw Exception("Invalid type of set. Expected tuple, got " + String(function_result.getTypeName()),
|
throw Exception("Invalid type of set. Expected tuple, got " + String(function_result.getTypeName()),
|
||||||
@ -185,10 +192,12 @@ static Block createBlockFromAST(const ASTPtr & node, const DataTypes & types, co
|
|||||||
tuple = &function_result.get<Tuple>();
|
tuple = &function_result.get<Tuple>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tuple can be represented as a literal in AST.
|
||||||
auto * literal = elem->as<ASTLiteral>();
|
auto * literal = elem->as<ASTLiteral>();
|
||||||
if (literal)
|
if (literal)
|
||||||
{
|
{
|
||||||
if (literal->value.getType() != Field::Types::Tuple)
|
/// The literal must be tuple.
|
||||||
|
if (literal->value.getType() != Field::Types::Tuple)
|
||||||
throw Exception("Invalid type in set. Expected tuple, got "
|
throw Exception("Invalid type in set. Expected tuple, got "
|
||||||
+ String(literal->value.getTypeName()), ErrorCodes::INCORRECT_ELEMENT_OF_SET);
|
+ String(literal->value.getTypeName()), ErrorCodes::INCORRECT_ELEMENT_OF_SET);
|
||||||
|
|
||||||
@ -203,13 +212,15 @@ static Block createBlockFromAST(const ASTPtr & node, const DataTypes & types, co
|
|||||||
if (tuple_values.empty())
|
if (tuple_values.empty())
|
||||||
tuple_values.resize(tuple_size);
|
tuple_values.resize(tuple_size);
|
||||||
|
|
||||||
|
/// Fill tuple values by evaluation of constant expressions.
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (; i < tuple_size; ++i)
|
for (; i < tuple_size; ++i)
|
||||||
{
|
{
|
||||||
Field value = tuple ? (*tuple)[i]
|
Field value = tuple ? convertFieldToType((*tuple)[i], *types[i])
|
||||||
: extractValueFromNode(func->arguments->children[i], *types[i], context);
|
: extractValueFromNode(func->arguments->children[i], *types[i], context);
|
||||||
|
|
||||||
/// If at least one of the elements of the tuple has an impossible (outside the range of the type) value, then the entire tuple too.
|
/// If at least one of the elements of the tuple has an impossible (outside the range of the type) value,
|
||||||
|
/// then the entire tuple too.
|
||||||
if (value.isNull() && !context.getSettings().transform_null_in)
|
if (value.isNull() && !context.getSettings().transform_null_in)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
1
tests/queries/0_stateless/01421_assert_in_in.sql
Normal file
1
tests/queries/0_stateless/01421_assert_in_in.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT (1, 2) IN ((1, (2, 3)), (1 + 1, 1)); -- { serverError 53 }
|
Loading…
Reference in New Issue
Block a user