Skip to content

Commit 1c531f2

Browse files
Backport ClickHouse#88879 to 25.8: Fix handling of non materialized Nested(Tuple(...)) (added via ALTER)
1 parent 6ba0c86 commit 1c531f2

File tree

3 files changed

+49
-5
lines changed

3 files changed

+49
-5
lines changed

src/DataTypes/ObjectUtils.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,19 @@ DataTypePtr getBaseTypeOfArray(const DataTypePtr & type)
7070
DataTypePtr getBaseTypeOfArray(DataTypePtr type, const Names & tuple_elements)
7171
{
7272
auto it = tuple_elements.begin();
73+
74+
/// Get underlying type for array, but w/o processing tuple elements that are not part of the nested, so it is done in 3 steps:
75+
/// 1. Find Nested type (since it can be part of Tuple/Array)
76+
/// 2. Process all Nested types (this is Array(Tuple()), it is responsibility of the caller to re-create proper Array nesting)
77+
/// 3. Strip all nested arrays (it is responsibility of the caller to re-create proper Array nesting)
78+
79+
/// 1. Find Nested type (since it can be part of Tuple/Array)
7380
while (true)
7481
{
75-
if (const auto * type_array = typeid_cast<const DataTypeArray *>(type.get()))
76-
{
82+
if (type->hasCustomName())
83+
break;
84+
else if (const auto * type_array = typeid_cast<const DataTypeArray *>(type.get()))
7785
type = type_array->getNestedType();
78-
}
7986
else if (const auto * type_tuple = typeid_cast<const DataTypeTuple *>(type.get()))
8087
{
8188
if (it == tuple_elements.end())
@@ -84,16 +91,38 @@ DataTypePtr getBaseTypeOfArray(DataTypePtr type, const Names & tuple_elements)
8491
auto pos = type_tuple->tryGetPositionByName(*it);
8592
if (!pos)
8693
break;
87-
8894
++it;
95+
8996
type = type_tuple->getElement(*pos);
9097
}
9198
else
92-
{
9399
break;
100+
}
101+
102+
/// 2. Process all Nested types (this is Array(Tuple()), it is responsibility of the caller to re-create proper Array nesting)
103+
while (type->hasCustomName())
104+
{
105+
if (const auto * type_nested = typeid_cast<const DataTypeNestedCustomName *>(type->getCustomName()))
106+
{
107+
if (it == tuple_elements.end())
108+
break;
109+
110+
const auto & names = type_nested->getNames();
111+
auto pos = std::find(names.begin(), names.end(), *it);
112+
if (pos == names.end())
113+
break;
114+
++it;
115+
116+
type = type_nested->getElements().at(std::distance(names.begin(), pos));
94117
}
118+
else
119+
break;
95120
}
96121

122+
/// 3. Strip all nested arrays (it is responsibility of the caller to re-create proper Array nesting)
123+
while (const auto * type_array = typeid_cast<const DataTypeArray *>(type.get()))
124+
type = type_array->getNestedType();
125+
97126
return type;
98127
}
99128

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[1,2,3] [(0),(0),(0)]
2+
[1,2,3] [((0)),((0)),((0))]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
DROP TABLE IF EXISTS nest;
2+
CREATE TABLE nest (nested_field Nested(e1 Int32)) ENGINE = MergeTree() ORDER BY nested_field.e1;
3+
INSERT INTO nest (nested_field.e1) VALUES ([1, 2, 3]);
4+
ALTER TABLE nest ADD COLUMN nested_field.e2 Array(Tuple(some_value Int32));
5+
OPTIMIZE TABLE nest FINAL;
6+
SELECT * FROM nest;
7+
8+
DROP TABLE IF EXISTS nest_2;
9+
CREATE TABLE nest_2 (nested_field Nested(e1 Int32)) ENGINE = MergeTree() ORDER BY nested_field.e1;
10+
INSERT INTO nest_2 (nested_field.e1) VALUES ([1, 2, 3]);
11+
ALTER TABLE nest_2 ADD COLUMN nested_field.e2 Array(Tuple(some_value Tuple(another_value Int32)));
12+
OPTIMIZE TABLE nest_2 FINAL;
13+
SELECT * FROM nest_2;

0 commit comments

Comments
 (0)