| 415 | } |
| 416 | |
| 417 | void HashProbe::asyncWaitForHashTable() { |
| 418 | checkRunning(); |
| 419 | BOLT_CHECK_NULL(table_); |
| 420 | |
| 421 | auto hashBuildResult = joinBridge_->tableOrFuture(&future_); |
| 422 | if (!hashBuildResult.has_value()) { |
| 423 | BOLT_CHECK(future_.valid()); |
| 424 | setState(ProbeOperatorState::kWaitForBuild); |
| 425 | return; |
| 426 | } |
| 427 | |
| 428 | if (hashBuildResult->hasNullKeys) { |
| 429 | BOLT_CHECK(nullAware_); |
| 430 | if (isAntiJoin(joinType_) && !joinNode_->filter()) { |
| 431 | // Null-aware anti join with null keys on the build side without a filter |
| 432 | // always returns nothing. |
| 433 | // The flag must be set on the first (and only) built 'table_'. |
| 434 | BOLT_CHECK(spillPartitionSet_.empty()); |
| 435 | noMoreInput(); |
| 436 | return; |
| 437 | } |
| 438 | buildSideHasNullKeys_ = true; |
| 439 | } |
| 440 | |
| 441 | table_ = std::move(hashBuildResult->table); |
| 442 | BOLT_CHECK_NOT_NULL(table_); |
| 443 | |
| 444 | maybeSetupSpillInput( |
| 445 | hashBuildResult->restoredPartitionId, |
| 446 | hashBuildResult->spillPartitionIds, |
| 447 | hashBuildResult->offsetToJoinBits); |
| 448 | |
| 449 | if (table_->numDistinct() == 0) { |
| 450 | if (skipProbeOnEmptyBuild()) { |
| 451 | if (!needSpillInput()) { |
| 452 | if (isSpillInput() || |
| 453 | operatorCtx_->driverCtx() |
| 454 | ->queryConfig() |
| 455 | .hashProbeFinishEarlyOnEmptyBuild()) { |
| 456 | noMoreInput(); |
| 457 | } else { |
| 458 | skipInput_ = true; |
| 459 | } |
| 460 | } |
| 461 | } |
| 462 | } else if ( |
| 463 | (isInnerJoin(joinType_) || isLeftSemiFilterJoin(joinType_) || |
| 464 | isRightSemiFilterJoin(joinType_) || isRightSemiProjectJoin(joinType_) || |
| 465 | isRightJoin(joinType_)) && |
| 466 | table_->hashMode() != BaseHashTable::HashMode::kHash && !isSpillInput() && |
| 467 | !hasMoreSpillData()) { |
| 468 | // Find out whether there are any upstream operators that can accept |
| 469 | // dynamic filters on all or a subset of the join keys. Create dynamic |
| 470 | // filters to push down. |
| 471 | // |
| 472 | // NOTE: this optimization is not applied in the following cases: (1) if the |
| 473 | // probe input is read from spilled data and there is no upstream operators |
| 474 | // involved; (2) if there is spill data to restore, then we can't filter |
nothing calls this directly
no test coverage detected