| 308 | } |
| 309 | |
| 310 | std::shared_ptr<Schema> HashJoinSchema::MakeOutputSchema( |
| 311 | const std::string& left_field_name_suffix, |
| 312 | const std::string& right_field_name_suffix) { |
| 313 | std::vector<std::shared_ptr<Field>> fields; |
| 314 | int left_size = proj_maps[0].num_cols(HashJoinProjection::OUTPUT); |
| 315 | int right_size = proj_maps[1].num_cols(HashJoinProjection::OUTPUT); |
| 316 | fields.resize(left_size + right_size); |
| 317 | |
| 318 | std::unordered_multimap<std::string, int> left_field_map; |
| 319 | left_field_map.reserve(left_size); |
| 320 | for (int i = 0; i < left_size; ++i) { |
| 321 | int side = 0; // left |
| 322 | int input_field_id = |
| 323 | proj_maps[side].map(HashJoinProjection::OUTPUT, HashJoinProjection::INPUT).get(i); |
| 324 | const std::string& input_field_name = |
| 325 | proj_maps[side].field_name(HashJoinProjection::INPUT, input_field_id); |
| 326 | const std::shared_ptr<DataType>& input_data_type = |
| 327 | proj_maps[side].data_type(HashJoinProjection::INPUT, input_field_id); |
| 328 | left_field_map.insert({input_field_name, i}); |
| 329 | // insert left table field |
| 330 | fields[i] = |
| 331 | std::make_shared<Field>(input_field_name, input_data_type, true /*nullable*/); |
| 332 | } |
| 333 | |
| 334 | for (int i = 0; i < right_size; ++i) { |
| 335 | int side = 1; // right |
| 336 | int input_field_id = |
| 337 | proj_maps[side].map(HashJoinProjection::OUTPUT, HashJoinProjection::INPUT).get(i); |
| 338 | const std::string& input_field_name = |
| 339 | proj_maps[side].field_name(HashJoinProjection::INPUT, input_field_id); |
| 340 | const std::shared_ptr<DataType>& input_data_type = |
| 341 | proj_maps[side].data_type(HashJoinProjection::INPUT, input_field_id); |
| 342 | // search the map and add suffix to the elements which |
| 343 | // are present both in left and right tables |
| 344 | auto search_it = left_field_map.equal_range(input_field_name); |
| 345 | bool match_found = false; |
| 346 | for (auto search = search_it.first; search != search_it.second; ++search) { |
| 347 | match_found = true; |
| 348 | auto left_val = search->first; |
| 349 | auto left_index = search->second; |
| 350 | auto left_field = fields[left_index]; |
| 351 | // update left table field with suffix |
| 352 | fields[left_index] = |
| 353 | std::make_shared<Field>(input_field_name + left_field_name_suffix, |
| 354 | left_field->type(), true /*nullable*/); |
| 355 | // insert right table field with suffix |
| 356 | fields[left_size + i] = std::make_shared<Field>( |
| 357 | input_field_name + right_field_name_suffix, input_data_type, true /*nullable*/); |
| 358 | } |
| 359 | |
| 360 | if (!match_found) { |
| 361 | // insert right table field without suffix |
| 362 | fields[left_size + i] = |
| 363 | std::make_shared<Field>(input_field_name, input_data_type, true /*nullable*/); |
| 364 | } |
| 365 | } |
| 366 | return std::make_shared<Schema>(std::move(fields)); |
| 367 | } |