mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-30 05:30:51 +00:00
dbms: fix [#METR-19266]
This commit is contained in:
parent
a9310a5568
commit
04c9975c84
@ -340,8 +340,11 @@ bool hasFixedStringsOfIdenticalLength(const DataTypes & args)
|
|||||||
|
|
||||||
for (size_t i = firstThen(); i < else_arg; i = nextThen(i))
|
for (size_t i = firstThen(); i < else_arg; i = nextThen(i))
|
||||||
{
|
{
|
||||||
|
if (args[i]->isNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
const IDataType * observed_type;
|
const IDataType * observed_type;
|
||||||
if (!args[i]->isNullable())
|
if (args[i]->isNullable())
|
||||||
{
|
{
|
||||||
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*args[i]);
|
||||||
observed_type = nullable_type.getNestedType().get();
|
observed_type = nullable_type.getNestedType().get();
|
||||||
@ -374,7 +377,9 @@ bool hasFixedStringsOfIdenticalLength(const DataTypes & args)
|
|||||||
else
|
else
|
||||||
observed_type = args[else_arg].get();
|
observed_type = args[else_arg].get();
|
||||||
|
|
||||||
if (has_length)
|
if (!has_length)
|
||||||
|
has_length = true;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
size_t length = get_length(observed_type, else_arg);
|
size_t length = get_length(observed_type, else_arg);
|
||||||
if (length != first_length)
|
if (length != first_length)
|
||||||
@ -382,6 +387,9 @@ bool hasFixedStringsOfIdenticalLength(const DataTypes & args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!has_length)
|
||||||
|
throw Exception{"Internal error", ErrorCodes::LOGICAL_ERROR};
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,34 @@ bool hasNullDataTypes(const DataTypes & args)
|
|||||||
return args[else_arg]->isNull();
|
return args[else_arg]->isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the type of the first non-null branch. Make it nullable
|
||||||
|
/// if there is at least one nullable branch or one null branch.
|
||||||
|
/// This function is used in a very few number of cases in getReturnTypeImpl().
|
||||||
|
DataTypePtr getReturnTypeFromFirstNonNullBranch(const DataTypes & args, bool has_nullable_types, bool has_null_types)
|
||||||
|
{
|
||||||
|
auto get_type_to_return = [has_nullable_types, has_null_types](const DataTypePtr & arg) -> DataTypePtr
|
||||||
|
{
|
||||||
|
if (arg->isNullable())
|
||||||
|
return arg;
|
||||||
|
else if (has_nullable_types || has_null_types)
|
||||||
|
return std::make_shared<DataTypeNullable>(arg);
|
||||||
|
else
|
||||||
|
return arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = Conditional::firstThen(); i < Conditional::elseArg(args); i = Conditional::nextThen(i))
|
||||||
|
{
|
||||||
|
if (!args[i]->isNull())
|
||||||
|
return get_type_to_return(args[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i = Conditional::elseArg(args);
|
||||||
|
if (!args[i]->isNull())
|
||||||
|
return get_type_to_return(args[i]);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerFunctionsConditional(FunctionFactory & factory)
|
void registerFunctionsConditional(FunctionFactory & factory)
|
||||||
@ -378,16 +406,14 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
|||||||
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT};
|
||||||
}
|
}
|
||||||
|
|
||||||
const IDataType * data = args[Conditional::firstThen()].get();
|
auto type = getReturnTypeFromFirstNonNullBranch(args, has_nullable_types, has_null_types);
|
||||||
const auto * fixed_str = typeid_cast<const DataTypeFixedString *>(data);
|
if (type)
|
||||||
|
|
||||||
if (fixed_str == nullptr)
|
|
||||||
throw Exception{"Internal error", ErrorCodes::LOGICAL_ERROR};
|
|
||||||
|
|
||||||
DataTypePtr type = std::make_shared<DataTypeFixedString>(fixed_str->getN());
|
|
||||||
if (has_nullable_types || has_null_types)
|
|
||||||
type = std::make_shared<DataTypeNullable>(type);
|
|
||||||
return type;
|
return type;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/// This cannot happen: at least one fixed string is not null.
|
||||||
|
throw Exception{"Internal error", ErrorCodes::LOGICAL_ERROR};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (Conditional::hasStrings(args))
|
else if (Conditional::hasStrings(args))
|
||||||
{
|
{
|
||||||
@ -410,29 +436,9 @@ DataTypePtr FunctionMultiIf::getReturnTypeInternal(const DataTypes & args) const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/// Return the type of the first non-null branch.
|
auto type = getReturnTypeFromFirstNonNullBranch(args, has_nullable_types, has_null_types);
|
||||||
/// Make it nullable if there is at least one nullable branch
|
if (type)
|
||||||
/// or one null branch.
|
return type;
|
||||||
|
|
||||||
auto get_type_to_return = [has_nullable_types, has_null_types](const DataTypePtr & arg) -> DataTypePtr
|
|
||||||
{
|
|
||||||
if (arg->isNullable())
|
|
||||||
return arg;
|
|
||||||
else if (has_nullable_types || has_null_types)
|
|
||||||
return std::make_shared<DataTypeNullable>(arg);
|
|
||||||
else
|
|
||||||
return arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = Conditional::firstThen(); i < Conditional::elseArg(args); i = Conditional::nextThen(i))
|
|
||||||
{
|
|
||||||
if (!args[i]->isNull())
|
|
||||||
return get_type_to_return(args[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t i = Conditional::elseArg(args);
|
|
||||||
if (!args[i]->isNull())
|
|
||||||
return get_type_to_return(args[i]);
|
|
||||||
|
|
||||||
/// All the branches are null.
|
/// All the branches are null.
|
||||||
return std::make_shared<DataTypeNull>();
|
return std::make_shared<DataTypeNull>();
|
||||||
|
Loading…
Reference in New Issue
Block a user