Merge branch 'master' into ks1322-master

This commit is contained in:
Alexey Milovidov 2017-12-19 20:38:29 +03:00
commit 1a6f38b27f
310 changed files with 4575 additions and 4737 deletions

2
contrib/poco vendored

@ -1 +1 @@
Subproject commit bcf9ebad48b2162d25f5fc432b176d74a09f498d
Subproject commit 81d4fdfcb887f89b0f7b1e9b503cbe63e6d8366b

View File

@ -54,7 +54,8 @@ done
# Копируем больше заголовочных файлов с интринсиками, так как на серверах, куда будут устанавливаться
# заголовочные файлы, будет использоваться опция -march=native.
for i in $(ls -1 $($CLANG -v -xc++ - <<<'' 2>&1 | grep '^ /' | grep 'include' | grep '/lib/clang/')/*.h | grep -vE 'arm|altivec|Intrin');
for i in $(ls -1 $($CLANG -v -xc++ - <<<'' 2>&1 | grep '^ /' | grep 'include' | grep -E '/lib/clang/|/include/clang/')/*.h | grep -vE 'arm|altivec|Intrin');
do
mkdir -p "$DST/$(echo $i | sed -r -e 's/\/[^/]*$/\//')";
cp "$i" "$DST/$i";
done

View File

@ -10,6 +10,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int SIZES_OF_ARRAYS_DOESNT_MATCH;
}
/** Not an aggregate function, but an adapter of aggregate functions,
* which any aggregate function `agg(x)` makes an aggregate function of the form `aggArray(x)`.
@ -92,11 +97,21 @@ public:
nested[i] = &static_cast<const ColumnArray &>(*columns[i]).getData();
const ColumnArray & first_array_column = static_cast<const ColumnArray &>(*columns[0]);
const IColumn::Offsets_t & offsets = first_array_column.getOffsets();
const IColumn::Offsets & offsets = first_array_column.getOffsets();
size_t begin = row_num == 0 ? 0 : offsets[row_num - 1];
size_t end = offsets[row_num];
/// Sanity check. NOTE We can implement specialization for a case with single argument, if the check will hurt performance.
for (size_t i = 1; i < num_agruments; ++i)
{
const ColumnArray & ith_column = static_cast<const ColumnArray &>(*columns[i]);
const IColumn::Offsets & ith_offsets = ith_column.getOffsets();
if (ith_offsets[row_num] != end || (row_num != 0 && ith_offsets[row_num - 1] != begin))
throw Exception("Arrays passed to " + getName() + " aggregate function have different sizes", ErrorCodes::SIZES_OF_ARRAYS_DOESNT_MATCH);
}
for (size_t i = begin; i < end; ++i)
nested_func->add(place, nested, i, arena);
}

View File

@ -17,7 +17,7 @@ namespace DB
class Context;
class IDataType;
using DataTypePtr = std::shared_ptr<IDataType>;
using DataTypePtr = std::shared_ptr<const IDataType>;
using DataTypes = std::vector<DataTypePtr>;

View File

@ -152,7 +152,7 @@ public:
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena) const override
{
const ColumnArray & first_array_column = static_cast<const ColumnArray &>(*columns[0]);
const IColumn::Offsets_t & offsets = first_array_column.getOffsets();
const IColumn::Offsets & offsets = first_array_column.getOffsets();
const IColumn * array_data = &first_array_column.getData();
size_t begin = row_num == 0 ? 0 : offsets[row_num - 1];
size_t end = offsets[row_num];
@ -221,7 +221,7 @@ public:
const AggregateFunctionForEachData & state = data(place);
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
IColumn & elems_to = arr_to.getData();
const char * nested_state = state.array_of_aggregate_datas;

View File

@ -125,11 +125,11 @@ public:
size_t size = value.size();
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
typename ColumnVector<T>::Container_t & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
typename ColumnVector<T>::Container & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
data_to.insert(this->data(place).value.begin(), this->data(place).value.end());
}

View File

@ -67,7 +67,7 @@ public:
void setArgumentsImpl(const DataTypes & arguments)
{
if (!arguments.at(1)->canBeUsedAsNonNegativeArrayIndex())
if (!arguments.at(1)->isUnsignedInteger())
throw Exception("Second argument of aggregate function " + getName() + " must be integer.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
type = arguments.front();
@ -184,7 +184,7 @@ public:
{
ColumnArray & to_array = static_cast<ColumnArray &>(to);
IColumn & to_data = to_array.getData();
ColumnArray::Offsets_t & to_offsets = to_array.getOffsets();
ColumnArray::Offsets & to_offsets = to_array.getOffsets();
const Array & arr = data(place).value;

View File

@ -83,14 +83,14 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
const typename State::Set & set = this->data(place).value;
size_t size = set.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
typename ColumnVector<T>::Container_t & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
typename ColumnVector<T>::Container & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(old_size + size);
@ -138,7 +138,7 @@ public:
DataTypePtr getReturnType() const override
{
return std::make_shared<DataTypeArray>(input_data_type->clone());
return std::make_shared<DataTypeArray>(input_data_type);
}
bool allocatesMemoryInArena() const override
@ -210,7 +210,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
IColumn & data_to = arr_to.getData();
auto & set = this->data(place).value;

View File

@ -151,8 +151,8 @@ public:
ColumnNullable & to_concrete = static_cast<ColumnNullable &>(to);
if (getFlag(place))
{
nested_function->insertResultInto(nestedPlace(place), *to_concrete.getNestedColumn());
to_concrete.getNullMap().push_back(0);
nested_function->insertResultInto(nestedPlace(place), to_concrete.getNestedColumn());
to_concrete.getNullMapData().push_back(0);
}
else
{
@ -205,7 +205,7 @@ public:
if (!column->isNullAt(row_num))
{
this->setFlag(place);
const IColumn * nested_column = column->getNestedColumn().get();
const IColumn * nested_column = &column->getNestedColumn();
this->nested_function->add(this->nestedPlace(place), &nested_column, row_num, arena);
}
}
@ -268,7 +268,7 @@ public:
/// we don't process this row.
return;
}
nested_columns[i] = nullable_col.getNestedColumn().get();
nested_columns[i] = &nullable_col.getNestedColumn();
}
else
nested_columns[i] = columns[i];

View File

@ -174,21 +174,21 @@ public:
Sample & sample = const_cast<Sample &>(this->data(place).sample);
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t size = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
if (returns_float)
{
ColumnFloat64::Container_t & data_to = static_cast<ColumnFloat64 &>(arr_to.getData()).getData();
ColumnFloat64::Container & data_to = static_cast<ColumnFloat64 &>(arr_to.getData()).getData();
for (size_t i = 0; i < size; ++i)
data_to.push_back(sample.quantileInterpolated(levels[i]));
}
else
{
typename ColumnVector<ArgumentFieldType>::Container_t & data_to = static_cast<ColumnVector<ArgumentFieldType> &>(arr_to.getData()).getData();
typename ColumnVector<ArgumentFieldType>::Container & data_to = static_cast<ColumnVector<ArgumentFieldType> &>(arr_to.getData()).getData();
for (size_t i = 0; i < size; ++i)
data_to.push_back(sample.quantileInterpolated(levels[i]));

View File

@ -186,21 +186,21 @@ public:
Sample & sample = const_cast<Sample &>(this->data(place).sample);
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t size = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
if (returns_float)
{
ColumnFloat64::Container_t & data_to = static_cast<ColumnFloat64 &>(arr_to.getData()).getData();
ColumnFloat64::Container & data_to = static_cast<ColumnFloat64 &>(arr_to.getData()).getData();
for (size_t i = 0; i < size; ++i)
data_to.push_back(sample.quantileInterpolated(levels[i]));
}
else
{
typename ColumnVector<ArgumentFieldType>::Container_t & data_to = static_cast<ColumnVector<ArgumentFieldType> &>(arr_to.getData()).getData();
typename ColumnVector<ArgumentFieldType>::Container & data_to = static_cast<ColumnVector<ArgumentFieldType> &>(arr_to.getData()).getData();
for (size_t i = 0; i < size; ++i)
data_to.push_back(sample.quantileInterpolated(levels[i]));

View File

@ -187,12 +187,12 @@ public:
auto & array = const_cast<typename AggregateFunctionQuantileExactData<T>::Array &>(this->data(place).array);
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t num_levels = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + num_levels);
typename ColumnVector<T>::Container_t & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
typename ColumnVector<T>::Container & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(old_size + num_levels);

View File

@ -230,7 +230,7 @@ public:
size_t size = map.size();
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t num_levels = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + num_levels);
@ -238,7 +238,7 @@ public:
if (!num_levels)
return;
typename ColumnVector<ValueType>::Container_t & data_to = static_cast<ColumnVector<ValueType> &>(arr_to.getData()).getData();
typename ColumnVector<ValueType>::Container & data_to = static_cast<ColumnVector<ValueType> &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(old_size + num_levels);

View File

@ -540,7 +540,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t size = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
@ -550,7 +550,7 @@ public:
if (returns_float)
{
typename ColumnFloat32::Container_t & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
typename ColumnFloat32::Container & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(data_to.size() + size);
@ -559,7 +559,7 @@ public:
}
else
{
typename ColumnVector<T>::Container_t & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
typename ColumnVector<T>::Container & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(data_to.size() + size);
@ -627,7 +627,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t size = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
@ -637,7 +637,7 @@ public:
if (returns_float)
{
typename ColumnFloat32::Container_t & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
typename ColumnFloat32::Container & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(data_to.size() + size);
@ -646,7 +646,7 @@ public:
}
else
{
typename ColumnVector<T>::Container_t & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
typename ColumnVector<T>::Container & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(data_to.size() + size);

View File

@ -961,7 +961,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t size = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
@ -969,7 +969,7 @@ public:
if (!size)
return;
typename ColumnFloat32::Container_t & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
typename ColumnFloat32::Container & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(data_to.size() + size);
@ -1029,7 +1029,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
size_t size = levels.size();
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
@ -1037,7 +1037,7 @@ public:
if (!size)
return;
typename ColumnFloat32::Container_t & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
typename ColumnFloat32::Container & data_to = static_cast<ColumnFloat32 &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(data_to.size() + size);

View File

@ -102,7 +102,7 @@ public:
{
// Column 0 contains array of keys of known type
const ColumnArray & array_column = static_cast<const ColumnArray &>(*columns[0]);
const IColumn::Offsets_t & offsets = array_column.getOffsets();
const IColumn::Offsets & offsets = array_column.getOffsets();
const auto & keys_vec = static_cast<const ColumnVector<T> &>(array_column.getData());
const size_t keys_vec_offset = row_num == 0 ? 0 : offsets[row_num - 1];
const size_t keys_vec_size = (offsets[row_num] - keys_vec_offset);
@ -113,7 +113,7 @@ public:
{
Field value;
const ColumnArray & array_column = static_cast<const ColumnArray &>(*columns[col + 1]);
const IColumn::Offsets_t & offsets = array_column.getOffsets();
const IColumn::Offsets & offsets = array_column.getOffsets();
const size_t values_vec_offset = row_num == 0 ? 0 : offsets[row_num - 1];
const size_t values_vec_size = (offsets[row_num] - values_vec_offset);
@ -221,8 +221,8 @@ public:
size_t size = merged_maps.size();
auto & to_cols = static_cast<ColumnTuple &>(to).getColumns();
auto & to_keys_arr = static_cast<ColumnArray &>(*to_cols[0]);
auto & to_tuple = static_cast<ColumnTuple &>(to);
auto & to_keys_arr = static_cast<ColumnArray &>(to_tuple.getColumn(0));
auto & to_keys_col = to_keys_arr.getData();
// Advance column offsets
@ -232,7 +232,7 @@ public:
for (size_t col = 0; col < values_types.size(); ++col)
{
auto & to_values_arr = static_cast<ColumnArray &>(*to_cols[col + 1]);
auto & to_values_arr = static_cast<ColumnArray &>(to_tuple.getColumn(col + 1));
auto & to_values_offsets = to_values_arr.getOffsets();
to_values_offsets.push_back((to_values_offsets.empty() ? 0 : to_values_offsets.back()) + size);
to_values_arr.getData().reserve(size);
@ -247,7 +247,7 @@ public:
// Write 0..n arrays of values
for (size_t col = 0; col < values_types.size(); ++col)
{
auto & to_values_col = static_cast<ColumnArray &>(*to_cols[col + 1]).getData();
auto & to_values_col = static_cast<ColumnArray &>(to_tuple.getColumn(col + 1)).getData();
to_values_col.insert(elem.second[col]);
}
}

View File

@ -108,7 +108,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
const typename State::Set & set = this->data(place).value;
auto result_vec = set.topK(threshold);
@ -116,7 +116,7 @@ public:
offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size);
typename ColumnVector<T>::Container_t & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
typename ColumnVector<T>::Container & data_to = static_cast<ColumnVector<T> &>(arr_to.getData()).getData();
size_t old_size = data_to.size();
data_to.resize(old_size + size);
@ -182,7 +182,7 @@ public:
DataTypePtr getReturnType() const override
{
return std::make_shared<DataTypeArray>(input_data_type->clone());
return std::make_shared<DataTypeArray>(input_data_type);
}
bool allocatesMemoryInArena() const override
@ -217,7 +217,7 @@ public:
set.readAlphaMap(buf);
}
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena *) const
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena * arena) const
{
auto & set = this->data(place).value;
if (set.capacity() != reserved)
@ -225,8 +225,10 @@ public:
set.resize(reserved);
}
StringRef str_serialized = column.getDataAt(row_num);
const char * begin = nullptr;
StringRef str_serialized = column.serializeValueIntoArena(row_num, *arena, begin);
set.insert(str_serialized);
arena->rollback(str_serialized.size);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
@ -237,7 +239,7 @@ public:
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
ColumnArray & arr_to = static_cast<ColumnArray &>(to);
ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets();
ColumnArray::Offsets & offsets_to = arr_to.getOffsets();
IColumn & data_to = arr_to.getData();
auto result_vec = this->data(place).value.topK(threshold);

View File

@ -19,7 +19,7 @@ class WriteBuffer;
class IColumn;
class IDataType;
using DataTypePtr = std::shared_ptr<IDataType>;
using DataTypePtr = std::shared_ptr<const IDataType>;
using DataTypes = std::vector<DataTypePtr>;
using AggregateDataPtr = char *;

View File

@ -26,10 +26,9 @@ void ColumnAggregateFunction::addArena(ArenaPtr arena_)
arenas.push_back(arena_);
}
ColumnPtr ColumnAggregateFunction::convertToValues() const
MutableColumnPtr ColumnAggregateFunction::convertToValues() const
{
const IAggregateFunction * function = func.get();
ColumnPtr res = function->getReturnType()->createColumn();
/** If the aggregate function returns an unfinalized/unfinished state,
* then you just need to copy pointers to it and also shared ownership of data.
@ -63,17 +62,18 @@ ColumnPtr ColumnAggregateFunction::convertToValues() const
*/
if (const AggregateFunctionState * function_state = typeid_cast<const AggregateFunctionState *>(function))
{
std::shared_ptr<ColumnAggregateFunction> res = std::make_shared<ColumnAggregateFunction>(*this);
auto res = createView();
res->set(function_state->getNestedFunction());
res->getData().assign(getData().begin(), getData().end());
return res;
return std::move(res);
}
IColumn & column = *res;
MutableColumnPtr res = function->getReturnType()->createColumn();
res->reserve(getData().size());
for (auto val : getData())
function->insertResultInto(val, column);
function->insertResultInto(val, *res);
return res;
}
@ -104,7 +104,7 @@ void ColumnAggregateFunction::insertRangeFrom(const IColumn & from, size_t start
else
{
/// Keep shared ownership of aggregation states.
src = from_concrete.shared_from_this();
src = from_concrete.getPtr();
auto & data = getData();
size_t old_size = data.size();
@ -114,17 +114,16 @@ void ColumnAggregateFunction::insertRangeFrom(const IColumn & from, size_t start
}
ColumnPtr ColumnAggregateFunction::filter(const Filter & filter, ssize_t result_size_hint) const
MutableColumnPtr ColumnAggregateFunction::filter(const Filter & filter, ssize_t result_size_hint) const
{
size_t size = getData().size();
if (size != filter.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<ColumnAggregateFunction> res = std::make_shared<ColumnAggregateFunction>(*this);
if (size == 0)
return res;
return cloneEmpty();
auto res = createView();
auto & res_data = res->getData();
if (result_size_hint)
@ -136,13 +135,13 @@ ColumnPtr ColumnAggregateFunction::filter(const Filter & filter, ssize_t result_
/// To save RAM in case of too strong filtering.
if (res_data.size() * 2 < res_data.capacity())
res_data = Container_t(res_data.cbegin(), res_data.cend());
res_data = Container(res_data.cbegin(), res_data.cend());
return res;
return std::move(res);
}
ColumnPtr ColumnAggregateFunction::permute(const Permutation & perm, size_t limit) const
MutableColumnPtr ColumnAggregateFunction::permute(const Permutation & perm, size_t limit) const
{
size_t size = getData().size();
@ -154,13 +153,13 @@ ColumnPtr ColumnAggregateFunction::permute(const Permutation & perm, size_t limi
if (perm.size() < limit)
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<ColumnAggregateFunction> res = std::make_shared<ColumnAggregateFunction>(*this);
auto res = createView();
res->getData().resize(limit);
for (size_t i = 0; i < limit; ++i)
res->getData()[i] = getData()[perm[i]];
return res;
return std::move(res);
}
/// Is required to support operations with Set
@ -194,9 +193,9 @@ size_t ColumnAggregateFunction::allocatedBytes() const
return res;
}
ColumnPtr ColumnAggregateFunction::cloneEmpty() const
MutableColumnPtr ColumnAggregateFunction::cloneEmpty() const
{
return std::make_shared<ColumnAggregateFunction>(func, Arenas(1, std::make_shared<Arena>()));
return create(func, Arenas(1, std::make_shared<Arena>()));
}
Field ColumnAggregateFunction::operator[](size_t n) const
@ -327,21 +326,20 @@ void ColumnAggregateFunction::popBack(size_t n)
data.resize_assume_reserved(new_size);
}
ColumnPtr ColumnAggregateFunction::replicate(const IColumn::Offsets_t & offsets) const
MutableColumnPtr ColumnAggregateFunction::replicate(const IColumn::Offsets & offsets) const
{
size_t size = data.size();
if (size != offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<ColumnAggregateFunction> res = std::make_shared<ColumnAggregateFunction>(*this);
if (size == 0)
return res;
return cloneEmpty();
auto res = createView();
auto & res_data = res->getData();
res_data.reserve(offsets.back());
IColumn::Offset_t prev_offset = 0;
IColumn::Offset prev_offset = 0;
for (size_t i = 0; i < size; ++i)
{
size_t size_to_replicate = offsets[i] - prev_offset;
@ -351,15 +349,15 @@ ColumnPtr ColumnAggregateFunction::replicate(const IColumn::Offsets_t & offsets)
res_data.push_back(data[i]);
}
return res;
return std::move(res);
}
Columns ColumnAggregateFunction::scatter(IColumn::ColumnIndex num_columns, const IColumn::Selector & selector) const
MutableColumns ColumnAggregateFunction::scatter(IColumn::ColumnIndex num_columns, const IColumn::Selector & selector) const
{
/// Columns with scattered values will point to this column as the owner of values.
Columns columns(num_columns);
MutableColumns columns(num_columns);
for (auto & column : columns)
column = std::make_shared<ColumnAggregateFunction>(*this);
column = createView();
size_t num_rows = size();

View File

@ -1,4 +1,4 @@
#pragma once
#pragma once
#include <Common/Arena.h>
@ -17,8 +17,7 @@ namespace DB
{
/** State column of aggregate functions.
/** Column of states of aggregate functions.
* Presented as an array of pointers to the states of aggregate functions (data).
* The states themselves are stored in one of the pools (arenas).
*
@ -42,12 +41,14 @@ namespace DB
* specifying which individual values should be destroyed and which ones should not.
* Clearly, this method would have a substantially non-zero price.
*/
class ColumnAggregateFunction final : public IColumn, public std::enable_shared_from_this<ColumnAggregateFunction>
class ColumnAggregateFunction final : public COWPtrHelper<IColumn, ColumnAggregateFunction>
{
public:
using Container_t = PaddedPODArray<AggregateDataPtr>;
using Container = PaddedPODArray<AggregateDataPtr>;
private:
friend class COWPtrHelper<IColumn, ColumnAggregateFunction>;
/// Memory pools. Aggregate states are allocated from them.
Arenas arenas;
@ -56,17 +57,19 @@ private:
/// Source column. Used (holds source from destruction),
/// if this column has been constructed from another and uses all or part of its values.
std::shared_ptr<const ColumnAggregateFunction> src;
ColumnPtr src;
/// Array of pointers to aggregation states, that are placed in arenas.
Container_t data;
Container data;
ColumnAggregateFunction() {}
public:
/// Create a new column that has another column as a source.
ColumnAggregateFunction(const ColumnAggregateFunction & other)
: std::enable_shared_from_this<ColumnAggregateFunction>(other),
arenas(other.arenas), func(other.func), src(other.shared_from_this())
MutablePtr createView() const
{
MutablePtr res = create(func, arenas);
res->src = getPtr();
return res;
}
ColumnAggregateFunction(const AggregateFunctionPtr & func_)
@ -79,6 +82,12 @@ public:
{
}
ColumnAggregateFunction(const ColumnAggregateFunction & src_)
: arenas(src_.arenas), func(src_.func), src(src_.getPtr())
{
}
public:
~ColumnAggregateFunction();
void set(const AggregateFunctionPtr & func_)
@ -94,7 +103,7 @@ public:
/** Transform column with states of aggregate functions to column with final result values.
*/
ColumnPtr convertToValues() const;
MutableColumnPtr convertToValues() const;
std::string getName() const override { return "AggregateFunction(" + func->getName() + ")"; }
const char * getFamilyName() const override { return "AggregateFunction"; }
@ -104,7 +113,7 @@ public:
return getData().size();
}
ColumnPtr cloneEmpty() const override;;
MutableColumnPtr cloneEmpty() const override;
Field operator[](size_t n) const override;
@ -143,13 +152,13 @@ public:
void popBack(size_t n) override;
ColumnPtr filter(const Filter & filter, ssize_t result_size_hint) const override;
MutableColumnPtr filter(const Filter & filter, ssize_t result_size_hint) const override;
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
ColumnPtr replicate(const Offsets_t & offsets) const override;
MutableColumnPtr replicate(const Offsets & offsets) const override;
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override;
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override;
void gather(ColumnGathererStream & gatherer_stream) override;
@ -161,12 +170,12 @@ public:
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override;
/** More efficient manipulation methods */
Container_t & getData()
Container & getData()
{
return data;
}
const Container_t & getData() const
const Container & getData() const
{
return data;
}

View File

@ -31,18 +31,11 @@ namespace ErrorCodes
}
ColumnArray::ColumnArray(ColumnPtr nested_column, ColumnPtr offsets_column)
ColumnArray::ColumnArray(const ColumnPtr & nested_column, const ColumnPtr & offsets_column)
: data(nested_column), offsets(offsets_column)
{
if (!offsets_column)
{
offsets = std::make_shared<ColumnOffsets_t>();
}
else
{
if (!typeid_cast<ColumnOffsets_t *>(&*offsets_column))
throw Exception("offsets_column must be a ColumnUInt64", ErrorCodes::ILLEGAL_COLUMN);
}
if (!typeid_cast<const ColumnOffsets *>(offsets_column.get()))
throw Exception("offsets_column must be a ColumnUInt64", ErrorCodes::ILLEGAL_COLUMN);
/** NOTE
* Arrays with constant value are possible and used in implementation of higher order functions (see FunctionReplicate).
@ -50,16 +43,25 @@ ColumnArray::ColumnArray(ColumnPtr nested_column, ColumnPtr offsets_column)
*/
}
ColumnArray::ColumnArray(const ColumnPtr & nested_column)
: data(nested_column)
{
if (!data->empty())
throw Exception("Not empty data passed to ColumnArray, but no offsets passed", ErrorCodes::ILLEGAL_COLUMN);
offsets = ColumnOffsets::create();
}
std::string ColumnArray::getName() const { return "Array(" + getData().getName() + ")"; }
ColumnPtr ColumnArray::cloneResized(size_t to_size) const
MutableColumnPtr ColumnArray::cloneResized(size_t to_size) const
{
auto res = std::make_shared<ColumnArray>(getData().cloneEmpty());
auto res = ColumnArray::create(getData().cloneEmpty());
if (to_size == 0)
return res;
return std::move(res);
size_t from_size = size();
@ -74,23 +76,20 @@ ColumnPtr ColumnArray::cloneResized(size_t to_size) const
{
/// Copy column and append empty arrays for extra elements.
Offset_t offset = 0;
Offset offset = 0;
if (from_size > 0)
{
res->getOffsets().assign(getOffsets().begin(), getOffsets().end());
res->getDataPtr() = getData().clone();
res->getData().insertRangeFrom(getData(), 0, getData().size());
offset = getOffsets().back();
}
res->getOffsets().resize(to_size);
for (size_t i = from_size; i < to_size; ++i)
{
++offset;
res->getOffsets()[i] = offset;
}
}
return res;
return std::move(res);
}
@ -151,7 +150,7 @@ void ColumnArray::insertData(const char * pos, size_t length)
{
/** Similarly - only for arrays of fixed length values.
*/
IColumn * data_ = data.get();
IColumn * data_ = &getData();
if (!data_->isFixedAndContiguous())
throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
@ -312,22 +311,22 @@ bool ColumnArray::hasEqualOffsets(const ColumnArray & other) const
if (offsets == other.offsets)
return true;
const Offsets_t & offsets1 = getOffsets();
const Offsets_t & offsets2 = other.getOffsets();
const Offsets & offsets1 = getOffsets();
const Offsets & offsets2 = other.getOffsets();
return offsets1.size() == offsets2.size() && 0 == memcmp(&offsets1[0], &offsets2[0], sizeof(offsets1[0]) * offsets1.size());
}
ColumnPtr ColumnArray::convertToFullColumnIfConst() const
MutableColumnPtr ColumnArray::convertToFullColumnIfConst() const
{
ColumnPtr new_data;
if (auto full_column = getData().convertToFullColumnIfConst())
if (ColumnPtr full_column = getData().convertToFullColumnIfConst())
new_data = full_column;
else
new_data = data;
return std::make_shared<ColumnArray>(new_data, offsets);
return ColumnArray::create(new_data, offsets);
}
@ -371,10 +370,10 @@ void ColumnArray::insertRangeFrom(const IColumn & src, size_t start, size_t leng
size_t nested_offset = src_concrete.offsetAt(start);
size_t nested_length = src_concrete.getOffsets()[start + length - 1] - nested_offset;
data->insertRangeFrom(src_concrete.getData(), nested_offset, nested_length);
getData().insertRangeFrom(src_concrete.getData(), nested_offset, nested_length);
Offsets_t & cur_offsets = getOffsets();
const Offsets_t & src_offsets = src_concrete.getOffsets();
Offsets & cur_offsets = getOffsets();
const Offsets & src_offsets = src_concrete.getOffsets();
if (start == 0 && cur_offsets.empty())
{
@ -392,7 +391,7 @@ void ColumnArray::insertRangeFrom(const IColumn & src, size_t start, size_t leng
}
ColumnPtr ColumnArray::filter(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnArray::filter(const Filter & filt, ssize_t result_size_hint) const
{
if (typeid_cast<const ColumnUInt8 *>(data.get())) return filterNumber<UInt8>(filt, result_size_hint);
if (typeid_cast<const ColumnUInt16 *>(data.get())) return filterNumber<UInt16>(filt, result_size_hint);
@ -411,39 +410,39 @@ ColumnPtr ColumnArray::filter(const Filter & filt, ssize_t result_size_hint) con
}
template <typename T>
ColumnPtr ColumnArray::filterNumber(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnArray::filterNumber(const Filter & filt, ssize_t result_size_hint) const
{
if (getOffsets().size() == 0)
return std::make_shared<ColumnArray>(data);
return ColumnArray::create(data);
auto res = std::make_shared<ColumnArray>(data->cloneEmpty());
auto res = ColumnArray::create(data->cloneEmpty());
auto & res_elems = static_cast<ColumnVector<T> &>(res->getData()).getData();
Offsets_t & res_offsets = res->getOffsets();
Offsets & res_offsets = res->getOffsets();
filterArraysImpl<T>(static_cast<const ColumnVector<T> &>(*data).getData(), getOffsets(), res_elems, res_offsets, filt, result_size_hint);
return res;
return std::move(res);
}
ColumnPtr ColumnArray::filterString(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnArray::filterString(const Filter & filt, ssize_t result_size_hint) const
{
size_t col_size = getOffsets().size();
if (col_size != filt.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
if (0 == col_size)
return std::make_shared<ColumnArray>(data);
return ColumnArray::create(data);
auto res = std::make_shared<ColumnArray>(data->cloneEmpty());
auto res = ColumnArray::create(data->cloneEmpty());
const ColumnString & src_string = typeid_cast<const ColumnString &>(*data);
const ColumnString::Chars_t & src_chars = src_string.getChars();
const Offsets_t & src_string_offsets = src_string.getOffsets();
const Offsets_t & src_offsets = getOffsets();
const Offsets & src_string_offsets = src_string.getOffsets();
const Offsets & src_offsets = getOffsets();
ColumnString::Chars_t & res_chars = typeid_cast<ColumnString &>(res->getData()).getChars();
Offsets_t & res_string_offsets = typeid_cast<ColumnString &>(res->getData()).getOffsets();
Offsets_t & res_offsets = res->getOffsets();
Offsets & res_string_offsets = typeid_cast<ColumnString &>(res->getData()).getOffsets();
Offsets & res_offsets = res->getOffsets();
if (result_size_hint < 0) /// Other cases are not considered.
{
@ -452,11 +451,11 @@ ColumnPtr ColumnArray::filterString(const Filter & filt, ssize_t result_size_hin
res_offsets.reserve(col_size);
}
Offset_t prev_src_offset = 0;
Offset_t prev_src_string_offset = 0;
Offset prev_src_offset = 0;
Offset prev_src_string_offset = 0;
Offset_t prev_res_offset = 0;
Offset_t prev_res_string_offset = 0;
Offset prev_res_offset = 0;
Offset prev_res_string_offset = 0;
for (size_t i = 0; i < col_size; ++i)
{
@ -490,17 +489,17 @@ ColumnPtr ColumnArray::filterString(const Filter & filt, ssize_t result_size_hin
}
}
return res;
return std::move(res);
}
ColumnPtr ColumnArray::filterGeneric(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnArray::filterGeneric(const Filter & filt, ssize_t result_size_hint) const
{
size_t size = getOffsets().size();
if (size != filt.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
if (size == 0)
return std::make_shared<ColumnArray>(data);
return ColumnArray::create(data);
Filter nested_filt(getOffsets().back());
for (size_t i = 0; i < size; ++i)
@ -511,7 +510,7 @@ ColumnPtr ColumnArray::filterGeneric(const Filter & filt, ssize_t result_size_hi
memset(&nested_filt[offsetAt(i)], 0, sizeAt(i));
}
std::shared_ptr<ColumnArray> res = std::make_shared<ColumnArray>(data);
auto res = ColumnArray::create(data);
ssize_t nested_result_size_hint = 0;
if (result_size_hint < 0)
@ -521,7 +520,7 @@ ColumnPtr ColumnArray::filterGeneric(const Filter & filt, ssize_t result_size_hi
res->data = data->filter(nested_filt, nested_result_size_hint);
Offsets_t & res_offsets = res->getOffsets();
Offsets & res_offsets = res->getOffsets();
if (result_size_hint)
res_offsets.reserve(result_size_hint > 0 ? result_size_hint : size);
@ -535,36 +534,36 @@ ColumnPtr ColumnArray::filterGeneric(const Filter & filt, ssize_t result_size_hi
}
}
return res;
return std::move(res);
}
ColumnPtr ColumnArray::filterNullable(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnArray::filterNullable(const Filter & filt, ssize_t result_size_hint) const
{
if (getOffsets().size() == 0)
return std::make_shared<ColumnArray>(data);
return ColumnArray::create(data);
const ColumnNullable & nullable_elems = static_cast<const ColumnNullable &>(*data);
auto array_of_nested = std::make_shared<ColumnArray>(nullable_elems.getNestedColumn(), offsets);
auto array_of_nested = ColumnArray::create(nullable_elems.getNestedColumnPtr(), offsets);
auto filtered_array_of_nested_owner = array_of_nested->filter(filt, result_size_hint);
auto & filtered_array_of_nested = static_cast<ColumnArray &>(*filtered_array_of_nested_owner);
auto & filtered_offsets = filtered_array_of_nested.getOffsetsColumn();
auto & filtered_array_of_nested = static_cast<const ColumnArray &>(*filtered_array_of_nested_owner);
auto & filtered_offsets = filtered_array_of_nested.getOffsetsPtr();
auto res_null_map = std::make_shared<ColumnUInt8>();
auto res = std::make_shared<ColumnArray>(
std::make_shared<ColumnNullable>(
auto res_null_map = ColumnUInt8::create();
filterArraysImplOnlyData(nullable_elems.getNullMapData(), getOffsets(), res_null_map->getData(), filt, result_size_hint);
return ColumnArray::create(
ColumnNullable::create(
filtered_array_of_nested.getDataPtr(),
res_null_map),
std::move(res_null_map)),
filtered_offsets);
filterArraysImplOnlyData(nullable_elems.getNullMap(), getOffsets(), res_null_map->getData(), filt, result_size_hint);
return res;
}
ColumnPtr ColumnArray::filterTuple(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnArray::filterTuple(const Filter & filt, ssize_t result_size_hint) const
{
if (getOffsets().size() == 0)
return std::make_shared<ColumnArray>(data);
return ColumnArray::create(data);
const ColumnTuple & tuple = static_cast<const ColumnTuple &>(*data);
@ -577,19 +576,19 @@ ColumnPtr ColumnArray::filterTuple(const Filter & filt, ssize_t result_size_hint
Columns temporary_arrays(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
temporary_arrays[i] = ColumnArray(tuple.getColumns()[i], getOffsetsColumn()).filter(filt, result_size_hint);
temporary_arrays[i] = ColumnArray(tuple.getColumns()[i], getOffsetsPtr()).filter(filt, result_size_hint);
Columns tuple_columns(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
tuple_columns[i] = static_cast<ColumnArray &>(*temporary_arrays[i]).getDataPtr();
tuple_columns[i] = static_cast<const ColumnArray &>(*temporary_arrays[i]).getDataPtr();
return std::make_shared<ColumnArray>(
std::make_shared<ColumnTuple>(tuple_columns),
static_cast<ColumnArray &>(*temporary_arrays.front()).getOffsetsColumn());
return ColumnArray::create(
ColumnTuple::create(tuple_columns),
static_cast<const ColumnArray &>(*temporary_arrays.front()).getOffsetsPtr());
}
ColumnPtr ColumnArray::permute(const Permutation & perm, size_t limit) const
MutableColumnPtr ColumnArray::permute(const Permutation & perm, size_t limit) const
{
size_t size = getOffsets().size();
@ -602,13 +601,13 @@ ColumnPtr ColumnArray::permute(const Permutation & perm, size_t limit) const
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
if (limit == 0)
return std::make_shared<ColumnArray>(data);
return ColumnArray::create(data);
Permutation nested_perm(getOffsets().back());
std::shared_ptr<ColumnArray> res = std::make_shared<ColumnArray>(data->cloneEmpty());
auto res = ColumnArray::create(data->cloneEmpty());
Offsets_t & res_offsets = res->getOffsets();
Offsets & res_offsets = res->getOffsets();
res_offsets.resize(limit);
size_t current_offset = 0;
@ -623,7 +622,7 @@ ColumnPtr ColumnArray::permute(const Permutation & perm, size_t limit) const
if (current_offset != 0)
res->data = data->permute(nested_perm, current_offset);
return res;
return std::move(res);
}
void ColumnArray::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
@ -653,7 +652,7 @@ void ColumnArray::getPermutation(bool reverse, size_t limit, int nan_direction_h
}
ColumnPtr ColumnArray::replicate(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicate(const Offsets & replicate_offsets) const
{
if (typeid_cast<const ColumnUInt8 *>(data.get())) return replicateNumber<UInt8>(replicate_offsets);
if (typeid_cast<const ColumnUInt16 *>(data.get())) return replicateNumber<UInt16>(replicate_offsets);
@ -674,31 +673,31 @@ ColumnPtr ColumnArray::replicate(const Offsets_t & replicate_offsets) const
template <typename T>
ColumnPtr ColumnArray::replicateNumber(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicateNumber(const Offsets & replicate_offsets) const
{
size_t col_size = size();
if (col_size != replicate_offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
ColumnPtr res = cloneEmpty();
MutableColumnPtr res = cloneEmpty();
if (0 == col_size)
return res;
ColumnArray & res_ = typeid_cast<ColumnArray &>(*res);
const typename ColumnVector<T>::Container_t & src_data = typeid_cast<const ColumnVector<T> &>(*data).getData();
const Offsets_t & src_offsets = getOffsets();
const typename ColumnVector<T>::Container & src_data = typeid_cast<const ColumnVector<T> &>(*data).getData();
const Offsets & src_offsets = getOffsets();
typename ColumnVector<T>::Container_t & res_data = typeid_cast<ColumnVector<T> &>(res_.getData()).getData();
Offsets_t & res_offsets = res_.getOffsets();
typename ColumnVector<T>::Container & res_data = typeid_cast<ColumnVector<T> &>(res_.getData()).getData();
Offsets & res_offsets = res_.getOffsets();
res_data.reserve(data->size() / col_size * replicate_offsets.back());
res_offsets.reserve(replicate_offsets.back());
Offset_t prev_replicate_offset = 0;
Offset_t prev_data_offset = 0;
Offset_t current_new_offset = 0;
Offset prev_replicate_offset = 0;
Offset prev_data_offset = 0;
Offset current_new_offset = 0;
for (size_t i = 0; i < col_size; ++i)
{
@ -722,13 +721,13 @@ ColumnPtr ColumnArray::replicateNumber(const Offsets_t & replicate_offsets) cons
}
ColumnPtr ColumnArray::replicateString(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicateString(const Offsets & replicate_offsets) const
{
size_t col_size = size();
if (col_size != replicate_offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
ColumnPtr res = cloneEmpty();
MutableColumnPtr res = cloneEmpty();
if (0 == col_size)
return res;
@ -737,24 +736,24 @@ ColumnPtr ColumnArray::replicateString(const Offsets_t & replicate_offsets) cons
const ColumnString & src_string = typeid_cast<const ColumnString &>(*data);
const ColumnString::Chars_t & src_chars = src_string.getChars();
const Offsets_t & src_string_offsets = src_string.getOffsets();
const Offsets_t & src_offsets = getOffsets();
const Offsets & src_string_offsets = src_string.getOffsets();
const Offsets & src_offsets = getOffsets();
ColumnString::Chars_t & res_chars = typeid_cast<ColumnString &>(res_.getData()).getChars();
Offsets_t & res_string_offsets = typeid_cast<ColumnString &>(res_.getData()).getOffsets();
Offsets_t & res_offsets = res_.getOffsets();
Offsets & res_string_offsets = typeid_cast<ColumnString &>(res_.getData()).getOffsets();
Offsets & res_offsets = res_.getOffsets();
res_chars.reserve(src_chars.size() / col_size * replicate_offsets.back());
res_string_offsets.reserve(src_string_offsets.size() / col_size * replicate_offsets.back());
res_offsets.reserve(replicate_offsets.back());
Offset_t prev_replicate_offset = 0;
Offset prev_replicate_offset = 0;
Offset_t prev_src_offset = 0;
Offset_t prev_src_string_offset = 0;
Offset prev_src_offset = 0;
Offset prev_src_string_offset = 0;
Offset_t current_res_offset = 0;
Offset_t current_res_string_offset = 0;
Offset current_res_offset = 0;
Offset current_res_string_offset = 0;
for (size_t i = 0; i < col_size; ++i)
{
@ -797,7 +796,7 @@ ColumnPtr ColumnArray::replicateString(const Offsets_t & replicate_offsets) cons
}
ColumnPtr ColumnArray::replicateConst(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicateConst(const Offsets & replicate_offsets) const
{
size_t col_size = size();
if (col_size != replicate_offsets.size())
@ -806,15 +805,15 @@ ColumnPtr ColumnArray::replicateConst(const Offsets_t & replicate_offsets) const
if (0 == col_size)
return cloneEmpty();
const Offsets_t & src_offsets = getOffsets();
const Offsets & src_offsets = getOffsets();
auto res_column_offsets = std::make_shared<ColumnOffsets_t>();
Offsets_t & res_offsets = res_column_offsets->getData();
auto res_column_offsets = ColumnOffsets::create();
Offsets & res_offsets = res_column_offsets->getData();
res_offsets.reserve(replicate_offsets.back());
Offset_t prev_replicate_offset = 0;
Offset_t prev_data_offset = 0;
Offset_t current_new_offset = 0;
Offset prev_replicate_offset = 0;
Offset prev_data_offset = 0;
Offset current_new_offset = 0;
for (size_t i = 0; i < col_size; ++i)
{
@ -831,23 +830,23 @@ ColumnPtr ColumnArray::replicateConst(const Offsets_t & replicate_offsets) const
prev_data_offset = src_offsets[i];
}
return std::make_shared<ColumnArray>(getData().cloneResized(current_new_offset), res_column_offsets);
return ColumnArray::create(getData().cloneResized(current_new_offset), std::move(res_column_offsets));
}
ColumnPtr ColumnArray::replicateGeneric(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicateGeneric(const Offsets & replicate_offsets) const
{
size_t col_size = size();
if (col_size != replicate_offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
ColumnPtr res = cloneEmpty();
MutableColumnPtr res = cloneEmpty();
ColumnArray & res_concrete = static_cast<ColumnArray &>(*res);
if (0 == col_size)
return res;
IColumn::Offset_t prev_offset = 0;
IColumn::Offset prev_offset = 0;
for (size_t i = 0; i < col_size; ++i)
{
size_t size_to_replicate = replicate_offsets[i] - prev_offset;
@ -861,25 +860,25 @@ ColumnPtr ColumnArray::replicateGeneric(const Offsets_t & replicate_offsets) con
}
ColumnPtr ColumnArray::replicateNullable(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicateNullable(const Offsets & replicate_offsets) const
{
const ColumnNullable & nullable = static_cast<const ColumnNullable &>(*data);
/// Make temporary arrays for each components of Nullable. Then replicate them independently and collect back to result.
/// NOTE Offsets are calculated twice and it is redundant.
auto array_of_nested = ColumnArray(nullable.getNestedColumn(), getOffsetsColumn()).replicate(replicate_offsets);
auto array_of_null_map = ColumnArray(nullable.getNullMapColumn(), getOffsetsColumn()).replicate(replicate_offsets);
auto array_of_nested = ColumnArray(nullable.getNestedColumnPtr(), getOffsetsPtr()).replicate(replicate_offsets);
auto array_of_null_map = ColumnArray(nullable.getNullMapColumnPtr(), getOffsetsPtr()).replicate(replicate_offsets);
return std::make_shared<ColumnArray>(
std::make_shared<ColumnNullable>(
return ColumnArray::create(
ColumnNullable::create(
static_cast<ColumnArray &>(*array_of_nested).getDataPtr(),
static_cast<ColumnArray &>(*array_of_null_map).getDataPtr()),
static_cast<ColumnArray &>(*array_of_nested).getOffsetsColumn());
static_cast<ColumnArray &>(*array_of_nested).getOffsetsPtr());
}
ColumnPtr ColumnArray::replicateTuple(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnArray::replicateTuple(const Offsets & replicate_offsets) const
{
const ColumnTuple & tuple = static_cast<const ColumnTuple &>(*data);
@ -892,15 +891,15 @@ ColumnPtr ColumnArray::replicateTuple(const Offsets_t & replicate_offsets) const
Columns temporary_arrays(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
temporary_arrays[i] = ColumnArray(tuple.getColumns()[i], getOffsetsColumn()).replicate(replicate_offsets);
temporary_arrays[i] = ColumnArray(tuple.getColumns()[i], getOffsetsPtr()).replicate(replicate_offsets);
Columns tuple_columns(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
tuple_columns[i] = static_cast<ColumnArray &>(*temporary_arrays[i]).getDataPtr();
tuple_columns[i] = static_cast<const ColumnArray &>(*temporary_arrays[i]).getDataPtr();
return std::make_shared<ColumnArray>(
std::make_shared<ColumnTuple>(tuple_columns),
static_cast<ColumnArray &>(*temporary_arrays.front()).getOffsetsColumn());
return ColumnArray::create(
ColumnTuple::create(tuple_columns),
static_cast<const ColumnArray &>(*temporary_arrays.front()).getOffsetsPtr());
}

View File

@ -18,18 +18,26 @@ namespace ErrorCodes
* In memory, it is represented as one column of a nested type, whose size is equal to the sum of the sizes of all arrays,
* and as an array of offsets in it, which allows you to get each element.
*/
class ColumnArray final : public IColumn
class ColumnArray final : public COWPtrHelper<IColumn, ColumnArray>
{
public:
/** On the index i there is an offset to the beginning of the i + 1 -th element. */
using ColumnOffsets_t = ColumnVector<Offset_t>;
private:
friend class COWPtrHelper<IColumn, ColumnArray>;
/** Create an array column with specified values and offsets. */
ColumnArray(const ColumnPtr & nested_column, const ColumnPtr & offsets_column);
/** Create an empty column of arrays with the type of values as in the column `nested_column` */
explicit ColumnArray(ColumnPtr nested_column, ColumnPtr offsets_column = nullptr);
ColumnArray(const ColumnPtr & nested_column);
ColumnArray(const ColumnArray &) = default;
public:
/** On the index i there is an offset to the beginning of the i + 1 -th element. */
using ColumnOffsets = ColumnVector<Offset>;
std::string getName() const override;
const char * getFamilyName() const override { return "Array"; }
ColumnPtr cloneResized(size_t size) const override;
MutableColumnPtr cloneResized(size_t size) const override;
size_t size() const override;
Field operator[](size_t n) const override;
void get(size_t n, Field & res) const override;
@ -43,40 +51,45 @@ public:
void insertFrom(const IColumn & src_, size_t n) override;
void insertDefault() override;
void popBack(size_t n) override;
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
MutableColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override;
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override;
void reserve(size_t n) override;
size_t byteSize() const override;
size_t allocatedBytes() const override;
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
ColumnPtr convertToFullColumnIfConst() const override;
MutableColumnPtr replicate(const Offsets & replicate_offsets) const override;
MutableColumnPtr convertToFullColumnIfConst() const override;
void getExtremes(Field & min, Field & max) const override;
bool hasEqualOffsets(const ColumnArray & other) const;
/** More efficient methods of manipulation */
IColumn & getData() { return *data.get(); }
const IColumn & getData() const { return *data.get(); }
IColumn & getData() { return *data->assumeMutable(); }
const IColumn & getData() const { return *data; }
ColumnPtr & getDataPtr() { return data; }
IColumn & getOffsetsColumn() { return *offsets->assumeMutable(); }
const IColumn & getOffsetsColumn() const { return *offsets; }
Offsets & ALWAYS_INLINE getOffsets()
{
return static_cast<ColumnOffsets &>(*offsets->assumeMutable()).getData();
}
const Offsets & ALWAYS_INLINE getOffsets() const
{
return static_cast<const ColumnOffsets &>(*offsets).getData();
}
//MutableColumnPtr getDataMutablePtr() { return data->assumeMutable(); }
const ColumnPtr & getDataPtr() const { return data; }
ColumnPtr & getDataPtr() { return data; }
Offsets_t & ALWAYS_INLINE getOffsets()
{
return static_cast<ColumnOffsets_t &>(*offsets.get()).getData();
}
//MutableColumnPtr getOffsetsMutablePtr() { return offsets->assumeMutable(); }
const ColumnPtr & getOffsetsPtr() const { return offsets; }
ColumnPtr & getOffsetsPtr() { return offsets; }
const Offsets_t & ALWAYS_INLINE getOffsets() const
{
return static_cast<const ColumnOffsets_t &>(*offsets.get()).getData();
}
ColumnPtr & getOffsetsColumn() { return offsets; }
const ColumnPtr & getOffsetsColumn() const { return offsets; }
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override
{
return scatterImpl<ColumnArray>(num_columns, selector);
}
@ -91,41 +104,41 @@ public:
private:
ColumnPtr data;
ColumnPtr offsets; /// Displacements can be shared across multiple columns - to implement nested data structures.
ColumnPtr offsets;
size_t ALWAYS_INLINE offsetAt(size_t i) const { return i == 0 ? 0 : getOffsets()[i - 1]; }
size_t ALWAYS_INLINE sizeAt(size_t i) const { return i == 0 ? getOffsets()[0] : (getOffsets()[i] - getOffsets()[i - 1]); }
size_t ALWAYS_INLINE offsetAt(size_t i) const { return i == 0 ? 0 : getOffsets()[i - 1]; }
size_t ALWAYS_INLINE sizeAt(size_t i) const { return i == 0 ? getOffsets()[0] : (getOffsets()[i] - getOffsets()[i - 1]); }
/// Multiply values if the nested column is ColumnVector<T>.
template <typename T>
ColumnPtr replicateNumber(const Offsets_t & replicate_offsets) const;
MutableColumnPtr replicateNumber(const Offsets & replicate_offsets) const;
/// Multiply the values if the nested column is ColumnString. The code is too complicated.
ColumnPtr replicateString(const Offsets_t & replicate_offsets) const;
MutableColumnPtr replicateString(const Offsets & replicate_offsets) const;
/** Non-constant arrays of constant values are quite rare.
* Most functions can not work with them, and does not create such columns as a result.
* An exception is the function `replicate`(see FunctionsMiscellaneous.h), which has service meaning for the implementation of lambda functions.
* Only for its sake is the implementation of the `replicate` method for ColumnArray(ColumnConst).
*/
ColumnPtr replicateConst(const Offsets_t & replicate_offsets) const;
MutableColumnPtr replicateConst(const Offsets & replicate_offsets) const;
/** The following is done by simply replicating of nested columns.
*/
ColumnPtr replicateTuple(const Offsets_t & replicate_offsets) const;
ColumnPtr replicateNullable(const Offsets_t & replicate_offsets) const;
ColumnPtr replicateGeneric(const Offsets_t & replicate_offsets) const;
MutableColumnPtr replicateTuple(const Offsets & replicate_offsets) const;
MutableColumnPtr replicateNullable(const Offsets & replicate_offsets) const;
MutableColumnPtr replicateGeneric(const Offsets & replicate_offsets) const;
/// Specializations for the filter function.
template <typename T>
ColumnPtr filterNumber(const Filter & filt, ssize_t result_size_hint) const;
MutableColumnPtr filterNumber(const Filter & filt, ssize_t result_size_hint) const;
ColumnPtr filterString(const Filter & filt, ssize_t result_size_hint) const;
ColumnPtr filterTuple(const Filter & filt, ssize_t result_size_hint) const;
ColumnPtr filterNullable(const Filter & filt, ssize_t result_size_hint) const;
ColumnPtr filterGeneric(const Filter & filt, ssize_t result_size_hint) const;
MutableColumnPtr filterString(const Filter & filt, ssize_t result_size_hint) const;
MutableColumnPtr filterTuple(const Filter & filt, ssize_t result_size_hint) const;
MutableColumnPtr filterNullable(const Filter & filt, ssize_t result_size_hint) const;
MutableColumnPtr filterGeneric(const Filter & filt, ssize_t result_size_hint) const;
};

View File

@ -1,20 +1,23 @@
#include <IO/Operators.h>
#include <IO/WriteBufferFromString.h>
#include <IO/WriteHelpers.h>
#include <Columns/ColumnConst.h>
#include <Columns/ColumnNullable.h>
#include <Common/FieldVisitors.h>
#include <Columns/ColumnsCommon.h>
#include <Common/typeid_cast.h>
namespace DB
{
ColumnConst::ColumnConst(ColumnPtr data_, size_t s)
namespace ErrorCodes
{
extern const int SIZES_OF_COLUMNS_DOESNT_MATCH;
}
ColumnConst::ColumnConst(const ColumnPtr & data_, size_t s)
: data(data_), s(s)
{
/// Squash Const of Const.
while (ColumnConst * const_data = typeid_cast<ColumnConst *>(data.get()))
while (const ColumnConst * const_data = typeid_cast<const ColumnConst *>(data.get()))
data = const_data->getDataColumnPtr();
if (data->size() != 1)
@ -22,9 +25,66 @@ ColumnConst::ColumnConst(ColumnPtr data_, size_t s)
ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
}
ColumnPtr ColumnConst::convertToFullColumn() const
MutableColumnPtr ColumnConst::convertToFullColumn() const
{
return data->replicate(Offsets_t(1, s));
return data->replicate(Offsets(1, s));
}
MutableColumnPtr ColumnConst::filter(const Filter & filt, ssize_t /*result_size_hint*/) const
{
if (s != filt.size())
throw Exception("Size of filter (" + toString(filt.size()) + ") doesn't match size of column (" + toString(s) + ")",
ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
return ColumnConst::create(data, countBytesInFilter(filt));
}
MutableColumnPtr ColumnConst::replicate(const Offsets & offsets) const
{
if (s != offsets.size())
throw Exception("Size of offsets (" + toString(offsets.size()) + ") doesn't match size of column (" + toString(s) + ")",
ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
size_t replicated_size = 0 == s ? 0 : offsets.back();
return ColumnConst::create(data, replicated_size);
}
MutableColumnPtr ColumnConst::permute(const Permutation & perm, size_t limit) const
{
if (limit == 0)
limit = s;
else
limit = std::min(s, limit);
if (perm.size() < limit)
throw Exception("Size of permutation (" + toString(perm.size()) + ") is less than required (" + toString(limit) + ")",
ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
return ColumnConst::create(data, limit);
}
MutableColumns ColumnConst::scatter(ColumnIndex num_columns, const Selector & selector) const
{
if (s != selector.size())
throw Exception("Size of selector (" + toString(selector.size()) + ") doesn't match size of column (" + toString(s) + ")",
ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::vector<size_t> counts(num_columns);
for (auto idx : selector)
++counts[idx];
MutableColumns res(num_columns);
for (size_t i = 0; i < num_columns; ++i)
res[i] = cloneResized(counts[i]);
return res;
}
void ColumnConst::getPermutation(bool /*reverse*/, size_t /*limit*/, int /*nan_direction_hint*/, Permutation & res) const
{
res.resize(s);
for (size_t i = 0; i < s; ++i)
res[i] = i;
}
}

View File

@ -3,7 +3,6 @@
#include <Core/Field.h>
#include <Common/Exception.h>
#include <Columns/IColumn.h>
#include <Columns/ColumnsCommon.h>
namespace DB
@ -11,7 +10,6 @@ namespace DB
namespace ErrorCodes
{
extern const int SIZES_OF_COLUMNS_DOESNT_MATCH;
extern const int NOT_IMPLEMENTED;
}
@ -19,18 +17,21 @@ namespace ErrorCodes
/** ColumnConst contains another column with single element,
* but looks like a column with arbitary amount of same elements.
*/
class ColumnConst final : public IColumn
class ColumnConst final : public COWPtrHelper<IColumn, ColumnConst>
{
private:
friend class COWPtrHelper<IColumn, ColumnConst>;
ColumnPtr data;
size_t s;
ColumnConst(const ColumnPtr & data, size_t s);
ColumnConst(const ColumnConst & src) = default;
public:
ColumnConst(ColumnPtr data, size_t s);
MutableColumnPtr convertToFullColumn() const;
ColumnPtr convertToFullColumn() const;
ColumnPtr convertToFullColumnIfConst() const override
MutableColumnPtr convertToFullColumnIfConst() const override
{
return convertToFullColumn();
}
@ -45,9 +46,9 @@ public:
return "Const";
}
ColumnPtr cloneResized(size_t new_size) const override
MutableColumnPtr cloneResized(size_t new_size) const override
{
return std::make_shared<ColumnConst>(data, new_size);
return ColumnConst::create(data, new_size);
}
size_t size() const override
@ -132,8 +133,9 @@ public:
const char * deserializeAndInsertFromArena(const char * pos) override
{
auto res = data->deserializeAndInsertFromArena(pos);
data->popBack(1);
MutableColumnPtr mutable_data = data->assumeMutable();
auto res = mutable_data->deserializeAndInsertFromArena(pos);
mutable_data->popBack(1);
++s;
return res;
}
@ -143,22 +145,10 @@ public:
data->updateHashWithValue(0, hash);
}
ColumnPtr filter(const Filter & filt, ssize_t /*result_size_hint*/) const override
{
if (s != filt.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
return std::make_shared<ColumnConst>(data, countBytesInFilter(filt));
}
ColumnPtr replicate(const Offsets_t & offsets) const override
{
if (s != offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
size_t replicated_size = 0 == s ? 0 : offsets.back();
return std::make_shared<ColumnConst>(data, replicated_size);
}
MutableColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr replicate(const Offsets & offsets) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override;
size_t byteSize() const override
{
@ -170,46 +160,12 @@ public:
return data->allocatedBytes() + sizeof(s);
}
ColumnPtr permute(const Permutation & perm, size_t limit) const override
{
if (limit == 0)
limit = s;
else
limit = std::min(s, limit);
if (perm.size() < limit)
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
return std::make_shared<ColumnConst>(data, limit);
}
int compareAt(size_t, size_t, const IColumn & rhs, int nan_direction_hint) const override
{
return data->compareAt(0, 0, *static_cast<const ColumnConst &>(rhs).data, nan_direction_hint);
}
void getPermutation(bool /*reverse*/, size_t /*limit*/, int /*nan_direction_hint*/, Permutation & res) const override
{
res.resize(s);
for (size_t i = 0; i < s; ++i)
res[i] = i;
}
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
{
if (size() != selector.size())
throw Exception("Size of selector doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::vector<size_t> counts(num_columns);
for (auto idx : selector)
++counts[idx];
Columns res(num_columns);
for (size_t i = 0; i < num_columns; ++i)
res[i] = cloneResized(counts[i]);
return res;
}
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override;
void gather(ColumnGathererStream &) override
{
@ -235,10 +191,11 @@ public:
/// Not part of the common interface.
IColumn & getDataColumn() { return *data; }
IColumn & getDataColumn() { return *data->assumeMutable(); }
const IColumn & getDataColumn() const { return *data; }
ColumnPtr & getDataColumnPtr() { return data; }
//MutableColumnPtr getDataColumnMutablePtr() { return data; }
const ColumnPtr & getDataColumnPtr() const { return data; }
//ColumnPtr & getDataColumnPtr() { return data; }
Field getField() const { return getDataColumn()[0]; }

View File

@ -6,20 +6,22 @@ namespace DB
{
ColumnExpression::ColumnExpression(
size_t s_, ExpressionActionsPtr expression_, const NamesAndTypes & arguments_, DataTypePtr return_type_, std::string return_name_)
: IColumnDummy(s_), expression(expression_), arguments(arguments_), return_type(return_type_), return_name(return_name_)
size_t s_, const ExpressionActionsPtr & expression_, const NamesAndTypes & arguments_, const DataTypePtr & return_type_, const String & return_name_)
: expression(expression_), arguments(arguments_), return_type(return_type_), return_name(return_name_)
{
s = s_;
}
ColumnExpression::ColumnExpression(
size_t s_, ExpressionActionsPtr expression_, const NamesAndTypesList & arguments_, DataTypePtr return_type_, std::string return_name_)
: IColumnDummy(s_), expression(expression_), arguments(arguments_.begin(), arguments_.end()), return_type(return_type_), return_name(return_name_)
size_t s_, const ExpressionActionsPtr & expression_, const NamesAndTypesList & arguments_, const DataTypePtr & return_type_, const String & return_name_)
: expression(expression_), arguments(arguments_.begin(), arguments_.end()), return_type(return_type_), return_name(return_name_)
{
s = s_;
}
ColumnPtr ColumnExpression::cloneDummy(size_t s_) const
MutableColumnPtr ColumnExpression::cloneDummy(size_t s_) const
{
return std::make_shared<ColumnExpression>(s_, expression, arguments, return_type, return_name);
return ColumnExpression::create(s_, expression, arguments, return_type, return_name);
}
const ExpressionActionsPtr & ColumnExpression::getExpression() const { return expression; }

View File

@ -12,17 +12,21 @@ class ExpressionActions;
/** A column containing a lambda expression.
* Behaves like a constant-column. Contains an expression, but not input or output data.
*/
class ColumnExpression final : public IColumnDummy
class ColumnExpression final : public COWPtrHelper<IColumnDummy, ColumnExpression>
{
private:
friend class COWPtrHelper<IColumnDummy, ColumnExpression>;
using ExpressionActionsPtr = std::shared_ptr<ExpressionActions>;
public:
ColumnExpression(size_t s_, ExpressionActionsPtr expression_, const NamesAndTypes & arguments_, DataTypePtr return_type_, String return_name_);
ColumnExpression(size_t s_, ExpressionActionsPtr expression_, const NamesAndTypesList & arguments_, DataTypePtr return_type_, String return_name_);
ColumnExpression(size_t s_, const ExpressionActionsPtr & expression_, const NamesAndTypes & arguments_, const DataTypePtr & return_type_, const String & return_name_);
ColumnExpression(size_t s_, const ExpressionActionsPtr & expression_, const NamesAndTypesList & arguments_, const DataTypePtr & return_type_, const String & return_name_);
ColumnExpression(const ColumnExpression &) = default;
public:
const char * getFamilyName() const override { return "Expression"; }
ColumnPtr cloneDummy(size_t s_) const override;
MutableColumnPtr cloneDummy(size_t s_) const override;
const ExpressionActionsPtr & getExpression() const;
const DataTypePtr & getReturnType() const;

View File

@ -25,9 +25,9 @@ namespace ErrorCodes
}
ColumnPtr ColumnFixedString::cloneResized(size_t size) const
MutableColumnPtr ColumnFixedString::cloneResized(size_t size) const
{
ColumnPtr new_col_holder = std::make_shared<ColumnFixedString>(n);
MutableColumnPtr new_col_holder = ColumnFixedString::create(n);
if (size > 0)
{
@ -153,13 +153,13 @@ void ColumnFixedString::insertRangeFrom(const IColumn & src, size_t start, size_
memcpy(&chars[old_size], &src_concrete.chars[start * n], length * n);
}
ColumnPtr ColumnFixedString::filter(const IColumn::Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnFixedString::filter(const IColumn::Filter & filt, ssize_t result_size_hint) const
{
size_t col_size = size();
if (col_size != filt.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<ColumnFixedString> res = std::make_shared<ColumnFixedString>(n);
auto res = ColumnFixedString::create(n);
if (result_size_hint)
res->chars.reserve(result_size_hint > 0 ? result_size_hint * n : chars.size());
@ -227,10 +227,10 @@ ColumnPtr ColumnFixedString::filter(const IColumn::Filter & filt, ssize_t result
data_pos += n;
}
return res;
return std::move(res);
}
ColumnPtr ColumnFixedString::permute(const Permutation & perm, size_t limit) const
MutableColumnPtr ColumnFixedString::permute(const Permutation & perm, size_t limit) const
{
size_t col_size = size();
@ -243,9 +243,9 @@ ColumnPtr ColumnFixedString::permute(const Permutation & perm, size_t limit) con
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
if (limit == 0)
return std::make_shared<ColumnFixedString>(n);
return ColumnFixedString::create(n);
std::shared_ptr<ColumnFixedString> res = std::make_shared<ColumnFixedString>(n);
auto res = ColumnFixedString::create(n);
Chars_t & res_chars = res->chars;
@ -255,29 +255,29 @@ ColumnPtr ColumnFixedString::permute(const Permutation & perm, size_t limit) con
for (size_t i = 0; i < limit; ++i, offset += n)
memcpySmallAllowReadWriteOverflow15(&res_chars[offset], &chars[perm[i] * n], n);
return res;
return std::move(res);
}
ColumnPtr ColumnFixedString::replicate(const Offsets_t & offsets) const
MutableColumnPtr ColumnFixedString::replicate(const Offsets & offsets) const
{
size_t col_size = size();
if (col_size != offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<ColumnFixedString> res = std::make_shared<ColumnFixedString>(n);
auto res = ColumnFixedString::create(n);
if (0 == col_size)
return res;
return std::move(res);
Chars_t & res_chars = res->chars;
res_chars.resize(n * offsets.back());
Offset_t curr_offset = 0;
Offset curr_offset = 0;
for (size_t i = 0; i < col_size; ++i)
for (size_t next_offset = offsets[i]; curr_offset < next_offset; ++curr_offset)
memcpySmallAllowReadWriteOverflow15(&res->chars[curr_offset * n], &chars[i * n], n);
return res;
return std::move(res);
}
void ColumnFixedString::gather(ColumnGathererStream & gatherer)

View File

@ -12,9 +12,11 @@ namespace DB
/** A column of values of "fixed-length string" type.
* If you insert a smaller string, it will be padded with zero bytes.
*/
class ColumnFixedString final : public IColumn
class ColumnFixedString final : public COWPtrHelper<IColumn, ColumnFixedString>
{
public:
friend class COWPtrHelper<IColumn, ColumnFixedString>;
using Chars_t = PaddedPODArray<UInt8>;
private:
@ -29,14 +31,16 @@ private:
template <bool positive>
struct less;
public:
/** Create an empty column of strings of fixed-length `n` */
ColumnFixedString(size_t n_) : n(n_) {}
ColumnFixedString(const ColumnFixedString & src) : chars(src.chars.begin(), src.chars.end()), n(src.n) {};
public:
std::string getName() const override { return "FixedString(" + std::to_string(n) + ")"; }
const char * getFamilyName() const override { return "FixedString"; }
ColumnPtr cloneResized(size_t size) const override;
MutableColumnPtr cloneResized(size_t size) const override;
size_t size() const override
{
@ -100,13 +104,13 @@ public:
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
ColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override;
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
ColumnPtr replicate(const Offsets_t & offsets) const override;
MutableColumnPtr replicate(const Offsets & offsets) const override;
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override
{
return scatterImpl<ColumnFixedString>(num_columns, selector);
}

View File

@ -6,13 +6,21 @@
namespace DB
{
class ColumnNothing final : public IColumnDummy
class ColumnNothing final : public COWPtrHelper<IColumnDummy, ColumnNothing>
{
public:
using IColumnDummy::IColumnDummy;
private:
friend class COWPtrHelper<IColumnDummy, ColumnNothing>;
ColumnNothing(size_t s_)
{
s = s_;
}
ColumnNothing(const ColumnNothing &) = default;
public:
const char * getFamilyName() const override { return "Nothing"; }
ColumnPtr cloneDummy(size_t s) const override { return std::make_shared<ColumnNothing>(s); };
MutableColumnPtr cloneDummy(size_t s) const override { return ColumnNothing::create(s); };
bool canBeInsideNullable() const override { return true; }
};

View File

@ -18,14 +18,14 @@ namespace ErrorCodes
}
ColumnNullable::ColumnNullable(ColumnPtr nested_column_, ColumnPtr null_map_)
ColumnNullable::ColumnNullable(const ColumnPtr & nested_column_, const ColumnPtr & null_map_)
: nested_column{nested_column_}, null_map{null_map_}
{
/// ColumnNullable cannot have constant nested column. But constant argument could be passed. Materialize it.
if (auto nested_column_materialized = nested_column->convertToFullColumnIfConst())
if (ColumnPtr nested_column_materialized = getNestedColumn().convertToFullColumnIfConst())
nested_column = nested_column_materialized;
if (!nested_column->canBeInsideNullable())
if (!getNestedColumn().canBeInsideNullable())
throw Exception{getName() + " cannot be inside Nullable column", ErrorCodes::ILLEGAL_COLUMN};
if (null_map->isColumnConst())
@ -35,43 +35,37 @@ ColumnNullable::ColumnNullable(ColumnPtr nested_column_, ColumnPtr null_map_)
void ColumnNullable::updateHashWithValue(size_t n, SipHash & hash) const
{
const auto & arr = getNullMap();
const auto & arr = getNullMapData();
hash.update(reinterpret_cast<const char *>(&arr[n]), sizeof(arr[0]));
if (arr[n] == 0)
nested_column->updateHashWithValue(n, hash);
getNestedColumn().updateHashWithValue(n, hash);
}
ColumnPtr ColumnNullable::cloneResized(size_t new_size) const
MutableColumnPtr ColumnNullable::cloneResized(size_t new_size) const
{
ColumnPtr new_nested_col = nested_column->cloneResized(new_size);
auto new_null_map = std::make_shared<ColumnUInt8>();
ColumnPtr new_nested_col = getNestedColumn().cloneResized(new_size);
auto new_null_map = ColumnUInt8::create();
if (new_size > 0)
{
new_null_map->getData().resize(new_size);
size_t count = std::min(size(), new_size);
memcpy(new_null_map->getData().data(), getNullMap().data(), count * sizeof(getNullMap()[0]));
memcpy(new_null_map->getData().data(), getNullMapData().data(), count * sizeof(getNullMapData()[0]));
/// If resizing to bigger one, set all new values to NULLs.
if (new_size > count)
memset(&new_null_map->getData()[count], 1, new_size - count);
}
return std::make_shared<ColumnNullable>(new_nested_col, new_null_map);
return ColumnNullable::create(new_nested_col, std::move(new_null_map));
}
Field ColumnNullable::operator[](size_t n) const
{
if (isNullAt(n))
return Null();
else
{
const IColumn & col = *nested_column;
return col[n];
}
return isNullAt(n) ? Null() : getNestedColumn()[n];
}
@ -80,7 +74,7 @@ void ColumnNullable::get(size_t n, Field & res) const
if (isNullAt(n))
res = Null();
else
nested_column->get(n, res);
getNestedColumn().get(n, res);
}
StringRef ColumnNullable::getDataAt(size_t /*n*/) const
@ -95,7 +89,7 @@ void ColumnNullable::insertData(const char * /*pos*/, size_t /*length*/)
StringRef ColumnNullable::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
{
const auto & arr = getNullMap();
const auto & arr = getNullMapData();
static constexpr auto s = sizeof(arr[0]);
auto pos = arena.allocContinue(s, begin);
@ -104,7 +98,7 @@ StringRef ColumnNullable::serializeValueIntoArena(size_t n, Arena & arena, char
size_t nested_size = 0;
if (arr[n] == 0)
nested_size = nested_column->serializeValueIntoArena(n, arena, begin).size;
nested_size = getNestedColumn().serializeValueIntoArena(n, arena, begin).size;
return StringRef{begin, s + nested_size};
}
@ -114,12 +108,12 @@ const char * ColumnNullable::deserializeAndInsertFromArena(const char * pos)
UInt8 val = *reinterpret_cast<const UInt8 *>(pos);
pos += sizeof(val);
getNullMap().push_back(val);
getNullMapData().push_back(val);
if (val == 0)
pos = nested_column->deserializeAndInsertFromArena(pos);
pos = getNestedColumn().deserializeAndInsertFromArena(pos);
else
nested_column->insertDefault();
getNestedColumn().insertDefault();
return pos;
}
@ -127,49 +121,49 @@ const char * ColumnNullable::deserializeAndInsertFromArena(const char * pos)
void ColumnNullable::insertRangeFrom(const IColumn & src, size_t start, size_t length)
{
const ColumnNullable & nullable_col = static_cast<const ColumnNullable &>(src);
getNullMapConcreteColumn().insertRangeFrom(*nullable_col.null_map, start, length);
nested_column->insertRangeFrom(*nullable_col.nested_column, start, length);
getNullMapColumn().insertRangeFrom(*nullable_col.null_map, start, length);
getNestedColumn().insertRangeFrom(*nullable_col.nested_column, start, length);
}
void ColumnNullable::insert(const Field & x)
{
if (x.isNull())
{
nested_column->insertDefault();
getNullMap().push_back(1);
getNestedColumn().insertDefault();
getNullMapData().push_back(1);
}
else
{
nested_column->insert(x);
getNullMap().push_back(0);
getNestedColumn().insert(x);
getNullMapData().push_back(0);
}
}
void ColumnNullable::insertFrom(const IColumn & src, size_t n)
{
const ColumnNullable & src_concrete = static_cast<const ColumnNullable &>(src);
nested_column->insertFrom(*src_concrete.getNestedColumn(), n);
getNullMap().push_back(src_concrete.getNullMap()[n]);
getNestedColumn().insertFrom(src_concrete.getNestedColumn(), n);
getNullMapData().push_back(src_concrete.getNullMapData()[n]);
}
void ColumnNullable::popBack(size_t n)
{
nested_column->popBack(n);
getNullMapConcreteColumn().popBack(n);
getNestedColumn().popBack(n);
getNullMapColumn().popBack(n);
}
ColumnPtr ColumnNullable::filter(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnNullable::filter(const Filter & filt, ssize_t result_size_hint) const
{
ColumnPtr filtered_data = nested_column->filter(filt, result_size_hint);
ColumnPtr filtered_null_map = getNullMapConcreteColumn().filter(filt, result_size_hint);
return std::make_shared<ColumnNullable>(filtered_data, filtered_null_map);
ColumnPtr filtered_data = getNestedColumn().filter(filt, result_size_hint);
ColumnPtr filtered_null_map = getNullMapColumn().filter(filt, result_size_hint);
return ColumnNullable::create(filtered_data, filtered_null_map);
}
ColumnPtr ColumnNullable::permute(const Permutation & perm, size_t limit) const
MutableColumnPtr ColumnNullable::permute(const Permutation & perm, size_t limit) const
{
ColumnPtr permuted_data = nested_column->permute(perm, limit);
ColumnPtr permuted_null_map = getNullMapConcreteColumn().permute(perm, limit);
return std::make_shared<ColumnNullable>(permuted_data, permuted_null_map);
ColumnPtr permuted_data = getNestedColumn().permute(perm, limit);
ColumnPtr permuted_null_map = getNullMapColumn().permute(perm, limit);
return ColumnNullable::create(permuted_data, permuted_null_map);
}
int ColumnNullable::compareAt(size_t n, size_t m, const IColumn & rhs_, int null_direction_hint) const
@ -193,14 +187,14 @@ int ColumnNullable::compareAt(size_t n, size_t m, const IColumn & rhs_, int null
return lval_is_null ? null_direction_hint : -null_direction_hint;
}
const IColumn & nested_rhs = *(nullable_rhs.getNestedColumn());
return nested_column->compareAt(n, m, nested_rhs, null_direction_hint);
const IColumn & nested_rhs = nullable_rhs.getNestedColumn();
return getNestedColumn().compareAt(n, m, nested_rhs, null_direction_hint);
}
void ColumnNullable::getPermutation(bool reverse, size_t limit, int null_direction_hint, Permutation & res) const
{
/// Cannot pass limit because of unknown amount of NULLs.
nested_column->getPermutation(reverse, 0, null_direction_hint, res);
getNestedColumn().getPermutation(reverse, 0, null_direction_hint, res);
if ((null_direction_hint > 0) != reverse)
{
@ -277,18 +271,18 @@ void ColumnNullable::gather(ColumnGathererStream & gatherer)
void ColumnNullable::reserve(size_t n)
{
nested_column->reserve(n);
getNullMap().reserve(n);
getNestedColumn().reserve(n);
getNullMapData().reserve(n);
}
size_t ColumnNullable::byteSize() const
{
return nested_column->byteSize() + getNullMapConcreteColumn().byteSize();
return getNestedColumn().byteSize() + getNullMapColumn().byteSize();
}
size_t ColumnNullable::allocatedBytes() const
{
return nested_column->allocatedBytes() + getNullMapConcreteColumn().allocatedBytes();
return getNestedColumn().allocatedBytes() + getNullMapColumn().allocatedBytes();
}
@ -365,7 +359,7 @@ void ColumnNullable::getExtremes(Field & min, Field & max) const
min = Null();
max = Null();
const auto & null_map = getNullMap();
const auto & null_map = getNullMapData();
if (const auto col = typeid_cast<const ColumnInt8 *>(nested_column.get()))
getExtremesFromNullableContent<Int8>(*col, null_map, min, max);
@ -390,18 +384,18 @@ void ColumnNullable::getExtremes(Field & min, Field & max) const
}
ColumnPtr ColumnNullable::replicate(const Offsets_t & offsets) const
MutableColumnPtr ColumnNullable::replicate(const Offsets & offsets) const
{
ColumnPtr replicated_data = nested_column->replicate(offsets);
ColumnPtr replicated_null_map = getNullMapConcreteColumn().replicate(offsets);
return std::make_shared<ColumnNullable>(replicated_data, replicated_null_map);
ColumnPtr replicated_data = getNestedColumn().replicate(offsets);
ColumnPtr replicated_null_map = getNullMapColumn().replicate(offsets);
return ColumnNullable::create(replicated_data, replicated_null_map);
}
template <bool negative>
void ColumnNullable::applyNullMapImpl(const ColumnUInt8 & map)
{
NullMap & arr1 = getNullMap();
NullMap & arr1 = getNullMapData();
const NullMap & arr2 = map.getData();
if (arr1.size() != arr2.size())
@ -425,13 +419,13 @@ void ColumnNullable::applyNegatedNullMap(const ColumnUInt8 & map)
void ColumnNullable::applyNullMap(const ColumnNullable & other)
{
applyNullMap(other.getNullMapConcreteColumn());
applyNullMap(other.getNullMapColumn());
}
void ColumnNullable::checkConsistency() const
{
if (null_map->size() != nested_column->size())
if (null_map->size() != getNestedColumn().size())
throw Exception("Logical error: Sizes of nested column and null map of Nullable column are not equal",
ErrorCodes::SIZES_OF_NESTED_COLUMNS_ARE_INCONSISTENT);
}
@ -443,9 +437,9 @@ ColumnPtr makeNullable(const ColumnPtr & column)
return column;
if (column->isColumnConst())
return std::make_shared<ColumnConst>(makeNullable(static_cast<ColumnConst &>(*column).getDataColumnPtr()), column->size());
return ColumnConst::create(makeNullable(static_cast<const ColumnConst &>(*column).getDataColumnPtr()), column->size());
return std::make_shared<ColumnNullable>(column, std::make_shared<ColumnUInt8>(column->size(), 0));
return ColumnNullable::create(column, ColumnUInt8::create(column->size(), 0));
}
}

View File

@ -6,7 +6,7 @@
namespace DB
{
using NullMap = ColumnUInt8::Container_t;
using NullMap = ColumnUInt8::Container;
using ConstNullMapPtr = const NullMap *;
/// Class that specifies nullable columns. A nullable column represents
@ -18,13 +18,18 @@ using ConstNullMapPtr = const NullMap *;
/// over a bitmap because columns are usually stored on disk as compressed
/// files. In this regard, using a bitmap instead of a byte map would
/// greatly complicate the implementation with little to no benefits.
class ColumnNullable final : public IColumn
class ColumnNullable final : public COWPtrHelper<IColumn, ColumnNullable>
{
private:
friend class COWPtrHelper<IColumn, ColumnNullable>;
ColumnNullable(const ColumnPtr & nested_column_, const ColumnPtr & null_map_);
ColumnNullable(const ColumnNullable &) = default;
public:
ColumnNullable(ColumnPtr nested_column_, ColumnPtr null_map_);
const char * getFamilyName() const override { return "Nullable"; }
std::string getName() const override { return "Nullable(" + nested_column->getName() + ")"; }
ColumnPtr cloneResized(size_t size) const override;
MutableColumnPtr cloneResized(size_t size) const override;
size_t size() const override { return nested_column->size(); }
bool isNullAt(size_t n) const override { return static_cast<const ColumnUInt8 &>(*null_map).getData()[n] != 0;}
Field operator[](size_t n) const override;
@ -40,23 +45,23 @@ public:
void insertDefault() override
{
nested_column->insertDefault();
getNullMap().push_back(1);
getNestedColumn().insertDefault();
getNullMapData().push_back(1);
}
void popBack(size_t n) override;
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
MutableColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
int compareAt(size_t n, size_t m, const IColumn & rhs_, int null_direction_hint) const override;
void getPermutation(bool reverse, size_t limit, int null_direction_hint, Permutation & res) const override;
void reserve(size_t n) override;
size_t byteSize() const override;
size_t allocatedBytes() const override;
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
MutableColumnPtr replicate(const Offsets & replicate_offsets) const override;
void updateHashWithValue(size_t n, SipHash & hash) const override;
void getExtremes(Field & min, Field & max) const override;
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override
{
return scatterImpl<ColumnNullable>(num_columns, selector);
}
@ -76,18 +81,21 @@ public:
/// Return the column that represents values.
ColumnPtr & getNestedColumn() { return nested_column; }
const ColumnPtr & getNestedColumn() const { return nested_column; }
IColumn & getNestedColumn() { return *nested_column->assumeMutable(); }
const IColumn & getNestedColumn() const { return *nested_column; }
//ColumnPtr & getNestedColumnPtr() { return nested_column->assumeMutable(); }
const ColumnPtr & getNestedColumnPtr() const { return nested_column; }
/// Return the column that represents the byte map.
ColumnPtr & getNullMapColumn() { return null_map; }
const ColumnPtr & getNullMapColumn() const { return null_map; }
//ColumnPtr & getNullMapColumnPtr() { return null_map; }
const ColumnPtr & getNullMapColumnPtr() const { return null_map; }
ColumnUInt8 & getNullMapConcreteColumn() { return static_cast<ColumnUInt8 &>(*null_map); }
const ColumnUInt8 & getNullMapConcreteColumn() const { return static_cast<const ColumnUInt8 &>(*null_map); }
ColumnUInt8 & getNullMapColumn() { return static_cast<ColumnUInt8 &>(*null_map->assumeMutable()); }
const ColumnUInt8 & getNullMapColumn() const { return static_cast<const ColumnUInt8 &>(*null_map); }
NullMap & getNullMap() { return getNullMapConcreteColumn().getData(); }
const NullMap & getNullMap() const { return getNullMapConcreteColumn().getData(); }
NullMap & getNullMapData() { return getNullMapColumn().getData(); }
const NullMap & getNullMapData() const { return getNullMapColumn().getData(); }
/// Apply the null byte map of a specified nullable column onto the
/// null byte map of the current column by performing an element-wise OR

View File

@ -14,13 +14,17 @@ using ConstSetPtr = std::shared_ptr<const Set>;
* Behaves like a constant-column (because the set is one, not its own for each line).
* This column has a nonstandard value, so it can not be obtained via a normal interface.
*/
class ColumnSet final : public IColumnDummy
class ColumnSet final : public COWPtrHelper<IColumnDummy, ColumnSet>
{
public:
ColumnSet(size_t s_, const ConstSetPtr & data_) : IColumnDummy(s_), data(data_) {}
private:
friend class COWPtrHelper<IColumnDummy, ColumnSet>;
ColumnSet(size_t s_, const ConstSetPtr & data_) : data(data_) { s = s_; }
ColumnSet(const ColumnSet &) = default;
public:
const char * getFamilyName() const override { return "Set"; }
ColumnPtr cloneDummy(size_t s_) const override { return std::make_shared<ColumnSet>(s_, data); }
MutableColumnPtr cloneDummy(size_t s_) const override { return ColumnSet::create(s_, data); }
ConstSetPtr getData() const { return data; }

View File

@ -19,12 +19,12 @@ namespace ErrorCodes
}
ColumnPtr ColumnString::cloneResized(size_t to_size) const
MutableColumnPtr ColumnString::cloneResized(size_t to_size) const
{
auto res = std::make_shared<ColumnString>();
auto res = ColumnString::create();
if (to_size == 0)
return res;
return std::move(res);
size_t from_size = size();
@ -39,7 +39,7 @@ ColumnPtr ColumnString::cloneResized(size_t to_size) const
{
/// Copy column and append empty strings for extra elements.
Offset_t offset = 0;
Offset offset = 0;
if (from_size > 0)
{
res->offsets.assign(offsets.begin(), offsets.end());
@ -59,7 +59,7 @@ ColumnPtr ColumnString::cloneResized(size_t to_size) const
}
}
return res;
return std::move(res);
}
@ -97,22 +97,22 @@ void ColumnString::insertRangeFrom(const IColumn & src, size_t start, size_t len
}
ColumnPtr ColumnString::filter(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnString::filter(const Filter & filt, ssize_t result_size_hint) const
{
if (offsets.size() == 0)
return std::make_shared<ColumnString>();
return ColumnString::create();
auto res = std::make_shared<ColumnString>();
auto res = ColumnString::create();
Chars_t & res_chars = res->chars;
Offsets_t & res_offsets = res->offsets;
Offsets & res_offsets = res->offsets;
filterArraysImpl<UInt8>(chars, offsets, res_chars, res_offsets, filt, result_size_hint);
return res;
return std::move(res);
}
ColumnPtr ColumnString::permute(const Permutation & perm, size_t limit) const
MutableColumnPtr ColumnString::permute(const Permutation & perm, size_t limit) const
{
size_t size = offsets.size();
@ -125,12 +125,12 @@ ColumnPtr ColumnString::permute(const Permutation & perm, size_t limit) const
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
if (limit == 0)
return std::make_shared<ColumnString>();
return ColumnString::create();
std::shared_ptr<ColumnString> res = std::make_shared<ColumnString>();
auto res = ColumnString::create();
Chars_t & res_chars = res->chars;
Offsets_t & res_offsets = res->offsets;
Offsets & res_offsets = res->offsets;
if (limit == size)
res_chars.resize(chars.size());
@ -144,7 +144,7 @@ ColumnPtr ColumnString::permute(const Permutation & perm, size_t limit) const
res_offsets.resize(limit);
Offset_t current_new_offset = 0;
Offset current_new_offset = 0;
for (size_t i = 0; i < limit; ++i)
{
@ -158,7 +158,7 @@ ColumnPtr ColumnString::permute(const Permutation & perm, size_t limit) const
res_offsets[i] = current_new_offset;
}
return res;
return std::move(res);
}
@ -208,25 +208,25 @@ void ColumnString::getPermutation(bool reverse, size_t limit, int /*nan_directio
}
ColumnPtr ColumnString::replicate(const Offsets_t & replicate_offsets) const
MutableColumnPtr ColumnString::replicate(const Offsets & replicate_offsets) const
{
size_t col_size = size();
if (col_size != replicate_offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<ColumnString> res = std::make_shared<ColumnString>();
auto res = ColumnString::create();
if (0 == col_size)
return res;
return std::move(res);
Chars_t & res_chars = res->chars;
Offsets_t & res_offsets = res->offsets;
Offsets & res_offsets = res->offsets;
res_chars.reserve(chars.size() / col_size * replicate_offsets.back());
res_offsets.reserve(replicate_offsets.back());
Offset_t prev_replicate_offset = 0;
Offset_t prev_string_offset = 0;
Offset_t current_new_offset = 0;
Offset prev_replicate_offset = 0;
Offset prev_string_offset = 0;
Offset current_new_offset = 0;
for (size_t i = 0; i < col_size; ++i)
{
@ -247,7 +247,7 @@ ColumnPtr ColumnString::replicate(const Offsets_t & replicate_offsets) const
prev_string_offset = offsets[i];
}
return res;
return std::move(res);
}

View File

@ -17,23 +17,25 @@ namespace DB
/** Column for String values.
*/
class ColumnString final : public IColumn
class ColumnString final : public COWPtrHelper<IColumn, ColumnString>
{
public:
using Chars_t = PaddedPODArray<UInt8>;
private:
friend class COWPtrHelper<IColumn, ColumnString>;
/// Maps i'th position to offset to i+1'th element. Last offset maps to the end of all chars (is the size of all chars).
Offsets_t offsets;
Offsets offsets;
/// Bytes of strings, placed contiguously.
/// For convenience, every string ends with terminating zero byte. Note that strings could contain zero bytes in the middle.
Chars_t chars;
size_t __attribute__((__always_inline__)) offsetAt(size_t i) const { return i == 0 ? 0 : offsets[i - 1]; }
size_t ALWAYS_INLINE offsetAt(size_t i) const { return i == 0 ? 0 : offsets[i - 1]; }
/// Size of i-th element, including terminating zero.
size_t __attribute__((__always_inline__)) sizeAt(size_t i) const { return i == 0 ? offsets[0] : (offsets[i] - offsets[i - 1]); }
size_t ALWAYS_INLINE sizeAt(size_t i) const { return i == 0 ? offsets[0] : (offsets[i] - offsets[i - 1]); }
template <bool positive>
struct less;
@ -41,6 +43,12 @@ private:
template <bool positive>
struct lessWithCollation;
ColumnString() = default;
ColumnString(const ColumnString & src)
: offsets(src.offsets.begin(), src.offsets.end()),
chars(src.chars.begin(), src.chars.end()) {};
public:
const char * getFamilyName() const override { return "String"; }
@ -59,7 +67,7 @@ public:
return chars.allocated_bytes() + offsets.allocated_bytes();
}
ColumnPtr cloneResized(size_t to_size) const override;
MutableColumnPtr cloneResized(size_t to_size) const override;
Field operator[](size_t n) const override
{
@ -198,9 +206,9 @@ public:
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
void insertDefault() override
{
@ -231,9 +239,9 @@ public:
/// Sorting with respect of collation.
void getPermutationWithCollation(const Collator & collator, bool reverse, size_t limit, Permutation & res) const;
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
MutableColumnPtr replicate(const Offsets & replicate_offsets) const override;
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override
{
return scatterImpl<ColumnString>(num_columns, selector);
}
@ -251,8 +259,8 @@ public:
Chars_t & getChars() { return chars; }
const Chars_t & getChars() const { return chars; }
Offsets_t & getOffsets() { return offsets; }
const Offsets_t & getOffsets() const { return offsets; }
Offsets & getOffsets() { return offsets; }
const Offsets & getOffsets() const { return offsets; }
};

View File

@ -38,14 +38,14 @@ ColumnTuple::ColumnTuple(const Columns & columns) : columns(columns)
throw Exception{"ColumnTuple cannot have ColumnConst as its element", ErrorCodes::ILLEGAL_COLUMN};
}
ColumnPtr ColumnTuple::cloneEmpty() const
MutableColumnPtr ColumnTuple::cloneEmpty() const
{
const size_t tuple_size = columns.size();
Columns new_columns(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
new_columns[i] = columns[i]->cloneEmpty();
return std::make_shared<ColumnTuple>(new_columns);
return ColumnTuple::create(new_columns);
}
Field ColumnTuple::operator[](size_t n) const
@ -81,7 +81,7 @@ void ColumnTuple::insert(const Field & x)
throw Exception("Cannot insert value of different size into tuple", ErrorCodes::CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE);
for (size_t i = 0; i < tuple_size; ++i)
columns[i]->insert(tuple[i]);
columns[i]->assumeMutable()->insert(tuple[i]);
}
void ColumnTuple::insertFrom(const IColumn & src_, size_t n)
@ -93,19 +93,19 @@ void ColumnTuple::insertFrom(const IColumn & src_, size_t n)
throw Exception("Cannot insert value of different size into tuple", ErrorCodes::CANNOT_INSERT_VALUE_OF_DIFFERENT_SIZE_INTO_TUPLE);
for (size_t i = 0; i < tuple_size; ++i)
columns[i]->insertFrom(*src.columns[i], n);
columns[i]->assumeMutable()->insertFrom(*src.columns[i], n);
}
void ColumnTuple::insertDefault()
{
for (auto & column : columns)
column->insertDefault();
column->assumeMutable()->insertDefault();
}
void ColumnTuple::popBack(size_t n)
{
for (auto & column : columns)
column->popBack(n);
column->assumeMutable()->popBack(n);
}
StringRef ColumnTuple::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
@ -120,7 +120,7 @@ StringRef ColumnTuple::serializeValueIntoArena(size_t n, Arena & arena, char con
const char * ColumnTuple::deserializeAndInsertFromArena(const char * pos)
{
for (auto & column : columns)
pos = column->deserializeAndInsertFromArena(pos);
pos = column->assumeMutable()->deserializeAndInsertFromArena(pos);
return pos;
}
@ -135,12 +135,12 @@ void ColumnTuple::insertRangeFrom(const IColumn & src, size_t start, size_t leng
{
const size_t tuple_size = columns.size();
for (size_t i = 0; i < tuple_size; ++i)
columns[i]->insertRangeFrom(
columns[i]->assumeMutable()->insertRangeFrom(
*static_cast<const ColumnTuple &>(src).columns[i],
start, length);
}
ColumnPtr ColumnTuple::filter(const Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnTuple::filter(const Filter & filt, ssize_t result_size_hint) const
{
const size_t tuple_size = columns.size();
Columns new_columns(tuple_size);
@ -148,10 +148,10 @@ ColumnPtr ColumnTuple::filter(const Filter & filt, ssize_t result_size_hint) con
for (size_t i = 0; i < tuple_size; ++i)
new_columns[i] = columns[i]->filter(filt, result_size_hint);
return std::make_shared<ColumnTuple>(new_columns);
return ColumnTuple::create(new_columns);
}
ColumnPtr ColumnTuple::permute(const Permutation & perm, size_t limit) const
MutableColumnPtr ColumnTuple::permute(const Permutation & perm, size_t limit) const
{
const size_t tuple_size = columns.size();
Columns new_columns(tuple_size);
@ -159,10 +159,10 @@ ColumnPtr ColumnTuple::permute(const Permutation & perm, size_t limit) const
for (size_t i = 0; i < tuple_size; ++i)
new_columns[i] = columns[i]->permute(perm, limit);
return std::make_shared<ColumnTuple>(new_columns);
return ColumnTuple::create(new_columns);
}
ColumnPtr ColumnTuple::replicate(const Offsets_t & offsets) const
MutableColumnPtr ColumnTuple::replicate(const Offsets & offsets) const
{
const size_t tuple_size = columns.size();
Columns new_columns(tuple_size);
@ -170,25 +170,25 @@ ColumnPtr ColumnTuple::replicate(const Offsets_t & offsets) const
for (size_t i = 0; i < tuple_size; ++i)
new_columns[i] = columns[i]->replicate(offsets);
return std::make_shared<ColumnTuple>(new_columns);
return ColumnTuple::create(new_columns);
}
Columns ColumnTuple::scatter(ColumnIndex num_columns, const Selector & selector) const
MutableColumns ColumnTuple::scatter(ColumnIndex num_columns, const Selector & selector) const
{
const size_t tuple_size = columns.size();
std::vector<Columns> scattered_tuple_elements(tuple_size);
std::vector<MutableColumns> scattered_tuple_elements(tuple_size);
for (size_t tuple_element_idx = 0; tuple_element_idx < tuple_size; ++tuple_element_idx)
scattered_tuple_elements[tuple_element_idx] = columns[tuple_element_idx]->scatter(num_columns, selector);
Columns res(num_columns);
MutableColumns res(num_columns);
for (size_t scattered_idx = 0; scattered_idx < num_columns; ++scattered_idx)
{
Columns new_columns(tuple_size);
for (size_t tuple_element_idx = 0; tuple_element_idx < tuple_size; ++tuple_element_idx)
new_columns[tuple_element_idx] = scattered_tuple_elements[tuple_element_idx][scattered_idx];
res[scattered_idx] = std::make_shared<ColumnTuple>(new_columns);
new_columns[tuple_element_idx] = std::move(scattered_tuple_elements[tuple_element_idx][scattered_idx]);
res[scattered_idx] = ColumnTuple::create(new_columns);
}
return res;
@ -207,7 +207,7 @@ int ColumnTuple::compareAt(size_t n, size_t m, const IColumn & rhs, int nan_dire
template <bool positive>
struct ColumnTuple::Less
{
ConstColumnPlainPtrs plain_columns;
ColumnRawPtrs plain_columns;
int nan_direction_hint;
Less(const Columns & columns, int nan_direction_hint_)
@ -219,7 +219,7 @@ struct ColumnTuple::Less
bool operator() (size_t a, size_t b) const
{
for (ConstColumnPlainPtrs::const_iterator it = plain_columns.begin(); it != plain_columns.end(); ++it)
for (ColumnRawPtrs::const_iterator it = plain_columns.begin(); it != plain_columns.end(); ++it)
{
int res = (*it)->compareAt(a, b, **it, nan_direction_hint);
if (res < 0)
@ -264,8 +264,9 @@ void ColumnTuple::gather(ColumnGathererStream & gatherer)
void ColumnTuple::reserve(size_t n)
{
for (auto & column : columns)
column->reserve(n);
const size_t tuple_size = columns.size();
for (size_t i = 0; i < tuple_size; ++i)
getColumn(i).reserve(n);
}
size_t ColumnTuple::byteSize() const

View File

@ -12,21 +12,24 @@ namespace DB
* Mixed constant/non-constant columns is prohibited in tuple
* for implementation simplicity.
*/
class ColumnTuple final : public IColumn
class ColumnTuple final : public COWPtrHelper<IColumn, ColumnTuple>
{
private:
friend class COWPtrHelper<IColumn, ColumnTuple>;
Columns columns;
template <bool positive>
struct Less;
public:
ColumnTuple(const Columns & columns);
ColumnTuple(const ColumnTuple &) = default;
public:
std::string getName() const override;
const char * getFamilyName() const override { return "Tuple"; }
ColumnPtr cloneEmpty() const override;
MutableColumnPtr cloneEmpty() const override;
size_t size() const override
{
@ -46,10 +49,10 @@ public:
const char * deserializeAndInsertFromArena(const char * pos) override;
void updateHashWithValue(size_t n, SipHash & hash) const override;
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
ColumnPtr replicate(const Offsets_t & offsets) const override;
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override;
MutableColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override;
MutableColumnPtr replicate(const Offsets & offsets) const override;
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override;
void gather(ColumnGathererStream & gatherer_stream) override;
int compareAt(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint) const override;
void getExtremes(Field & min, Field & max) const override;
@ -59,8 +62,16 @@ public:
size_t allocatedBytes() const override;
void forEachSubcolumn(ColumnCallback callback) override;
size_t tupleSize() const { return columns.size(); }
const IColumn & getColumn(size_t idx) const { return *columns[idx]; }
IColumn & getColumn(size_t idx) { return *columns[idx]->assumeMutable(); }
const Columns & getColumns() const { return columns; }
Columns & getColumns() { return columns; }
const ColumnPtr & getColumnPtr(size_t idx) const { return columns[idx]; }
//ColumnPtr & getColumnPtr(size_t idx) { return columns[idx]; }
//MutableColumnPtr getColumnMutablePtr(size_t idx) { return columns[idx]->assumeMutable(); }
};

View File

@ -70,7 +70,7 @@ struct ColumnVector<T>::greater
};
template <typename T>
void ColumnVector<T>::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
void ColumnVector<T>::getPermutation(bool reverse, size_t limit, int nan_direction_hint, IColumn::Permutation & res) const
{
size_t s = data.size();
res.resize(s);
@ -103,13 +103,13 @@ const char * ColumnVector<T>::getFamilyName() const
}
template <typename T>
ColumnPtr ColumnVector<T>::cloneResized(size_t size) const
MutableColumnPtr ColumnVector<T>::cloneResized(size_t size) const
{
ColumnPtr new_col_holder = std::make_shared<Self>();
auto res = this->create();
if (size > 0)
{
auto & new_col = static_cast<Self &>(*new_col_holder);
auto & new_col = static_cast<Self &>(*res);
new_col.data.resize(size);
size_t count = std::min(this->size(), size);
@ -119,7 +119,7 @@ ColumnPtr ColumnVector<T>::cloneResized(size_t size) const
memset(&new_col.data[count], static_cast<int>(value_type()), size - count);
}
return new_col_holder;
return std::move(res);
}
template <typename T>
@ -146,14 +146,14 @@ void ColumnVector<T>::insertRangeFrom(const IColumn & src, size_t start, size_t
}
template <typename T>
ColumnPtr ColumnVector<T>::filter(const IColumn::Filter & filt, ssize_t result_size_hint) const
MutableColumnPtr ColumnVector<T>::filter(const IColumn::Filter & filt, ssize_t result_size_hint) const
{
size_t size = data.size();
if (size != filt.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<Self> res = std::make_shared<Self>();
typename Self::Container_t & res_data = res->getData();
auto res = this->create();
Container & res_data = res->getData();
if (result_size_hint)
res_data.reserve(result_size_hint > 0 ? result_size_hint : size);
@ -206,11 +206,11 @@ ColumnPtr ColumnVector<T>::filter(const IColumn::Filter & filt, ssize_t result_s
++data_pos;
}
return res;
return std::move(res);
}
template <typename T>
ColumnPtr ColumnVector<T>::permute(const IColumn::Permutation & perm, size_t limit) const
MutableColumnPtr ColumnVector<T>::permute(const IColumn::Permutation & perm, size_t limit) const
{
size_t size = data.size();
@ -222,29 +222,29 @@ ColumnPtr ColumnVector<T>::permute(const IColumn::Permutation & perm, size_t lim
if (perm.size() < limit)
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
std::shared_ptr<Self> res = std::make_shared<Self>(limit);
typename Self::Container_t & res_data = res->getData();
auto res = this->create(limit);
typename Self::Container & res_data = res->getData();
for (size_t i = 0; i < limit; ++i)
res_data[i] = data[perm[i]];
return res;
return std::move(res);
}
template <typename T>
ColumnPtr ColumnVector<T>::replicate(const IColumn::Offsets_t & offsets) const
MutableColumnPtr ColumnVector<T>::replicate(const IColumn::Offsets & offsets) const
{
size_t size = data.size();
if (size != offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
if (0 == size)
return std::make_shared<Self>();
return this->create();
std::shared_ptr<Self> res = std::make_shared<Self>();
typename Self::Container_t & res_data = res->getData();
auto res = this->create();
typename Self::Container & res_data = res->getData();
res_data.reserve(offsets.back());
IColumn::Offset_t prev_offset = 0;
IColumn::Offset prev_offset = 0;
for (size_t i = 0; i < size; ++i)
{
size_t size_to_replicate = offsets[i] - prev_offset;
@ -254,7 +254,7 @@ ColumnPtr ColumnVector<T>::replicate(const IColumn::Offsets_t & offsets) const
res_data.push_back(data[i]);
}
return res;
return std::move(res);
}
template <typename T>

View File

@ -120,9 +120,11 @@ template <> inline UInt64 unionCastToUInt64(Float32 x)
/** A template for columns that use a simple array to store.
*/
template <typename T>
class ColumnVector final : public IColumn
class ColumnVector final : public COWPtrHelper<IColumn, ColumnVector<T>>
{
private:
friend class COWPtrHelper<IColumn, ColumnVector<T>>;
using Self = ColumnVector<T>;
struct less;
@ -130,12 +132,18 @@ private:
public:
using value_type = T;
using Container_t = PaddedPODArray<value_type>;
using Container = PaddedPODArray<value_type>;
private:
ColumnVector() {}
ColumnVector(const size_t n) : data{n} {}
ColumnVector(const size_t n, const value_type x) : data{n, x} {}
ColumnVector(const size_t n) : data(n) {}
ColumnVector(const size_t n, const value_type x) : data(n, x) {}
ColumnVector(const ColumnVector & src) : data(src.data.begin(), src.data.end()) {};
/// Sugar constructor.
ColumnVector(std::initializer_list<T> il) : data{il} {}
public:
bool isNumeric() const override { return IsNumber<T>; }
size_t size() const override
@ -195,7 +203,7 @@ public:
return CompareHelper<T>::compare(data[n], static_cast<const Self &>(rhs_).data[m], nan_direction_hint);
}
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override;
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, IColumn::Permutation & res) const override;
void reserve(size_t n) override
{
@ -204,7 +212,7 @@ public:
const char * getFamilyName() const override;
ColumnPtr cloneResized(size_t size) const override;
MutableColumnPtr cloneResized(size_t size) const override;
Field operator[](size_t n) const override
{
@ -235,17 +243,17 @@ public:
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
ColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override;
MutableColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override;
ColumnPtr permute(const IColumn::Permutation & perm, size_t limit) const override;
MutableColumnPtr permute(const IColumn::Permutation & perm, size_t limit) const override;
ColumnPtr replicate(const IColumn::Offsets_t & offsets) const override;
MutableColumnPtr replicate(const IColumn::Offsets & offsets) const override;
void getExtremes(Field & min, Field & max) const override;
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
MutableColumns scatter(IColumn::ColumnIndex num_columns, const IColumn::Selector & selector) const override
{
return this->scatterImpl<Self>(num_columns, selector);
return this->template scatterImpl<Self>(num_columns, selector);
}
void gather(ColumnGathererStream & gatherer_stream) override;
@ -258,12 +266,12 @@ public:
/** More efficient methods of manipulation - to manipulate with data directly. */
Container_t & getData()
Container & getData()
{
return data;
}
const Container_t & getData() const
const Container & getData() const
{
return data;
}
@ -279,7 +287,7 @@ public:
}
protected:
Container_t data;
Container data;
};

View File

@ -100,10 +100,10 @@ namespace
struct ResultOffsetsBuilder
{
IColumn::Offsets_t & res_offsets;
IColumn::Offset_t current_src_offset = 0;
IColumn::Offsets & res_offsets;
IColumn::Offset current_src_offset = 0;
explicit ResultOffsetsBuilder(IColumn::Offsets_t * res_offsets_) : res_offsets(*res_offsets_) {}
explicit ResultOffsetsBuilder(IColumn::Offsets * res_offsets_) : res_offsets(*res_offsets_) {}
void reserve(ssize_t result_size_hint, size_t src_size)
{
@ -118,14 +118,14 @@ namespace
template <size_t SIMD_BYTES>
void insertChunk(
const IColumn::Offset_t * src_offsets_pos,
const IColumn::Offset * src_offsets_pos,
bool first,
IColumn::Offset_t chunk_offset,
IColumn::Offset chunk_offset,
size_t chunk_size)
{
const auto offsets_size_old = res_offsets.size();
res_offsets.resize(offsets_size_old + SIMD_BYTES);
memcpy(&res_offsets[offsets_size_old], src_offsets_pos, SIMD_BYTES * sizeof(IColumn::Offset_t));
memcpy(&res_offsets[offsets_size_old], src_offsets_pos, SIMD_BYTES * sizeof(IColumn::Offset));
if (!first)
{
@ -147,15 +147,15 @@ namespace
struct NoResultOffsetsBuilder
{
explicit NoResultOffsetsBuilder(IColumn::Offsets_t *) {}
explicit NoResultOffsetsBuilder(IColumn::Offsets *) {}
void reserve(ssize_t, size_t) {}
void insertOne(size_t) {}
template <size_t SIMD_BYTES>
void insertChunk(
const IColumn::Offset_t *,
const IColumn::Offset *,
bool,
IColumn::Offset_t,
IColumn::Offset,
size_t)
{
}
@ -164,8 +164,8 @@ namespace
template <typename T, typename ResultOffsetsBuilder>
void filterArraysImplGeneric(
const PaddedPODArray<T> & src_elems, const IColumn::Offsets_t & src_offsets,
PaddedPODArray<T> & res_elems, IColumn::Offsets_t * res_offsets,
const PaddedPODArray<T> & src_elems, const IColumn::Offsets & src_offsets,
PaddedPODArray<T> & res_elems, IColumn::Offsets * res_offsets,
const IColumn::Filter & filt, ssize_t result_size_hint)
{
const size_t size = src_offsets.size();
@ -191,7 +191,7 @@ namespace
const auto offsets_begin = offsets_pos;
/// copy array ending at *end_offset_ptr
const auto copy_array = [&] (const IColumn::Offset_t * offset_ptr)
const auto copy_array = [&] (const IColumn::Offset * offset_ptr)
{
const auto offset = offset_ptr == offsets_begin ? 0 : offset_ptr[-1];
const auto size = *offset_ptr - offset;
@ -259,8 +259,8 @@ namespace
template <typename T>
void filterArraysImpl(
const PaddedPODArray<T> & src_elems, const IColumn::Offsets_t & src_offsets,
PaddedPODArray<T> & res_elems, IColumn::Offsets_t & res_offsets,
const PaddedPODArray<T> & src_elems, const IColumn::Offsets & src_offsets,
PaddedPODArray<T> & res_elems, IColumn::Offsets & res_offsets,
const IColumn::Filter & filt, ssize_t result_size_hint)
{
return filterArraysImplGeneric<T, ResultOffsetsBuilder>(src_elems, src_offsets, res_elems, &res_offsets, filt, result_size_hint);
@ -268,7 +268,7 @@ void filterArraysImpl(
template <typename T>
void filterArraysImplOnlyData(
const PaddedPODArray<T> & src_elems, const IColumn::Offsets_t & src_offsets,
const PaddedPODArray<T> & src_elems, const IColumn::Offsets & src_offsets,
PaddedPODArray<T> & res_elems,
const IColumn::Filter & filt, ssize_t result_size_hint)
{
@ -279,11 +279,11 @@ void filterArraysImplOnlyData(
/// Explicit instantiations - not to place the implementation of the function above in the header file.
#define INSTANTIATE(TYPE) \
template void filterArraysImpl<TYPE>( \
const PaddedPODArray<TYPE> &, const IColumn::Offsets_t &, \
PaddedPODArray<TYPE> &, IColumn::Offsets_t &, \
const PaddedPODArray<TYPE> &, const IColumn::Offsets &, \
PaddedPODArray<TYPE> &, IColumn::Offsets &, \
const IColumn::Filter &, ssize_t); \
template void filterArraysImplOnlyData<TYPE>( \
const PaddedPODArray<TYPE> &, const IColumn::Offsets_t &, \
const PaddedPODArray<TYPE> &, const IColumn::Offsets &, \
PaddedPODArray<TYPE> &, \
const IColumn::Filter &, ssize_t);

View File

@ -18,14 +18,14 @@ bool memoryIsZero(const void * data, size_t size);
/// The general implementation of `filter` function for ColumnArray and ColumnString.
template <typename T>
void filterArraysImpl(
const PaddedPODArray<T> & src_elems, const IColumn::Offsets_t & src_offsets,
PaddedPODArray<T> & res_elems, IColumn::Offsets_t & res_offsets,
const PaddedPODArray<T> & src_elems, const IColumn::Offsets & src_offsets,
PaddedPODArray<T> & res_elems, IColumn::Offsets & res_offsets,
const IColumn::Filter & filt, ssize_t result_size_hint);
/// Same as above, but not fills res_offsets.
template <typename T>
void filterArraysImplOnlyData(
const PaddedPODArray<T> & src_elems, const IColumn::Offsets_t & src_offsets,
const PaddedPODArray<T> & src_elems, const IColumn::Offsets & src_offsets,
PaddedPODArray<T> & res_elems,
const IColumn::Filter & filt, ssize_t result_size_hint);

View File

@ -0,0 +1,70 @@
#include <Columns/FilterDescription.h>
#include <Common/typeid_cast.h>
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnNullable.h>
#include <Columns/ColumnConst.h>
namespace DB
{
namespace ErrorCodes
{
extern const int ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER;
}
ConstantFilterDescription::ConstantFilterDescription(const IColumn & column)
{
if (column.onlyNull())
{
always_false = true;
return;
}
if (column.isColumnConst())
{
if (static_cast<const ColumnConst &>(column).getValue<UInt8>())
always_true = true;
else
always_false = true;
return;
}
}
FilterDescription::FilterDescription(const IColumn & column)
{
if (const ColumnUInt8 * concrete_column = typeid_cast<const ColumnUInt8 *>(&column))
{
data = &concrete_column->getData();
return;
}
if (const ColumnNullable * nullable_column = typeid_cast<const ColumnNullable *>(&column))
{
MutableColumnPtr mutable_holder = nullable_column->getNestedColumn().mutate();
ColumnUInt8 * concrete_column = typeid_cast<ColumnUInt8 *>(mutable_holder.get());
if (!concrete_column)
throw Exception("Illegal type " + column.getName() + " of column for filter. Must be UInt8 or Nullable(UInt8).",
ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
const NullMap & null_map = nullable_column->getNullMapData();
IColumn::Filter & res = concrete_column->getData();
size_t size = res.size();
for (size_t i = 0; i < size; ++i)
res[i] = res[i] && !null_map[i];
data = &res;
data_holder = std::move(mutable_holder);
return;
}
throw Exception("Illegal type " + column.getName() + " of column for filter. Must be UInt8 or Nullable(UInt8) or Const variants of them.",
ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <Columns/IColumn.h>
namespace DB
{
/// Support methods for implementation of WHERE, PREWHERE and HAVING.
/// Analyze if the column for filter is constant thus filter is always false or always true.
struct ConstantFilterDescription
{
bool always_false = false;
bool always_true = false;
ConstantFilterDescription() {}
explicit ConstantFilterDescription(const IColumn & column);
};
/// Obtain a filter from non constant Column, that may have type: UInt8, Nullable(UInt8).
struct FilterDescription
{
const IColumn::Filter * data = nullptr; /// Pointer to filter when it is not always true or always false.
ColumnPtr data_holder; /// If new column was generated, it will be owned by holder.
explicit FilterDescription(const IColumn & column);
};
}

View File

@ -1,9 +1,7 @@
#pragma once
#include <memory>
#include <boost/noncopyable.hpp>
#include <Core/Field.h>
#include <Common/COWPtr.h>
#include <Common/PODArray.h>
#include <Common/Exception.h>
#include <common/StringRef.h>
@ -22,19 +20,21 @@ namespace ErrorCodes
extern const int SIZES_OF_COLUMNS_DOESNT_MATCH;
}
class IColumn;
using ColumnPtr = std::shared_ptr<IColumn>;
using Columns = std::vector<ColumnPtr>;
using ColumnPlainPtrs = std::vector<IColumn *>;
using ConstColumnPlainPtrs = std::vector<const IColumn *>;
class Arena;
class ColumnGathererStream;
/// Declares interface to store columns in memory.
class IColumn : private boost::noncopyable
class IColumn : public COWPtr<IColumn>
{
private:
friend class COWPtr<IColumn>;
/// Creates the same column with the same data.
/// This is internal method to use from COWPtr.
/// It performs shallow copy with copy-ctor and not useful from outside.
/// If you want to copy column for modification, look at 'mutate' method.
virtual MutablePtr clone() const = 0;
public:
/// Name of a Column. It is used in info messages.
virtual std::string getName() const { return getFamilyName(); };
@ -45,18 +45,15 @@ public:
/** If column isn't constant, returns nullptr (or itself).
* If column is constant, transforms constant to full column (if column type allows such tranform) and return it.
*/
virtual ColumnPtr convertToFullColumnIfConst() const { return {}; }
/// Creates the same column with the same data.
virtual ColumnPtr clone() const { return cut(0, size()); }
virtual MutablePtr convertToFullColumnIfConst() const { return {}; }
/// Creates empty column with the same type.
virtual ColumnPtr cloneEmpty() const { return cloneResized(0); }
virtual MutablePtr cloneEmpty() const { return cloneResized(0); }
/// Creates column with the same type and specified size.
/// If size is less current size, then data is cut.
/// If size is greater, than default values are appended.
virtual ColumnPtr cloneResized(size_t /*size*/) const { throw Exception("Cannot cloneResized() column " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
virtual MutablePtr cloneResized(size_t /*size*/) const { throw Exception("Cannot cloneResized() column " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
/// Returns number of values in column.
virtual size_t size() const = 0;
@ -107,9 +104,9 @@ public:
/// Removes all elements outside of specified range.
/// Is used in LIMIT operation, for example.
virtual ColumnPtr cut(size_t start, size_t length) const
virtual MutablePtr cut(size_t start, size_t length) const
{
ColumnPtr res = cloneEmpty();
MutablePtr res = cloneEmpty();
res->insertRangeFrom(*this, start, length);
return res;
}
@ -174,12 +171,12 @@ public:
* otherwise (i.e. < 0), makes reserve() using size of source column.
*/
using Filter = PaddedPODArray<UInt8>;
virtual ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const = 0;
virtual MutablePtr filter(const Filter & filt, ssize_t result_size_hint) const = 0;
/// Permutes elements using specified permutation. Is used in sortings.
/// limit - if it isn't 0, puts only first limit elements in the result.
using Permutation = PaddedPODArray<size_t>;
virtual ColumnPtr permute(const Permutation & perm, size_t limit) const = 0;
virtual MutablePtr permute(const Permutation & perm, size_t limit) const = 0;
/** Compares (*this)[n] and rhs[m].
* Returns negative number, 0, or positive number (*this)[n] is less, equal, greater than rhs[m] respectively.
@ -206,9 +203,9 @@ public:
* (i-th element should be copied offsets[i] - offsets[i - 1] times.)
* It is necessary in ARRAY JOIN operation.
*/
using Offset_t = UInt64;
using Offsets_t = PaddedPODArray<Offset_t>;
virtual ColumnPtr replicate(const Offsets_t & offsets) const = 0;
using Offset = UInt64;
using Offsets = PaddedPODArray<Offset>;
virtual MutablePtr replicate(const Offsets & offsets) const = 0;
/** Split column to smaller columns. Each value goes to column index, selected by corresponding element of 'selector'.
* Selector must contain values from 0 to num_columns - 1.
@ -216,7 +213,7 @@ public:
*/
using ColumnIndex = UInt64;
using Selector = PaddedPODArray<ColumnIndex>;
virtual Columns scatter(ColumnIndex num_columns, const Selector & selector) const = 0;
virtual std::vector<MutablePtr> scatter(ColumnIndex num_columns, const Selector & selector) const = 0;
/// Insert data from several other columns according to source mask (used in vertical merge).
/// For now it is a helper to de-virtualize calls to insert*() functions inside gather loop
@ -246,9 +243,18 @@ public:
/// If the column contains subcolumns (such as Array, Nullable, etc), do callback on them.
/// Shallow: doesn't do recursive calls; don't do call for itself.
using ColumnCallback = std::function<void(ColumnPtr&)>;
using ColumnCallback = std::function<void(Ptr&)>;
virtual void forEachSubcolumn(ColumnCallback) {}
MutablePtr mutate() const
{
MutablePtr res = COWPtr<IColumn>::mutate();
res->forEachSubcolumn([](Ptr & subcolumn) { subcolumn = subcolumn->mutate(); });
return res;
}
/** Some columns can contain another columns inside.
* So, we have a tree of columns. But not all combinations are possible.
* There are the following rules:
@ -318,7 +324,7 @@ protected:
/// Template is to devirtualize calls to insertFrom method.
/// In derived classes (that use final keyword), implement scatter method as call to scatterImpl.
template <typename Derived>
Columns scatterImpl(ColumnIndex num_columns, const Selector & selector) const
std::vector<MutablePtr> scatterImpl(ColumnIndex num_columns, const Selector & selector) const
{
size_t num_rows = size();
@ -327,7 +333,7 @@ protected:
"Size of selector: " + std::to_string(selector.size()) + " doesn't match size of column: " + std::to_string(num_rows),
ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
Columns columns(num_columns);
std::vector<MutablePtr> columns(num_columns);
for (auto & column : columns)
column = cloneEmpty();
@ -346,5 +352,12 @@ protected:
}
};
using ColumnPtr = IColumn::Ptr;
using MutableColumnPtr = IColumn::MutablePtr;
using Columns = std::vector<ColumnPtr>;
using MutableColumns = std::vector<MutableColumnPtr>;
using ColumnRawPtrs = std::vector<const IColumn *>;
//using MutableColumnRawPtrs = std::vector<IColumn *>;
}

View File

@ -21,11 +21,13 @@ namespace ErrorCodes
class IColumnDummy : public IColumn
{
public:
IColumnDummy() : s(0) {}
IColumnDummy(size_t s_) : s(s_) {}
virtual ColumnPtr cloneDummy(size_t s_) const = 0;
public:
virtual MutableColumnPtr cloneDummy(size_t s_) const = 0;
ColumnPtr cloneResized(size_t s_) const override { return cloneDummy(s_); }
MutableColumnPtr cloneResized(size_t s_) const override { return cloneDummy(s_); }
size_t size() const override { return s; }
void insertDefault() override { ++s; }
void popBack(size_t n) override { s -= n; }
@ -72,12 +74,12 @@ public:
s += length;
}
ColumnPtr filter(const Filter & filt, ssize_t /*result_size_hint*/) const override
MutableColumnPtr filter(const Filter & filt, ssize_t /*result_size_hint*/) const override
{
return cloneDummy(countBytesInFilter(filt));
}
ColumnPtr permute(const Permutation & perm, size_t limit) const override
MutableColumnPtr permute(const Permutation & perm, size_t limit) const override
{
if (s != perm.size())
throw Exception("Size of permutation doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
@ -92,7 +94,7 @@ public:
res[i] = i;
}
ColumnPtr replicate(const Offsets_t & offsets) const override
MutableColumnPtr replicate(const Offsets & offsets) const override
{
if (s != offsets.size())
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
@ -100,7 +102,7 @@ public:
return cloneDummy(s == 0 ? 0 : offsets.back());
}
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override
{
if (s != selector.size())
throw Exception("Size of selector doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
@ -109,7 +111,7 @@ public:
for (auto idx : selector)
++counts[idx];
Columns res(num_columns);
MutableColumns res(num_columns);
for (size_t i = 0; i < num_columns; ++i)
res[i] = cloneResized(counts[i]);
@ -135,7 +137,7 @@ public:
return true;
}
private:
protected:
size_t s;
};

240
dbms/src/Common/COWPtr.h Normal file
View File

@ -0,0 +1,240 @@
#pragma once
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
#include <initializer_list>
/** Copy-on-write shared ptr.
* Allows to work with shared immutable objects and sometimes unshare and mutate you own unique copy.
*
* Usage:
class Column : public COWPtr<Column>
{
private:
friend class COWPtr<Column>;
/// Leave all constructors in private section. They will be avaliable through 'create' method.
Column();
/// Provide 'clone' method. It can be virtual if you want polymorphic behaviour.
virtual Column * clone() const;
public:
/// Correctly use const qualifiers in your interface.
virtual ~IColumn() {}
};
* It will provide 'create' and 'mutate' methods.
* And 'Ptr' and 'MutablePtr' types.
* Ptr is refcounted pointer to immutable object.
* MutablePtr is refcounted noncopyable pointer to mutable object.
* MutablePtr can be assigned to Ptr through move assignment.
*
* 'create' method creates MutablePtr: you cannot share mutable objects.
* To share, move-assign to immutable pointer.
* 'mutate' method allows to create mutable noncopyable object from immutable object:
* either by cloning or by using directly, if it is not shared.
* These methods are thread-safe.
*
* Example:
*
/// Creating and assigning to immutable ptr.
Column::Ptr x = Column::create(1);
/// Sharing single immutable object in two ptrs.
Column::Ptr y = x;
/// Now x and y are shared.
/// Change value of x.
{
/// Creating mutable ptr. It can clone an object under the hood if it was shared.
Column::MutablePtr mutate_x = x->mutate();
/// Using non-const methods of an object.
mutate_x->set(2);
/// Assigning pointer 'x' to mutated object.
x = std::move(mutate_x);
}
/// Now x and y are unshared and have different values.
* Note. You may have heard that COW is bad practice.
* Actually it is, if your values are small or if copying is done implicitly.
* This is the case for string implementations.
*
* In contrast, COWPtr is intended for the cases when you need to share states of large objects,
* (when you usually will use std::shared_ptr) but you also want precise control over modification
* of this shared state.
*/
template <typename Derived>
class COWPtr : public boost::intrusive_ref_counter<Derived>
{
private:
Derived * derived() { return static_cast<Derived *>(this); }
const Derived * derived() const { return static_cast<const Derived *>(this); }
protected:
template <typename T>
class mutable_ptr : public boost::intrusive_ptr<T>
{
private:
using Base = boost::intrusive_ptr<T>;
template <typename> friend class COWPtr;
template <typename, typename> friend class COWPtrHelper;
explicit mutable_ptr(T * ptr) : Base(ptr) {}
public:
/// Copy: not possible.
mutable_ptr(const mutable_ptr &) = delete;
/// Move: ok.
mutable_ptr(mutable_ptr &&) = default;
mutable_ptr & operator=(mutable_ptr &&) = default;
/// Initializing from temporary of compatible type.
template <typename U>
mutable_ptr(mutable_ptr<U> && other) : Base(std::move(other)) {}
mutable_ptr() = default;
mutable_ptr(const std::nullptr_t *) {}
};
public:
using MutablePtr = mutable_ptr<Derived>;
protected:
template <typename T>
class immutable_ptr : public boost::intrusive_ptr<const T>
{
private:
using Base = boost::intrusive_ptr<const T>;
template <typename> friend class COWPtr;
template <typename, typename> friend class COWPtrHelper;
explicit immutable_ptr(const T * ptr) : Base(ptr) {}
public:
/// Copy from immutable ptr: ok.
immutable_ptr(const immutable_ptr &) = default;
immutable_ptr & operator=(const immutable_ptr &) = default;
template <typename U>
immutable_ptr(const immutable_ptr<U> & other) : Base(other) {}
/// Move: ok.
immutable_ptr(immutable_ptr &&) = default;
immutable_ptr & operator=(immutable_ptr &&) = default;
/// Initializing from temporary of compatible type.
template <typename U>
immutable_ptr(immutable_ptr<U> && other) : Base(std::move(other)) {}
/// Move from mutable ptr: ok.
template <typename U>
immutable_ptr(mutable_ptr<U> && other) : Base(std::move(other)) {}
/// Copy from mutable ptr: not possible.
template <typename U>
immutable_ptr(const mutable_ptr<U> &) = delete;
immutable_ptr() = default;
immutable_ptr(const std::nullptr_t *) {}
};
public:
using Ptr = immutable_ptr<Derived>;
template <typename... Args>
static MutablePtr create(Args &&... args) { return MutablePtr(new Derived(std::forward<Args>(args)...)); }
template <typename T>
static MutablePtr create(std::initializer_list<T> && arg) { return create(std::forward<std::initializer_list<T>>(arg)); }
public:
Ptr getPtr() const { return static_cast<Ptr>(derived()); }
MutablePtr getPtr() { return static_cast<MutablePtr>(derived()); }
MutablePtr mutate() const
{
if (this->use_count() > 1)
return derived()->clone();
else
return assumeMutable();
}
MutablePtr assumeMutable() const
{
return const_cast<COWPtr*>(this)->getPtr();
}
};
/** Helper class to support inheritance.
* Example:
*
* class IColumn : public COWPtr<IColumn>
* {
* friend class COWPtr<IColumn>;
* virtual MutablePtr clone() const = 0;
* virtual ~IColumn() {}
* };
*
* class ConcreteColumn : public COWPtrHelper<IColumn, ConcreteColumn>
* {
* friend class COWPtrHelper<IColumn, ConcreteColumn>;
* };
*
* Here is complete inheritance diagram:
*
* ConcreteColumn
* COWPtrHelper<IColumn, ConcreteColumn>
* IColumn
* CowPtr<IColumn>
* boost::intrusive_ref_counter<IColumn>
*/
template <typename Base, typename Derived>
class COWPtrHelper : public Base
{
private:
Derived * derived() { return static_cast<Derived *>(this); }
const Derived * derived() const { return static_cast<const Derived *>(this); }
public:
using Ptr = typename Base::template immutable_ptr<Derived>;
using MutablePtr = typename Base::template mutable_ptr<Derived>;
template <typename... Args>
static MutablePtr create(Args &&... args) { return MutablePtr(new Derived(std::forward<Args>(args)...)); }
template <typename T>
static MutablePtr create(std::initializer_list<T> && arg) { return create(std::forward<std::initializer_list<T>>(arg)); }
typename Base::MutablePtr clone() const override { return typename Base::MutablePtr(new Derived(*derived())); }
};
/** Compositions.
*
* Sometimes your objects contain another objects, and you have tree-like structure.
* And you want non-const methods of your object to also modify your subobjects.
*
* There are the following possible solutions:
*
* 1. Store subobjects as immutable ptrs. Call mutate method of subobjects inside non-const methods of your objects; modify them and assign back.
* Drawback: additional checks inside methods: CPU overhead on atomic ops.
*
* 2. Store subobjects as mutable ptrs. Subobjects cannot be shared in another objects.
* Drawback: it's not possible to share subobjects.
*
* 3. Store subobjects as immutable ptrs. Implement copy-constructor to do shallow copy.
* But reimplement 'mutate' method, so it will call 'mutate' of all subobjects (do deep mutate).
* It will guarantee, that mutable object have all subobjects unshared.
* From non-const method, you can modify subobjects with 'assumeMutable' method.
* Drawback: it's more complex than other solutions.
*/

View File

@ -197,7 +197,7 @@ public:
ExternalTableData data = getData(context);
/// Create table
NamesAndTypesListPtr columns = std::make_shared<NamesAndTypesList>(sample_block.getColumnsList());
NamesAndTypesListPtr columns = std::make_shared<NamesAndTypesList>(sample_block.getNamesAndTypesList());
StoragePtr storage = StorageMemory::create(data.second, columns, NamesAndTypesList{}, NamesAndTypesList{}, ColumnDefaults{});
storage->startup();
context.addExternalTable(data.second, storage);

View File

@ -166,6 +166,8 @@ public:
insert(from_begin, from_end);
}
PODArray(std::initializer_list<T> il) : PODArray(std::begin(il), std::end(il)) {}
~PODArray()
{
dealloc();

View File

@ -46,7 +46,7 @@ int main(int argc, char ** argv)
code = e.code;
}
std::cout << time(0) - time0 << "s: " << zkutil::ZooKeeper::error2string(code) << std::endl;
std::cout << time(nullptr) - time0 << "s: " << zkutil::ZooKeeper::error2string(code) << std::endl;
}
sleep(1);

View File

@ -65,3 +65,6 @@ target_link_libraries (integer_hash_tables_and_hashes clickhouse_common_io)
add_executable (allocator allocator.cpp)
target_link_libraries (allocator clickhouse_common_io)
add_executable (cow_columns cow_columns.cpp)
target_link_libraries (cow_columns clickhouse_common_io)

View File

@ -0,0 +1,86 @@
#include <Common/COWPtr.h>
#include <iostream>
class IColumn : public COWPtr<IColumn>
{
private:
friend class COWPtr<IColumn>;
virtual MutablePtr clone() const = 0;
public:
virtual ~IColumn() {}
virtual int get() const = 0;
virtual void set(int value) = 0;
virtual MutablePtr test() const = 0;
};
using ColumnPtr = IColumn::Ptr;
using MutableColumnPtr = IColumn::MutablePtr;
class ConcreteColumn : public COWPtrHelper<IColumn, ConcreteColumn>
{
private:
friend class COWPtrHelper<IColumn, ConcreteColumn>;
int data;
ConcreteColumn(int data) : data(data) {}
ConcreteColumn(const ConcreteColumn &) = default;
MutableColumnPtr test() const override
{
MutableColumnPtr res = create(123);
return res;
}
public:
int get() const override { return data; }
void set(int value) override { data = value; }
};
int main(int, char **)
{
ColumnPtr x = ConcreteColumn::create(1);
ColumnPtr y = x;//x->test();
std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n";
{
MutableColumnPtr mut = y->mutate();
mut->set(2);
std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << ", " << mut->use_count() << "\n";
std::cerr << "addresses: " << x.get() << ", " << y.get() << ", " << mut.get() << "\n";
y = std::move(mut);
}
std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n";
x = ConcreteColumn::create(0);
std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n";
{
MutableColumnPtr mut = y->mutate();
mut->set(3);
std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << ", " << mut->use_count() << "\n";
std::cerr << "addresses: " << x.get() << ", " << y.get() << ", " << mut.get() << "\n";
y = std::move(mut);
}
std::cerr << "values: " << x->get() << ", " << y->get() << "\n";
std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n";
return 0;
}

View File

@ -8,6 +8,7 @@
#include <Poco/Exception.h>
#include <Common/HashTable/Hash.h>
#include <Common/Stopwatch.h>
#include <Core/Defines.h>
#include "AvalancheTest.h" /// Taken from SMHasher.
@ -33,7 +34,7 @@ void setAffinity()
}
static inline __attribute__((__always_inline__)) UInt64 rdtsc()
static inline ALWAYS_INLINE UInt64 rdtsc()
{
#if __x86_64__
UInt32 a, d;

View File

@ -42,7 +42,7 @@ int main(int argc, char ** argv)
std::vector<Key> data(n);
// srand(time(0));
// srand(time(nullptr));
{
Stopwatch watch;

View File

@ -18,7 +18,6 @@ namespace ErrorCodes
extern const int POSITION_OUT_OF_BOUND;
extern const int NOT_FOUND_COLUMN_IN_BLOCK;
extern const int SIZES_OF_COLUMNS_DOESNT_MATCH;
extern const int SIZES_OF_ARRAYS_DOESNT_MATCH;
}
@ -300,6 +299,46 @@ Block Block::cloneEmpty() const
}
MutableColumns Block::cloneEmptyColumns() const
{
size_t num_columns = data.size();
MutableColumns columns(num_columns);
for (size_t i = 0; i < num_columns; ++i)
columns[i] = data[i].column ? data[i].column->cloneEmpty() : data[i].type->createColumn();
return columns;
}
MutableColumns Block::mutateColumns() const
{
size_t num_columns = data.size();
MutableColumns columns(num_columns);
for (size_t i = 0; i < num_columns; ++i)
columns[i] = data[i].column ? data[i].column->mutate() : data[i].type->createColumn();
return columns;
}
void Block::setColumns(MutableColumns && columns)
{
size_t num_columns = data.size();
for (size_t i = 0; i < num_columns; ++i)
data[i].column = std::move(columns[i]);
}
Block Block::cloneWithColumns(MutableColumns && columns) const
{
Block res;
size_t num_columns = data.size();
for (size_t i = 0; i < num_columns; ++i)
res.insert({ std::move(columns[i]), data[i].type, data[i].name });
return res;
}
Block Block::sortColumns() const
{
Block sorted_block;
@ -311,13 +350,13 @@ Block Block::sortColumns() const
}
ColumnsWithTypeAndName Block::getColumns() const
const ColumnsWithTypeAndName & Block::getColumnsWithTypeAndName() const
{
return data;
}
NamesAndTypesList Block::getColumnsList() const
NamesAndTypesList Block::getNamesAndTypesList() const
{
NamesAndTypesList res;
@ -328,6 +367,18 @@ NamesAndTypesList Block::getColumnsList() const
}
Names Block::getNames() const
{
Names res;
res.reserve(columns());
for (const auto & elem : data)
res.push_back(elem.name);
return res;
}
bool blocksHaveEqualStructure(const Block & lhs, const Block & rhs)
{
size_t columns = lhs.columns();
@ -428,31 +479,11 @@ void Block::swap(Block & other) noexcept
}
void Block::unshareColumns()
{
std::unordered_set<void*> pointers;
IColumn::ColumnCallback callback = [&](ColumnPtr & subcolumn)
{
if (!pointers.insert(subcolumn.get()).second)
subcolumn = subcolumn->clone();
subcolumn->forEachSubcolumn(callback);
};
for (auto & elem : data)
{
callback(elem.column);
elem.column->forEachSubcolumn(callback);
}
}
void Block::updateHash(SipHash & hash) const
{
for (size_t row_no = 0, num_rows = rows(); row_no < num_rows; ++row_no)
{
for (auto & col : getColumns())
for (const auto & col : data)
col.column->updateHashWithValue(row_no, hash);
}
}
}

View File

@ -76,8 +76,9 @@ public:
size_t getPositionByName(const std::string & name) const;
ColumnsWithTypeAndName getColumns() const;
NamesAndTypesList getColumnsList() const;
const ColumnsWithTypeAndName & getColumnsWithTypeAndName() const;
NamesAndTypesList getNamesAndTypesList() const;
Names getNames() const;
/// Returns number of rows from first column in block, not equal to nullptr. If no columns, returns 0.
size_t rows() const;
@ -105,19 +106,22 @@ public:
/** Get the same block, but empty. */
Block cloneEmpty() const;
/** Get empty columns with the same types as in block. */
MutableColumns cloneEmptyColumns() const;
/** Get columns from block for mutation. */
MutableColumns mutateColumns() const;
/** Replace columns in a block */
void setColumns(MutableColumns && columns);
Block cloneWithColumns(MutableColumns && columns) const;
/** Get a block with columns that have been rearranged in the order of their names. */
Block sortColumns() const;
void clear();
void swap(Block & other) noexcept;
/** Some column implementations (ColumnArray) may have shared parts between different columns
* (common array sizes of elements of nested data structures).
* Before doing mutating operations on such columns, you must unshare that parts.
* Also unsharing columns, if whole columns are shared_ptrs pointing to same instances.
*/
void unshareColumns();
/** Updates SipHash of the Block, using update method of columns.
* Returns hash for block, that could be used to differentiate blocks
* with same structure, but different data.

View File

@ -11,8 +11,7 @@ ColumnWithTypeAndName ColumnWithTypeAndName::cloneEmpty() const
ColumnWithTypeAndName res;
res.name = name;
if (type)
res.type = type->clone();
res.type = type;
if (column)
res.column = column->cloneEmpty();

View File

@ -8,6 +8,7 @@
#include <Common/Exception.h>
#include <Common/UInt128.h>
#include <Core/Types.h>
#include <Core/Defines.h>
#include <common/strong_typedef.h>
@ -197,14 +198,14 @@ public:
template <typename T> T & get()
{
using TWithoutRef = typename std::remove_reference<T>::type;
TWithoutRef * __attribute__((__may_alias__)) ptr = reinterpret_cast<TWithoutRef*>(storage);
TWithoutRef * __attribute__((__may_alias__)) ptr = reinterpret_cast<TWithoutRef*>(&storage);
return *ptr;
};
template <typename T> const T & get() const
{
using TWithoutRef = typename std::remove_reference<T>::type;
const TWithoutRef * __attribute__((__may_alias__)) ptr = reinterpret_cast<const TWithoutRef*>(storage);
const TWithoutRef * __attribute__((__may_alias__)) ptr = reinterpret_cast<const TWithoutRef*>(&storage);
return *ptr;
};
@ -327,11 +328,10 @@ public:
}
private:
static const size_t storage_size = std::max({
DBMS_MIN_FIELD_SIZE - sizeof(Types::Which),
sizeof(Null), sizeof(UInt64), sizeof(UInt128), sizeof(Int64), sizeof(Float64), sizeof(String), sizeof(Array), sizeof(Tuple)});
std::aligned_union<DBMS_MIN_FIELD_SIZE - sizeof(Types::Which),
Null, UInt64, UInt128, Int64, Float64, String, Array, Tuple
>::type storage;
char storage[storage_size] __attribute__((aligned(8)));
Types::Which which;
@ -340,7 +340,7 @@ private:
void createConcrete(T && x)
{
using JustT = typename std::decay<T>::type;
JustT * __attribute__((__may_alias__)) ptr = reinterpret_cast<JustT *>(storage);
JustT * __attribute__((__may_alias__)) ptr = reinterpret_cast<JustT *>(&storage);
new (ptr) JustT(std::forward<T>(x));
which = TypeToEnum<JustT>::value;
}
@ -350,7 +350,7 @@ private:
void assignConcrete(T && x)
{
using JustT = typename std::decay<T>::type;
JustT * __attribute__((__may_alias__)) ptr = reinterpret_cast<JustT *>(storage);
JustT * __attribute__((__may_alias__)) ptr = reinterpret_cast<JustT *>(&storage);
*ptr = std::forward<T>(x);
}
@ -398,7 +398,7 @@ private:
void create(const char * data, size_t size)
{
String * __attribute__((__may_alias__)) ptr = reinterpret_cast<String*>(storage);
String * __attribute__((__may_alias__)) ptr = reinterpret_cast<String*>(&storage);
new (ptr) String(data, size);
which = Types::String;
}
@ -408,7 +408,7 @@ private:
create(reinterpret_cast<const char *>(data), size);
}
__attribute__((__always_inline__)) void destroy()
ALWAYS_INLINE void destroy()
{
if (which < Types::MIN_NON_POD)
return;
@ -434,7 +434,7 @@ private:
template <typename T>
void destroy()
{
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(storage);
T * __attribute__((__may_alias__)) ptr = reinterpret_cast<T*>(&storage);
ptr->~T();
}
};

View File

@ -16,8 +16,8 @@ namespace DB
*/
struct SortCursorImpl
{
ConstColumnPlainPtrs all_columns;
ConstColumnPlainPtrs sort_columns;
ColumnRawPtrs all_columns;
ColumnRawPtrs sort_columns;
SortDescription desc;
size_t sort_columns_size = 0;
size_t pos = 0;

View File

@ -33,7 +33,7 @@ std::ostream & operator<<(std::ostream & stream, const DB::NameAndTypePair & wha
std::ostream & operator<<(std::ostream & stream, const DB::IDataType & what)
{
stream << "IDataType(name = " << what.getName() << ", default = " << what.getDefault();
stream << "IDataType(name = " << what.getName() << ", default = " << what.getDefault() << ")";
return stream;
}
@ -62,22 +62,39 @@ std::ostream & operator<<(std::ostream & stream, const DB::IFunction & what)
std::ostream & operator<<(std::ostream & stream, const DB::Block & what)
{
stream << "Block("
<< "size = " << what.getColumns().size()
<< "size = " << what.columns()
<< "){" << what.dumpStructure() << "}";
return stream;
}
#include <Common/COWPtr.h>
template <typename T>
std::ostream & printCOWPtr(std::ostream & stream, const typename COWPtr<T>::Ptr & what)
{
stream << "COWPtr::Ptr(" << what.get();
if (what)
stream << ", use_count = " << what->use_count();
stream << ") {";
if (what)
stream << *what;
else
stream << "nullptr";
stream << "}";
return stream;
}
std::ostream & operator<<(std::ostream & stream, const DB::ColumnWithTypeAndName & what)
{
stream << "ColumnWithTypeAndName(name = " << what.name << ", type = " << what.type << ", column = " << what.column << ")";
return stream;
stream << "ColumnWithTypeAndName(name = " << what.name << ", type = " << what.type << ", column = ";
return printCOWPtr<DB::IColumn>(stream, what.column) << ")";
}
std::ostream & operator<<(std::ostream & stream, const DB::IColumn & what)
{
stream << "IColumn(name = " << what.getName()
// TODO: maybe many flags here
<< ")";
stream << "IColumn(" << what.dumpStructure() << ")";
return stream;
}
@ -116,7 +133,7 @@ std::ostream & operator<<(std::ostream & stream, const DB::IAST & what)
std::ostream & operator<<(std::ostream & stream, const DB::ExpressionAnalyzer & what)
{
stream << "ExpressionAnalyzer{"
<< "hasAggregation="<<what.hasAggregation()
<< "hasAggregation=" << what.hasAggregation()
<< ", RequiredColumns=" << what.getRequiredColumns()
<< ", SubqueriesForSet=" << what.getSubqueriesForSets()
<< ", ExternalTables=" << what.getExternalTables()

View File

@ -249,7 +249,7 @@ struct Factory3 : IFactory
int main(int, char **)
{
srand(time(0));
srand(time(nullptr));
std::cerr << "f1: " << f1().data << std::endl;
std::cerr << "f2: " << f2().data << std::endl;

View File

@ -41,7 +41,7 @@ void AddingDefaultBlockOutputStream::write(const DB::Block & block)
/// If for some reason there are different offset columns for one nested structure, then we take nonempty.
if (!offsets_column || offsets_column->empty())
offsets_column = array->getOffsetsColumn();
offsets_column = array->getOffsetsPtr();
}
}
@ -61,15 +61,15 @@ void AddingDefaultBlockOutputStream::write(const DB::Block & block)
DataTypePtr nested_type = typeid_cast<const DataTypeArray &>(*column_to_add.type).getNestedType();
UInt64 nested_rows = rows ? get<UInt64>((*offsets_column)[rows - 1]) : 0;
ColumnPtr nested_column = nested_type->createColumnConst(nested_rows, nested_type->getDefault())->convertToFullColumnIfConst();
column_to_add.column = std::make_shared<ColumnArray>(nested_column, offsets_column);
ColumnPtr nested_column = nested_type->createColumnConstWithDefaultValue(nested_rows)->convertToFullColumnIfConst();
column_to_add.column = ColumnArray::create(nested_column, offsets_column);
}
else
{
/** It is necessary to turn a constant column into a full column, since in part of blocks (from other parts),
* it can be full (or the interpreter may decide that it is constant everywhere).
*/
column_to_add.column = column_to_add.type->createColumnConst(rows, column_to_add.type->getDefault())->convertToFullColumnIfConst();
column_to_add.column = column_to_add.type->createColumnConstWithDefaultValue(rows)->convertToFullColumnIfConst();
}
res.insert(std::move(column_to_add));

View File

@ -6,6 +6,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
Block AggregatingSortedBlockInputStream::readImpl()
{
@ -15,10 +20,14 @@ Block AggregatingSortedBlockInputStream::readImpl()
if (children.size() == 1)
return children[0]->read();
Block merged_block;
ColumnPlainPtrs merged_columns;
Block header;
MutableColumns merged_columns;
init(header, merged_columns);
if (has_collation)
throw Exception("Logical error: " + getName() + " does not support collations", ErrorCodes::LOGICAL_ERROR);
init(merged_block, merged_columns);
if (merged_columns.empty())
return Block();
@ -30,7 +39,7 @@ Block AggregatingSortedBlockInputStream::readImpl()
/// Fill in the column numbers that need to be aggregated.
for (size_t i = 0; i < num_columns; ++i)
{
ColumnWithTypeAndName & column = merged_block.safeGetByPosition(i);
ColumnWithTypeAndName & column = header.safeGetByPosition(i);
/// We leave only states of aggregate functions.
if (!startsWith(column.type->getName(), "AggregateFunction"))
@ -57,26 +66,21 @@ Block AggregatingSortedBlockInputStream::readImpl()
columns_to_aggregate.resize(column_numbers_to_aggregate.size());
for (size_t i = 0, size = columns_to_aggregate.size(); i < size; ++i)
columns_to_aggregate[i] = typeid_cast<ColumnAggregateFunction *>(merged_columns[column_numbers_to_aggregate[i]]);
columns_to_aggregate[i] = typeid_cast<ColumnAggregateFunction *>(merged_columns[column_numbers_to_aggregate[i]].get());
if (has_collation)
merge(merged_columns, queue_with_collation);
else
merge(merged_columns, queue);
return merged_block;
merge(merged_columns, queue);
return header.cloneWithColumns(std::move(merged_columns));
}
template <typename TSortCursor>
void AggregatingSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue)
void AggregatingSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue)
{
size_t merged_rows = 0;
/// We take the rows in the correct order and put them in `merged_block`, while the rows are no more than `max_block_size`
while (!queue.empty())
{
TSortCursor current = queue.top();
SortCursor current = queue.top();
setPrimaryKeyRef(next_key, current);
@ -133,8 +137,7 @@ void AggregatingSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns,
}
template <typename TSortCursor>
void AggregatingSortedBlockInputStream::addRow(TSortCursor & cursor)
void AggregatingSortedBlockInputStream::addRow(SortCursor & cursor)
{
for (size_t i = 0, size = column_numbers_to_aggregate.size(); i < size; ++i)
{

View File

@ -70,13 +70,11 @@ private:
/** We support two different cursors - with Collation and without.
* Templates are used instead of polymorphic SortCursor and calls to virtual functions.
*/
template <typename TSortCursor>
void merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue);
void merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue);
/** Extract all states of aggregate functions and merge them with the current group.
*/
template <typename TSortCursor>
void addRow(TSortCursor & cursor);
void addRow(SortCursor & cursor);
};
}

View File

@ -6,20 +6,20 @@
namespace DB
{
BinaryRowInputStream::BinaryRowInputStream(ReadBuffer & istr_)
: istr(istr_)
BinaryRowInputStream::BinaryRowInputStream(ReadBuffer & istr_, const Block & header_)
: istr(istr_), header(header_)
{
}
bool BinaryRowInputStream::read(Block & block)
bool BinaryRowInputStream::read(MutableColumns & columns)
{
if (istr.eof())
return false;
size_t columns = block.columns();
for (size_t i = 0; i < columns; ++i)
block.getByPosition(i).type->deserializeBinary(*block.getByPosition(i).column.get(), istr);
size_t num_columns = columns.size();
for (size_t i = 0; i < num_columns; ++i)
header.getByPosition(i).type->deserializeBinary(*columns[i], istr);
return true;
}

View File

@ -15,12 +15,13 @@ class ReadBuffer;
class BinaryRowInputStream : public IRowInputStream
{
public:
BinaryRowInputStream(ReadBuffer & istr_);
BinaryRowInputStream(ReadBuffer & istr_, const Block & header_);
bool read(Block & block) override;
bool read(MutableColumns & columns) override;
private:
ReadBuffer & istr;
Block header;
};
}

View File

@ -43,7 +43,8 @@ static bool isParseError(int code)
Block BlockInputStreamFromRowInputStream::readImpl()
{
Block res = sample.cloneEmpty();
size_t num_columns = sample.columns();
MutableColumns columns = sample.cloneEmptyColumns();
try
{
@ -52,7 +53,7 @@ Block BlockInputStreamFromRowInputStream::readImpl()
try
{
++total_rows;
if (!row_input->read(res))
if (!row_input->read(columns))
break;
}
catch (Exception & e)
@ -87,14 +88,13 @@ Block BlockInputStreamFromRowInputStream::readImpl()
/// Truncate all columns in block to minimal size (remove values, that was appended to only part of columns).
size_t columns = res.columns();
size_t min_size = std::numeric_limits<size_t>::max();
for (size_t column_idx = 0; column_idx < columns; ++column_idx)
min_size = std::min(min_size, res.getByPosition(column_idx).column->size());
for (size_t column_idx = 0; column_idx < num_columns; ++column_idx)
min_size = std::min(min_size, columns[column_idx]->size());
for (size_t column_idx = 0; column_idx < columns; ++column_idx)
for (size_t column_idx = 0; column_idx < num_columns; ++column_idx)
{
auto & column = res.getByPosition(column_idx).column;
auto & column = columns[column_idx];
if (column->size() > min_size)
column->popBack(column->size() - min_size);
}
@ -120,10 +120,10 @@ Block BlockInputStreamFromRowInputStream::readImpl()
throw;
}
if (res.rows() == 0)
res.clear();
if (columns.empty() || columns[0]->empty())
return {};
return res;
return sample.cloneWithColumns(std::move(columns));
}
}

View File

@ -43,7 +43,7 @@ protected:
private:
RowInputStreamPtr row_input;
const Block sample;
Block sample;
size_t max_block_size;
UInt64 allow_errors_num;

View File

@ -15,13 +15,13 @@ namespace ErrorCodes
}
CSVRowInputStream::CSVRowInputStream(ReadBuffer & istr_, const Block & sample_, const char delimiter_, bool with_names_, bool with_types_)
: istr(istr_), sample(sample_), delimiter(delimiter_), with_names(with_names_), with_types(with_types_)
CSVRowInputStream::CSVRowInputStream(ReadBuffer & istr_, const Block & header_, const char delimiter_, bool with_names_, bool with_types_)
: istr(istr_), header(header_), delimiter(delimiter_), with_names(with_names_), with_types(with_types_)
{
size_t columns = sample.columns();
data_types.resize(columns);
for (size_t i = 0; i < columns; ++i)
data_types[i] = sample.safeGetByPosition(i).type;
size_t num_columns = header.columns();
data_types.resize(num_columns);
for (size_t i = 0; i < num_columns; ++i)
data_types[i] = header.safeGetByPosition(i).type;
}
@ -81,16 +81,16 @@ static inline void skipWhitespacesAndTabs(ReadBuffer & buf)
}
static void skipRow(ReadBuffer & istr, const char delimiter, size_t columns)
static void skipRow(ReadBuffer & istr, const char delimiter, size_t num_columns)
{
String tmp;
for (size_t i = 0; i < columns; ++i)
for (size_t i = 0; i < num_columns; ++i)
{
skipWhitespacesAndTabs(istr);
readCSVString(tmp, istr);
skipWhitespacesAndTabs(istr);
skipDelimiter(istr, delimiter, i + 1 == columns);
skipDelimiter(istr, delimiter, i + 1 == num_columns);
}
}
@ -101,18 +101,18 @@ void CSVRowInputStream::readPrefix()
/// so BOM at beginning of stream cannot be confused with BOM in first string value, and it is safe to skip it.
skipBOMIfExists(istr);
size_t columns = sample.columns();
size_t num_columns = data_types.size();
String tmp;
if (with_names)
skipRow(istr, delimiter, columns);
skipRow(istr, delimiter, num_columns);
if (with_types)
skipRow(istr, delimiter, columns);
skipRow(istr, delimiter, num_columns);
}
bool CSVRowInputStream::read(Block & block)
bool CSVRowInputStream::read(MutableColumns & columns)
{
if (istr.eof())
return false;
@ -124,7 +124,7 @@ bool CSVRowInputStream::read(Block & block)
for (size_t i = 0; i < size; ++i)
{
skipWhitespacesAndTabs(istr);
data_types[i]->deserializeTextCSV(*block.getByPosition(i).column.get(), istr, delimiter);
data_types[i]->deserializeTextCSV(*columns[i], istr, delimiter);
skipWhitespacesAndTabs(istr);
skipDelimiter(istr, delimiter, i + 1 == size);
@ -140,7 +140,8 @@ String CSVRowInputStream::getDiagnosticInfo()
return {};
WriteBufferFromOwnString out;
Block block = sample.cloneEmpty();
MutableColumns columns = header.cloneEmptyColumns();
/// It is possible to display detailed diagnostics only if the last and next to last rows are still in the read buffer.
size_t bytes_read_at_start_of_buffer = istr.count() - istr.offset();
@ -151,14 +152,14 @@ String CSVRowInputStream::getDiagnosticInfo()
}
size_t max_length_of_column_name = 0;
for (size_t i = 0; i < sample.columns(); ++i)
if (sample.safeGetByPosition(i).name.size() > max_length_of_column_name)
max_length_of_column_name = sample.safeGetByPosition(i).name.size();
for (size_t i = 0; i < header.columns(); ++i)
if (header.safeGetByPosition(i).name.size() > max_length_of_column_name)
max_length_of_column_name = header.safeGetByPosition(i).name.size();
size_t max_length_of_data_type_name = 0;
for (size_t i = 0; i < sample.columns(); ++i)
if (sample.safeGetByPosition(i).type->getName().size() > max_length_of_data_type_name)
max_length_of_data_type_name = sample.safeGetByPosition(i).type->getName().size();
for (size_t i = 0; i < header.columns(); ++i)
if (header.safeGetByPosition(i).type->getName().size() > max_length_of_data_type_name)
max_length_of_data_type_name = header.safeGetByPosition(i).type->getName().size();
/// Roll back the cursor to the beginning of the previous or current row and parse all over again. But now we derive detailed information.
@ -167,7 +168,7 @@ String CSVRowInputStream::getDiagnosticInfo()
istr.position() = pos_of_prev_row;
out << "\nRow " << (row_num - 1) << ":\n";
if (!parseRowAndPrintDiagnosticInfo(block, out, max_length_of_column_name, max_length_of_data_type_name))
if (!parseRowAndPrintDiagnosticInfo(columns, out, max_length_of_column_name, max_length_of_data_type_name))
return out.str();
}
else
@ -182,14 +183,14 @@ String CSVRowInputStream::getDiagnosticInfo()
}
out << "\nRow " << row_num << ":\n";
parseRowAndPrintDiagnosticInfo(block, out, max_length_of_column_name, max_length_of_data_type_name);
parseRowAndPrintDiagnosticInfo(columns, out, max_length_of_column_name, max_length_of_data_type_name);
out << "\n";
return out.str();
}
bool CSVRowInputStream::parseRowAndPrintDiagnosticInfo(Block & block,
bool CSVRowInputStream::parseRowAndPrintDiagnosticInfo(MutableColumns & columns,
WriteBuffer & out, size_t max_length_of_column_name, size_t max_length_of_data_type_name)
{
size_t size = data_types.size();
@ -202,7 +203,7 @@ bool CSVRowInputStream::parseRowAndPrintDiagnosticInfo(Block & block,
}
out << "Column " << i << ", " << std::string((i < 10 ? 2 : i < 100 ? 1 : 0), ' ')
<< "name: " << sample.safeGetByPosition(i).name << ", " << std::string(max_length_of_column_name - sample.safeGetByPosition(i).name.size(), ' ')
<< "name: " << header.safeGetByPosition(i).name << ", " << std::string(max_length_of_column_name - header.safeGetByPosition(i).name.size(), ' ')
<< "type: " << data_types[i]->getName() << ", " << std::string(max_length_of_data_type_name - data_types[i]->getName().size(), ' ');
BufferBase::Position prev_position = istr.position();
@ -213,7 +214,7 @@ bool CSVRowInputStream::parseRowAndPrintDiagnosticInfo(Block & block,
{
skipWhitespacesAndTabs(istr);
prev_position = istr.position();
data_types[i]->deserializeTextCSV(*block.safeGetByPosition(i).column, istr, delimiter);
data_types[i]->deserializeTextCSV(*columns[i], istr, delimiter);
curr_position = istr.position();
skipWhitespacesAndTabs(istr);
}

View File

@ -18,9 +18,9 @@ public:
/** with_names - in the first line the header with column names
* with_types - on the next line header with type names
*/
CSVRowInputStream(ReadBuffer & istr_, const Block & sample_, const char delimiter_, bool with_names_ = false, bool with_types_ = false);
CSVRowInputStream(ReadBuffer & istr_, const Block & header_, const char delimiter_, bool with_names_ = false, bool with_types_ = false);
bool read(Block & block) override;
bool read(MutableColumns & columns) override;
void readPrefix() override;
bool allowSyncAfterError() const override { return true; };
void syncAfterError() override;
@ -29,7 +29,7 @@ public:
private:
ReadBuffer & istr;
const Block sample;
Block header;
const char delimiter;
bool with_names;
bool with_types;
@ -48,7 +48,7 @@ private:
void updateDiagnosticInfo();
bool parseRowAndPrintDiagnosticInfo(Block & block,
bool parseRowAndPrintDiagnosticInfo(MutableColumns & columns,
WriteBuffer & out, size_t max_length_of_column_name, size_t max_length_of_data_type_name);
};

View File

@ -20,12 +20,12 @@ static String getSchemaPath(const String & schema_dir, const String & schema_fil
return schema_dir + escapeForFileName(schema_file) + ".capnp";
}
CapnProtoRowInputStream::NestedField split(const Block & sample, size_t i)
CapnProtoRowInputStream::NestedField split(const Block & header, size_t i)
{
CapnProtoRowInputStream::NestedField field = {{}, i};
// Remove leading dot in field definition, e.g. ".msg" -> "msg"
String name(sample.safeGetByPosition(i).name);
String name(header.safeGetByPosition(i).name);
if (name.size() > 0 && name[0] == '.')
name.erase(0, 1);
@ -91,7 +91,7 @@ void CapnProtoRowInputStream::createActions(const NestedFieldList & sortedFields
String last;
size_t level = 0;
capnp::StructSchema::Field parent;
for (const auto & field : sortedFields)
{
// Move to a different field in the same structure, keep parent
@ -115,8 +115,8 @@ void CapnProtoRowInputStream::createActions(const NestedFieldList & sortedFields
}
}
CapnProtoRowInputStream::CapnProtoRowInputStream(ReadBuffer & istr_, const Block & sample_, const String & schema_dir, const String & schema_file, const String & root_object)
: istr(istr_), sample(sample_), parser(std::make_shared<SchemaParser>())
CapnProtoRowInputStream::CapnProtoRowInputStream(ReadBuffer & istr_, const Block & header_, const String & schema_dir, const String & schema_file, const String & root_object)
: istr(istr_), header(header_), parser(std::make_shared<SchemaParser>())
{
// Parse the schema and fetch the root object
@ -129,9 +129,9 @@ CapnProtoRowInputStream::CapnProtoRowInputStream(ReadBuffer & istr_, const Block
* and the nesting level doesn't decrease to make traversal easier.
*/
NestedFieldList list;
size_t columns = sample.columns();
for (size_t i = 0; i < columns; ++i)
list.push_back(split(sample, i));
size_t num_columns = header.columns();
for (size_t i = 0; i < num_columns; ++i)
list.push_back(split(header, i));
// Reorder list to make sure we don't have to backtrack
std::sort(list.begin(), list.end(), [](const NestedField & a, const NestedField & b)
@ -145,7 +145,7 @@ CapnProtoRowInputStream::CapnProtoRowInputStream(ReadBuffer & istr_, const Block
}
bool CapnProtoRowInputStream::read(Block & block)
bool CapnProtoRowInputStream::read(MutableColumns & columns)
{
if (istr.eof())
return false;
@ -153,7 +153,7 @@ bool CapnProtoRowInputStream::read(Block & block)
// Read from underlying buffer directly
auto buf = istr.buffer();
auto base = reinterpret_cast<const capnp::word *>(istr.position());
// Check if there's enough bytes in the buffer to read the full message
kj::Array<capnp::word> heap_array;
auto array = kj::arrayPtr(base, buf.size() - istr.offset());
@ -174,9 +174,9 @@ bool CapnProtoRowInputStream::read(Block & block)
{
switch (action.type) {
case Action::READ: {
auto & col = block.getByPosition(action.column);
auto & col = columns[i];
Field value = convertNodeToField(stack.back().get(action.field));
col.column->insert(value);
col->insert(value);
break;
}
case Action::POP:

View File

@ -32,9 +32,9 @@ public:
* schema_file - location of the capnproto schema, e.g. "schema.canpn"
* root_object - name to the root object, e.g. "Message"
*/
CapnProtoRowInputStream(ReadBuffer & istr_, const Block & sample_, const String & schema_dir, const String & schema_file, const String & root_object);
CapnProtoRowInputStream(ReadBuffer & istr_, const Block & header_, const String & schema_dir, const String & schema_file, const String & root_object);
bool read(Block & block) override;
bool read(MutableColumns & columns) override;
private:
// Build a traversal plan from a sorted list of fields
@ -62,7 +62,7 @@ private:
using SchemaParser = DestructorCatcher<capnp::SchemaParser>;
ReadBuffer & istr;
const Block sample;
Block header;
std::shared_ptr<SchemaParser> parser;
capnp::StructSchema root;
std::vector<Action> actions;
@ -70,4 +70,4 @@ private:
}
#endif // USE_CAPNP
#endif // USE_CAPNP

View File

@ -96,7 +96,7 @@ private:
IColumn::Filter filter;
/// Point to `block`.
ConstColumnPlainPtrs sort_columns;
ColumnRawPtrs sort_columns;
const ColumnInt8 * sign_column;
/// When it reaches zero, the block can be outputted in response.

View File

@ -12,6 +12,7 @@ namespace DB
namespace ErrorCodes
{
extern const int INCORRECT_DATA;
extern const int LOGICAL_ERROR;
}
@ -39,14 +40,14 @@ void CollapsingSortedBlockInputStream::reportIncorrectData()
}
void CollapsingSortedBlockInputStream::insertRows(ColumnPlainPtrs & merged_columns, size_t & merged_rows, bool last_in_stream)
void CollapsingSortedBlockInputStream::insertRows(MutableColumns & merged_columns, size_t & merged_rows, bool last_in_stream)
{
if (count_positive == 0 && count_negative == 0)
return;
if (count_positive == count_negative && !last_is_positive)
{
/// If all the rows in the input streams collapsed, we still want to give at least one block in the result.
/// If all the rows in the input streams was collapsed, we still want to give at least one block in the result.
if (last_in_stream && merged_rows == 0 && !blocks_written)
{
LOG_INFO(log, "All rows collapsed");
@ -97,25 +98,29 @@ void CollapsingSortedBlockInputStream::insertRows(ColumnPlainPtrs & merged_colum
if (out_row_sources_buf)
out_row_sources_buf->write(
reinterpret_cast<const char *>(current_row_sources.data()),
current_row_sources.size() * sizeof(RowSourcePart));
reinterpret_cast<const char *>(current_row_sources.data()),
current_row_sources.size() * sizeof(RowSourcePart));
}
Block CollapsingSortedBlockInputStream::readImpl()
{
if (finished)
return Block();
return {};
if (children.size() == 1)
return children[0]->read();
Block merged_block;
ColumnPlainPtrs merged_columns;
Block header;
MutableColumns merged_columns;
init(header, merged_columns);
if (has_collation)
throw Exception("Logical error: " + getName() + " does not support collations", ErrorCodes::LOGICAL_ERROR);
init(merged_block, merged_columns);
if (merged_columns.empty())
return Block();
return {};
/// Additional initialization.
if (first_negative.empty())
@ -124,27 +129,22 @@ Block CollapsingSortedBlockInputStream::readImpl()
last_negative.columns.resize(num_columns);
last_positive.columns.resize(num_columns);
sign_column_number = merged_block.getPositionByName(sign_column);
sign_column_number = header.getPositionByName(sign_column);
}
if (has_collation)
merge(merged_columns, queue_with_collation);
else
merge(merged_columns, queue);
return merged_block;
merge(merged_columns, queue);
return header.cloneWithColumns(std::move(merged_columns));
}
template <typename TSortCursor>
void CollapsingSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue)
void CollapsingSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue)
{
size_t merged_rows = 0;
/// Take rows in correct order and put them into `merged_block` until the rows no more than `max_block_size`
/// Take rows in correct order and put them into `merged_columns` until the rows no more than `max_block_size`
for (; !queue.empty(); ++current_pos)
{
TSortCursor current = queue.top();
SortCursor current = queue.top();
if (current_key.empty())
{

View File

@ -90,11 +90,10 @@ private:
/** We support two different cursors - with Collation and without.
* Templates are used instead of polymorphic SortCursors and calls to virtual functions.
*/
template <typename TSortCursor>
void merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue);
void merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue);
/// Output to result rows for the current primary key.
void insertRows(ColumnPlainPtrs & merged_columns, size_t & merged_rows, bool last_in_stream = false);
void insertRows(MutableColumns & merged_columns, size_t & merged_rows, bool last_in_stream = false);
void reportIncorrectData();
};

View File

@ -65,7 +65,7 @@ void ColumnGathererStream::init()
if (i == 0)
{
column.name = name;
column.type = block.getByName(name).type->clone();
column.type = block.getByName(name).type;
column.column = column.type->createColumn();
}
@ -89,8 +89,12 @@ Block ColumnGathererStream::readImpl()
return Block();
output_block = Block{column.cloneEmpty()};
output_block.getByPosition(0).column->gather(*this);
return std::move(output_block);
MutableColumnPtr output_column = output_block.getByPosition(0).column->mutate();
output_column->gather(*this);
if (!output_column->empty())
output_block.getByPosition(0).column = std::move(output_column);
return output_block;
}

View File

@ -39,7 +39,7 @@ Block DistinctBlockInputStream::readImpl()
if (!block)
return Block();
const ConstColumnPlainPtrs column_ptrs(getKeyColumns(block));
const ColumnRawPtrs column_ptrs(getKeyColumns(block));
if (column_ptrs.empty())
return block;
@ -106,7 +106,7 @@ bool DistinctBlockInputStream::checkLimits() const
template <typename Method>
void DistinctBlockInputStream::buildFilter(
Method & method,
const ConstColumnPlainPtrs & columns,
const ColumnRawPtrs & columns,
IColumn::Filter & filter,
size_t rows,
SetVariants & variants) const
@ -132,11 +132,11 @@ void DistinctBlockInputStream::buildFilter(
}
}
ConstColumnPlainPtrs DistinctBlockInputStream::getKeyColumns(const Block & block) const
ColumnRawPtrs DistinctBlockInputStream::getKeyColumns(const Block & block) const
{
size_t columns = columns_names.empty() ? block.columns() : columns_names.size();
ConstColumnPlainPtrs column_ptrs;
ColumnRawPtrs column_ptrs;
column_ptrs.reserve(columns);
for (size_t i = 0; i < columns; ++i)

View File

@ -30,12 +30,12 @@ protected:
private:
bool checkLimits() const;
ConstColumnPlainPtrs getKeyColumns(const Block & block) const;
ColumnRawPtrs getKeyColumns(const Block & block) const;
template <typename Method>
void buildFilter(
Method & method,
const ConstColumnPlainPtrs & key_columns,
const ColumnRawPtrs & key_columns,
IColumn::Filter & filter,
size_t rows,
SetVariants & variants) const;

View File

@ -40,11 +40,11 @@ Block DistinctSortedBlockInputStream::readImpl()
if (!block)
return Block();
const ConstColumnPlainPtrs column_ptrs(getKeyColumns(block));
const ColumnRawPtrs column_ptrs(getKeyColumns(block));
if (column_ptrs.empty())
return block;
const ConstColumnPlainPtrs clearing_hint_columns(getClearingColumns(block, column_ptrs));
const ColumnRawPtrs clearing_hint_columns(getClearingColumns(block, column_ptrs));
if (data.type == ClearableSetVariants::Type::EMPTY)
data.init(ClearableSetVariants::chooseMethod(column_ptrs, key_sizes));
@ -112,8 +112,8 @@ bool DistinctSortedBlockInputStream::checkLimits() const
template <typename Method>
bool DistinctSortedBlockInputStream::buildFilter(
Method & method,
const ConstColumnPlainPtrs & columns,
const ConstColumnPlainPtrs & clearing_hint_columns,
const ColumnRawPtrs & columns,
const ColumnRawPtrs & clearing_hint_columns,
IColumn::Filter & filter,
size_t rows,
ClearableSetVariants & variants) const
@ -158,11 +158,11 @@ bool DistinctSortedBlockInputStream::buildFilter(
return has_new_data;
}
ConstColumnPlainPtrs DistinctSortedBlockInputStream::getKeyColumns(const Block & block) const
ColumnRawPtrs DistinctSortedBlockInputStream::getKeyColumns(const Block & block) const
{
size_t columns = columns_names.empty() ? block.columns() : columns_names.size();
ConstColumnPlainPtrs column_ptrs;
ColumnRawPtrs column_ptrs;
column_ptrs.reserve(columns);
for (size_t i = 0; i < columns; ++i)
@ -179,9 +179,9 @@ ConstColumnPlainPtrs DistinctSortedBlockInputStream::getKeyColumns(const Block &
return column_ptrs;
}
ConstColumnPlainPtrs DistinctSortedBlockInputStream::getClearingColumns(const Block & block, const ConstColumnPlainPtrs & key_columns) const
ColumnRawPtrs DistinctSortedBlockInputStream::getClearingColumns(const Block & block, const ColumnRawPtrs & key_columns) const
{
ConstColumnPlainPtrs clearing_hint_columns;
ColumnRawPtrs clearing_hint_columns;
clearing_hint_columns.reserve(description.size());
for(const auto & sort_column_description : description)
{
@ -195,7 +195,7 @@ ConstColumnPlainPtrs DistinctSortedBlockInputStream::getClearingColumns(const Bl
return clearing_hint_columns;
}
bool DistinctSortedBlockInputStream::rowsEqual(const ConstColumnPlainPtrs & lhs, size_t n, const ConstColumnPlainPtrs & rhs, size_t m)
bool DistinctSortedBlockInputStream::rowsEqual(const ColumnRawPtrs & lhs, size_t n, const ColumnRawPtrs & rhs, size_t m)
{
for (size_t column_index = 0, num_columns = lhs.size(); column_index < num_columns; ++column_index)
{

View File

@ -33,18 +33,18 @@ protected:
private:
bool checkLimits() const;
ConstColumnPlainPtrs getKeyColumns(const Block & block) const;
ColumnRawPtrs getKeyColumns(const Block & block) const;
/// When clearing_columns changed, we can clean HashSet to memory optimization
/// clearing_columns is a left-prefix of SortDescription exists in key_columns
ConstColumnPlainPtrs getClearingColumns(const Block & block, const ConstColumnPlainPtrs & key_columns) const;
static bool rowsEqual(const ConstColumnPlainPtrs & lhs, size_t n, const ConstColumnPlainPtrs & rhs, size_t m);
ColumnRawPtrs getClearingColumns(const Block & block, const ColumnRawPtrs & key_columns) const;
static bool rowsEqual(const ColumnRawPtrs & lhs, size_t n, const ColumnRawPtrs & rhs, size_t m);
/// return true if has new data
template <typename Method>
bool buildFilter(
Method & method,
const ConstColumnPlainPtrs & key_columns,
const ConstColumnPlainPtrs & clearing_hint_columns,
const ColumnRawPtrs & key_columns,
const ColumnRawPtrs & clearing_hint_columns,
IColumn::Filter & filter,
size_t rows,
ClearableSetVariants & variants) const;
@ -54,7 +54,7 @@ private:
struct PreviousBlock
{
Block block;
ConstColumnPlainPtrs clearing_hint_columns;
ColumnRawPtrs clearing_hint_columns;
};
PreviousBlock prev_block;

View File

@ -1,7 +1,7 @@
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnNullable.h>
#include <Columns/ColumnsCommon.h>
#include <Columns/ColumnConst.h>
#include <Columns/FilterDescription.h>
#include <Interpreters/ExpressionActions.h>
#include <Common/typeid_cast.h>
@ -53,22 +53,6 @@ const Block & FilterBlockInputStream::getTotals()
}
static void analyzeConstantFilter(const IColumn & column, bool & filter_always_false, bool & filter_always_true)
{
if (column.onlyNull())
{
filter_always_false = true;
}
else if (column.isColumnConst())
{
if (static_cast<const ColumnConst &>(column).getValue<UInt8>())
filter_always_true = true;
else
filter_always_false = true;
}
}
Block FilterBlockInputStream::readImpl()
{
Block res;
@ -95,9 +79,9 @@ Block FilterBlockInputStream::readImpl()
ColumnPtr column = sample_block.safeGetByPosition(filter_column_in_sample_block).column;
if (column)
analyzeConstantFilter(*column, filter_always_false, filter_always_true);
constant_filter_description = ConstantFilterDescription(*column);
if (filter_always_false)
if (constant_filter_description.always_false)
return res;
}
@ -110,7 +94,7 @@ Block FilterBlockInputStream::readImpl()
expression->execute(res);
if (filter_always_true)
if (constant_filter_description.always_true)
return res;
/// Find the current position of the filter column in the block.
@ -120,47 +104,23 @@ Block FilterBlockInputStream::readImpl()
size_t columns = res.columns();
ColumnPtr column = res.safeGetByPosition(filter_column).column;
IColumn * observed_column = column.get();
bool is_nullable_column = observed_column->isColumnNullable();
if (is_nullable_column)
observed_column = static_cast<const ColumnNullable &>(*column.get()).getNestedColumn().get();
/** It happens that at the stage of analysis of expressions (in sample_block) the columns-constants have not been calculated yet,
* and now - are calculated. That is, not all cases are covered by the code above.
* This happens if the function returns a constant for a non-constant argument.
* For example, `ignore` function.
*/
constant_filter_description = ConstantFilterDescription(*column);
ColumnUInt8 * column_vec = typeid_cast<ColumnUInt8 *>(observed_column);
if (!column_vec)
if (constant_filter_description.always_false)
{
/** It happens that at the stage of analysis of expressions (in sample_block) the columns-constants have not been calculated yet,
* and now - are calculated. That is, not all cases are covered by the code above.
* This happens if the function returns a constant for a non-constant argument.
* For example, `ignore` function.
*/
analyzeConstantFilter(*observed_column, filter_always_false, filter_always_true);
if (filter_always_false)
{
res.clear();
return res;
}
if (filter_always_true)
return res;
throw Exception("Illegal type " + column->getName() + " of column for filter. Must be ColumnUInt8 or ColumnConstUInt8 or Nullable variants of them.",
ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
res.clear();
return res;
}
IColumn::Filter & filter = column_vec->getData();
if (constant_filter_description.always_true)
return res;
if (is_nullable_column)
{
/// Exclude the entries of the filter column that actually are NULL values.
const NullMap & null_map = static_cast<ColumnNullable &>(*column).getNullMap();
IColumn::Filter & filter = column_vec->getData();
for (size_t i = 0, size = null_map.size(); i < size; ++i)
if (null_map[i])
filter[i] = 0;
}
FilterDescription filter_and_holder(*column);
/** Let's find out how many rows will be in result.
* To do this, we filter out the first non-constant column
@ -182,12 +142,12 @@ Block FilterBlockInputStream::readImpl()
if (first_non_constant_column != static_cast<size_t>(filter_column))
{
ColumnWithTypeAndName & current_column = res.safeGetByPosition(first_non_constant_column);
current_column.column = current_column.column->filter(filter, -1);
current_column.column = current_column.column->filter(*filter_and_holder.data, -1);
filtered_rows = current_column.column->size();
}
else
{
filtered_rows = countBytesInFilter(filter);
filtered_rows = countBytesInFilter(*filter_and_holder.data);
}
/// If the current block is completely filtered out, let's move on to the next one.
@ -195,7 +155,7 @@ Block FilterBlockInputStream::readImpl()
continue;
/// If all the rows pass through the filter.
if (filtered_rows == filter.size())
if (filtered_rows == filter_and_holder.data->size())
{
/// Replace the column with the filter by a constant.
res.safeGetByPosition(filter_column).column = res.safeGetByPosition(filter_column).type->createColumnConst(filtered_rows, UInt64(1));
@ -225,7 +185,7 @@ Block FilterBlockInputStream::readImpl()
if (current_column.column->isColumnConst())
current_column.column = current_column.column->cut(0, filtered_rows);
else
current_column.column = current_column.column->filter(filter, -1);
current_column.column = current_column.column->filter(*filter_and_holder.data, -1);
}
return res;

View File

@ -1,6 +1,7 @@
#pragma once
#include <DataStreams/IProfilingBlockInputStream.h>
#include <Columns/FilterDescription.h>
namespace DB
@ -36,8 +37,8 @@ private:
String filter_column_name;
bool is_first = true;
bool filter_always_true = false;
bool filter_always_false = false;
ConstantFilterDescription constant_filter_description;
};
}

View File

@ -63,7 +63,7 @@ BlockInputStreamPtr FormatFactory::getInput(const String & name, ReadBuffer & bu
}
else if (name == "RowBinary")
{
return wrap_row_stream(std::make_shared<BinaryRowInputStream>(buf));
return wrap_row_stream(std::make_shared<BinaryRowInputStream>(buf, sample));
}
else if (name == "TabSeparated" || name == "TSV") /// TSV is a synonym/alias for the original TabSeparated format
{
@ -79,7 +79,7 @@ BlockInputStreamPtr FormatFactory::getInput(const String & name, ReadBuffer & bu
}
else if (name == "Values")
{
return wrap_row_stream(std::make_shared<ValuesRowInputStream>(buf, context, settings.input_format_values_interpret_expressions));
return wrap_row_stream(std::make_shared<ValuesRowInputStream>(buf, sample, context, settings.input_format_values_interpret_expressions));
}
else if (name == "CSV")
{

View File

@ -8,6 +8,7 @@ namespace DB
namespace ErrorCodes
{
extern const int NO_SUCH_COLUMN_IN_TABLE;
extern const int LOGICAL_ERROR;
}
@ -67,10 +68,14 @@ Block GraphiteRollupSortedBlockInputStream::readImpl()
if (finished)
return Block();
Block merged_block;
ColumnPlainPtrs merged_columns;
Block header;
MutableColumns merged_columns;
init(header, merged_columns);
if (has_collation)
throw Exception("Logical error: " + getName() + " does not support collations", ErrorCodes::LOGICAL_ERROR);
init(merged_block, merged_columns);
if (merged_columns.empty())
return Block();
@ -85,10 +90,10 @@ Block GraphiteRollupSortedBlockInputStream::readImpl()
place_for_aggregate_state.resize(max_size_of_aggregate_state);
/// Memoize column numbers in block.
path_column_num = merged_block.getPositionByName(params.path_column_name);
time_column_num = merged_block.getPositionByName(params.time_column_name);
value_column_num = merged_block.getPositionByName(params.value_column_name);
version_column_num = merged_block.getPositionByName(params.version_column_name);
path_column_num = header.getPositionByName(params.path_column_name);
time_column_num = header.getPositionByName(params.time_column_name);
value_column_num = header.getPositionByName(params.value_column_name);
version_column_num = header.getPositionByName(params.version_column_name);
for (size_t i = 0; i < num_columns; ++i)
if (i != time_column_num && i != value_column_num && i != version_column_num)
@ -98,23 +103,18 @@ Block GraphiteRollupSortedBlockInputStream::readImpl()
current_selected_row.columns.resize(num_columns);
}
if (has_collation)
merge(merged_columns, queue_with_collation);
else
merge(merged_columns, queue);
return merged_block;
merge(merged_columns, queue);
return header.cloneWithColumns(std::move(merged_columns));
}
template <typename TSortCursor>
void GraphiteRollupSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue)
void GraphiteRollupSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue)
{
const DateLUTImpl & date_lut = DateLUT::instance();
size_t started_rows = 0; /// Number of times startNextRow() has been called.
/// Take rows in needed order and put them into `merged_block` until we get `max_block_size` rows.
/// Take rows in needed order and put them into `merged_columns` until we get `max_block_size` rows.
///
/// Variables starting with current_* refer to the rows previously popped from the queue that will
/// contribute towards current output row.
@ -122,7 +122,7 @@ void GraphiteRollupSortedBlockInputStream::merge(ColumnPlainPtrs & merged_column
while (!queue.empty())
{
TSortCursor next_cursor = queue.top();
SortCursor next_cursor = queue.top();
StringRef next_path = next_cursor->all_columns[path_column_num]->getDataAt(next_cursor->pos);
bool path_differs = is_first || next_path != current_path;
@ -218,8 +218,7 @@ void GraphiteRollupSortedBlockInputStream::merge(ColumnPlainPtrs & merged_column
}
template <typename TSortCursor>
void GraphiteRollupSortedBlockInputStream::startNextRow(ColumnPlainPtrs & merged_columns, TSortCursor & cursor, const Graphite::Pattern * next_pattern)
void GraphiteRollupSortedBlockInputStream::startNextRow(MutableColumns & merged_columns, SortCursor & cursor, const Graphite::Pattern * next_pattern)
{
/// Copy unmodified column values.
for (size_t i = 0, size = unmodified_column_numbers.size(); i < size; ++i)
@ -238,7 +237,7 @@ void GraphiteRollupSortedBlockInputStream::startNextRow(ColumnPlainPtrs & merged
}
void GraphiteRollupSortedBlockInputStream::finishCurrentRow(ColumnPlainPtrs & merged_columns)
void GraphiteRollupSortedBlockInputStream::finishCurrentRow(MutableColumns & merged_columns)
{
/// Insert calculated values of the columns `time`, `value`, `version`.
merged_columns[time_column_num]->insert(UInt64(current_time_rounded));
@ -252,7 +251,7 @@ void GraphiteRollupSortedBlockInputStream::finishCurrentRow(ColumnPlainPtrs & me
}
else
merged_columns[value_column_num]->insertFrom(
*current_selected_row.columns[value_column_num], current_selected_row.row_num);
*current_selected_row.columns[value_column_num], current_selected_row.row_num);
}

View File

@ -195,15 +195,13 @@ private:
UInt32 selectPrecision(const Graphite::Retentions & retentions, time_t time) const;
template <typename TSortCursor>
void merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue);
void merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue);
/// Insert the values into the resulting columns, which will not be changed in the future.
template <typename TSortCursor>
void startNextRow(ColumnPlainPtrs & merged_columns, TSortCursor & cursor, const Graphite::Pattern * next_pattern);
void startNextRow(MutableColumns & merged_columns, SortCursor & cursor, const Graphite::Pattern * next_pattern);
/// Insert the calculated `time`, `value`, `version` values into the resulting columns by the last group of rows.
void finishCurrentRow(ColumnPlainPtrs & merged_columns);
void finishCurrentRow(MutableColumns & merged_columns);
/// Update the state of the aggregate function with the new `value`.
void accumulateRow(RowRef & row);

View File

@ -91,36 +91,48 @@ void IProfilingBlockInputStream::readSuffix()
void IProfilingBlockInputStream::updateExtremes(Block & block)
{
size_t columns = block.columns();
size_t num_columns = block.columns();
if (!extremes)
{
extremes = block.cloneEmpty();
MutableColumns extremes_columns(num_columns);
for (size_t i = 0; i < columns; ++i)
for (size_t i = 0; i < num_columns; ++i)
{
Field min_value;
Field max_value;
const ColumnPtr & src = block.safeGetByPosition(i).column;
block.safeGetByPosition(i).column->getExtremes(min_value, max_value);
if (src->isColumnConst())
{
/// Equal min and max.
extremes_columns[i] = src->cloneResized(2);
}
else
{
Field min_value;
Field max_value;
ColumnPtr & column = extremes.safeGetByPosition(i).column;
src->getExtremes(min_value, max_value);
if (auto converted = column->convertToFullColumnIfConst())
column = converted;
extremes_columns[i] = src->cloneEmpty();
column->insert(min_value);
column->insert(max_value);
extremes_columns[i]->insert(min_value);
extremes_columns[i]->insert(max_value);
}
}
extremes = block.cloneWithColumns(std::move(extremes_columns));
}
else
{
for (size_t i = 0; i < columns; ++i)
for (size_t i = 0; i < num_columns; ++i)
{
ColumnPtr & column = extremes.safeGetByPosition(i).column;
ColumnPtr & old_extremes = extremes.safeGetByPosition(i).column;
Field min_value = (*column)[0];
Field max_value = (*column)[1];
if (old_extremes->isColumnConst())
continue;
Field min_value = (*old_extremes)[0];
Field max_value = (*old_extremes)[1];
Field cur_min_value;
Field cur_max_value;
@ -132,9 +144,12 @@ void IProfilingBlockInputStream::updateExtremes(Block & block)
if (cur_max_value > max_value)
max_value = cur_max_value;
column = column->cloneEmpty();
column->insert(min_value);
column->insert(max_value);
MutableColumnPtr new_extremes = old_extremes->cloneEmpty();
new_extremes->insert(min_value);
new_extremes->insert(max_value);
old_extremes = std::move(new_extremes);
}
}
}
@ -299,7 +314,7 @@ void IProfilingBlockInputStream::progressImpl(const Progress & value)
if (quota != nullptr && limits.mode == LIMITS_TOTAL)
{
quota->checkAndAddReadRowsBytes(time(0), value.rows, value.bytes);
quota->checkAndAddReadRowsBytes(time(nullptr), value.rows, value.bytes);
}
}
}

View File

@ -4,21 +4,22 @@
#include <memory>
#include <string>
#include <Columns/IColumn.h>
namespace DB
{
class Block;
/** Interface of stream, that allows to read data by rows.
*/
class IRowInputStream : private boost::noncopyable
{
public:
/** Read next row and append it to block.
/** Read next row and append it to the columns.
* If no more rows - return false.
*/
virtual bool read(Block & block) = 0;
virtual bool read(MutableColumns & columns) = 0;
virtual void readPrefix() {}; /// delimiter before begin of result
virtual void readSuffix() {}; /// delimiter after end of result

View File

@ -12,15 +12,15 @@ namespace ErrorCodes
}
JSONEachRowRowInputStream::JSONEachRowRowInputStream(ReadBuffer & istr_, const Block & sample_, bool skip_unknown_)
: istr(istr_), sample(sample_), skip_unknown(skip_unknown_), name_map(sample.columns())
JSONEachRowRowInputStream::JSONEachRowRowInputStream(ReadBuffer & istr_, const Block & header_, bool skip_unknown_)
: istr(istr_), header(header_), skip_unknown(skip_unknown_), name_map(header.columns())
{
/// In this format, BOM at beginning of stream cannot be confused with value, so it is safe to skip it.
skipBOMIfExists(istr);
size_t columns = sample.columns();
for (size_t i = 0; i < columns; ++i)
name_map[sample.safeGetByPosition(i).name] = i; /// NOTE You could place names more cache-locally.
size_t num_columns = header.columns();
for (size_t i = 0; i < num_columns; ++i)
name_map[header.safeGetByPosition(i).name] = i; /// NOTE You could place names more cache-locally.
}
@ -58,15 +58,15 @@ static void skipColonDelimeter(ReadBuffer & istr)
}
bool JSONEachRowRowInputStream::read(Block & block)
bool JSONEachRowRowInputStream::read(MutableColumns & columns)
{
skipWhitespaceIfAny(istr);
/// We consume ;, or \n before scanning a new row, instead scanning to next row at the end.
/// The reason is that if we want an exact number of rows read with LIMIT x
/// The reason is that if we want an exact number of rows read with LIMIT x
/// from a streaming table engine with text data format, like File or Kafka
/// then seeking to next ;, or \n would trigger reading of an extra row at the end.
/// Semicolon is added for convenience as it could be used at end of INSERT query.
if (!istr.eof() && (*istr.position() == ',' || *istr.position() == ';'))
++istr.position();
@ -77,12 +77,12 @@ bool JSONEachRowRowInputStream::read(Block & block)
assertChar('{', istr);
size_t columns = block.columns();
size_t num_columns = columns.size();
/// Set of columns for which the values were read. The rest will be filled with default values.
/// TODO Ability to provide your DEFAULTs.
bool read_columns[columns];
memset(read_columns, 0, columns);
bool read_columns[num_columns];
memset(read_columns, 0, num_columns);
bool first = true;
while (true)
@ -130,19 +130,13 @@ bool JSONEachRowRowInputStream::read(Block & block)
read_columns[index] = true;
auto & col = block.getByPosition(index);
col.type->deserializeTextJSON(*col.column, istr);
header.getByPosition(index).type->deserializeTextJSON(*columns[index], istr);
}
/// Fill non-visited columns with the default values.
for (size_t i = 0; i < columns; ++i)
{
for (size_t i = 0; i < num_columns; ++i)
if (!read_columns[i])
{
ColumnWithTypeAndName & elem = block.getByPosition(i);
elem.type->insertDefaultInto(*elem.column);
}
}
header.getByPosition(i).type->insertDefaultInto(*columns[i]);
return true;
}

View File

@ -18,15 +18,15 @@ class ReadBuffer;
class JSONEachRowRowInputStream : public IRowInputStream
{
public:
JSONEachRowRowInputStream(ReadBuffer & istr_, const Block & sample_, bool skip_unknown_);
JSONEachRowRowInputStream(ReadBuffer & istr_, const Block & header_, bool skip_unknown_);
bool read(Block & block) override;
bool read(MutableColumns & columns) override;
bool allowSyncAfterError() const override { return true; };
void syncAfterError() override;
private:
ReadBuffer & istr;
const Block sample;
Block header;
bool skip_unknown;
/// Buffer for the read from the stream field name. Used when you have to copy it.

View File

@ -9,7 +9,7 @@ namespace DB
JSONRowOutputStream::JSONRowOutputStream(WriteBuffer & ostr_, const Block & sample_, bool write_statistics_, const FormatSettingsJSON & settings_)
: dst_ostr(ostr_), write_statistics(write_statistics_), settings(settings_)
{
NamesAndTypesList columns(sample_.getColumnsList());
NamesAndTypesList columns(sample_.getNamesAndTypesList());
fields.assign(columns.begin(), columns.end());
bool need_validate_utf8 = false;

View File

@ -20,7 +20,7 @@ Block LimitByBlockInputStream::readImpl()
if (!block)
return Block();
const ConstColumnPlainPtrs column_ptrs(getKeyColumns(block));
const ColumnRawPtrs column_ptrs(getKeyColumns(block));
const size_t rows = block.rows();
IColumn::Filter filter(rows);
size_t inserted_count = 0;
@ -56,9 +56,9 @@ Block LimitByBlockInputStream::readImpl()
}
}
ConstColumnPlainPtrs LimitByBlockInputStream::getKeyColumns(Block & block) const
ColumnRawPtrs LimitByBlockInputStream::getKeyColumns(Block & block) const
{
ConstColumnPlainPtrs column_ptrs;
ColumnRawPtrs column_ptrs;
column_ptrs.reserve(columns_names.size());
for (const auto & name : columns_names)

View File

@ -26,7 +26,7 @@ protected:
Block readImpl() override;
private:
ConstColumnPlainPtrs getKeyColumns(Block & block) const;
ColumnRawPtrs getKeyColumns(Block & block) const;
private:
using MapHashed = HashMap<UInt128, UInt64, UInt128TrivialHash>;

View File

@ -204,12 +204,10 @@ Block MergeSortingBlocksBlockInputStream::readImpl()
template <typename TSortCursor>
Block MergeSortingBlocksBlockInputStream::mergeImpl(std::priority_queue<TSortCursor> & queue)
{
Block merged = blocks[0].cloneEmpty();
size_t num_columns = blocks[0].columns();
ColumnPlainPtrs merged_columns;
for (size_t i = 0; i < num_columns; ++i) /// TODO: reserve
merged_columns.push_back(merged.safeGetByPosition(i).column.get());
MutableColumns merged_columns = blocks[0].cloneEmptyColumns();
/// TODO: reserve (in each column)
/// Take rows from queue in right order and push to 'merged'.
size_t merged_rows = 0;
@ -230,19 +228,20 @@ Block MergeSortingBlocksBlockInputStream::mergeImpl(std::priority_queue<TSortCur
++total_merged_rows;
if (limit && total_merged_rows == limit)
{
auto res = blocks[0].cloneWithColumns(std::move(merged_columns));
blocks.clear();
return merged;
return res;
}
++merged_rows;
if (merged_rows == max_merged_block_size)
return merged;
return blocks[0].cloneWithColumns(std::move(merged_columns));
}
if (merged_rows == 0)
merged.clear();
return {};
return merged;
return blocks[0].cloneWithColumns(std::move(merged_columns));
}

View File

@ -46,7 +46,7 @@ String MergingSortedBlockInputStream::getID() const
return res.str();
}
void MergingSortedBlockInputStream::init(Block & merged_block, ColumnPlainPtrs & merged_columns)
void MergingSortedBlockInputStream::init(Block & header, MutableColumns & merged_columns)
{
/// Read the first blocks, initialize the queue.
if (first)
@ -95,7 +95,7 @@ void MergingSortedBlockInputStream::init(Block & merged_block, ColumnPlainPtrs &
if (*shared_block_ptr)
{
merged_block = shared_block_ptr->cloneEmpty();
header = shared_block_ptr->cloneEmpty();
break;
}
}
@ -114,7 +114,7 @@ void MergingSortedBlockInputStream::init(Block & merged_block, ColumnPlainPtrs &
continue;
size_t src_columns = shared_block_ptr->columns();
size_t dst_columns = merged_block.columns();
size_t dst_columns = header.columns();
if (src_columns != dst_columns)
throw Exception("Merging blocks has different number of columns ("
@ -122,22 +122,17 @@ void MergingSortedBlockInputStream::init(Block & merged_block, ColumnPlainPtrs &
ErrorCodes::NUMBER_OF_COLUMNS_DOESNT_MATCH);
for (size_t i = 0; i < src_columns; ++i)
{
if (shared_block_ptr->safeGetByPosition(i).name != merged_block.safeGetByPosition(i).name
|| shared_block_ptr->safeGetByPosition(i).type->getName() != merged_block.safeGetByPosition(i).type->getName()
|| shared_block_ptr->safeGetByPosition(i).column->getName() != merged_block.safeGetByPosition(i).column->getName())
{
if (!blocksHaveEqualStructure(*shared_block_ptr, header))
throw Exception("Merging blocks has different names or types of columns:\n"
+ shared_block_ptr->dumpStructure() + "\nand\n" + merged_block.dumpStructure(),
+ shared_block_ptr->dumpStructure() + "\nand\n" + header.dumpStructure(),
ErrorCodes::BLOCKS_HAVE_DIFFERENT_STRUCTURE);
}
}
}
merged_columns.resize(num_columns);
for (size_t i = 0; i < num_columns; ++i)
{
merged_columns.emplace_back(merged_block.safeGetByPosition(i).column.get());
merged_columns.back()->reserve(expected_block_size);
merged_columns[i] = header.safeGetByPosition(i).column->cloneEmpty();
merged_columns[i]->reserve(expected_block_size);
}
}
@ -154,24 +149,24 @@ void MergingSortedBlockInputStream::initQueue(std::priority_queue<TSortCursor> &
Block MergingSortedBlockInputStream::readImpl()
{
if (finished)
return Block();
return {};
if (children.size() == 1)
return children[0]->read();
Block merged_block;
ColumnPlainPtrs merged_columns;
Block header;
MutableColumns merged_columns;
init(merged_block, merged_columns);
init(header, merged_columns);
if (merged_columns.empty())
return Block();
return {};
if (has_collation)
merge(merged_block, merged_columns, queue_with_collation);
merge(merged_columns, queue_with_collation);
else
merge(merged_block, merged_columns, queue);
merge(merged_columns, queue);
return merged_block;
return header.cloneWithColumns(std::move(merged_columns));
}
@ -207,7 +202,7 @@ void MergingSortedBlockInputStream::fetchNextBlock<SortCursorWithCollation>(cons
template <typename TSortCursor>
void MergingSortedBlockInputStream::merge(Block & merged_block, ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue)
void MergingSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<TSortCursor> & queue)
{
size_t merged_rows = 0;
@ -235,7 +230,7 @@ void MergingSortedBlockInputStream::merge(Block & merged_block, ColumnPlainPtrs
return false;
};
/// Take rows in required order and put them into `merged_block`, while the rows are no more than `max_block_size`
/// Take rows in required order and put them into `merged_columns`, while the rows are no more than `max_block_size`
while (!queue.empty())
{
TSortCursor current = queue.top();
@ -243,8 +238,8 @@ void MergingSortedBlockInputStream::merge(Block & merged_block, ColumnPlainPtrs
while (true)
{
/** And what if the block is smaller or equal than the rest for the current cursor?
* Or is there only one data source left in the queue? Then you can take the entire block of current cursor.
/** And what if the block is totally less or equal than the rest for the current cursor?
* Or is there only one data source left in the queue? Then you can take the entire block on current cursor.
*/
if (current.impl->isFirst() && (queue.empty() || current.totallyLessOrEquals(queue.top())))
{
@ -265,18 +260,18 @@ void MergingSortedBlockInputStream::merge(Block & merged_block, ColumnPlainPtrs
throw Exception("Logical error in MergingSortedBlockInputStream", ErrorCodes::LOGICAL_ERROR);
for (size_t i = 0; i < num_columns; ++i)
merged_block.getByPosition(i).column = source_blocks[source_num]->getByPosition(i).column;
merged_columns[i] = source_blocks[source_num]->getByPosition(i).column->mutate();
// std::cerr << "copied columns\n";
size_t merged_rows = merged_block.rows();
size_t merged_rows = merged_columns.at(0)->size();
if (limit && total_merged_rows + merged_rows > limit)
{
merged_rows = limit - total_merged_rows;
for (size_t i = 0; i < num_columns; ++i)
{
auto & column = merged_block.getByPosition(i).column;
auto & column = merged_columns[i];
column = column->cut(0, merged_rows);
}

View File

@ -77,7 +77,7 @@ public:
protected:
struct RowRef
{
ConstColumnPlainPtrs columns;
ColumnRawPtrs columns;
size_t row_num;
SharedBlockPtr shared_block;
@ -113,7 +113,7 @@ protected:
void readSuffixImpl() override;
/// Initializes the queue and the next result block.
void init(Block & merged_block, ColumnPlainPtrs & merged_columns);
void init(Block & header, MutableColumns & merged_columns);
/// Gets the next block from the source corresponding to the `current`.
template <typename TSortCursor>
@ -214,7 +214,7 @@ private:
void initQueue(std::priority_queue<TSortCursor> & queue);
template <typename TSortCursor>
void merge(Block & merged_block, ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue);
void merge(MutableColumns & merged_columns, std::priority_queue<TSortCursor> & queue);
Logger * log = &Logger::get("MergingSortedBlockInputStream");

View File

@ -114,11 +114,13 @@ Block NativeBlockInputStream::readImpl()
}
/// Data
column.column = column.type->createColumn();
MutableColumnPtr read_column = column.type->createColumn();
double avg_value_size_hint = avg_value_size_hints.empty() ? 0 : avg_value_size_hints[i];
if (rows) /// If no rows, nothing to read.
readData(*column.type, *column.column, istr, rows, avg_value_size_hint);
readData(*column.type, *read_column, istr, rows, avg_value_size_hint);
column.column = std::move(read_column);
res.insert(std::move(column));

View File

@ -47,7 +47,7 @@ void NativeBlockOutputStream::writeData(const IDataType & type, const ColumnPtr
*/
ColumnPtr full_column;
if (auto converted = column->convertToFullColumnIfConst())
if (ColumnPtr converted = column->convertToFullColumnIfConst())
full_column = converted;
else
full_column = column;

View File

@ -50,7 +50,7 @@ Block NullableAdapterBlockInputStream::readImpl()
const auto & nullable_col = static_cast<const ColumnNullable &>(*elem.column);
const auto & nullable_type = static_cast<const DataTypeNullable &>(*elem.type);
const auto & null_map = nullable_col.getNullMap();
const auto & null_map = nullable_col.getNullMapData();
bool has_nulls = !memoryIsZero(null_map.data(), null_map.size());
if (has_nulls)
@ -58,7 +58,7 @@ Block NullableAdapterBlockInputStream::readImpl()
ErrorCodes::CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN};
else
res.insert({
nullable_col.getNestedColumn(),
nullable_col.getNestedColumnPtr(),
nullable_type.getNestedType(),
rename[i].value_or(elem.name)
});
@ -66,13 +66,12 @@ Block NullableAdapterBlockInputStream::readImpl()
}
case TO_NULLABLE:
{
auto null_map = std::make_shared<ColumnUInt8>(elem.column->size(), 0);
ColumnPtr null_map = ColumnUInt8::create(elem.column->size(), 0);
res.insert({
std::make_shared<ColumnNullable>(elem.column, null_map),
ColumnNullable::create(elem.column, null_map),
std::make_shared<DataTypeNullable>(elem.type),
rename[i].value_or(elem.name)
});
rename[i].value_or(elem.name)});
break;
}
case NONE:

View File

@ -81,7 +81,7 @@ private:
size_t src_bytes = 0;
StringRefs key;
ConstColumnPlainPtrs key_columns;
ColumnRawPtrs key_columns;
Aggregator::AggregateColumns aggregate_columns;
Sizes key_sizes;

View File

@ -6,8 +6,13 @@
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
void ReplacingSortedBlockInputStream::insertRow(ColumnPlainPtrs & merged_columns, size_t & merged_rows)
void ReplacingSortedBlockInputStream::insertRow(MutableColumns & merged_columns, size_t & merged_rows)
{
if (out_row_sources_buf)
{
@ -33,10 +38,14 @@ Block ReplacingSortedBlockInputStream::readImpl()
if (children.size() == 1)
return children[0]->read();
Block merged_block;
ColumnPlainPtrs merged_columns;
Block header;
MutableColumns merged_columns;
init(header, merged_columns);
if (has_collation)
throw Exception("Logical error: " + getName() + " does not support collations", ErrorCodes::LOGICAL_ERROR);
init(merged_block, merged_columns);
if (merged_columns.empty())
return Block();
@ -46,27 +55,22 @@ Block ReplacingSortedBlockInputStream::readImpl()
selected_row.columns.resize(num_columns);
if (!version_column.empty())
version_column_number = merged_block.getPositionByName(version_column);
version_column_number = header.getPositionByName(version_column);
}
if (has_collation)
merge(merged_columns, queue_with_collation);
else
merge(merged_columns, queue);
return merged_block;
merge(merged_columns, queue);
return header.cloneWithColumns(std::move(merged_columns));
}
template <typename TSortCursor>
void ReplacingSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue)
void ReplacingSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue)
{
size_t merged_rows = 0;
/// Take the rows in needed order and put them into `merged_block` until rows no more than `max_block_size`
/// Take the rows in needed order and put them into `merged_columns` until rows no more than `max_block_size`
while (!queue.empty())
{
TSortCursor current = queue.top();
SortCursor current = queue.top();
if (current_key.empty())
{

View File

@ -63,11 +63,10 @@ private:
PODArray<RowSourcePart> current_row_sources; /// Sources of rows with the current primary key
template <typename TSortCursor>
void merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue);
void merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue);
/// Output into result the rows for current primary key.
void insertRow(ColumnPlainPtrs & merged_columns, size_t & merged_rows);
void insertRow(MutableColumns & merged_columns, size_t & merged_rows);
};
}

View File

@ -24,7 +24,6 @@ SquashingTransform::Result SquashingTransform::add(Block && block)
/// Return accumulated data (may be it has small size) and place new block to accumulated data.
accumulated_block.swap(block);
accumulated_block.unshareColumns();
return Result(std::move(block));
}
@ -33,7 +32,6 @@ SquashingTransform::Result SquashingTransform::add(Block && block)
{
/// Return accumulated data and place new block to accumulated data.
accumulated_block.swap(block);
accumulated_block.unshareColumns();
return Result(std::move(block));
}
@ -56,7 +54,6 @@ void SquashingTransform::append(Block && block)
if (!accumulated_block)
{
accumulated_block = std::move(block);
accumulated_block.unshareColumns();
return;
}
@ -64,8 +61,11 @@ void SquashingTransform::append(Block && block)
size_t rows = block.rows();
for (size_t i = 0; i < columns; ++i)
accumulated_block.getByPosition(i).column->insertRangeFrom(
*block.getByPosition(i).column, 0, rows);
{
MutableColumnPtr mutable_column = accumulated_block.getByPosition(i).column->mutate();
mutable_column->insertRangeFrom(*block.getByPosition(i).column, 0, rows);
accumulated_block.getByPosition(i).column = std::move(mutable_column);
}
}

Some files were not shown because too many files have changed in this diff Show More