ColumnPtr 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); MutableColumnPtr res = cloneEmpty(); if (0 == col_size) return res; ColumnArray & res_ = typeid_cast<ColumnArray &>(*res); const typename ColumnVector<T>::Container & src_data = typeid_cast<const ColumnVector<T> &>(*data).getData(); const Offsets & src_offsets = 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 prev_replicate_offset = 0; Offset prev_data_offset = 0; Offset 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); if (value_size) { 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; }
ColumnPtr 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); auto res = ColumnFixedString::create(n); if (0 == col_size) return std::move(res); Chars_t & res_chars = res->chars; res_chars.resize(n * offsets.back()); 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 std::move(res); }
ColumnPtr ColumnArray::replicateConst(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); if (0 == col_size) return cloneEmpty(); const Offsets & src_offsets = getOffsets(); auto res_column_offsets = ColumnOffsets::create(); Offsets & res_offsets = res_column_offsets->getData(); res_offsets.reserve(replicate_offsets.back()); Offset prev_replicate_offset = 0; Offset prev_data_offset = 0; Offset 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 ColumnArray::create(getData().cloneResized(current_new_offset), std::move(res_column_offsets)); }
ColumnPtr 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); MutableColumnPtr 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 & src_chars = src_string.getChars(); const Offsets & src_string_offsets = src_string.getOffsets(); const Offsets & src_offsets = getOffsets(); ColumnString::Chars & res_chars = typeid_cast<ColumnString &>(res_.getData()).getChars(); 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 prev_replicate_offset = 0; Offset prev_src_offset = 0; Offset prev_src_string_offset = 0; Offset current_res_offset = 0; Offset current_res_string_offset = 0; for (size_t i = 0; i < col_size; ++i) { /// How much to replicate the array. size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset; /// The number of rows in the array. size_t value_size = src_offsets[i] - prev_src_offset; /// Number of characters in rows of the array, including zero/null bytes. 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 of one row. 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; } if (sum_chars_size) { /// Copies the characters of the array of rows. 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; }