Support types with non-standard defaults in ROLLUP, CUBE, GROUPING SETS

This commit is contained in:
Dmitry Novik 2022-05-31 00:10:47 +00:00
parent 18bda56e4c
commit 0e63583b8f
8 changed files with 178 additions and 4 deletions

View File

@ -90,7 +90,7 @@ public:
/// Creates column with the same type and specified size. /// Creates column with the same type and specified size.
/// If size is less current size, then data is cut. /// If size is less current size, then data is cut.
/// If size is greater, than default values are appended. /// If size is greater, than default values are appended.
[[nodiscard]] virtual MutablePtr cloneResized(size_t /*size*/) const { throw Exception("Cannot cloneResized() column " + getName(), ErrorCodes::NOT_IMPLEMENTED); } [[nodiscard]] virtual MutablePtr cloneResized(size_t /*size*/) const { throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Cannot cloneResized() column {}", getName()); }
/// Returns number of values in column. /// Returns number of values in column.
[[nodiscard]] virtual size_t size() const = 0; [[nodiscard]] virtual size_t size() const = 0;

View File

@ -1,3 +1,4 @@
#include <cstddef>
#include <Columns/IColumn.h> #include <Columns/IColumn.h>
#include <Columns/ColumnConst.h> #include <Columns/ColumnConst.h>
#include <Columns/ColumnSparse.h> #include <Columns/ColumnSparse.h>
@ -162,6 +163,12 @@ void IDataType::insertDefaultInto(IColumn & column) const
column.insertDefault(); column.insertDefault();
} }
void IDataType::insertManyDefaultsInto(IColumn & column, size_t n) const
{
for (size_t i = 0; i < n; ++i)
insertDefaultInto(column);
}
void IDataType::setCustomization(DataTypeCustomDescPtr custom_desc_) const void IDataType::setCustomization(DataTypeCustomDescPtr custom_desc_) const
{ {
/// replace only if not null /// replace only if not null

View File

@ -159,6 +159,8 @@ public:
*/ */
virtual void insertDefaultInto(IColumn & column) const; virtual void insertDefaultInto(IColumn & column) const;
void insertManyDefaultsInto(IColumn & column, size_t n) const;
/// Checks that two instances belong to the same type /// Checks that two instances belong to the same type
virtual bool equals(const IDataType & rhs) const = 0; virtual bool equals(const IDataType & rhs) const = 0;

View File

@ -241,7 +241,9 @@ void AggregatingStep::transformPipeline(QueryPipelineBuilder & pipeline, const B
if (missign_column_index < missing_columns.size() && missing_columns[missign_column_index] == i) if (missign_column_index < missing_columns.size() && missing_columns[missign_column_index] == i)
{ {
++missign_column_index; ++missign_column_index;
auto column = ColumnConst::create(col.column->cloneResized(1), 0); auto column_with_default = col.column->cloneEmpty();
col.type->insertDefaultInto(*column_with_default);
auto column = ColumnConst::create(std::move(column_with_default), 0);
const auto * node = &dag->addColumn({ColumnPtr(std::move(column)), col.type, col.name}); const auto * node = &dag->addColumn({ColumnPtr(std::move(column)), col.type, col.name});
node = &dag->materializeNode(*node); node = &dag->materializeNode(*node);
index.push_back(node); index.push_back(node);

View File

@ -35,6 +35,8 @@ void CubeTransform::consume(Chunk chunk)
consumed_chunks.emplace_back(std::move(chunk)); consumed_chunks.emplace_back(std::move(chunk));
} }
MutableColumnPtr getColumnWithDefaults(Block const & header, size_t key, size_t n);
Chunk CubeTransform::generate() Chunk CubeTransform::generate()
{ {
if (!consumed_chunks.empty()) if (!consumed_chunks.empty())
@ -53,8 +55,9 @@ Chunk CubeTransform::generate()
current_zero_columns.clear(); current_zero_columns.clear();
current_zero_columns.reserve(keys.size()); current_zero_columns.reserve(keys.size());
auto const & input_header = getInputPort().getHeader();
for (auto key : keys) for (auto key : keys)
current_zero_columns.emplace_back(current_columns[key]->cloneEmpty()->cloneResized(num_rows)); current_zero_columns.emplace_back(getColumnWithDefaults(input_header, key, num_rows));
} }
auto gen_chunk = std::move(cube_chunk); auto gen_chunk = std::move(cube_chunk);

View File

@ -29,6 +29,14 @@ Chunk RollupTransform::merge(Chunks && chunks, bool final)
return Chunk(rollup_block.getColumns(), num_rows); return Chunk(rollup_block.getColumns(), num_rows);
} }
MutableColumnPtr getColumnWithDefaults(Block const & header, size_t key, size_t n)
{
auto const & col = header.getByPosition(key);
auto result_column = col.column->cloneEmpty();
col.type->insertManyDefaultsInto(*result_column, n);
return result_column;
}
Chunk RollupTransform::generate() Chunk RollupTransform::generate()
{ {
if (!consumed_chunks.empty()) if (!consumed_chunks.empty())
@ -51,7 +59,7 @@ Chunk RollupTransform::generate()
auto num_rows = gen_chunk.getNumRows(); auto num_rows = gen_chunk.getNumRows();
auto columns = gen_chunk.getColumns(); auto columns = gen_chunk.getColumns();
columns[key] = columns[key]->cloneEmpty()->cloneResized(num_rows); columns[key] = getColumnWithDefaults(getInputPort().getHeader(), key, num_rows);
Chunks chunks; Chunks chunks;
chunks.emplace_back(std::move(columns), num_rows); chunks.emplace_back(std::move(columns), num_rows);

View File

@ -0,0 +1,113 @@
-- { echoOn }
SELECT
count() as d, a, b, c
FROM test02313
GROUP BY ROLLUP(a, b, c)
ORDER BY d, a, b, c;
1 one default 0
1 one default 2
1 one default 4
1 one default 6
1 one default 8
1 two non-default 1
1 two non-default 3
1 two non-default 5
1 two non-default 7
1 two non-default 9
5 one default 0
5 one default 0
5 two default 0
5 two non-default 0
10 one default 0
SELECT
count() as d, a, b, c
FROM test02313
GROUP BY CUBE(a, b, c)
ORDER BY d, a, b, c;
1 one default 0
1 one default 0
1 one default 0
1 one default 0
1 one default 1
1 one default 2
1 one default 2
1 one default 2
1 one default 2
1 one default 3
1 one default 4
1 one default 4
1 one default 4
1 one default 4
1 one default 5
1 one default 6
1 one default 6
1 one default 6
1 one default 6
1 one default 7
1 one default 8
1 one default 8
1 one default 8
1 one default 8
1 one default 9
1 one non-default 1
1 one non-default 3
1 one non-default 5
1 one non-default 7
1 one non-default 9
1 two default 1
1 two default 3
1 two default 5
1 two default 7
1 two default 9
1 two non-default 1
1 two non-default 3
1 two non-default 5
1 two non-default 7
1 two non-default 9
5 one default 0
5 one default 0
5 one default 0
5 one non-default 0
5 two default 0
5 two non-default 0
10 one default 0
SELECT
count() as d, a, b, c
FROM test02313
GROUP BY GROUPING SETS
(
(c),
(a, c),
(b, c)
)
ORDER BY d, a, b, c;
1 one default 0
1 one default 0
1 one default 0
1 one default 1
1 one default 2
1 one default 2
1 one default 2
1 one default 3
1 one default 4
1 one default 4
1 one default 4
1 one default 5
1 one default 6
1 one default 6
1 one default 6
1 one default 7
1 one default 8
1 one default 8
1 one default 8
1 one default 9
1 one non-default 1
1 one non-default 3
1 one non-default 5
1 one non-default 7
1 one non-default 9
1 two default 1
1 two default 3
1 two default 5
1 two default 7
1 two default 9

View File

@ -0,0 +1,39 @@
DROP TABLE IF EXISTS test02313;
CREATE TABLE test02313
(
a Enum('one' = 1, 'two' = 2),
b Enum('default' = 0, 'non-default' = 1),
c UInt8
)
ENGINE = MergeTree()
ORDER BY (a, b, c);
INSERT INTO test02313 SELECT number % 2 + 1 AS a, number % 2 AS b, number FROM numbers(10);
-- { echoOn }
SELECT
count() as d, a, b, c
FROM test02313
GROUP BY ROLLUP(a, b, c)
ORDER BY d, a, b, c;
SELECT
count() as d, a, b, c
FROM test02313
GROUP BY CUBE(a, b, c)
ORDER BY d, a, b, c;
SELECT
count() as d, a, b, c
FROM test02313
GROUP BY GROUPING SETS
(
(c),
(a, c),
(b, c)
)
ORDER BY d, a, b, c;
-- { echoOff }
DROP TABLE test02313;