diff --git a/Dashboard/Services/PlanAnalyzer.cs b/Dashboard/Services/PlanAnalyzer.cs index a4058a04..e96cf0c2 100644 --- a/Dashboard/Services/PlanAnalyzer.cs +++ b/Dashboard/Services/PlanAnalyzer.cs @@ -399,15 +399,15 @@ private static void AnalyzeNode(PlanNode node, PlanStatement stmt) } } - // Rule 15: Join OR clause (Concatenation + Constant Scan pattern) - // Pattern: Concatenation → Compute Scalar → Constant Scan (one per OR branch) + // Rule 15: Join OR clause (Concatenation + Constant Scan under Merge Interval) + // Pattern: Merge Interval → TopN Sort → Concatenation → Constant Scans if (node.PhysicalOp == "Concatenation") { var constantScanBranches = node.Children .Count(c => c.PhysicalOp == "Constant Scan" || c.Children.Any(gc => gc.PhysicalOp == "Constant Scan")); - if (constantScanBranches >= 2 && HasJoinAncestor(node)) + if (constantScanBranches >= 2 && HasMergeIntervalAncestor(node)) { node.Warnings.Add(new PlanWarning { @@ -612,14 +612,14 @@ private static void DetectMultiReferenceCte(PlanStatement stmt) } /// - /// Checks whether a node has a join operator as an ancestor. + /// Checks whether a node has a Merge Interval ancestor (OR expansion pattern). /// - private static bool HasJoinAncestor(PlanNode node) + private static bool HasMergeIntervalAncestor(PlanNode node) { var ancestor = node.Parent; while (ancestor != null) { - if (ancestor.LogicalOp.Contains("Join", StringComparison.OrdinalIgnoreCase)) + if (ancestor.PhysicalOp == "Merge Interval") return true; ancestor = ancestor.Parent; } diff --git a/Lite/Services/PlanAnalyzer.cs b/Lite/Services/PlanAnalyzer.cs index 5760afaa..e9652625 100644 --- a/Lite/Services/PlanAnalyzer.cs +++ b/Lite/Services/PlanAnalyzer.cs @@ -399,15 +399,15 @@ private static void AnalyzeNode(PlanNode node, PlanStatement stmt) } } - // Rule 15: Join OR clause (Concatenation + Constant Scan pattern) - // Pattern: Concatenation → Compute Scalar → Constant Scan (one per OR branch) + // Rule 15: Join OR clause (Concatenation + Constant Scan under Merge Interval) + // Pattern: Merge Interval → TopN Sort → Concatenation → Constant Scans if (node.PhysicalOp == "Concatenation") { var constantScanBranches = node.Children .Count(c => c.PhysicalOp == "Constant Scan" || c.Children.Any(gc => gc.PhysicalOp == "Constant Scan")); - if (constantScanBranches >= 2 && HasJoinAncestor(node)) + if (constantScanBranches >= 2 && HasMergeIntervalAncestor(node)) { node.Warnings.Add(new PlanWarning { @@ -612,14 +612,14 @@ private static void DetectMultiReferenceCte(PlanStatement stmt) } /// - /// Checks whether a node has a join operator as an ancestor. + /// Checks whether a node has a Merge Interval ancestor (OR expansion pattern). /// - private static bool HasJoinAncestor(PlanNode node) + private static bool HasMergeIntervalAncestor(PlanNode node) { var ancestor = node.Parent; while (ancestor != null) { - if (ancestor.LogicalOp.Contains("Join", StringComparison.OrdinalIgnoreCase)) + if (ancestor.PhysicalOp == "Merge Interval") return true; ancestor = ancestor.Parent; }