2017-07-21 06:35:58 +00:00
|
|
|
#include <Functions/FunctionHelpers.h>
|
|
|
|
#include <Columns/ColumnTuple.h>
|
|
|
|
#include <Columns/ColumnString.h>
|
|
|
|
#include <Columns/ColumnFixedString.h>
|
2017-07-24 01:00:31 +00:00
|
|
|
#include <Columns/ColumnNullable.h>
|
|
|
|
#include <DataTypes/DataTypeNullable.h>
|
2017-09-26 15:25:24 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include "FunctionsArithmetic.h"
|
2017-07-21 06:35:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
const ColumnConst * checkAndGetColumnConstStringOrFixedString(const IColumn * column)
|
|
|
|
{
|
|
|
|
if (!column->isConst())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
const ColumnConst * res = static_cast<const ColumnConst *>(column);
|
|
|
|
|
|
|
|
if (checkColumn<ColumnString>(&res->getDataColumn())
|
|
|
|
|| checkColumn<ColumnFixedString>(&res->getDataColumn()))
|
|
|
|
return res;
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2017-07-24 01:00:31 +00:00
|
|
|
|
2017-07-21 06:35:58 +00:00
|
|
|
ColumnPtr convertConstTupleToTupleOfConstants(const ColumnConst & column)
|
|
|
|
{
|
|
|
|
Block res;
|
|
|
|
const ColumnTuple & src_tuple = static_cast<const ColumnTuple &>(column.getDataColumn());
|
|
|
|
const Block & src_tuple_block = src_tuple.getData();
|
|
|
|
size_t rows = src_tuple_block.rows();
|
|
|
|
|
|
|
|
for (size_t i = 0, size = src_tuple_block.columns(); i < size; ++i)
|
|
|
|
res.insert({
|
|
|
|
std::make_shared<ColumnConst>(src_tuple_block.getByPosition(i).column, rows),
|
|
|
|
src_tuple_block.getByPosition(i).type,
|
|
|
|
src_tuple_block.getByPosition(i).name});
|
|
|
|
|
|
|
|
return std::make_shared<ColumnTuple>(res);
|
|
|
|
}
|
|
|
|
|
2017-07-24 01:00:31 +00:00
|
|
|
|
|
|
|
Block createBlockWithNestedColumns(const Block & block, ColumnNumbers args)
|
|
|
|
{
|
|
|
|
std::sort(args.begin(), args.end());
|
|
|
|
|
|
|
|
Block res;
|
|
|
|
|
|
|
|
size_t j = 0;
|
|
|
|
for (size_t i = 0; i < block.columns(); ++i)
|
|
|
|
{
|
|
|
|
const auto & col = block.getByPosition(i);
|
|
|
|
bool is_inserted = false;
|
|
|
|
|
|
|
|
if ((j < args.size()) && (i == args[j]))
|
|
|
|
{
|
|
|
|
++j;
|
|
|
|
|
|
|
|
if (col.column->isNullable())
|
|
|
|
{
|
|
|
|
auto nullable_col = static_cast<const ColumnNullable *>(col.column.get());
|
|
|
|
const ColumnPtr & nested_col = nullable_col->getNestedColumn();
|
|
|
|
|
|
|
|
auto nullable_type = static_cast<const DataTypeNullable *>(col.type.get());
|
|
|
|
const DataTypePtr & nested_type = nullable_type->getNestedType();
|
|
|
|
|
|
|
|
res.insert(i, {nested_col, nested_type, col.name});
|
|
|
|
|
|
|
|
is_inserted = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_inserted)
|
|
|
|
res.insert(i, col);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Block createBlockWithNestedColumns(const Block & block, ColumnNumbers args, size_t result)
|
|
|
|
{
|
|
|
|
std::sort(args.begin(), args.end());
|
|
|
|
|
|
|
|
Block res;
|
|
|
|
|
|
|
|
size_t j = 0;
|
|
|
|
for (size_t i = 0; i < block.columns(); ++i)
|
|
|
|
{
|
|
|
|
const auto & col = block.getByPosition(i);
|
|
|
|
bool is_inserted = false;
|
|
|
|
|
|
|
|
if ((j < args.size()) && (i == args[j]))
|
|
|
|
{
|
|
|
|
++j;
|
|
|
|
|
2017-09-26 15:25:24 +00:00
|
|
|
if (col.type->isNullable())
|
2017-07-24 01:00:31 +00:00
|
|
|
{
|
2017-09-26 15:25:24 +00:00
|
|
|
bool is_const = col.column->isConst();
|
|
|
|
auto const_col = static_cast<const ColumnConst *>(col.column.get());
|
|
|
|
|
|
|
|
if (is_const && !const_col->isNullable())
|
|
|
|
throw Exception("Column at position " + toString(i + 1) + " with type " + col.type->getName() +
|
|
|
|
" should be nullable, but got " + const_col->getName(), ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
auto nullable_col = static_cast<const ColumnNullable *>(
|
|
|
|
is_const ? &const_col->getDataColumn() : col.column.get());
|
|
|
|
|
|
|
|
ColumnPtr nested_col = nullable_col->getNestedColumn();
|
|
|
|
if (is_const)
|
|
|
|
nested_col = std::make_shared<ColumnConst>(nested_col, const_col->size());
|
2017-07-24 01:00:31 +00:00
|
|
|
|
|
|
|
auto nullable_type = static_cast<const DataTypeNullable *>(col.type.get());
|
|
|
|
const DataTypePtr & nested_type = nullable_type->getNestedType();
|
|
|
|
|
|
|
|
res.insert(i, {nested_col, nested_type, col.name});
|
|
|
|
|
|
|
|
is_inserted = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (i == result)
|
|
|
|
{
|
|
|
|
if (col.type->isNullable())
|
|
|
|
{
|
|
|
|
auto nullable_type = static_cast<const DataTypeNullable *>(col.type.get());
|
|
|
|
const DataTypePtr & nested_type = nullable_type->getNestedType();
|
|
|
|
|
|
|
|
res.insert(i, {nullptr, nested_type, col.name});
|
|
|
|
is_inserted = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!is_inserted)
|
|
|
|
res.insert(i, col);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2017-07-21 06:35:58 +00:00
|
|
|
}
|