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