| 1280 | |
| 1281 | template <ASTTableJoin::Kind KIND, ASTTableJoin::Strictness STRICTNESS, typename Maps> |
| 1282 | Block HashJoin::joinBlockImpl( |
| 1283 | Block & block, |
| 1284 | const Names & key_names_left, |
| 1285 | const Block & block_with_columns_to_add, |
| 1286 | const Maps & maps_, |
| 1287 | bool is_join_get) const |
| 1288 | { |
| 1289 | JoinFeatures<KIND, STRICTNESS, false> join_feature; |
| 1290 | |
| 1291 | /// Rare case, when keys are constant or low cardinality. To avoid code bloat, simply materialize them. |
| 1292 | const auto *null_safe_columns = table_join->keyIdsNullSafe(); |
| 1293 | Columns materialized_keys = JoinCommon::materializeColumns(block, key_names_left, null_safe_columns); |
| 1294 | ColumnRawPtrs left_key_columns = JoinCommon::getRawPointers(materialized_keys); |
| 1295 | |
| 1296 | /// Keys with NULL value in any column won't join to anything. |
| 1297 | ConstNullMapPtr null_map{}; |
| 1298 | ColumnPtr null_map_holder = extractNestedColumnsAndNullMap(left_key_columns, null_map, null_safe_columns); |
| 1299 | |
| 1300 | size_t existing_columns = block.columns(); |
| 1301 | |
| 1302 | /** If you use FULL or RIGHT JOIN, then the columns from the "left" table must be materialized. |
| 1303 | * Because if they are constants, then in the "not joined" rows, they may have different values |
| 1304 | * - default values, which can differ from the values of these constants. |
| 1305 | */ |
| 1306 | if constexpr (join_feature.right || join_feature.full) |
| 1307 | { |
| 1308 | materializeBlockInplace(block); |
| 1309 | if (nullable_left_side) |
| 1310 | JoinCommon::convertColumnsToNullable(block); |
| 1311 | } |
| 1312 | |
| 1313 | /** For LEFT/INNER JOIN, the saved blocks do not contain keys. |
| 1314 | * For FULL/RIGHT JOIN, the saved blocks contain keys; |
| 1315 | * but they will not be used at this stage of joining (and will be in `AdderNonJoined`), and they need to be skipped. |
| 1316 | * For ASOF, the last column is used as the ASOF column |
| 1317 | */ |
| 1318 | AddedColumns added_columns(block_with_columns_to_add, block, savedBlockSample(), *this, left_key_columns, key_sizes, join_feature.is_asof_join, is_join_get); |
| 1319 | bool has_required_right_keys = (required_right_keys.columns() != 0); |
| 1320 | added_columns.need_filter = join_feature.need_filter || has_required_right_keys; |
| 1321 | Stopwatch watch; |
| 1322 | added_columns.max_joined_block_rows = table_join->maxJoinedBlockRows(); |
| 1323 | if (!added_columns.max_joined_block_rows) |
| 1324 | added_columns.max_joined_block_rows = std::numeric_limits<size_t>::max(); |
| 1325 | else |
| 1326 | added_columns.reserve(join_feature.need_replication); |
| 1327 | |
| 1328 | size_t num_joined = overDictionary() ? |
| 1329 | dictionaryJoinRightColumns<KIND, STRICTNESS>(*table_join, added_columns, null_map) : |
| 1330 | switchJoinRightColumns<KIND, STRICTNESS>(maps_, added_columns, data->type, null_map, used_flags, false); |
| 1331 | Block remaining_block = sliceBlock(block, num_joined); |
| 1332 | |
| 1333 | for (size_t i = 0; i < added_columns.size(); ++i) |
| 1334 | block.insert(added_columns.moveColumn(i)); |
| 1335 | |
| 1336 | std::vector<size_t> right_keys_to_replicate [[maybe_unused]]; |
| 1337 | |
| 1338 | if (join_feature.need_filter) |
| 1339 | { |
nothing calls this directly
no test coverage detected