Fix nullable primary key with constant conversion

This commit is contained in:
Amos Bird 2021-09-06 12:12:23 +08:00
parent 8f5b3f51b7
commit 8fac97692a
No known key found for this signature in database
GPG Key ID: 80D430DCBECFEDB4
3 changed files with 32 additions and 7 deletions

View File

@ -1342,34 +1342,48 @@ bool KeyCondition::tryParseAtomFromAST(const ASTPtr & node, ContextPtr context,
}
}
key_expr_type = recursiveRemoveLowCardinality(key_expr_type);
DataTypePtr key_expr_type_not_null;
bool key_expr_type_is_nullable = false;
if (const auto * nullable_type = typeid_cast<const DataTypeNullable *>(key_expr_type.get()))
{
key_expr_type_is_nullable = true;
key_expr_type_not_null = nullable_type->getNestedType();
}
else
key_expr_type_not_null = key_expr_type;
bool cast_not_needed = is_set_const /// Set args are already casted inside Set::createFromAST
|| ((isNativeNumber(key_expr_type) || isDateTime(key_expr_type))
|| ((isNativeNumber(key_expr_type_not_null) || isDateTime(key_expr_type_not_null))
&& (isNativeNumber(const_type) || isDateTime(const_type))); /// Numbers and DateTime are accurately compared without cast.
if (!cast_not_needed && !key_expr_type->equals(*const_type))
if (!cast_not_needed && !key_expr_type_not_null->equals(*const_type))
{
if (const_value.getType() == Field::Types::String)
{
const_value = convertFieldToType(const_value, *key_expr_type);
const_value = convertFieldToType(const_value, *key_expr_type_not_null);
if (const_value.isNull())
return false;
// No need to set is_constant_transformed because we're doing exact conversion
}
else
{
DataTypePtr common_type = getLeastSupertype({key_expr_type, const_type});
DataTypePtr common_type = getLeastSupertype({key_expr_type_not_null, const_type});
if (!const_type->equals(*common_type))
{
castValueToType(common_type, const_value, const_type, node);
// Need to set is_constant_transformed unless we're doing exact conversion
if (!key_expr_type->equals(*common_type))
if (!key_expr_type_not_null->equals(*common_type))
is_constant_transformed = true;
}
if (!key_expr_type->equals(*common_type))
if (!key_expr_type_not_null->equals(*common_type))
{
auto common_type_maybe_nullable
= key_expr_type_is_nullable ? DataTypePtr(std::make_shared<DataTypeNullable>(common_type)) : common_type;
ColumnsWithTypeAndName arguments{
{nullptr, key_expr_type, ""}, {DataTypeString().createColumnConst(1, common_type->getName()), common_type, ""}};
{nullptr, key_expr_type, ""},
{DataTypeString().createColumnConst(1, common_type_maybe_nullable->getName()), common_type_maybe_nullable, ""}};
FunctionOverloadResolverPtr func_builder_cast = CastInternalOverloadResolver<CastType::nonAccurate>::createImpl();
auto func_cast = func_builder_cast->build(arguments);

View File

@ -0,0 +1 @@
21585718595728998

View File

@ -0,0 +1,10 @@
drop table if exists t1;
set allow_suspicious_low_cardinality_types = 1;
create table t1 (id LowCardinality(Nullable(Int64))) engine MergeTree order by id settings allow_nullable_key = 1, index_granularity = 1;
insert into t1 values (21585718595728998), (null);
select * from t1 where id = 21585718595728998;
drop table t1;