| 311 | |
| 312 | template <bool INCLUSIVE_EQUALITY> |
| 313 | bool HashTableCtx::Equals(const TupleRow* build_row, const uint8_t* expr_values, |
| 314 | const uint8_t* expr_values_null) const noexcept { |
| 315 | for (int i = 0; i < build_expr_evals_.size(); ++i) { |
| 316 | void* val = build_expr_evals_[i]->GetValue(build_row); |
| 317 | if (val == NULL) { |
| 318 | if (!(INCLUSIVE_EQUALITY || finds_nulls_[i])) return false; |
| 319 | if (!expr_values_null[i]) return false; |
| 320 | continue; |
| 321 | } else { |
| 322 | if (expr_values_null[i]) return false; |
| 323 | } |
| 324 | |
| 325 | const void* loc = expr_values_cache_.ExprValuePtr(expr_values, i); |
| 326 | DCHECK(build_exprs_[i] == &build_expr_evals_[i]->root()); |
| 327 | |
| 328 | const ColumnType& expr_type = build_exprs_[i]->type(); |
| 329 | if (!RawValue::Eq(loc, val, expr_type)) { |
| 330 | if (INCLUSIVE_EQUALITY) { |
| 331 | bool val_is_nan = RawValue::IsNaN(val, expr_type); |
| 332 | bool local_is_nan = RawValue::IsNaN(loc, expr_type); |
| 333 | if (val_is_nan && local_is_nan) continue; |
| 334 | } |
| 335 | return false; |
| 336 | } |
| 337 | } |
| 338 | return true; |
| 339 | } |
| 340 | template bool HashTableCtx::Equals<true>(const TupleRow* build_row, |
| 341 | const uint8_t* expr_values, const uint8_t* expr_values_null) const; |
| 342 | template bool HashTableCtx::Equals<false>(const TupleRow* build_row, |