| 431 | } |
| 432 | |
| 433 | const uint64_t* DecodedVector::nulls(const SelectivityVector* rows) { |
| 434 | if (allNulls_.has_value()) { |
| 435 | return allNulls_.value(); |
| 436 | } |
| 437 | |
| 438 | if (hasExtraNulls_) { |
| 439 | allNulls_ = nulls_; |
| 440 | } else if (!nulls_ || size_ == 0) { |
| 441 | allNulls_ = nullptr; |
| 442 | } else { |
| 443 | if (isIdentityMapping_) { |
| 444 | allNulls_ = nulls_; |
| 445 | } else if (isConstantMapping_) { |
| 446 | copiedNulls_.resize(0); |
| 447 | copiedNulls_.resize(bits::nwords(size_), bits::kNull64); |
| 448 | allNulls_ = copiedNulls_.data(); |
| 449 | } else { |
| 450 | // Copy base nulls. |
| 451 | copiedNulls_.resize(bits::nwords(size_)); |
| 452 | auto* rawCopiedNulls = copiedNulls_.data(); |
| 453 | if (rows != nullptr) { |
| 454 | // Partial consistency check: The end may be less than the decode time |
| 455 | // end but not greater. |
| 456 | BOLT_CHECK_LE(rows->end(), size_); |
| 457 | } |
| 458 | auto baseSize = baseVector_->size(); |
| 459 | applyToRows(rows, [&](auto i) { |
| 460 | BOLT_DCHECK_LT(indices_[i], baseSize); |
| 461 | bits::setNull(rawCopiedNulls, i, bits::isBitNull(nulls_, indices_[i])); |
| 462 | }); |
| 463 | allNulls_ = copiedNulls_.data(); |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | return allNulls_.value(); |
| 468 | } |
| 469 | |
| 470 | template <typename Func> |
| 471 | void DecodedVector::applyToRows(const SelectivityVector* rows, Func&& func) |