TODO(Xiyang): we don't apply SIP from build to probe.
| 325 | |
| 326 | // TODO(Xiyang): we don't apply SIP from build to probe. |
| 327 | void HashJoinSIPOptimizer::visitIntersect(LogicalOperator* op) { |
| 328 | auto& intersect = op->cast<LogicalIntersect>(); |
| 329 | switch (intersect.getSIPInfo().position) { |
| 330 | case SemiMaskPosition::PROHIBIT_PROBE_TO_BUILD: |
| 331 | case SemiMaskPosition::PROHIBIT: |
| 332 | return; |
| 333 | default: |
| 334 | break; |
| 335 | } |
| 336 | if (!isProbeSideQualified(op->getChild(0).get())) { |
| 337 | return; |
| 338 | } |
| 339 | auto probeRoot = intersect.getChild(0); |
| 340 | auto hasSemiMaskApplied = false; |
| 341 | for (auto& nodeID : intersect.getKeyNodeIDs()) { |
| 342 | std::vector<LogicalOperator*> ops; |
| 343 | for (auto i = 1u; i < intersect.getNumChildren(); ++i) { |
| 344 | auto buildRoot = intersect.getChild(i); |
| 345 | for (auto& op_ : getScanNodeCandidates(*nodeID, buildRoot.get())) { |
| 346 | ops.push_back(op_); |
| 347 | } |
| 348 | } |
| 349 | if (!ops.empty()) { |
| 350 | probeRoot = appendSemiMasker(SemiMaskKeyType::NODE, SemiMaskTargetType::SCAN_NODE, |
| 351 | nodeID, ops, probeRoot); |
| 352 | hasSemiMaskApplied = true; |
| 353 | } |
| 354 | } |
| 355 | if (!hasSemiMaskApplied) { |
| 356 | return; |
| 357 | } |
| 358 | auto& sipInfo = intersect.getSIPInfoUnsafe(); |
| 359 | sipInfo.position = SemiMaskPosition::ON_PROBE; |
| 360 | sipInfo.dependency = SIPDependency::PROBE_DEPENDS_ON_BUILD; |
| 361 | sipInfo.direction = SIPDirection::PROBE_TO_BUILD; |
| 362 | intersect.setChild(0, appendAccumulate(probeRoot)); |
| 363 | } |
| 364 | |
| 365 | void HashJoinSIPOptimizer::visitPathPropertyProbe(LogicalOperator* op) { |
| 366 | auto& pathPropertyProbe = op->cast<LogicalPathPropertyProbe>(); |
nothing calls this directly
no test coverage detected