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; }
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)); }
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); }
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); }
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; }
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; }
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]); }
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; }
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); }
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); }
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); }
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; }