| 429 | } |
| 430 | |
| 431 | Status NestedLoopJoinNode::GetNextRightSemiJoin(RuntimeState* state, |
| 432 | RowBatch* output_batch) { |
| 433 | ScalarExprEvaluator* const* join_conjunct_evals = join_conjunct_evals_.data(); |
| 434 | size_t num_join_conjuncts = join_conjuncts_.size(); |
| 435 | DCHECK_EQ(num_join_conjuncts, join_conjunct_evals_.size()); |
| 436 | DCHECK(matching_build_rows_ != NULL); |
| 437 | const int N = BitUtil::RoundUpToPowerOfTwo(state->batch_size()); |
| 438 | |
| 439 | while (!eos_) { |
| 440 | DCHECK(HasValidProbeRow()); |
| 441 | while (!build_row_iterator_.AtEnd()) { |
| 442 | DCHECK(HasValidProbeRow()); |
| 443 | // This loop can go on for a long time if the conjuncts are very selective. |
| 444 | // Do query maintenance every N iterations. |
| 445 | if ((current_build_row_idx_ & (N - 1)) == 0) { |
| 446 | if (ReachedLimit()) { |
| 447 | eos_ = true; |
| 448 | return Status::OK(); |
| 449 | } |
| 450 | RETURN_IF_CANCELLED(state); |
| 451 | RETURN_IF_ERROR(QueryMaintenance(state)); |
| 452 | } |
| 453 | |
| 454 | // Check if we already have a match for the build row. |
| 455 | if (matching_build_rows_->Get(current_build_row_idx_)) { |
| 456 | build_row_iterator_.Next(); |
| 457 | ++current_build_row_idx_; |
| 458 | continue; |
| 459 | } |
| 460 | CreateOutputRow(semi_join_staging_row_, current_probe_row_, |
| 461 | build_row_iterator_.GetRow()); |
| 462 | // Evaluate the join conjuncts on the semi-join staging row. |
| 463 | if (!EvalConjuncts( |
| 464 | join_conjunct_evals, num_join_conjuncts, semi_join_staging_row_)) { |
| 465 | build_row_iterator_.Next(); |
| 466 | ++current_build_row_idx_; |
| 467 | continue; |
| 468 | } |
| 469 | TupleRow* output_row = output_batch->GetRow(output_batch->AddRow()); |
| 470 | matching_build_rows_->Set(current_build_row_idx_, true); |
| 471 | output_batch->CopyRow(build_row_iterator_.GetRow(), output_row); |
| 472 | build_row_iterator_.Next(); |
| 473 | ++current_build_row_idx_; |
| 474 | VLOG_ROW << "match row: " << PrintRow(output_row, *row_desc()); |
| 475 | output_batch->CommitLastRow(); |
| 476 | IncrementNumRowsReturned(1); |
| 477 | if (output_batch->AtCapacity()) return Status::OK(); |
| 478 | } |
| 479 | RETURN_IF_ERROR(NextProbeRow(state, output_batch)); |
| 480 | if (output_batch->AtCapacity()) break; |
| 481 | } |
| 482 | return Status::OK(); |
| 483 | } |
| 484 | |
| 485 | Status NestedLoopJoinNode::GetNextRightAntiJoin(RuntimeState* state, |
| 486 | RowBatch* output_batch) { |
nothing calls this directly
no test coverage detected