mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Merge pull request #21357 from ClickHouse/fix-21140
Fix inconsistent column type for Values input format.
This commit is contained in:
commit
ee22eeea6c
@ -17,6 +17,7 @@
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Interpreters/convertFieldToType.h>
|
||||
#include <Interpreters/ExpressionActions.h>
|
||||
#include <Interpreters/castColumn.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <Parsers/ASTExpressionList.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
@ -589,7 +590,7 @@ bool ConstantExpressionTemplate::parseLiteralAndAssertType(ReadBuffer & istr, co
|
||||
}
|
||||
}
|
||||
|
||||
ColumnPtr ConstantExpressionTemplate::evaluateAll(BlockMissingValues & nulls, size_t column_idx, size_t offset)
|
||||
ColumnPtr ConstantExpressionTemplate::evaluateAll(BlockMissingValues & nulls, size_t column_idx, const DataTypePtr & expected_type, size_t offset)
|
||||
{
|
||||
Block evaluated = structure->literals.cloneWithColumns(std::move(columns));
|
||||
columns = structure->literals.cloneEmptyColumns();
|
||||
@ -607,12 +608,13 @@ ColumnPtr ConstantExpressionTemplate::evaluateAll(BlockMissingValues & nulls, si
|
||||
ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
rows_count = 0;
|
||||
ColumnPtr res = evaluated.getByName(structure->result_column_name).column->convertToFullColumnIfConst();
|
||||
auto res = evaluated.getByName(structure->result_column_name);
|
||||
res.column = res.column->convertToFullColumnIfConst();
|
||||
if (!structure->null_as_default)
|
||||
return res;
|
||||
return castColumn(res, expected_type);
|
||||
|
||||
/// Extract column with evaluated expression and mask for NULLs
|
||||
const auto & tuple = assert_cast<const ColumnTuple &>(*res);
|
||||
const auto & tuple = assert_cast<const ColumnTuple &>(*res.column);
|
||||
if (tuple.tupleSize() != 2)
|
||||
throw Exception("Invalid tuple size, it'a a bug", ErrorCodes::LOGICAL_ERROR);
|
||||
const auto & is_null = assert_cast<const ColumnUInt8 &>(tuple.getColumn(1));
|
||||
@ -621,7 +623,9 @@ ColumnPtr ConstantExpressionTemplate::evaluateAll(BlockMissingValues & nulls, si
|
||||
if (is_null.getUInt(i))
|
||||
nulls.setBit(column_idx, offset + i);
|
||||
|
||||
return tuple.getColumnPtr(0);
|
||||
res.column = tuple.getColumnPtr(0);
|
||||
res.type = assert_cast<const DataTypeTuple &>(*res.type).getElements()[0];
|
||||
return castColumn(res, expected_type);
|
||||
}
|
||||
|
||||
void ConstantExpressionTemplate::TemplateStructure::addNodesToCastResult(const IDataType & result_column_type, ASTPtr & expr, bool null_as_default)
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
|
||||
/// Evaluate batch of expressions were parsed using template.
|
||||
/// If template was deduced with null_as_default == true, set bits in nulls for NULL values in column_idx, starting from offset.
|
||||
ColumnPtr evaluateAll(BlockMissingValues & nulls, size_t column_idx, size_t offset = 0);
|
||||
ColumnPtr evaluateAll(BlockMissingValues & nulls, size_t column_idx, const DataTypePtr & expected_type, size_t offset = 0);
|
||||
|
||||
size_t rowsCount() const { return rows_count; }
|
||||
|
||||
|
@ -73,11 +73,13 @@ Chunk ValuesBlockInputFormat::generate()
|
||||
{
|
||||
if (!templates[i] || !templates[i]->rowsCount())
|
||||
continue;
|
||||
|
||||
const auto & expected_type = header.getByPosition(i).type;
|
||||
if (columns[i]->empty())
|
||||
columns[i] = IColumn::mutate(templates[i]->evaluateAll(block_missing_values, i));
|
||||
columns[i] = IColumn::mutate(templates[i]->evaluateAll(block_missing_values, i, expected_type));
|
||||
else
|
||||
{
|
||||
ColumnPtr evaluated = templates[i]->evaluateAll(block_missing_values, i, columns[i]->size());
|
||||
ColumnPtr evaluated = templates[i]->evaluateAll(block_missing_values, i, expected_type, columns[i]->size());
|
||||
columns[i]->insertRangeFrom(*evaluated, 0, evaluated->size());
|
||||
}
|
||||
}
|
||||
@ -135,13 +137,16 @@ bool ValuesBlockInputFormat::tryParseExpressionUsingTemplate(MutableColumnPtr &
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto & header = getPort().getHeader();
|
||||
const auto & expected_type = header.getByPosition(column_idx).type;
|
||||
|
||||
/// Expression in the current row is not match template deduced on the first row.
|
||||
/// Evaluate expressions, which were parsed using this template.
|
||||
if (column->empty())
|
||||
column = IColumn::mutate(templates[column_idx]->evaluateAll(block_missing_values, column_idx));
|
||||
column = IColumn::mutate(templates[column_idx]->evaluateAll(block_missing_values, column_idx, expected_type));
|
||||
else
|
||||
{
|
||||
ColumnPtr evaluated = templates[column_idx]->evaluateAll(block_missing_values, column_idx, column->size());
|
||||
ColumnPtr evaluated = templates[column_idx]->evaluateAll(block_missing_values, column_idx, expected_type, column->size());
|
||||
column->insertRangeFrom(*evaluated, 0, evaluated->size());
|
||||
}
|
||||
/// Do not use this template anymore
|
||||
|
@ -0,0 +1 @@
|
||||
a
|
14
tests/queries/0_stateless/01746_lc_values_format_bug.sql
Normal file
14
tests/queries/0_stateless/01746_lc_values_format_bug.sql
Normal file
@ -0,0 +1,14 @@
|
||||
drop table if exists lc_test;
|
||||
|
||||
CREATE TABLE lc_test
|
||||
(
|
||||
`id` LowCardinality(String)
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY tuple()
|
||||
ORDER BY id;
|
||||
|
||||
insert into lc_test values (toString('a'));
|
||||
|
||||
select id from lc_test;
|
||||
drop table if exists lc_test;
|
Loading…
Reference in New Issue
Block a user