예제 #1
0
ColumnPtr ColumnArray::replicateNumber(const Offsets_t & 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();

	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();

	typename ColumnVector<T>::Container_t & res_data = typeid_cast<ColumnVector<T> &>(res_.getData()).getData();
	Offsets_t & 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;

	for (size_t i = 0; i < col_size; ++i)
	{
		size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset;
		size_t value_size = src_offsets[i] - prev_data_offset;

		for (size_t j = 0; j < size_to_replicate; ++j)
		{
			current_new_offset += value_size;
			res_offsets.push_back(current_new_offset);

			res_data.resize(res_data.size() + value_size);
			memcpy(&res_data[res_data.size() - value_size], &src_data[prev_data_offset], value_size * sizeof(T));
		}

		prev_replicate_offset = replicate_offsets[i];
		prev_data_offset = src_offsets[i];
	}

	return res;
}
예제 #2
0
ColumnPtr ColumnString::replicate(const Offsets_t & 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>();

    if (0 == col_size)
        return res;

    Chars_t & res_chars = res->chars;
    Offsets_t & 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;

    for (size_t i = 0; i < col_size; ++i)
    {
        size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset;
        size_t string_size = offsets[i] - prev_string_offset;

        for (size_t j = 0; j < size_to_replicate; ++j)
        {
            current_new_offset += string_size;
            res_offsets.push_back(current_new_offset);

            res_chars.resize(res_chars.size() + string_size);
            memcpySmallAllowReadWriteOverflow15(
                &res_chars[res_chars.size() - string_size], &chars[prev_string_offset], string_size);
        }

        prev_replicate_offset = replicate_offsets[i];
        prev_string_offset = offsets[i];
    }

    return res;
}
예제 #3
0
ColumnPtr ColumnArray::replicateConst(const Offsets_t & 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);

	if (0 == col_size)
		return cloneEmpty();

	const Offsets_t & src_offsets = getOffsets();

	auto res_column_offsets = std::make_shared<ColumnOffsets_t>();
	Offsets_t & 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;

	for (size_t i = 0; i < col_size; ++i)
	{
		size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset;
		size_t value_size = src_offsets[i] - prev_data_offset;

		for (size_t j = 0; j < size_to_replicate; ++j)
		{
			current_new_offset += value_size;
			res_offsets.push_back(current_new_offset);
		}

		prev_replicate_offset = replicate_offsets[i];
		prev_data_offset = src_offsets[i];
	}

	return std::make_shared<ColumnArray>(getData().cloneResized(current_new_offset), res_column_offsets);
}
예제 #4
0
ColumnPtr ColumnArray::replicateString(const Offsets_t & 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();

	if (0 == col_size)
		return res;

	ColumnArray & res_ = static_cast<ColumnArray &>(*res);

	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();

	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();

	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_t prev_src_offset = 0;
	Offset_t prev_src_string_offset = 0;

	Offset_t current_res_offset = 0;
	Offset_t current_res_string_offset = 0;

	for (size_t i = 0; i < col_size; ++i)
	{
		/// Насколько размножить массив.
		size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset;
		/// Количество строк в массиве.
		size_t value_size = src_offsets[i] - prev_src_offset;
		/// Количество символов в строках массива, включая нулевые байты.
		size_t sum_chars_size = value_size == 0 ? 0 : (src_string_offsets[prev_src_offset + value_size - 1] - prev_src_string_offset);

		for (size_t j = 0; j < size_to_replicate; ++j)
		{
			current_res_offset += value_size;
			res_offsets.push_back(current_res_offset);

			size_t prev_src_string_offset_local = prev_src_string_offset;
			for (size_t k = 0; k < value_size; ++k)
			{
				/// Размер одной строки.
				size_t chars_size = src_string_offsets[k + prev_src_offset] - prev_src_string_offset_local;

				current_res_string_offset += chars_size;
				res_string_offsets.push_back(current_res_string_offset);

				prev_src_string_offset_local += chars_size;
			}

			/// Копирование символов массива строк.
			res_chars.resize(res_chars.size() + sum_chars_size);
			memcpySmallAllowReadWriteOverflow15(
				&res_chars[res_chars.size() - sum_chars_size], &src_chars[prev_src_string_offset], sum_chars_size);
		}

		prev_replicate_offset = replicate_offsets[i];
		prev_src_offset = src_offsets[i];
		prev_src_string_offset += sum_chars_size;
	}

	return res;
}