Skip to content

Commit 877445c

Browse files
committed
Fix reading dynamic subcolumns from altered Memory table
1 parent 5a6e6d3 commit 877445c

File tree

5 files changed

+62
-6
lines changed

5 files changed

+62
-6
lines changed

src/Interpreters/getColumnFromBlock.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,36 @@ ColumnPtr tryGetColumnFromBlock(const Block & block, const NameAndTypePair & req
3131
return castColumn({elem_column, elem_type, ""}, requested_column.type);
3232
}
3333

34+
ColumnPtr tryGetSubcolumnFromBlock(const Block & block, const DataTypePtr & requested_column_type, const NameAndTypePair & requested_subcolumn)
35+
{
36+
const auto * elem = block.findByName(requested_subcolumn.getNameInStorage());
37+
if (!elem)
38+
return nullptr;
39+
40+
auto subcolumn_name = requested_subcolumn.getSubcolumnName();
41+
/// If requested subcolumn is dynamic, we should first perform cast and then
42+
/// extract the subcolumn, because the data of dynamic subcolumn can change after cast.
43+
if (elem->type->hasDynamicSubcolumns() && !elem->type->equals(*requested_column_type))
44+
{
45+
auto casted_column = castColumn({elem->column, elem->type, ""}, requested_column_type);
46+
auto elem_column = requested_column_type->tryGetSubcolumn(subcolumn_name, casted_column);
47+
auto elem_type = requested_column_type->tryGetSubcolumnType(subcolumn_name);
48+
49+
if (!elem_type || !elem_column)
50+
return nullptr;
51+
52+
return elem_column;
53+
}
54+
55+
auto elem_column = elem->type->tryGetSubcolumn(subcolumn_name, elem->column);
56+
auto elem_type = elem->type->tryGetSubcolumnType(subcolumn_name);
57+
58+
if (!elem_type || !elem_column)
59+
return nullptr;
60+
61+
return castColumn({elem_column, elem_type, ""}, requested_subcolumn.type);
62+
}
63+
3464
ColumnPtr getColumnFromBlock(const Block & block, const NameAndTypePair & requested_column)
3565
{
3666
auto result_column = tryGetColumnFromBlock(block, requested_column);

src/Interpreters/getColumnFromBlock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ namespace DB
99
ColumnPtr getColumnFromBlock(const Block & block, const NameAndTypePair & requested_column);
1010

1111
ColumnPtr tryGetColumnFromBlock(const Block & block, const NameAndTypePair & requested_column);
12+
ColumnPtr tryGetSubcolumnFromBlock(const Block & block, const DataTypePtr & requested_column_type, const NameAndTypePair & requested_subcolumn);
1213

1314
}

src/Processors/QueryPlan/ReadFromMemoryStorageStep.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@ class MemorySource : public ISource
3030
std::shared_ptr<std::atomic<size_t>> parallel_execution_index_,
3131
InitializerFunc initializer_func_ = {})
3232
: ISource(storage_snapshot->getSampleBlockForColumns(column_names_))
33-
, column_names_and_types(storage_snapshot->getColumnsByNames(
33+
, requested_column_names_and_types(storage_snapshot->getColumnsByNames(
3434
GetColumnsOptions(GetColumnsOptions::All).withSubcolumns().withExtendedObjects(), column_names_))
3535
, data(data_)
3636
, parallel_execution_index(parallel_execution_index_)
3737
, initializer_func(std::move(initializer_func_))
3838
{
39+
auto all_column_names_and_types = storage_snapshot->getColumns(GetColumnsOptions(GetColumnsOptions::All).withSubcolumns().withExtendedObjects());
40+
for (const auto & [name, type] : all_column_names_and_types)
41+
all_names_to_types[name] = type;
3942
}
4043

4144
String getName() const override { return "Memory"; }
@@ -59,17 +62,20 @@ class MemorySource : public ISource
5962
const Block & src = (*data)[current_index];
6063

6164
Columns columns;
62-
size_t num_columns = column_names_and_types.size();
65+
size_t num_columns = requested_column_names_and_types.size();
6366
columns.reserve(num_columns);
6467

65-
auto name_and_type = column_names_and_types.begin();
68+
auto name_and_type = requested_column_names_and_types.begin();
6669
for (size_t i = 0; i < num_columns; ++i)
6770
{
68-
columns.emplace_back(tryGetColumnFromBlock(src, *name_and_type));
71+
if (name_and_type->isSubcolumn())
72+
columns.emplace_back(tryGetSubcolumnFromBlock(src, all_names_to_types[name_and_type->getNameInStorage()], *name_and_type));
73+
else
74+
columns.emplace_back(tryGetColumnFromBlock(src, *name_and_type));
6975
++name_and_type;
7076
}
7177

72-
fillMissingColumns(columns, src.rows(), column_names_and_types, column_names_and_types, {}, nullptr);
78+
fillMissingColumns(columns, src.rows(), requested_column_names_and_types, requested_column_names_and_types, {}, nullptr);
7379
assert(std::all_of(columns.begin(), columns.end(), [](const auto & column) { return column != nullptr; }));
7480

7581
return Chunk(std::move(columns), src.rows());
@@ -88,7 +94,9 @@ class MemorySource : public ISource
8894
}
8995
}
9096

91-
const NamesAndTypesList column_names_and_types;
97+
const NamesAndTypesList requested_column_names_and_types;
98+
/// Map (name -> type) for all columns from the storage header.
99+
std::unordered_map<String, DataTypePtr> all_names_to_types;
92100
size_t execution_index = 0;
93101
std::shared_ptr<const Blocks> data;
94102
std::shared_ptr<std::atomic<size_t>> parallel_execution_index;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
\N
2+
\N
3+
\N
4+
\N
5+
\N
6+
\N
7+
\N
8+
\N
9+
\N
10+
\N
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
set allow_experimental_dynamic_type=1;
2+
create table test (d Dynamic) engine=Memory;
3+
insert into table test select * from numbers(5);
4+
alter table test modify column d Dynamic(max_types=1);
5+
select d.UInt64 from test settings allow_experimental_analyzer=1;
6+
select d.UInt64 from test settings allow_experimental_analyzer=1;
7+

0 commit comments

Comments
 (0)