Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions Dashboard/Services/PlanAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,15 +399,16 @@
}
}

// Rule 15: Join OR clause (Concatenation + Constant Scan under Merge Interval)
// Pattern: Merge Interval → TopN Sort → Concatenation → Constant Scans
// Rule 15: Join OR clause (Concatenation + Constant Scan under join/Merge Interval)
// Best signal: Merge Interval → TopN Sort → Concatenation → Constant Scans
// Also fires under a join ancestor (broader catch)
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 && HasMergeIntervalAncestor(node))
if (constantScanBranches >= 2 && (HasMergeIntervalAncestor(node) || HasJoinAncestor(node)))
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -463,7 +464,7 @@

// Rule 22: Table variables (Object name starts with @)
if (!string.IsNullOrEmpty(node.ObjectName) &&
node.ObjectName.Contains("@"))

Check warning on line 467 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Dashboard/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -626,6 +627,22 @@
return false;
}

/// <summary>
/// Checks whether a node has any join ancestor.
/// </summary>
private static bool HasJoinAncestor(PlanNode node)
{
var ancestor = node.Parent;
while (ancestor != null)
{
if (ancestor.LogicalOp != null &&
ancestor.LogicalOp.Contains("Join", StringComparison.OrdinalIgnoreCase))
return true;
ancestor = ancestor.Parent;
}
return false;
}

/// <summary>
/// Finds Sort and Hash Match operators in the tree that consume memory.
/// </summary>
Expand Down
23 changes: 20 additions & 3 deletions Lite/Services/PlanAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,15 +399,16 @@
}
}

// Rule 15: Join OR clause (Concatenation + Constant Scan under Merge Interval)
// Pattern: Merge Interval → TopN Sort → Concatenation → Constant Scans
// Rule 15: Join OR clause (Concatenation + Constant Scan under join/Merge Interval)
// Best signal: Merge Interval → TopN Sort → Concatenation → Constant Scans
// Also fires under a join ancestor (broader catch)
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 && HasMergeIntervalAncestor(node))
if (constantScanBranches >= 2 && (HasMergeIntervalAncestor(node) || HasJoinAncestor(node)))
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -463,7 +464,7 @@

// Rule 22: Table variables (Object name starts with @)
if (!string.IsNullOrEmpty(node.ObjectName) &&
node.ObjectName.Contains("@"))

Check warning on line 467 in Lite/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Lite/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Lite/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)

Check warning on line 467 in Lite/Services/PlanAnalyzer.cs

View workflow job for this annotation

GitHub Actions / build

Use 'string.Contains(char)' instead of 'string.Contains(string)' when searching for a single character (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847)
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -626,6 +627,22 @@
return false;
}

/// <summary>
/// Checks whether a node has any join ancestor.
/// </summary>
private static bool HasJoinAncestor(PlanNode node)
{
var ancestor = node.Parent;
while (ancestor != null)
{
if (ancestor.LogicalOp != null &&
ancestor.LogicalOp.Contains("Join", StringComparison.OrdinalIgnoreCase))
return true;
ancestor = ancestor.Parent;
}
return false;
}

/// <summary>
/// Finds Sort and Hash Match operators in the tree that consume memory.
/// </summary>
Expand Down
Loading