| 376 | // CreateOutputRow, EvalOtherJoinConjuncts, and EvalConjuncts are replaced by codegen. |
| 377 | template <int const JoinOp> |
| 378 | int PartitionedHashJoinNode::ProcessProbeBatch(TPrefetchMode::type prefetch_mode, |
| 379 | RowBatch* out_batch, HashTableCtx* __restrict__ ht_ctx, Status* __restrict__ status) { |
| 380 | DCHECK(builder_->state() == HashJoinState::PARTITIONING_PROBE |
| 381 | || builder_->state() == HashJoinState::PROBING_SPILLED_PARTITION |
| 382 | || builder_->state() == HashJoinState::REPARTITIONING_PROBE); |
| 383 | ScalarExprEvaluator* const* other_join_conjunct_evals = |
| 384 | other_join_conjunct_evals_.data(); |
| 385 | const int num_other_join_conjuncts = other_join_conjunct_evals_.size(); |
| 386 | ScalarExprEvaluator* const* conjunct_evals = conjunct_evals_.data(); |
| 387 | const int num_conjuncts = conjunct_evals_.size(); |
| 388 | |
| 389 | DCHECK(!out_batch->AtCapacity()); |
| 390 | DCHECK_GE(probe_batch_pos_, 0); |
| 391 | RowBatch::Iterator out_batch_iterator(out_batch, out_batch->AddRow()); |
| 392 | const int max_rows = out_batch->capacity() - out_batch->num_rows(); |
| 393 | // Note that 'probe_batch_pos_' is the row no. of the row after 'current_probe_row_'. |
| 394 | RowBatch::Iterator probe_batch_iterator(probe_batch_.get(), probe_batch_pos_); |
| 395 | int remaining_capacity = max_rows; |
| 396 | HashTableCtx::ExprValuesCache* expr_vals_cache = ht_ctx->expr_values_cache(); |
| 397 | |
| 398 | // Keep processing more probe rows if there are more to process and the output batch |
| 399 | // has room and we haven't hit any error yet. |
| 400 | while ((current_probe_row_ != nullptr || !probe_batch_iterator.AtEnd()) |
| 401 | && remaining_capacity > 0 && status->ok()) { |
| 402 | // Prefetch for the current hash_tbl_iterator_. |
| 403 | if (prefetch_mode != TPrefetchMode::NONE) { |
| 404 | hash_tbl_iterator_.PrefetchBucket<true>(); |
| 405 | } |
| 406 | // Evaluate and hash more rows if prefetch group is empty. A prefetch group is a cache |
| 407 | // of probe expressions results, nullness of the expression values and hash values |
| 408 | // against some consecutive number of rows in the probe batch. Prefetching, if |
| 409 | // enabled, is interleaved with the rows' evaluation and hashing. If the prefetch |
| 410 | // group is partially full (e.g. we returned before the current prefetch group was |
| 411 | // exhausted in the previous iteration), we will proceed with the remaining items in |
| 412 | // the values cache. |
| 413 | if (expr_vals_cache->AtEnd()) { |
| 414 | EvalAndHashProbePrefetchGroup(prefetch_mode, ht_ctx); |
| 415 | } |
| 416 | // Process the prefetch group. |
| 417 | do { |
| 418 | // 'current_probe_row_' can be NULL on the first iteration through this loop. |
| 419 | if (current_probe_row_ != NULL) { |
| 420 | if (!ProcessProbeRow<JoinOp>(other_join_conjunct_evals, |
| 421 | num_other_join_conjuncts, conjunct_evals, num_conjuncts, |
| 422 | &out_batch_iterator, &remaining_capacity, status)) { |
| 423 | if (status->ok()) DCHECK_EQ(remaining_capacity, 0); |
| 424 | break; |
| 425 | } |
| 426 | } |
| 427 | // Must have reached the end of the hash table iterator for the current row before |
| 428 | // moving to the next row. |
| 429 | DCHECK(hash_tbl_iterator_.AtEnd()); |
| 430 | DCHECK(status->ok()); |
| 431 | } while (NextProbeRow<JoinOp>(ht_ctx, &probe_batch_iterator, &remaining_capacity, |
| 432 | status)); |
| 433 | // NextProbeRow() returns false either when it exhausts its input or hits |
| 434 | // an error. Otherwise we must have filled up the output batch. |
| 435 | DCHECK((ht_ctx->expr_values_cache()->AtEnd() && current_probe_row_ == nullptr) |
nothing calls this directly
no test coverage detected