From 32dabe1396bb8b602e82c30505d12247738afe38 Mon Sep 17 00:00:00 2001 From: Daniel Hunte Date: Mon, 23 Dec 2024 14:47:07 -0800 Subject: [PATCH] feat(fuzzer): Update "makeDefaultPlan" function to generate multi-join plans (#11939) Summary: Generates a cascading multi-join from left to right. ``` [t1, t2, t3, t4] t1 t2 \ / a t3 \ / b t4 \ / c ``` Differential Revision: D67607316 --- velox/exec/fuzzer/JoinFuzzer.cpp | 99 +++++++++++++++++--------------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/velox/exec/fuzzer/JoinFuzzer.cpp b/velox/exec/fuzzer/JoinFuzzer.cpp index 5d3f424f9e5c..c3d60e4c02c3 100644 --- a/velox/exec/fuzzer/JoinFuzzer.cpp +++ b/velox/exec/fuzzer/JoinFuzzer.cpp @@ -135,20 +135,18 @@ class JoinFuzzer { // Randomly pick a join type to test. core::JoinType pickJoinType(); - // Makes the query plan with default settings in JoinFuzzer and value inputs - // for both probe and build sides. + // Makes the query plan with default settings in JoinFuzzer using inputs + // joining each input from left to right. // - // NOTE: 'probeInput' and 'buildInput' could either input rows with lazy - // vectors or flatten ones. + // NOTE: inputs can be rows with lazy vectors or flattened ones. JoinFuzzer::PlanWithSplits makeDefaultPlan( - core::JoinType joinType, - bool nullAware, - const std::vector& probeKeys, - const std::vector& buildKeys, - const std::vector& probeInput, - const std::vector& buildInput, - const std::vector& outputColumns, - const std::string& filter); + const std::vector& joinTypes, + const std::vector& nullAwareList, + const std::vector>& probeKeysList, + const std::vector>& buildKeysList, + const std::vector>& inputs, + const std::vector>& outputColumnsList, + const std::vector& filterList); JoinFuzzer::PlanWithSplits makeMergeJoinPlan( core::JoinType joinType, @@ -735,28 +733,37 @@ std::vector fieldNames( } JoinFuzzer::PlanWithSplits JoinFuzzer::makeDefaultPlan( - core::JoinType joinType, - bool nullAware, - const std::vector& probeKeys, - const std::vector& buildKeys, - const std::vector& probeInput, - const std::vector& buildInput, - const std::vector& outputColumns, - const std::string& filter) { + const std::vector& joinTypes, + const std::vector& nullAwareList, + const std::vector>& probeKeysList, + const std::vector>& buildKeysList, + const std::vector>& inputs, + const std::vector>& outputColumnsList, + const std::vector& filterList) { + VELOX_CHECK(inputs.size() > 1); auto planNodeIdGenerator = std::make_shared(); - auto plan = + PlanBuilder plan = PlanBuilder(planNodeIdGenerator) - .values(probeInput) + .values(inputs[0]) .hashJoin( - probeKeys, - buildKeys, - PlanBuilder(planNodeIdGenerator).values(buildInput).planNode(), - filter, - outputColumns, - joinType, - nullAware) - .planNode(); - return PlanWithSplits{plan}; + probeKeysList[0], + buildKeysList[0], + PlanBuilder(planNodeIdGenerator).values(inputs[1]).planNode(), + filterList[0], + outputColumnsList[0], + joinTypes[0], + nullAwareList[0]); + for (auto i = 1; i < inputs.size() - 1; i++) { + plan = plan.hashJoin( + probeKeysList[i], + buildKeysList[i], + PlanBuilder(planNodeIdGenerator).values(inputs[i + 1]).planNode(), + filterList[i], + outputColumnsList[i], + joinTypes[i], + nullAwareList[i]); + } + return PlanWithSplits{plan.planNode()}; } JoinFuzzer::PlanWithSplits JoinFuzzer::makeDefaultPlanWithTableScan( @@ -1176,14 +1183,13 @@ void JoinFuzzer::verify(core::JoinType joinType) { shuffleJoinKeys(probeKeys, buildKeys); const auto defaultPlan = makeDefaultPlan( - joinType, - nullAware, - probeKeys, - buildKeys, - probeInput, - buildInput, - outputColumns, - filter); + {joinType}, + {nullAware}, + {probeKeys}, + {buildKeys}, + {probeInput, buildInput}, + {outputColumns}, + {filter}); const auto expected = execute(defaultPlan, /*injectSpill=*/false); @@ -1206,14 +1212,13 @@ void JoinFuzzer::verify(core::JoinType joinType) { std::vector altPlans; altPlans.push_back(makeDefaultPlan( - joinType, - nullAware, - probeKeys, - buildKeys, - flatProbeInput, - flatBuildInput, - outputColumns, - filter)); + {joinType}, + {nullAware}, + {probeKeys}, + {buildKeys}, + {flatProbeInput, flatBuildInput}, + {outputColumns}, + {filter})); makeAlternativePlans( defaultPlan.plan, probeInput, buildInput, altPlans, filter);