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: 22 additions & 1 deletion Dashboard/Services/PlanAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@
}

// Rule 11: Scan with residual predicate (skip if non-SARGable already flagged)
if (nonSargableReason == null && IsRowstoreScan(node) && !string.IsNullOrEmpty(node.Predicate))
// A PROBE() alone is just a bitmap filter — not a real residual predicate.
if (nonSargableReason == null && IsRowstoreScan(node) && !string.IsNullOrEmpty(node.Predicate) &&
!IsProbeOnly(node.Predicate))
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -469,7 +471,7 @@

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

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorDashboard.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorDashboard.Models.PlanNode, PerformanceMonitorDashboard.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -538,6 +540,25 @@
!node.PhysicalOp.Contains("Columnstore", StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Returns true when the predicate contains ONLY PROBE() bitmap filter(s)
/// with no real residual predicate. PROBE alone is a bitmap filter pushed
/// down from a hash join — not interesting by itself. If a real predicate
/// exists alongside PROBE (e.g. "[col]=(1) AND PROBE(...)"), returns false.
/// </summary>
private static bool IsProbeOnly(string predicate)
{
// Strip all PROBE(...) expressions — PROBE args can contain nested parens
var stripped = Regex.Replace(predicate, @"PROBE\s*\([^()]*(?:\([^()]*\)[^()]*)*\)", "",
RegexOptions.IgnoreCase).Trim();

// Remove leftover AND/OR connectors and whitespace
stripped = Regex.Replace(stripped, @"\b(AND|OR)\b", "", RegexOptions.IgnoreCase).Trim();

// If nothing meaningful remains, it was PROBE-only
return stripped.Length == 0;
}

/// <summary>
/// Returns true for any scan operator including columnstore.
/// Excludes spools and constant scans.
Expand Down
23 changes: 22 additions & 1 deletion Lite/Services/PlanAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@
}

// Rule 11: Scan with residual predicate (skip if non-SARGable already flagged)
if (nonSargableReason == null && IsRowstoreScan(node) && !string.IsNullOrEmpty(node.Predicate))
// A PROBE() alone is just a bitmap filter — not a real residual predicate.
if (nonSargableReason == null && IsRowstoreScan(node) && !string.IsNullOrEmpty(node.Predicate) &&
!IsProbeOnly(node.Predicate))
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -469,7 +471,7 @@

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

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorLite.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorLite.Models.PlanNode, PerformanceMonitorLite.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorLite.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorLite.Models.PlanNode, PerformanceMonitorLite.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorLite.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorLite.Models.PlanNode, PerformanceMonitorLite.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorLite.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorLite.Models.PlanNode, PerformanceMonitorLite.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorLite.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorLite.Models.PlanNode, PerformanceMonitorLite.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)

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

View workflow job for this annotation

GitHub Actions / build

The behavior of 'string.StartsWith(string)' could vary based on the current user's locale settings. Replace this call in 'PerformanceMonitorLite.Services.PlanAnalyzer.AnalyzeNode(PerformanceMonitorLite.Models.PlanNode, PerformanceMonitorLite.Models.PlanStatement)' with a call to 'string.StartsWith(string, System.StringComparison)'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310)

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

View workflow job for this annotation

GitHub Actions / build

Use 'string.StartsWith(char)' instead of 'string.StartsWith(string)' when you have a string with a single char (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1866)
{
node.Warnings.Add(new PlanWarning
{
Expand Down Expand Up @@ -538,6 +540,25 @@
!node.PhysicalOp.Contains("Columnstore", StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Returns true when the predicate contains ONLY PROBE() bitmap filter(s)
/// with no real residual predicate. PROBE alone is a bitmap filter pushed
/// down from a hash join — not interesting by itself. If a real predicate
/// exists alongside PROBE (e.g. "[col]=(1) AND PROBE(...)"), returns false.
/// </summary>
private static bool IsProbeOnly(string predicate)
{
// Strip all PROBE(...) expressions — PROBE args can contain nested parens
var stripped = Regex.Replace(predicate, @"PROBE\s*\([^()]*(?:\([^()]*\)[^()]*)*\)", "",
RegexOptions.IgnoreCase).Trim();

// Remove leftover AND/OR connectors and whitespace
stripped = Regex.Replace(stripped, @"\b(AND|OR)\b", "", RegexOptions.IgnoreCase).Trim();

// If nothing meaningful remains, it was PROBE-only
return stripped.Length == 0;
}

/// <summary>
/// Returns true for any scan operator including columnstore.
/// Excludes spools and constant scans.
Expand Down
Loading