Verify that dynamic filter pushed down from null-aware right semi project join into table scan doesn't filter out nulls.
| 3615 | {"t0"}, |
| 3616 | { |
| 3617 | makeNullableFlatVector<int32_t>({1, std::nullopt, 2}), |
| 3618 | }); |
| 3619 | |
| 3620 | auto build = makeRowVector( |
| 3621 | {"u0"}, |
| 3622 | { |
| 3623 | makeNullableFlatVector<int32_t>({1, 2, 3, std::nullopt}), |
| 3624 | }); |
| 3625 | |
| 3626 | std::shared_ptr<TempFilePath> probeFile = TempFilePath::create(); |
| 3627 | writeToFile(probeFile->path, {probe}); |
| 3628 | |
| 3629 | std::shared_ptr<TempFilePath> buildFile = TempFilePath::create(); |
| 3630 | writeToFile(buildFile->path, {build}); |
| 3631 | |
| 3632 | createDuckDbTable("t", {probe}); |
| 3633 | createDuckDbTable("u", {build}); |
| 3634 | |
| 3635 | core::PlanNodeId probeScanId; |
| 3636 | core::PlanNodeId buildScanId; |
| 3637 | auto planNodeIdGenerator = std::make_shared<core::PlanNodeIdGenerator>(); |
| 3638 | auto plan = PlanBuilder(planNodeIdGenerator) |
| 3639 | .tableScan(asRowType(probe->type())) |
| 3640 | .capturePlanNodeId(probeScanId) |
| 3641 | .hashJoin( |
| 3642 | {"t0"}, |
| 3643 | {"u0"}, |
| 3644 | PlanBuilder(planNodeIdGenerator) |
| 3645 | .tableScan(asRowType(build->type())) |
| 3646 | .capturePlanNodeId(buildScanId) |
| 3647 | .planNode(), |
| 3648 | "", |
| 3649 | {"u0", "match"}, |
| 3650 | core::JoinType::kRightSemiProject, |
| 3651 | true /*nullAware*/) |
| 3652 | .planNode(); |
| 3653 | |
| 3654 | SplitInput splitInput = { |
| 3655 | {probeScanId, {exec::Split(makeHiveConnectorSplit(probeFile->path))}}, |
| 3656 | {buildScanId, {exec::Split(makeHiveConnectorSplit(buildFile->path))}}, |
| 3657 | }; |
| 3658 | |
| 3659 | HashJoinBuilder(*pool_, duckDbQueryRunner_, driverExecutor_.get()) |
| 3660 | .planNode(plan) |
| 3661 | .inputSplits(splitInput) |
| 3662 | .checkSpillStats(false) |
| 3663 | .referenceQuery("SELECT u0, u0 IN (SELECT t0 FROM t) FROM u") |
| 3664 | .run(); |
| 3665 | } |
| 3666 | |
| 3667 | TEST_F(HashJoinTest, duplicateJoinKeys) { |
| 3668 | auto leftVectors = makeBatches(3, [&](int32_t /*unused*/) { |
| 3669 | return makeRowVector({ |
| 3670 | makeNullableFlatVector<int64_t>( |
| 3671 | {1, 2, 2, 3, 3, std::nullopt, 4, 5, 5, 6, 7}), |
| 3672 | makeNullableFlatVector<int64_t>( |
nothing calls this directly
no test coverage detected