| 1386 | } // namespace |
| 1387 | |
| 1388 | void HashProbe::applyFilterOnTableRowsForNullAwareJoin( |
| 1389 | const SelectivityVector& rows, |
| 1390 | SelectivityVector& filterPassedRows, |
| 1391 | std::function<int32_t(char**, int32_t)> iterator) { |
| 1392 | if (!rows.hasSelections()) { |
| 1393 | return; |
| 1394 | } |
| 1395 | auto* tableRows = table_->rows(); |
| 1396 | auto* hybridData = table_->hybridData(); |
| 1397 | std::vector<HybridRowId> outputRowIds; |
| 1398 | BOLT_CHECK(tableRows, "Should not move rows in hash joins"); |
| 1399 | char* data[kBatchSize]; |
| 1400 | while (auto numRows = iterator(data, kBatchSize)) { |
| 1401 | filterTableInput_->resize(numRows); |
| 1402 | filterTableInputRows_.resizeFill(numRows, true); |
| 1403 | if (hybridData != nullptr) { |
| 1404 | outputRowIds.resize(numRows); |
| 1405 | hybridData->getRowIds(data, numRows, outputRowIds); |
| 1406 | |
| 1407 | // For single container, extract directly without sorting. |
| 1408 | // For multiple containers, sort by containerId for better cache locality. |
| 1409 | const bool useSorting = hybridData->shouldUseSorting(); |
| 1410 | const char* const* extractRows = data; |
| 1411 | std::vector<HybridRowId>* extractRowIds = &outputRowIds; |
| 1412 | HybridContainer::SortedRows sorted; |
| 1413 | |
| 1414 | if (useSorting) { |
| 1415 | sorted = hybridData->sortByContainerId( |
| 1416 | data, folly::Range<const vector_size_t*>{}, outputRowIds); |
| 1417 | extractRows = sorted.rows.data(); |
| 1418 | extractRowIds = &sorted.rowIds; |
| 1419 | } |
| 1420 | |
| 1421 | for (auto& projection : filterTableProjections_) { |
| 1422 | hybridData->extractColumn( |
| 1423 | extractRows, |
| 1424 | extractRowIds->size(), |
| 1425 | projection.inputChannel, |
| 1426 | filterTableInput_->childAt(projection.outputChannel), |
| 1427 | *extractRowIds); |
| 1428 | } |
| 1429 | } else { |
| 1430 | for (auto& projection : filterTableProjections_) { |
| 1431 | tableRows->extractColumn( |
| 1432 | data, |
| 1433 | numRows, |
| 1434 | projection.inputChannel, |
| 1435 | filterTableInput_->childAt(projection.outputChannel)); |
| 1436 | } |
| 1437 | } |
| 1438 | rows.applyToSelected([&](vector_size_t row) { |
| 1439 | for (auto& projection : filterInputProjections_) { |
| 1440 | filterTableInput_->childAt(projection.outputChannel) = |
| 1441 | BaseVector::wrapInConstant( |
| 1442 | numRows, row, input_->childAt(projection.inputChannel)); |
| 1443 | } |
| 1444 | EvalCtx evalCtx( |
| 1445 | operatorCtx_->execCtx(), filter_.get(), filterTableInput_.get()); |
nothing calls this directly
no test coverage detected