diff --git a/src/Storages/MergeTree/KeyCondition.cpp b/src/Storages/MergeTree/KeyCondition.cpp index 2d57ea40c9c..80f425c3e06 100644 --- a/src/Storages/MergeTree/KeyCondition.cpp +++ b/src/Storages/MergeTree/KeyCondition.cpp @@ -2250,9 +2250,11 @@ static BoolMask forAnyHyperrectangle( if (left_bounded && right_bounded) hyperrectangle[prefix_size] = Range(left_keys[prefix_size], true, right_keys[prefix_size], true); else if (left_bounded) - hyperrectangle[prefix_size] = Range::createLeftBounded(left_keys[prefix_size], true, data_types[prefix_size]->isNullable()); + hyperrectangle[prefix_size] + = Range::createLeftBounded(left_keys[prefix_size], true, isNullableOrLowCardinalityNullable(data_types[prefix_size])); else if (right_bounded) - hyperrectangle[prefix_size] = Range::createRightBounded(right_keys[prefix_size], true, data_types[prefix_size]->isNullable()); + hyperrectangle[prefix_size] + = Range::createRightBounded(right_keys[prefix_size], true, isNullableOrLowCardinalityNullable(data_types[prefix_size])); return callback(hyperrectangle); } @@ -2262,13 +2264,15 @@ static BoolMask forAnyHyperrectangle( if (left_bounded && right_bounded) hyperrectangle[prefix_size] = Range(left_keys[prefix_size], false, right_keys[prefix_size], false); else if (left_bounded) - hyperrectangle[prefix_size] = Range::createLeftBounded(left_keys[prefix_size], false, data_types[prefix_size]->isNullable()); + hyperrectangle[prefix_size] + = Range::createLeftBounded(left_keys[prefix_size], false, isNullableOrLowCardinalityNullable(data_types[prefix_size])); else if (right_bounded) - hyperrectangle[prefix_size] = Range::createRightBounded(right_keys[prefix_size], false, data_types[prefix_size]->isNullable()); + hyperrectangle[prefix_size] + = Range::createRightBounded(right_keys[prefix_size], false, isNullableOrLowCardinalityNullable(data_types[prefix_size])); for (size_t i = prefix_size + 1; i < key_size; ++i) { - if (data_types[i]->isNullable()) + if (isNullableOrLowCardinalityNullable(data_types[i])) hyperrectangle[i] = Range::createWholeUniverse(); else hyperrectangle[i] = Range::createWholeUniverseWithoutNull(); @@ -2324,7 +2328,7 @@ BoolMask KeyCondition::checkInRange( key_ranges.reserve(used_key_size); for (size_t i = 0; i < used_key_size; ++i) { - if (data_types[i]->isNullable()) + if (isNullableOrLowCardinalityNullable(data_types[i])) key_ranges.push_back(Range::createWholeUniverse()); else key_ranges.push_back(Range::createWholeUniverseWithoutNull()); diff --git a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp index 345872efddf..cd0a7615762 100644 --- a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp +++ b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp @@ -383,7 +383,8 @@ MergeTreeDataSelectSamplingData MergeTreeDataSelectExecutor::getSampling( if (has_lower_limit) { if (!key_condition.addCondition( - sampling_key.column_names[0], Range::createLeftBounded(lower, true, sampling_key.data_types[0]->isNullable()))) + sampling_key.column_names[0], + Range::createLeftBounded(lower, true, isNullableOrLowCardinalityNullable(sampling_key.data_types[0])))) throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Sampling column not in primary key"); ASTPtr args = std::make_shared(); @@ -401,7 +402,8 @@ MergeTreeDataSelectSamplingData MergeTreeDataSelectExecutor::getSampling( if (has_upper_limit) { if (!key_condition.addCondition( - sampling_key.column_names[0], Range::createRightBounded(upper, false, sampling_key.data_types[0]->isNullable()))) + sampling_key.column_names[0], + Range::createRightBounded(upper, false, isNullableOrLowCardinalityNullable(sampling_key.data_types[0])))) throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Sampling column not in primary key"); ASTPtr args = std::make_shared(); diff --git a/tests/queries/0_stateless/03129_low_cardinality_nullable_non_first_primary_key.reference b/tests/queries/0_stateless/03129_low_cardinality_nullable_non_first_primary_key.reference new file mode 100644 index 00000000000..712cd79a3f2 --- /dev/null +++ b/tests/queries/0_stateless/03129_low_cardinality_nullable_non_first_primary_key.reference @@ -0,0 +1 @@ +1650 diff --git a/tests/queries/0_stateless/03129_low_cardinality_nullable_non_first_primary_key.sql b/tests/queries/0_stateless/03129_low_cardinality_nullable_non_first_primary_key.sql new file mode 100644 index 00000000000..457c288da69 --- /dev/null +++ b/tests/queries/0_stateless/03129_low_cardinality_nullable_non_first_primary_key.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS small; + +CREATE TABLE small (`dt` DateTime, `user_email` LowCardinality(Nullable(String))) +ENGINE = MergeTree order by (dt, user_email) settings allow_nullable_key = 1, min_bytes_for_wide_part=0, min_rows_for_wide_part=0; + +INSERT INTO small (dt, user_email) SELECT number, if(number % 3 = 2, NULL, number) FROM numbers(1e2); + +SELECT SUM(dt::int) FROM small WHERE user_email IS NULL; + +DROP TABLE small;