mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-28 02:21:59 +00:00
Merge pull request #28028 from ClickHouse/replicated-tree-attach-wip
Allow attaching parts with 'compatible' enum types
This commit is contained in:
commit
bcaff65457
@ -27,6 +27,8 @@ public:
|
||||
bool isCategorial() const override { return true; }
|
||||
bool canBeInsideNullable() const override { return true; }
|
||||
bool isComparable() const override { return true; }
|
||||
|
||||
virtual bool contains(const IDataType & rhs) const = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -76,7 +78,7 @@ public:
|
||||
/// Example:
|
||||
/// Enum('a' = 1, 'b' = 2) -> Enum('c' = 1, 'b' = 2, 'd' = 3) OK
|
||||
/// Enum('a' = 1, 'b' = 2) -> Enum('a' = 2, 'b' = 1) NOT OK
|
||||
bool contains(const IDataType & rhs) const;
|
||||
bool contains(const IDataType & rhs) const override;
|
||||
|
||||
SerializationPtr doGetDefaultSerialization() const override;
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <Common/quoteString.h>
|
||||
#include <Common/StringUtils/StringUtils.h>
|
||||
#include <Core/ColumnWithTypeAndName.h>
|
||||
#include <DataTypes/DataTypeEnum.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <IO/Operators.h>
|
||||
@ -495,6 +496,23 @@ namespace
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks compatibility of enums. It returns true if:
|
||||
* 1. Both types are enums.
|
||||
* 2. The first type can represent all possible values of the second one.
|
||||
* 3. Both types require the same amount of memory.
|
||||
*/
|
||||
bool isCompatibleEnumTypes(const IDataType * lhs, const IDataType * rhs)
|
||||
{
|
||||
if (IDataTypeEnum const * enum_type = dynamic_cast<IDataTypeEnum const *>(lhs))
|
||||
{
|
||||
if (!enum_type->contains(*rhs))
|
||||
return false;
|
||||
return enum_type->getMaximumSizeOfValueInMemory() == rhs->getMaximumSizeOfValueInMemory();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void StorageInMemoryMetadata::check(const Names & column_names, const NamesAndTypesList & virtuals, const StorageID & storage_id) const
|
||||
@ -546,12 +564,13 @@ void StorageInMemoryMetadata::check(const NamesAndTypesList & provided_columns)
|
||||
column.name,
|
||||
listOfColumns(available_columns));
|
||||
|
||||
if (!column.type->equals(*it->getMapped()))
|
||||
const auto * available_type = it->getMapped();
|
||||
if (!column.type->equals(*available_type) && !isCompatibleEnumTypes(available_type, column.type.get()))
|
||||
throw Exception(
|
||||
ErrorCodes::TYPE_MISMATCH,
|
||||
"Type mismatch for column {}. Column has type {}, got type {}",
|
||||
column.name,
|
||||
it->getMapped()->getName(),
|
||||
available_type->getName(),
|
||||
column.type->getName());
|
||||
|
||||
if (unique_names.end() != unique_names.find(column.name))
|
||||
@ -590,16 +609,16 @@ void StorageInMemoryMetadata::check(const NamesAndTypesList & provided_columns,
|
||||
name,
|
||||
listOfColumns(available_columns));
|
||||
|
||||
const auto & provided_column_type = *it->getMapped();
|
||||
const auto & available_column_type = *jt->getMapped();
|
||||
const auto * provided_column_type = it->getMapped();
|
||||
const auto * available_column_type = jt->getMapped();
|
||||
|
||||
if (!provided_column_type.equals(available_column_type))
|
||||
if (!provided_column_type->equals(*available_column_type) && !isCompatibleEnumTypes(available_column_type, provided_column_type))
|
||||
throw Exception(
|
||||
ErrorCodes::TYPE_MISMATCH,
|
||||
"Type mismatch for column {}. Column has type {}, got type {}",
|
||||
name,
|
||||
provided_column_type.getName(),
|
||||
available_column_type.getName());
|
||||
available_column_type->getName(),
|
||||
provided_column_type->getName());
|
||||
|
||||
if (unique_names.end() != unique_names.find(name))
|
||||
throw Exception(ErrorCodes::COLUMN_QUERIED_MORE_THAN_ONCE,
|
||||
@ -634,12 +653,13 @@ void StorageInMemoryMetadata::check(const Block & block, bool need_all) const
|
||||
column.name,
|
||||
listOfColumns(available_columns));
|
||||
|
||||
if (!column.type->equals(*it->getMapped()))
|
||||
const auto * available_type = it->getMapped();
|
||||
if (!column.type->equals(*available_type) && !isCompatibleEnumTypes(available_type, column.type.get()))
|
||||
throw Exception(
|
||||
ErrorCodes::TYPE_MISMATCH,
|
||||
"Type mismatch for column {}. Column has type {}, got type {}",
|
||||
column.name,
|
||||
it->getMapped()->getName(),
|
||||
available_type->getName(),
|
||||
column.type->getName());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
one
|
||||
one
|
||||
two
|
||||
two
|
@ -0,0 +1,8 @@
|
||||
create table enum_alter_issue (a Enum8('one' = 1, 'two' = 2)) engine = MergeTree() ORDER BY a;
|
||||
insert into enum_alter_issue values ('one'), ('two');
|
||||
alter table enum_alter_issue modify column a Enum8('one' = 1, 'two' = 2, 'three' = 3);
|
||||
insert into enum_alter_issue values ('one'), ('two');
|
||||
alter table enum_alter_issue detach partition id 'all';
|
||||
alter table enum_alter_issue attach partition id 'all';
|
||||
select * from enum_alter_issue order by a;
|
||||
drop table enum_alter_issue;
|
@ -0,0 +1,4 @@
|
||||
one 1
|
||||
two 2
|
||||
one 3
|
||||
two 4
|
@ -0,0 +1,13 @@
|
||||
create table enum_alter_issue (a Enum8('one' = 1, 'two' = 2), b Int)
|
||||
engine = ReplicatedMergeTree('/clickhouse/tables/{database}/test_02012/enum_alter_issue', 'r1')
|
||||
ORDER BY a;
|
||||
|
||||
insert into enum_alter_issue values ('one', 1), ('two', 2);
|
||||
alter table enum_alter_issue modify column a Enum8('one' = 1, 'two' = 2, 'three' = 3);
|
||||
insert into enum_alter_issue values ('one', 3), ('two', 4);
|
||||
|
||||
alter table enum_alter_issue detach partition id 'all';
|
||||
alter table enum_alter_issue attach partition id 'all';
|
||||
select * from enum_alter_issue order by b;
|
||||
|
||||
drop table enum_alter_issue;
|
@ -0,0 +1,12 @@
|
||||
drop table if exists enum_alter_issue;
|
||||
create table enum_alter_issue (a Enum16('one' = 1, 'two' = 2), b Int)
|
||||
engine = ReplicatedMergeTree('/clickhouse/tables/{database}/test_02012/enum_alter_issue', 'r2')
|
||||
ORDER BY b;
|
||||
|
||||
insert into enum_alter_issue values ('one', 1), ('two', 1);
|
||||
alter table enum_alter_issue detach partition id 'all';
|
||||
alter table enum_alter_issue modify column a Enum8('one' = 1, 'two' = 2, 'three' = 3);
|
||||
insert into enum_alter_issue values ('one', 1), ('two', 1);
|
||||
|
||||
alter table enum_alter_issue attach partition id 'all'; -- {serverError TYPE_MISMATCH}
|
||||
drop table enum_alter_issue;
|
@ -161,6 +161,9 @@
|
||||
"00980_zookeeper_merge_tree_alter_settings",
|
||||
"00980_merge_alter_settings",
|
||||
"02009_array_join_partition",
|
||||
"02012_changed_enum_type_non_replicated",
|
||||
"02012_zookeeper_changed_enum_type",
|
||||
"02012_zookeeper_changed_enum_type_incompatible",
|
||||
/// Old syntax is not allowed
|
||||
"01062_alter_on_mutataion_zookeeper",
|
||||
"00925_zookeeper_empty_replicated_merge_tree_optimize_final",
|
||||
|
Loading…
Reference in New Issue
Block a user