Beispiel #1
0
ColumnPtr ColumnArray::indexImpl(const PaddedPODArray<T> & indexes, size_t limit) const
{
    if (limit == 0)
        return ColumnArray::create(data);

    /// Convert indexes to UInt64 in case of overflow.
    auto nested_indexes_column = ColumnUInt64::create();
    PaddedPODArray<UInt64> & nested_indexes = nested_indexes_column->getData();
    nested_indexes.reserve(getOffsets().back());

    auto res = ColumnArray::create(data->cloneEmpty());

    Offsets & res_offsets = res->getOffsets();
    res_offsets.resize(limit);
    size_t current_offset = 0;

    for (size_t i = 0; i < limit; ++i)
    {
        for (size_t j = 0; j < sizeAt(indexes[i]); ++j)
            nested_indexes.push_back(offsetAt(indexes[i]) + j);
        current_offset += sizeAt(indexes[i]);
        res_offsets[i] = current_offset;
    }

    if (current_offset != 0)
        res->data = data->index(*nested_indexes_column, current_offset);

    return res;
}
Beispiel #2
0
int ColumnString::compareAtWithCollation(size_t n, size_t m, const IColumn & rhs_, const Collator & collator) const
{
	const ColumnString & rhs = static_cast<const ColumnString &>(rhs_);

	return collator.compare(
		reinterpret_cast<const char *>(&chars[offsetAt(n)]), sizeAt(n),
		reinterpret_cast<const char *>(&rhs.chars[rhs.offsetAt(m)]), rhs.sizeAt(m));
}
Beispiel #3
0
void ColumnArray::popBack(size_t n)
{
    auto & offsets_data = getOffsets();
    size_t nested_n = offsets_data.back() - offsetAt(offsets_data.size() - n);
    if (nested_n)
        getData().popBack(nested_n);
    offsets_data.resize_assume_reserved(offsets_data.size() - n);
}
Beispiel #4
0
void ColumnArray::updateHashWithValue(size_t n, SipHash & hash) const
{
    size_t array_size = sizeAt(n);
    size_t offset = offsetAt(n);

    hash.update(array_size);
    for (size_t i = 0; i < array_size; ++i)
        getData().updateHashWithValue(offset + i, hash);
}
Beispiel #5
0
ColumnPtr 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);

	Filter nested_filt(getOffsets().back());
	for (size_t i = 0; i < size; ++i)
	{
		if (filt[i])
			memset(&nested_filt[offsetAt(i)], 1, sizeAt(i));
		else
			memset(&nested_filt[offsetAt(i)], 0, sizeAt(i));
	}

	std::shared_ptr<ColumnArray> res = std::make_shared<ColumnArray>(data);

	ssize_t nested_result_size_hint = 0;
	if (result_size_hint < 0)
		nested_result_size_hint = result_size_hint;
	else if (result_size_hint && result_size_hint < 1000000000 && data->size() < 1000000000)	/// Избегаем переполнения.
		nested_result_size_hint = result_size_hint * data->size() / size;

	res->data = data->filter(nested_filt, nested_result_size_hint);

	Offsets_t & res_offsets = res->getOffsets();
	if (result_size_hint)
		res_offsets.reserve(result_size_hint > 0 ? result_size_hint : size);

	size_t current_offset = 0;
	for (size_t i = 0; i < size; ++i)
	{
		if (filt[i])
		{
			current_offset += sizeAt(i);
			res_offsets.push_back(current_offset);
		}
	}

	return res;
}
Beispiel #6
0
ColumnPtr 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 ColumnArray::create(data);

    Filter nested_filt(getOffsets().back());
    for (size_t i = 0; i < size; ++i)
    {
        if (filt[i])
            memset(&nested_filt[offsetAt(i)], 1, sizeAt(i));
        else
            memset(&nested_filt[offsetAt(i)], 0, sizeAt(i));
    }

    auto res = ColumnArray::create(data->cloneEmpty());

    ssize_t nested_result_size_hint = 0;
    if (result_size_hint < 0)
        nested_result_size_hint = result_size_hint;
    else if (result_size_hint && result_size_hint < 1000000000 && data->size() < 1000000000)    /// Avoid overflow.
         nested_result_size_hint = result_size_hint * data->size() / size;

    res->data = data->filter(nested_filt, nested_result_size_hint);

    Offsets & res_offsets = res->getOffsets();
    if (result_size_hint)
        res_offsets.reserve(result_size_hint > 0 ? result_size_hint : size);

    size_t current_offset = 0;
    for (size_t i = 0; i < size; ++i)
    {
        if (filt[i])
        {
            current_offset += sizeAt(i);
            res_offsets.push_back(current_offset);
        }
    }

    return res;
}
Beispiel #7
0
void ColumnArray::get(size_t n, Field & res) const
{
    size_t offset = offsetAt(n);
    size_t size = sizeAt(n);
    res = Array(size);
    Array & res_arr = DB::get<Array &>(res);

    for (size_t i = 0; i < size; ++i)
        getData().get(offset + i, res_arr[i]);
}
Beispiel #8
0
Field ColumnArray::operator[](size_t n) const
{
    size_t offset = offsetAt(n);
    size_t size = sizeAt(n);
    Array res(size);

    for (size_t i = 0; i < size; ++i)
        res[i] = getData()[offset + i];

    return res;
}
Beispiel #9
0
StringRef ColumnArray::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
{
    size_t array_size = sizeAt(n);
    size_t offset = offsetAt(n);

    char * pos = arena.allocContinue(sizeof(array_size), begin);
    memcpy(pos, &array_size, sizeof(array_size));

    size_t values_size = 0;
    for (size_t i = 0; i < array_size; ++i)
        values_size += getData().serializeValueIntoArena(offset + i, arena, begin).size;

    return StringRef(begin, sizeof(array_size) + values_size);
}
Beispiel #10
0
int ColumnArray::compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const
{
    const ColumnArray & rhs = static_cast<const ColumnArray &>(rhs_);

    /// Suboptimal
    size_t lhs_size = sizeAt(n);
    size_t rhs_size = rhs.sizeAt(m);
    size_t min_size = std::min(lhs_size, rhs_size);
    for (size_t i = 0; i < min_size; ++i)
        if (int res = getData().compareAt(offsetAt(n) + i, rhs.offsetAt(m) + i, *rhs.data.get(), nan_direction_hint))
            return res;

    return lhs_size < rhs_size
        ? -1
        : (lhs_size == rhs_size
            ? 0
            : 1);
}
Beispiel #11
0
StringRef ColumnArray::getDataAt(size_t n) const
{
    /** Returns the range of memory that covers all elements of the array.
      * Works for arrays of fixed length values.
      * For arrays of strings and arrays of arrays, the resulting chunk of memory may not be one-to-one correspondence with the elements,
      *  since it contains only the data laid in succession, but not the offsets.
      */

    size_t offset_of_first_elem = offsetAt(n);
    StringRef first = getData().getDataAtWithTerminatingZero(offset_of_first_elem);

    size_t array_size = sizeAt(n);
    if (array_size == 0)
        return StringRef(first.data, 0);

    size_t offset_of_last_elem = getOffsets()[n] - 1;
    StringRef last = getData().getDataAtWithTerminatingZero(offset_of_last_elem);

    return StringRef(first.data, last.data + last.size - first.data);
}
Beispiel #12
0
ColumnPtr ColumnArray::permute(const Permutation & perm, size_t limit) const
{
	size_t size = getOffsets().size();

	if (limit == 0)
		limit = size;
	else
		limit = std::min(size, limit);

	if (perm.size() < limit)
		throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);

	if (limit == 0)
		return std::make_shared<ColumnArray>(data);

	Permutation nested_perm(getOffsets().back());

	std::shared_ptr<ColumnArray> res = std::make_shared<ColumnArray>(data->cloneEmpty());

	Offsets_t & res_offsets = res->getOffsets();
	res_offsets.resize(limit);
	size_t current_offset = 0;

	for (size_t i = 0; i < limit; ++i)
	{
		for (size_t j = 0; j < sizeAt(perm[i]); ++j)
			nested_perm[current_offset + j] = offsetAt(perm[i]) + j;
		current_offset += sizeAt(perm[i]);
		res_offsets[i] = current_offset;
	}

	if (current_offset != 0)
		res->data = data->permute(nested_perm, current_offset);

	return res;
}