Merge pull request #21357 from ClickHouse/fix-21140

Fix inconsistent column type for Values input format.
This commit is contained in:
tavplubix 2021-03-02 13:12:12 +03:00 committed by GitHub
commit ee22eeea6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 10 deletions

View File

@ -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)

View File

@ -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; }

View File

@ -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

View File

@ -0,0 +1 @@
a

View 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;