| 167 | |
| 168 | template <bool nullable> |
| 169 | bool executeString( |
| 170 | const IColumn & src_data, const ColumnArray::Offsets & src_array_offsets, |
| 171 | IColumn & res_data_col, ColumnArray::Offsets & res_array_offsets, |
| 172 | const NullMap * src_null_map, |
| 173 | NullMap * res_null_map) |
| 174 | { |
| 175 | if (const ColumnString * src_data_concrete = checkAndGetColumn<ColumnString>(&src_data)) |
| 176 | { |
| 177 | const ColumnString::Offsets & src_string_offsets = src_data_concrete->getOffsets(); |
| 178 | |
| 179 | auto * concrete_res_string_offsets = typeid_cast<ColumnString *>(&res_data_col); |
| 180 | if (!concrete_res_string_offsets) |
| 181 | throw Exception(ErrorCodes::LOGICAL_ERROR, "Internal error"); |
| 182 | ColumnString::Offsets & res_string_offsets = concrete_res_string_offsets->getOffsets(); |
| 183 | |
| 184 | const ColumnString::Chars & src_data_vec = src_data_concrete->getChars(); |
| 185 | |
| 186 | auto * concrete_res_data = typeid_cast<ColumnString *>(&res_data_col); |
| 187 | if (!concrete_res_data) |
| 188 | throw Exception(ErrorCodes::LOGICAL_ERROR, "Internal error"); |
| 189 | ColumnString::Chars & res_data = concrete_res_data->getChars(); |
| 190 | |
| 191 | size_t size = src_array_offsets.size(); |
| 192 | res_array_offsets.resize(size); |
| 193 | res_string_offsets.reserve(src_string_offsets.size()); |
| 194 | res_data.reserve(src_data_vec.size()); |
| 195 | |
| 196 | if (nullable) |
| 197 | res_null_map->reserve(src_null_map->size()); |
| 198 | |
| 199 | ColumnArray::Offset src_array_prev_offset = 0; |
| 200 | ColumnArray::Offset res_array_prev_offset = 0; |
| 201 | |
| 202 | ColumnString::Offset src_string_prev_offset = 0; |
| 203 | ColumnString::Offset res_string_prev_offset = 0; |
| 204 | |
| 205 | for (size_t i = 0; i < size; ++i) |
| 206 | { |
| 207 | if (src_array_offsets[i] != src_array_prev_offset) |
| 208 | { |
| 209 | size_t array_size = src_array_offsets[i] - src_array_prev_offset; |
| 210 | |
| 211 | size_t bytes_to_copy = 0; |
| 212 | size_t from_string_prev_offset_local = src_string_prev_offset; |
| 213 | for (size_t j = 0; j < array_size; ++j) |
| 214 | { |
| 215 | size_t string_size = src_string_offsets[src_array_prev_offset + j] - from_string_prev_offset_local; |
| 216 | |
| 217 | res_string_prev_offset += string_size; |
| 218 | res_string_offsets.push_back(res_string_prev_offset); |
| 219 | |
| 220 | from_string_prev_offset_local += string_size; |
| 221 | bytes_to_copy += string_size; |
| 222 | } |
| 223 | |
| 224 | size_t res_data_old_size = res_data.size(); |
| 225 | res_data.resize(res_data_old_size + bytes_to_copy); |
| 226 | memcpy(&res_data[res_data_old_size], &src_data_vec[src_string_prev_offset], bytes_to_copy); |
no test coverage detected