mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
dbms: fixed error with tuples of consts [#METR-18586].
This commit is contained in:
parent
400588148c
commit
c9a8f19def
@ -266,6 +266,25 @@ public:
|
||||
|
||||
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
|
||||
|
||||
|
||||
ColumnPtr convertToFullColumnIfConst() const override
|
||||
{
|
||||
ColumnPtr new_data;
|
||||
ColumnPtr new_offsets;
|
||||
|
||||
if (auto full_column = data->convertToFullColumnIfConst())
|
||||
new_data = full_column;
|
||||
else
|
||||
new_data = data;
|
||||
|
||||
if (auto full_column = offsets->convertToFullColumnIfConst())
|
||||
new_offsets = full_column;
|
||||
else
|
||||
new_offsets = offsets;
|
||||
|
||||
return new ColumnArray(new_data, new_offsets);
|
||||
}
|
||||
|
||||
private:
|
||||
ColumnPtr data;
|
||||
ColumnPtr offsets; /// Смещения могут быть разделяемыми для нескольких столбцов - для реализации вложенных структур данных.
|
||||
|
@ -21,6 +21,7 @@ class IColumnConst : public IColumn
|
||||
public:
|
||||
bool isConst() const override { return true; }
|
||||
virtual ColumnPtr convertToFullColumn() const = 0;
|
||||
ColumnPtr convertToFullColumnIfConst() const override { return convertToFullColumn(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -242,6 +242,16 @@ public:
|
||||
columns[i]->getExtremes(min.get<Array &>()[i], max.get<Array &>()[i]);
|
||||
}
|
||||
|
||||
ColumnPtr convertToFullColumnIfConst() const override
|
||||
{
|
||||
Block materialized = data;
|
||||
for (size_t i = 0, size = materialized.columns(); i < size; ++i)
|
||||
if (auto converted = materialized.unsafeGetByPosition(i).column->convertToFullColumnIfConst())
|
||||
materialized.unsafeGetByPosition(i).column = converted;
|
||||
|
||||
return new ColumnTuple(materialized);
|
||||
}
|
||||
|
||||
|
||||
const Block & getData() const { return data; }
|
||||
Block & getData() { return data; }
|
||||
|
@ -42,6 +42,15 @@ public:
|
||||
*/
|
||||
virtual bool isConst() const { return false; }
|
||||
|
||||
/** Если столбец не константа - возвращает nullptr (либо может вернуть самого себя).
|
||||
* Если столбец константа, то превращает его в полноценный столбец (если тип столбца предполагает такую возможность) и возвращает его.
|
||||
* Отдельный случай:
|
||||
* Если столбец состоит из нескольких других столбцов (пример: кортеж),
|
||||
* и он может содержать как константные, так и полноценные столбцы,
|
||||
* то превратить в нём все константные столбцы в полноценные, и вернуть результат.
|
||||
*/
|
||||
virtual SharedPtr<IColumn> convertToFullColumnIfConst() const { return {}; }
|
||||
|
||||
/** Значения имеют фиксированную длину.
|
||||
*/
|
||||
virtual bool isFixed() const { return false; }
|
||||
|
@ -38,9 +38,10 @@ protected:
|
||||
size_t columns = res.columns();
|
||||
for (size_t i = 0; i < columns; ++i)
|
||||
{
|
||||
ColumnPtr col = res.getByPosition(i).column;
|
||||
if (col->isConst())
|
||||
res.getByPosition(i).column = dynamic_cast<IColumnConst &>(*col).convertToFullColumn();
|
||||
auto & src = res.getByPosition(i).column;
|
||||
ColumnPtr converted = src->convertToFullColumnIfConst();
|
||||
if (converted)
|
||||
src = converted;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -23,9 +23,10 @@ public:
|
||||
|
||||
for (const auto i : ext::range(0, block.columns()))
|
||||
{
|
||||
ColumnPtr & col = block.getByPosition(i).column;
|
||||
if (col->isConst())
|
||||
col = dynamic_cast<IColumnConst &>(*col).convertToFullColumn();
|
||||
auto & src = block.getByPosition(i).column;
|
||||
ColumnPtr converted = src->convertToFullColumnIfConst();
|
||||
if (converted)
|
||||
src = converted;
|
||||
}
|
||||
|
||||
output->write(block);
|
||||
|
@ -44,8 +44,8 @@ inline void evaluateMissingDefaults(Block & block,
|
||||
/// move evaluated columns to the original block, materializing them at the same time
|
||||
for (auto & column_name_type : copy_block.getColumns())
|
||||
{
|
||||
if (column_name_type.column->isConst())
|
||||
column_name_type.column = static_cast<const IColumnConst &>(*column_name_type.column).convertToFullColumn();
|
||||
if (auto converted = column_name_type.column->convertToFullColumnIfConst())
|
||||
column_name_type.column = converted;
|
||||
|
||||
block.insert(std::move(column_name_type));
|
||||
}
|
||||
|
@ -159,8 +159,8 @@ bool filterBlockWithQuery(ASTPtr query, Block & block, const Context & context)
|
||||
/// Отфильтруем блок.
|
||||
String filter_column_name = expression_ast->getColumnName();
|
||||
ColumnPtr filter_column = block.getByName(filter_column_name).column;
|
||||
if (IColumnConst * const_column = dynamic_cast<IColumnConst *>(&*filter_column))
|
||||
filter_column = const_column->convertToFullColumn();
|
||||
if (auto converted = filter_column->convertToFullColumnIfConst())
|
||||
filter_column = converted;
|
||||
const IColumn::Filter & filter = dynamic_cast<ColumnUInt8 &>(*filter_column).getData();
|
||||
|
||||
if (std::accumulate(filter.begin(), filter.end(), 0ul) == filter.size())
|
||||
|
@ -116,8 +116,8 @@ void IProfilingBlockInputStream::updateExtremes(Block & block)
|
||||
|
||||
ColumnPtr & column = extremes.getByPosition(i).column;
|
||||
|
||||
if (column->isConst())
|
||||
column = dynamic_cast<const IColumnConst &>(*column).convertToFullColumn();
|
||||
if (auto converted = column->convertToFullColumnIfConst())
|
||||
column = converted;
|
||||
|
||||
column->insert(min_value);
|
||||
column->insert(max_value);
|
||||
|
@ -37,9 +37,12 @@ void NativeBlockOutputStream::writeData(const IDataType & type, const ColumnPtr
|
||||
/** Если есть столбцы-константы - то материализуем их.
|
||||
* (Так как тип данных не умеет сериализовывать/десериализовывать константы.)
|
||||
*/
|
||||
ColumnPtr full_column = column->isConst()
|
||||
? static_cast<const IColumnConst &>(*column).convertToFullColumn()
|
||||
: column;
|
||||
ColumnPtr full_column;
|
||||
|
||||
if (auto converted = column->convertToFullColumnIfConst())
|
||||
full_column = converted;
|
||||
else
|
||||
full_column = column;
|
||||
|
||||
/** Для массивов требуется сначала сериализовать смещения, а потом значения.
|
||||
*/
|
||||
|
@ -117,8 +117,8 @@ void Aggregator::initialize(const Block & block)
|
||||
for (size_t i = 0; i < keys_size; ++i)
|
||||
{
|
||||
sample.insert(block.getByPosition(keys[i]).cloneEmpty());
|
||||
if (sample.getByPosition(i).column->isConst())
|
||||
sample.getByPosition(i).column = dynamic_cast<IColumnConst &>(*sample.getByPosition(i).column).convertToFullColumn();
|
||||
if (auto converted = sample.getByPosition(i).column->convertToFullColumnIfConst())
|
||||
sample.getByPosition(i).column = converted;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aggregates_size; ++i)
|
||||
@ -593,9 +593,9 @@ bool Aggregator::executeOnBlock(Block & block, AggregatedDataVariants & result,
|
||||
{
|
||||
key_columns[i] = block.getByPosition(keys[i]).column;
|
||||
|
||||
if (const IColumnConst * column_const = dynamic_cast<const IColumnConst *>(key_columns[i]))
|
||||
if (auto converted = key_columns[i]->convertToFullColumnIfConst())
|
||||
{
|
||||
materialized_columns.push_back(column_const->convertToFullColumn());
|
||||
materialized_columns.push_back(converted);
|
||||
key_columns[i] = materialized_columns.back().get();
|
||||
}
|
||||
}
|
||||
@ -606,9 +606,9 @@ bool Aggregator::executeOnBlock(Block & block, AggregatedDataVariants & result,
|
||||
{
|
||||
aggregate_columns[i][j] = block.getByPosition(aggregates[i].arguments[j]).column;
|
||||
|
||||
if (const IColumnConst * column_const = dynamic_cast<const IColumnConst *>(aggregate_columns[i][j]))
|
||||
if (auto converted = aggregate_columns[i][j]->convertToFullColumnIfConst())
|
||||
{
|
||||
materialized_columns.push_back(column_const->convertToFullColumn());
|
||||
materialized_columns.push_back(converted);
|
||||
aggregate_columns[i][j] = materialized_columns.back().get();
|
||||
}
|
||||
}
|
||||
|
@ -264,8 +264,8 @@ void ExpressionAction::execute(Block & block) const
|
||||
throw Exception("No arrays to join", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
ColumnPtr any_array_ptr = block.getByName(*array_joined_columns.begin()).column;
|
||||
if (any_array_ptr->isConst())
|
||||
any_array_ptr = dynamic_cast<const IColumnConst &>(*any_array_ptr).convertToFullColumn();
|
||||
if (auto converted = any_array_ptr->convertToFullColumnIfConst())
|
||||
any_array_ptr = converted;
|
||||
|
||||
const ColumnArray * any_array = typeid_cast<const ColumnArray *>(&*any_array_ptr);
|
||||
if (!any_array)
|
||||
@ -301,8 +301,8 @@ void ExpressionAction::execute(Block & block) const
|
||||
|
||||
ColumnPtr array_ptr = array_join_is_left ? non_empty_array_columns[current.name] : current.column;
|
||||
|
||||
if (array_ptr->isConst())
|
||||
array_ptr = dynamic_cast<const IColumnConst &>(*array_ptr).convertToFullColumn();
|
||||
if (auto converted = array_ptr->convertToFullColumnIfConst())
|
||||
array_ptr = converted;
|
||||
|
||||
const ColumnArray & array = typeid_cast<const ColumnArray &>(*array_ptr);
|
||||
if (!array.hasEqualOffsets(typeid_cast<const ColumnArray &>(*any_array_ptr)))
|
||||
|
@ -418,9 +418,9 @@ bool Join::insertFromBlock(const Block & block)
|
||||
{
|
||||
key_columns[i] = block.getByName(key_names_right[i]).column;
|
||||
|
||||
if (auto * col_const = dynamic_cast<const IColumnConst *>(key_columns[i]))
|
||||
if (auto converted = key_columns[i]->convertToFullColumnIfConst())
|
||||
{
|
||||
materialized_columns.emplace_back(col_const->convertToFullColumn());
|
||||
materialized_columns.emplace_back(converted);
|
||||
key_columns[i] = materialized_columns.back();
|
||||
}
|
||||
}
|
||||
@ -456,8 +456,8 @@ bool Join::insertFromBlock(const Block & block)
|
||||
for (size_t i = 0, size = stored_block->columns(); i < size; ++i)
|
||||
{
|
||||
ColumnPtr col = stored_block->getByPosition(i).column;
|
||||
if (auto * col_const = dynamic_cast<const IColumnConst *>(col.get()))
|
||||
stored_block->getByPosition(i).column = col_const->convertToFullColumn();
|
||||
if (auto converted = col->convertToFullColumnIfConst())
|
||||
stored_block->getByPosition(i).column = converted;
|
||||
}
|
||||
|
||||
if (kind != ASTJoin::Cross)
|
||||
@ -604,9 +604,9 @@ void Join::joinBlockImpl(Block & block, const Maps & maps) const
|
||||
{
|
||||
key_columns[i] = block.getByName(key_names_left[i]).column;
|
||||
|
||||
if (auto * col_const = dynamic_cast<const IColumnConst *>(key_columns[i]))
|
||||
if (auto converted = key_columns[i]->convertToFullColumnIfConst())
|
||||
{
|
||||
materialized_columns.emplace_back(col_const->convertToFullColumn());
|
||||
materialized_columns.emplace_back(converted);
|
||||
key_columns[i] = materialized_columns.back();
|
||||
}
|
||||
}
|
||||
@ -623,8 +623,8 @@ void Join::joinBlockImpl(Block & block, const Maps & maps) const
|
||||
{
|
||||
auto & col = block.getByPosition(i).column;
|
||||
|
||||
if (auto * col_const = dynamic_cast<IColumnConst *>(col.get()))
|
||||
col = col_const->convertToFullColumn();
|
||||
if (auto converted = col->convertToFullColumnIfConst())
|
||||
col = converted;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,9 +185,9 @@ bool Set::insertFromBlock(const Block & block, bool create_ordered_set)
|
||||
key_columns[i] = block.getByPosition(i).column;
|
||||
data_types[i] = block.getByPosition(i).type;
|
||||
|
||||
if (key_columns[i]->isConst())
|
||||
if (auto converted = key_columns[i]->convertToFullColumnIfConst())
|
||||
{
|
||||
materialized_columns.emplace_back(static_cast<const IColumnConst *>(key_columns[i])->convertToFullColumn());
|
||||
materialized_columns.emplace_back(converted);
|
||||
key_columns[i] = materialized_columns.back().get();
|
||||
}
|
||||
}
|
||||
@ -475,11 +475,8 @@ ColumnPtr Set::execute(const Block & block, bool negative) const
|
||||
|
||||
/// Константный столбец слева от IN поддерживается не напрямую. Для этого, он сначала материализуется.
|
||||
ColumnPtr materialized_column;
|
||||
if (in_column->isConst())
|
||||
{
|
||||
materialized_column = static_cast<const IColumnConst *>(in_column)->convertToFullColumn();
|
||||
if (materialized_column = in_column->convertToFullColumnIfConst())
|
||||
in_column = materialized_column.get();
|
||||
}
|
||||
|
||||
if (const ColumnArray * col = typeid_cast<const ColumnArray *>(in_column))
|
||||
executeArray(col, vec_res, negative);
|
||||
@ -507,9 +504,9 @@ ColumnPtr Set::execute(const Block & block, bool negative) const
|
||||
Columns materialized_columns;
|
||||
for (auto & column_ptr : key_columns)
|
||||
{
|
||||
if (column_ptr->isConst())
|
||||
if (auto converted = column_ptr->convertToFullColumnIfConst())
|
||||
{
|
||||
materialized_columns.emplace_back(static_cast<const IColumnConst *>(column_ptr)->convertToFullColumn());
|
||||
materialized_columns.emplace_back(converted);
|
||||
column_ptr = materialized_columns.back().get();
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ Block LogBlockInputStream::readImpl()
|
||||
rows = res.rows();
|
||||
if (rows > 0)
|
||||
{
|
||||
ColumnPtr column_ptr = ColumnConst<String> (rows, current_table.first, new DataTypeString).convertToFullColumn();
|
||||
ColumnPtr column_ptr = ColumnConst<String>(rows, current_table.first, new DataTypeString).convertToFullColumn();
|
||||
ColumnWithTypeAndName column(column_ptr, new DataTypeString, storage._table_column_name);
|
||||
res.insert(column);
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
(1)
|
||||
(1)
|
||||
(1)
|
||||
(2)
|
||||
(0)
|
||||
(0)
|
||||
(0)
|
||||
(0)
|
||||
(0)
|
||||
(1)
|
@ -0,0 +1,5 @@
|
||||
select * from (select tuple(1) as a union all select tuple(1) as a) order by a;
|
||||
select * from (select tuple(1) as a union all select tuple(2) as a) order by a;
|
||||
select * from (select tuple(materialize(0)) as a union all select tuple(0) as a) order by a;
|
||||
select * from (select tuple(range(1)[1]) as a union all select tuple(0) as a) order by a;
|
||||
select * from (select tuple(range(1)[2]) as a union all select tuple(1) as a) order by a;
|
Loading…
Reference in New Issue
Block a user