mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
fix union all supertype column
This commit is contained in:
parent
d4f474cd19
commit
28c1a60eb7
67
dbms/src/Columns/getLeastSuperColumn.cpp
Normal file
67
dbms/src/Columns/getLeastSuperColumn.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <Columns/getLeastSuperColumn.h>
|
||||
#include <Columns/IColumn.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <DataTypes/getLeastSupertype.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
static bool sameConstants(const IColumn & a, const IColumn & b)
|
||||
{
|
||||
return static_cast<const ColumnConst &>(a).getField() == static_cast<const ColumnConst &>(b).getField();
|
||||
}
|
||||
|
||||
ColumnWithTypeAndName getLeastSuperColumn(std::vector<const ColumnWithTypeAndName *> columns)
|
||||
{
|
||||
if (columns.empty())
|
||||
throw Exception("Logical error: no src columns for supercolumn", ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
ColumnWithTypeAndName result = *columns[0];
|
||||
|
||||
/// Determine common type.
|
||||
|
||||
size_t num_const = 0;
|
||||
DataTypes types(columns.size());
|
||||
for (size_t i = 0; i < columns.size(); ++i)
|
||||
{
|
||||
types[i] = columns[i]->type;
|
||||
if (columns[i]->column->isColumnConst())
|
||||
++num_const;
|
||||
}
|
||||
|
||||
result.type = getLeastSupertype(types);
|
||||
|
||||
/// Create supertype column saving constness if possible.
|
||||
|
||||
bool save_constness = false;
|
||||
if (columns.size() == num_const)
|
||||
{
|
||||
save_constness = true;
|
||||
for (size_t i = 1; i < columns.size(); ++i)
|
||||
{
|
||||
const ColumnWithTypeAndName & first = *columns[0];
|
||||
const ColumnWithTypeAndName & other = *columns[i];
|
||||
|
||||
if (!sameConstants(*first.column, *other.column))
|
||||
{
|
||||
save_constness = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (save_constness)
|
||||
result.column = result.type->createColumnConst(1, static_cast<const ColumnConst &>(*columns[0]->column).getField());
|
||||
else
|
||||
result.column = result.type->createColumn();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
12
dbms/src/Columns/getLeastSuperColumn.h
Normal file
12
dbms/src/Columns/getLeastSuperColumn.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/ColumnWithTypeAndName.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/// getLeastSupertype + related column changes
|
||||
ColumnWithTypeAndName getLeastSuperColumn(std::vector<const ColumnWithTypeAndName *> columns);
|
||||
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
#include <DataStreams/NullBlockInputStream.h>
|
||||
#include <DataStreams/ConcatBlockInputStream.h>
|
||||
#include <DataStreams/ConvertingBlockInputStream.h>
|
||||
#include <DataTypes/getLeastSupertype.h>
|
||||
#include <Columns/getLeastSuperColumn.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Parsers/queryToString.h>
|
||||
@ -114,39 +114,13 @@ InterpreterSelectWithUnionQuery::InterpreterSelectWithUnionQuery(
|
||||
|
||||
for (size_t column_num = 0; column_num < num_columns; ++column_num)
|
||||
{
|
||||
std::vector<const ColumnWithTypeAndName *> columns;
|
||||
columns.reserve(num_selects);
|
||||
for (size_t i = 0; i < num_selects; ++i)
|
||||
columns.push_back(&headers[i].getByPosition(column_num));
|
||||
|
||||
ColumnWithTypeAndName & result_elem = result_header.getByPosition(column_num);
|
||||
|
||||
/// Determine common type.
|
||||
|
||||
DataTypes types(num_selects);
|
||||
for (size_t query_num = 0; query_num < num_selects; ++query_num)
|
||||
types[query_num] = headers[query_num].getByPosition(column_num).type;
|
||||
|
||||
result_elem.type = getLeastSupertype(types);
|
||||
|
||||
/// If there are different constness or different values of constants, the result must be non-constant.
|
||||
|
||||
if (result_elem.column->isColumnConst())
|
||||
{
|
||||
bool need_materialize = false;
|
||||
for (size_t query_num = 1; query_num < num_selects; ++query_num)
|
||||
{
|
||||
const ColumnWithTypeAndName & source_elem = headers[query_num].getByPosition(column_num);
|
||||
|
||||
if (!source_elem.column->isColumnConst()
|
||||
|| (static_cast<const ColumnConst &>(*result_elem.column).getField()
|
||||
!= static_cast<const ColumnConst &>(*source_elem.column).getField()))
|
||||
{
|
||||
need_materialize = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_materialize)
|
||||
result_elem.column = result_elem.type->createColumn();
|
||||
}
|
||||
|
||||
/// BTW, result column names are from first SELECT.
|
||||
result_elem = getLeastSuperColumn(columns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
UInt64 Nullable(String)
|
||||
UInt64 Nullable(String)
|
||||
Decimal(18, 8) Nullable(String)
|
||||
Decimal(18, 8) Nullable(String)
|
||||
v2
|
||||
v1 \N
|
||||
v1 w1
|
||||
key1 value1
|
30
dbms/tests/queries/0_stateless/00864_union_all_supertype.sql
Normal file
30
dbms/tests/queries/0_stateless/00864_union_all_supertype.sql
Normal file
@ -0,0 +1,30 @@
|
||||
select toTypeName(key), toTypeName(value) from (
|
||||
select 1 as key, '' as value
|
||||
union all
|
||||
select toUInt64(2) as key, toNullable('') as value
|
||||
);
|
||||
|
||||
select toTypeName(key), toTypeName(value) from (
|
||||
select toDecimal64(2, 8) as key, toNullable('') as value
|
||||
union all
|
||||
select toDecimal32(2, 4) as key, toFixedString('', 1) as value
|
||||
);
|
||||
|
||||
select * from (
|
||||
select 'v1' as c1, null as c2
|
||||
union all
|
||||
select 'v2' as c1, '' as c2
|
||||
) ALL FULL JOIN (
|
||||
select 'v1' as c1, 'w1' as c2
|
||||
) using c1,c2;
|
||||
|
||||
select key, s1.value, s2.value
|
||||
from (
|
||||
select 'key1' as key, 'value1' as value
|
||||
) s1
|
||||
all left join (
|
||||
select 'key1' as key, '' as value
|
||||
union all
|
||||
select 'key2' as key, toNullable('') as value
|
||||
) s2
|
||||
using key;
|
Loading…
Reference in New Issue
Block a user