Allow nullable key in MergeTree

This commit is contained in:
Amos Bird 2020-07-12 20:58:17 +08:00
parent 0fe4c37033
commit cac5a89169
No known key found for this signature in database
GPG Key ID: 80D430DCBECFEDB4
5 changed files with 58 additions and 5 deletions

View File

@ -140,6 +140,9 @@ MergeTreeData::MergeTreeData(
, data_parts_by_state_and_info(data_parts_indexes.get<TagByStateAndInfo>())
, parts_mover(this)
{
const auto settings = getSettings();
allow_nullable_key = attach || settings->allow_nullable_key;
if (relative_data_path.empty())
throw Exception("MergeTree storages require data path", ErrorCodes::INCORRECT_FILE_NAME);
@ -167,7 +170,6 @@ MergeTreeData::MergeTreeData(
}
setProperties(metadata_, metadata_, attach);
const auto settings = getSettings();
/// NOTE: using the same columns list as is read when performing actual merges.
merging_params.check(metadata_);
@ -244,7 +246,7 @@ StoragePolicyPtr MergeTreeData::getStoragePolicy() const
return global_context.getStoragePolicy(getSettings()->storage_policy);
}
static void checkKeyExpression(const ExpressionActions & expr, const Block & sample_block, const String & key_name)
static void checkKeyExpression(const ExpressionActions & expr, const Block & sample_block, const String & key_name, bool allow_nullable_key)
{
for (const ExpressionAction & action : expr.getActions())
{
@ -267,7 +269,7 @@ static void checkKeyExpression(const ExpressionActions & expr, const Block & sam
if (column && (isColumnConst(*column) || column->isDummy()))
throw Exception{key_name + " key cannot contain constants", ErrorCodes::ILLEGAL_COLUMN};
if (element.type->isNullable())
if (!allow_nullable_key && element.type->isNullable())
throw Exception{key_name + " key cannot contain nullable columns", ErrorCodes::ILLEGAL_COLUMN};
}
}
@ -376,7 +378,7 @@ void MergeTreeData::checkProperties(
}
}
checkKeyExpression(*new_sorting_key.expression, new_sorting_key.sample_block, "Sorting");
checkKeyExpression(*new_sorting_key.expression, new_sorting_key.sample_block, "Sorting", allow_nullable_key);
}
@ -423,7 +425,7 @@ void MergeTreeData::checkPartitionKeyAndInitMinMax(const KeyDescription & new_pa
if (new_partition_key.expression_list_ast->children.empty())
return;
checkKeyExpression(*new_partition_key.expression, new_partition_key.sample_block, "Partition");
checkKeyExpression(*new_partition_key.expression, new_partition_key.sample_block, "Partition", allow_nullable_key);
/// Add all columns used in the partition key to the min-max index.
const NamesAndTypesList & minmax_idx_columns_with_types = new_partition_key.expression->getRequiredColumnsWithTypes();

View File

@ -886,6 +886,8 @@ private:
WriteAheadLogPtr write_ahead_log;
virtual void startBackgroundMovesIfNeeded() = 0;
bool allow_nullable_key{};
};
}

View File

@ -99,6 +99,7 @@ struct MergeTreeSettings : public SettingsCollection<MergeTreeSettings>
M(SettingMaxThreads, max_part_removal_threads, 0, "The number of threads for concurrent removal of inactive data parts. One is usually enough, but in 'Google Compute Environment SSD Persistent Disks' file removal (unlink) operation is extraordinarily slow and you probably have to increase this number (recommended is up to 16).", 0) \
M(SettingUInt64, concurrent_part_removal_threshold, 100, "Activate concurrent part removal (see 'max_part_removal_threads') only if the number of inactive data parts is at least this.", 0) \
M(SettingString, storage_policy, "default", "Name of storage disk policy", 0) \
M(SettingBool, allow_nullable_key, false, "Allow Nullable types as primary keys.", 0) \
\
/** Obsolete settings. Kept for backward compatibility only. */ \
M(SettingUInt64, min_relative_delay_to_yield_leadership, 120, "Obsolete setting, does nothing.", 0) \

View File

@ -0,0 +1,35 @@
0 0
2 3
4 6
6 9
8 12
10 15
12 18
14 21
16 24
18 27
\N 0
\N -1
\N -2
\N 0
\N -1
\N -2
0 0
2 3
4 6
6 9
8 12
10 15
12 18
14 21
16 24
18 27
12 18
14 21
16 24
18 27
0 0
2 3
4 6
6 9
8 12

View File

@ -0,0 +1,13 @@
DROP TABLE IF EXISTS nullable_key;
CREATE TABLE nullable_key (k Nullable(int), v int) ENGINE MergeTree ORDER BY k SETTINGS allow_nullable_key = 1;
INSERT INTO nullable_key SELECT number * 2, number * 3 FROM numbers(10);
INSERT INTO nullable_key SELECT NULL, -number FROM numbers(3);
SELECT * FROM nullable_key ORDER BY k;
SELECT * FROM nullable_key WHERE k IS NULL;
SELECT * FROM nullable_key WHERE k IS NOT NULL;
SELECT * FROM nullable_key WHERE k > 10;
SELECT * FROM nullable_key WHERE k < 10;
DROP TABLE nullable_key;