diff --git a/src/Analyzer/Passes/LogicalExpressionOptimizerPass.cpp b/src/Analyzer/Passes/LogicalExpressionOptimizerPass.cpp index 11811ae4f2d..ac221bd66e7 100644 --- a/src/Analyzer/Passes/LogicalExpressionOptimizerPass.cpp +++ b/src/Analyzer/Passes/LogicalExpressionOptimizerPass.cpp @@ -551,14 +551,25 @@ private: in_function->getArguments().getNodes() = std::move(in_arguments); in_function->resolveAsFunction(in_function_resolver); + + DataTypePtr result_type = in_function->getResultType(); + const auto * type_low_cardinality = typeid_cast(result_type.get()); + if (type_low_cardinality) + result_type = type_low_cardinality->getDictionaryType(); /** For `k :: UInt8`, expression `k = 1 OR k = NULL` with result type Nullable(UInt8) * is replaced with `k IN (1, NULL)` with result type UInt8. * Convert it back to Nullable(UInt8). + * And for `k :: LowCardinality(UInt8)`, the transformation of `k IN (1, NULL)` results in type LowCardinality(UInt8). + * Convert it to LowCardinality(Nullable(UInt8)). */ - if (is_any_nullable && !in_function->getResultType()->isNullable()) + if (is_any_nullable && !result_type->isNullable()) { - auto nullable_result_type = std::make_shared(in_function->getResultType()); - auto in_function_nullable = createCastFunction(std::move(in_function), std::move(nullable_result_type), getContext()); + DataTypePtr new_result_type = std::make_shared(result_type); + if (type_low_cardinality) + { + new_result_type = std::make_shared(new_result_type); + } + auto in_function_nullable = createCastFunction(std::move(in_function), std::move(new_result_type), getContext()); or_operands.push_back(std::move(in_function_nullable)); } else