From a19b4e49cc8a75ce46b9c3bf72ebc5b71f6e0cee Mon Sep 17 00:00:00 2001 From: Sebastien Marichal Date: Thu, 8 Aug 2024 14:42:26 +0200 Subject: [PATCH] Repro for S2077: Ternary in formatted string --- .../Rules/Hotspots/ExecutingSqlQueriesTest.cs | 301 +++++++++--------- .../Hotspots/ExecutingSqlQueries.Dapper.cs | 16 + ...xecutingSqlQueries.EntityFrameworkCore2.cs | 24 ++ ...xecutingSqlQueries.EntityFrameworkCore2.vb | 23 ++ ...ingSqlQueries.EntityFrameworkCoreLatest.cs | 24 ++ ...ingSqlQueries.EntityFrameworkCoreLatest.vb | 23 ++ .../Hotspots/ExecutingSqlQueries.MySqlData.cs | 18 ++ .../ExecutingSqlQueries.NHibernate.cs | 44 +++ .../Hotspots/ExecutingSqlQueries.Net46.cs | 21 ++ .../Hotspots/ExecutingSqlQueries.Net46.vb | 19 ++ 10 files changed, 367 insertions(+), 146 deletions(-) create mode 100644 analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.MySqlData.cs diff --git a/analyzers/tests/SonarAnalyzer.Test/Rules/Hotspots/ExecutingSqlQueriesTest.cs b/analyzers/tests/SonarAnalyzer.Test/Rules/Hotspots/ExecutingSqlQueriesTest.cs index 9ba37549c07..e12650104ca 100644 --- a/analyzers/tests/SonarAnalyzer.Test/Rules/Hotspots/ExecutingSqlQueriesTest.cs +++ b/analyzers/tests/SonarAnalyzer.Test/Rules/Hotspots/ExecutingSqlQueriesTest.cs @@ -21,159 +21,168 @@ using CS = SonarAnalyzer.Rules.CSharp; using VB = SonarAnalyzer.Rules.VisualBasic; -namespace SonarAnalyzer.Test.Rules +namespace SonarAnalyzer.Test.Rules; + +[TestClass] +public class ExecutingSqlQueriesTest { - [TestClass] - public class ExecutingSqlQueriesTest - { - private readonly VerifierBuilder builderCS = new VerifierBuilder().AddAnalyzer(() => new CS.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots"); - private readonly VerifierBuilder builderVB = new VerifierBuilder().AddAnalyzer(() => new VB.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots"); + private readonly VerifierBuilder builderCS = new VerifierBuilder().AddAnalyzer(() => new CS.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots"); + private readonly VerifierBuilder builderVB = new VerifierBuilder().AddAnalyzer(() => new VB.ExecutingSqlQueries(AnalyzerConfiguration.AlwaysEnabled)).WithBasePath("Hotspots"); + + [TestMethod] + public void ExecutingSqlQueries_CS_Dapper() => + builderCS + .AddPaths("ExecutingSqlQueries.Dapper.cs") + .AddReferences(MetadataReferenceFacade.SystemData) + .AddReferences(NuGetMetadataReference.Dapper()) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CS_MySqlData() => + builderCS + .AddPaths("ExecutingSqlQueries.MySqlData.cs") + .AddReferences(MetadataReferenceFacade.SystemData) + .AddReferences(MetadataReferenceFacade.SystemComponentModelPrimitives) + .AddReferences(NuGetMetadataReference.Dapper("2.1.35")) + .AddReferences(NuGetMetadataReference.MySqlData("9.0.0")) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CS_EF6() => + builderCS.AddPaths("ExecutingSqlQueries.EF6.cs") + .AddReferences(NuGetMetadataReference.EntityFramework()) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_OrmLite_CS() => + builderCS + .AddPaths(@"ExecutingSqlQueries.OrmLite.cs") + .AddReferences(MetadataReferenceFacade.SystemData) + .AddReferences(NuGetMetadataReference.ServiceStackOrmLite(Constants.NuGetLatestVersion)) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_NHibernate_CS() => + builderCS + .AddPaths("ExecutingSqlQueries.NHibernate.cs") + .AddReferences(NuGetMetadataReference.NHibernate(Constants.NuGetLatestVersion)) + .Verify(); #if NETFRAMEWORK // System.Data.OracleClient.dll is not available on .Net Core - [TestMethod] - public void ExecutingSqlQueries_CS_Net46() => - builderCS - .AddPaths("ExecutingSqlQueries.Net46.cs") - .AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion)) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_VB_Net46() => - builderVB - .AddPaths("ExecutingSqlQueries.Net46.vb") - .WithOptions(ParseOptionsHelper.FromVisualBasic15) - .AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion)) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_MonoSqlLite_Net46_CS() => - builderCS - .AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.cs") - .AddReferences(FrameworkMetadataReference.SystemData) - .AddReferences(NuGetMetadataReference.MonoDataSqlite()) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_MonoSqlLite_Net46_VB() => - builderVB - .AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.vb") - .AddReferences(FrameworkMetadataReference.SystemData) - .AddReferences(NuGetMetadataReference.MonoDataSqlite()) - .WithOptions(ParseOptionsHelper.FromVisualBasic14) - .Verify(); - - internal static IEnumerable GetReferencesNet46(string sqlServerCeVersion) => - MetadataReferenceFacade.NetStandard - .Concat(FrameworkMetadataReference.SystemData) - .Concat(FrameworkMetadataReference.SystemDataOracleClient) - .Concat(NuGetMetadataReference.SystemDataSqlServerCe(sqlServerCeVersion)) - .Concat(NuGetMetadataReference.MySqlData("8.0.22")) - .Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()) - .Concat(NuGetMetadataReference.SystemDataSQLiteCore()); + [TestMethod] + public void ExecutingSqlQueries_CS_Net46() => + builderCS + .AddPaths("ExecutingSqlQueries.Net46.cs") + .AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion)) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_VB_Net46() => + builderVB + .AddPaths("ExecutingSqlQueries.Net46.vb") + .WithOptions(ParseOptionsHelper.FromVisualBasic15) + .AddReferences(GetReferencesNet46(Constants.NuGetLatestVersion)) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_MonoSqlLite_Net46_CS() => + builderCS + .AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.cs") + .AddReferences(FrameworkMetadataReference.SystemData) + .AddReferences(NuGetMetadataReference.MonoDataSqlite()) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_MonoSqlLite_Net46_VB() => + builderVB + .AddPaths("ExecutingSqlQueries.Net46.MonoSqlLite.vb") + .AddReferences(FrameworkMetadataReference.SystemData) + .AddReferences(NuGetMetadataReference.MonoDataSqlite()) + .WithOptions(ParseOptionsHelper.FromVisualBasic14) + .Verify(); + + internal static IEnumerable GetReferencesNet46(string sqlServerCeVersion) => + MetadataReferenceFacade.NetStandard + .Concat(FrameworkMetadataReference.SystemData) + .Concat(FrameworkMetadataReference.SystemDataOracleClient) + .Concat(NuGetMetadataReference.SystemDataSqlServerCe(sqlServerCeVersion)) + .Concat(NuGetMetadataReference.MySqlData("8.0.22")) + .Concat(NuGetMetadataReference.MicrosoftDataSqliteCore()) + .Concat(NuGetMetadataReference.SystemDataSQLiteCore()); #else - [TestMethod] - public void ExecutingSqlQueries_CS_EntityFrameworkCore2() => - builderCS - .AddPaths("ExecutingSqlQueries.EntityFrameworkCore2.cs") - .WithOptions(ParseOptionsHelper.FromCSharp8) - .AddReferences(GetReferencesEntityFrameworkNetCore("2.2.6").Concat(NuGetMetadataReference.SystemComponentModelTypeConverter())) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_CS_EntityFrameworkCore7() => - builderCS - .AddPaths("ExecutingSqlQueries.EntityFrameworkCoreLatest.cs") - .WithOptions(ParseOptionsHelper.FromCSharp8) - .AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14")) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_CSharp9() => - builderCS - .AddPaths("ExecutingSqlQueries.CSharp9.cs") - .WithTopLevelStatements() - .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_CSharp10() => - builderCS - .AddPaths("ExecutingSqlQueries.CSharp10.cs") - .WithOptions(ParseOptionsHelper.FromCSharp10) - .WithTopLevelStatements() - .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_CSharp11() => - builderCS - .AddPaths("ExecutingSqlQueries.CSharp11.cs") - .WithOptions(ParseOptionsHelper.FromCSharp11) - .WithTopLevelStatements() - .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_CSharp12() => - builderCS - .AddPaths("ExecutingSqlQueries.CSharp12.cs") - .WithOptions(ParseOptionsHelper.FromCSharp12) - .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_VB_EntityFrameworkCore2() => - builderVB - .AddPaths(@"ExecutingSqlQueries.EntityFrameworkCore2.vb") - .WithOptions(ParseOptionsHelper.FromVisualBasic15) - .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version)) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_VB_EntityFrameworkCore7() => - builderVB - .AddPaths(@"ExecutingSqlQueries.EntityFrameworkCoreLatest.vb") - .WithOptions(ParseOptionsHelper.FromVisualBasic15) - .AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14")) - .Verify(); - - internal static IEnumerable GetReferencesEntityFrameworkNetCore(string entityFrameworkVersion) => - Enumerable.Empty() - .Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCore(entityFrameworkVersion)) - .Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCoreRelational(entityFrameworkVersion)); + [TestMethod] + public void ExecutingSqlQueries_CS_EntityFrameworkCore2() => + builderCS + .AddPaths("ExecutingSqlQueries.EntityFrameworkCore2.cs") + .WithOptions(ParseOptionsHelper.FromCSharp8) + .AddReferences(GetReferencesEntityFrameworkNetCore("2.2.6").Concat(NuGetMetadataReference.SystemComponentModelTypeConverter())) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CS_EntityFrameworkCore7() => + builderCS + .AddPaths("ExecutingSqlQueries.EntityFrameworkCoreLatest.cs") + .WithOptions(ParseOptionsHelper.FromCSharp8) + .AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14")) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CSharp9() => + builderCS + .AddPaths("ExecutingSqlQueries.CSharp9.cs") + .WithTopLevelStatements() + .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CSharp10() => + builderCS + .AddPaths("ExecutingSqlQueries.CSharp10.cs") + .WithOptions(ParseOptionsHelper.FromCSharp10) + .WithTopLevelStatements() + .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CSharp11() => + builderCS + .AddPaths("ExecutingSqlQueries.CSharp11.cs") + .WithOptions(ParseOptionsHelper.FromCSharp11) + .WithTopLevelStatements() + .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_CSharp12() => + builderCS + .AddPaths("ExecutingSqlQueries.CSharp12.cs") + .WithOptions(ParseOptionsHelper.FromCSharp12) + .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version).Concat(NuGetMetadataReference.MicrosoftDataSqliteCore())) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_VB_EntityFrameworkCore2() => + builderVB + .AddPaths(@"ExecutingSqlQueries.EntityFrameworkCore2.vb") + .WithOptions(ParseOptionsHelper.FromVisualBasic15) + .AddReferences(GetReferencesEntityFrameworkNetCore(Constants.DotNetCore220Version)) + .Verify(); + + [TestMethod] + public void ExecutingSqlQueries_VB_EntityFrameworkCore7() => + builderVB + .AddPaths(@"ExecutingSqlQueries.EntityFrameworkCoreLatest.vb") + .WithOptions(ParseOptionsHelper.FromVisualBasic15) + .AddReferences(GetReferencesEntityFrameworkNetCore("7.0.14")) + .Verify(); + + internal static IEnumerable GetReferencesEntityFrameworkNetCore(string entityFrameworkVersion) => + Enumerable.Empty() + .Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCore(entityFrameworkVersion)) + .Concat(NuGetMetadataReference.MicrosoftEntityFrameworkCoreRelational(entityFrameworkVersion)); #endif - - [TestMethod] - public void ExecutingSqlQueries_CS_Dapper() => - builderCS - .AddPaths("ExecutingSqlQueries.Dapper.cs") - .AddReferences(MetadataReferenceFacade.SystemData) - .AddReferences(NuGetMetadataReference.Dapper()) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_CS_EF6() => - builderCS.AddPaths("ExecutingSqlQueries.EF6.cs") - .AddReferences(NuGetMetadataReference.EntityFramework()) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_OrmLite_CS() => - builderCS - .AddPaths(@"ExecutingSqlQueries.OrmLite.cs") - .AddReferences(MetadataReferenceFacade.SystemData) - .AddReferences(NuGetMetadataReference.ServiceStackOrmLite(Constants.NuGetLatestVersion)) - .Verify(); - - [TestMethod] - public void ExecutingSqlQueries_NHibernate_CS() => - builderCS - .AddPaths("ExecutingSqlQueries.NHibernate.cs") - .AddReferences(NuGetMetadataReference.NHibernate(Constants.NuGetLatestVersion)) - .Verify(); - } } diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Dapper.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Dapper.cs index 3cfc0154f12..35440d66e07 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Dapper.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Dapper.cs @@ -210,4 +210,20 @@ public void CommandDefinition_Constructor(string query, string param) new CommandDefinition(query + param, new { Id = 1 }); // Noncompliant } } + + // https://github.com/SonarSource/sonar-dotnet/issues/9602 + class Repro_9602 + { + public void ConstantQuery(IDbConnection dbConnection, bool onlyEnabled) + { + string query = "SELECT id FROM users"; + if(onlyEnabled) + query += " WHERE enabled = 1"; + string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary - FP + + dbConnection.Query(query); // Compliant + dbConnection.Query(query2); // Noncompliant - FP + dbConnection.Query($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + } + } } diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.cs index fba969ec849..7a7e3b0c0d8 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.cs @@ -108,4 +108,28 @@ public class Blog { public string Url { get; set; } } + + // https://github.com/SonarSource/sonar-dotnet/issues/9602 + class Repro_9602 + { + public void ConstantQuery(DbContext context, bool onlyEnabled) + { + string query = "SELECT id FROM users"; + if(onlyEnabled) + query += " WHERE enabled = 1"; + string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary [c1, c2, c3] + + context.Database.ExecuteSqlCommand(query); // Compliant + context.Database.ExecuteSqlCommand(query2); // Noncompliant [c1] - FP + context.Database.ExecuteSqlCommand($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Compliant + + context.Database.ExecuteSqlCommandAsync(query); // Compliant + context.Database.ExecuteSqlCommandAsync(query2); // Noncompliant [c2] - FP + context.Database.ExecuteSqlCommandAsync($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Compliant + + context.Query().FromSql(query); // Compliant + context.Query().FromSql(query2); // Noncompliant [c3] - FP + context.Query().FromSql($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Compliant + } + } } diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.vb b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.vb index 2f3f26d8f64..4c281f4aed2 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.vb +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCore2.vb @@ -97,6 +97,29 @@ Namespace Tests.Diagnostics End Class + ' https://github.com/SonarSource/sonar-dotnet/issues/9602 + Class Repro_9602 + Public Sub ConstantQuery(context As DbContext, onlyEnabled As Boolean) + Dim query As String = "SELECT id FROM users" + If onlyEnabled Then + query += " WHERE enabled = 1" + End If + Dim query2 As String = $"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}" ' Secondary [c1,c2,c3] + + context.Database.ExecuteSqlCommand(query) ' Compliant + context.Database.ExecuteSqlCommand(query2) ' Noncompliant [c1] - FP + context.Database.ExecuteSqlCommand($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Compliant + + context.Database.ExecuteSqlCommandAsync(query) ' Compliant + context.Database.ExecuteSqlCommandAsync(query2) ' Noncompliant [c2] - FP + context.Database.ExecuteSqlCommandAsync($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Compliant + + context.Query(Of User)().FromSql(query) ' Compliant + context.Query(Of User)().FromSql(query2) ' Noncompliant [c3] - FP + context.Query(Of User)().FromSql($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Compliant + End Sub + End Class + Class User Private Property Id As String Private Property Name As String diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.cs index 940dffa4cab..cc6bed0bb6c 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.cs @@ -109,4 +109,28 @@ public class Blog { public string Url { get; set; } } + + // https://github.com/SonarSource/sonar-dotnet/issues/9602 + class Repro_9602 + { + public void ConstantQuery(DbContext context, bool onlyEnabled) + { + string query = "SELECT id FROM users"; + if(onlyEnabled) + query += " WHERE enabled = 1"; + string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary [c1, c2, c3] + + context.Database.ExecuteSqlRaw(query); // Compliant + context.Database.ExecuteSqlRaw(query2); // Noncompliant [c1] - FP + context.Database.ExecuteSqlRaw($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + context.Database.ExecuteSqlRawAsync(query); // Compliant + context.Database.ExecuteSqlRawAsync(query2); // Noncompliant [c2] - FP + context.Database.ExecuteSqlRawAsync($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + context.Set().FromSqlRaw(query); // Compliant + context.Set().FromSqlRaw(query2); // Noncompliant [c3] - FP + context.Set().FromSqlRaw($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + } + } } diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.vb b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.vb index d48deab5ce3..f0aaad844ec 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.vb +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.EntityFrameworkCoreLatest.vb @@ -97,6 +97,29 @@ Namespace Tests.Diagnostics End Class + ' https://github.com/SonarSource/sonar-dotnet/issues/9602 + Class Repro_9602 + Public Sub ConstantQuery(context As DbContext, onlyEnabled As Boolean) + Dim query As String = "SELECT id FROM users" + If onlyEnabled Then + query += " WHERE enabled = 1" + End If + Dim query2 As String = $"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}" ' Secondary [c1, c2, c3] + + context.Database.ExecuteSqlRaw(query) ' Compliant + context.Database.ExecuteSqlRaw(query2) ' Noncompliant [c1] - FP + context.Database.ExecuteSqlRaw($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Noncompliant - FP + + context.Database.ExecuteSqlRawAsync(query) ' Compliant + context.Database.ExecuteSqlRawAsync(query2) ' Noncompliant [c2] - FP + context.Database.ExecuteSqlRawAsync($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Noncompliant - FP + + context.Set(Of User)().FromSqlRaw(query) ' Compliant + context.Set(Of User)().FromSqlRaw(query2) ' Noncompliant [c3] - FP + context.Set(Of User)().FromSqlRaw($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}") ' Noncompliant - FP + End Sub + End Class + Class User Private Property Id As String Private Property Name As String diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.MySqlData.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.MySqlData.cs new file mode 100644 index 00000000000..0aa3f7640bc --- /dev/null +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.MySqlData.cs @@ -0,0 +1,18 @@ +using Dapper; +using MySql.Data.MySqlClient; + +// https://github.com/SonarSource/sonar-dotnet/issues/9602 +class Repro_9602 +{ + public void ConstantQuery(MySqlConnection db, bool onlyEnabled) + { + string query = "SELECT id FROM users"; + if(onlyEnabled) + query += " WHERE enabled = 1"; + string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary + + db.Query(query); // Compliant + db.Query(query2); // Noncompliant - FP + db.Query($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + } +} diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.NHibernate.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.NHibernate.cs index 2264a662569..3d31933616d 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.NHibernate.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.NHibernate.cs @@ -72,3 +72,47 @@ public async Task AbstractSessionImplMethods(AbstractSessionImpl session, string session.GetNamedSQLQuery(query + param); // Noncompliant } } + +// https://github.com/SonarSource/sonar-dotnet/issues/9602 +class Repro_9602 +{ + public async Task ConstantQuery(ISession session, bool onlyEnabled) + { + string query = "SELECT id FROM users"; + if(onlyEnabled) + query += " WHERE enabled = 1"; + string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary [s1, s2, s3, s4, s5, s6, s7, s8] + + session.CreateFilter(null, query); // Compliant + session.CreateFilter(null, query2); // Noncompliant [s1] - FP + session.CreateFilter(null, $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + session.CreateFilter(null, query); // Compliant + session.CreateFilter(null, query2); // Noncompliant [s2] - FP + session.CreateFilter(null, $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + await session.CreateFilterAsync(null, query); // Compliant + await session.CreateFilterAsync(null, query2); // Noncompliant [s3] - FP + await session.CreateFilterAsync(null, $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + session.CreateQuery(query); // Compliant + session.CreateQuery(query2); // Noncompliant [s4] - FP + session.CreateQuery($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + session.CreateSQLQuery(query); // Compliant + session.CreateSQLQuery(query2); // Noncompliant [s5] - FP + session.CreateSQLQuery($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + session.Delete(query); // Compliant + session.Delete(query2); // Noncompliant [s6] - FP + session.Delete($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + await session.DeleteAsync(query); // Compliant + await session.DeleteAsync(query2); // Noncompliant [s7] - FP + await session.DeleteAsync($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + + session.GetNamedQuery(query); // Compliant + session.GetNamedQuery(query2); // Noncompliant [s8] - FP + session.GetNamedQuery($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"); // Noncompliant - FP + } +} diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.cs b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.cs index 6520ddd4462..2edd5f8d418 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.cs +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.cs @@ -322,4 +322,25 @@ public void IDbCommand_CommandText(IDbCommand command, string param) command.CommandText = string.Format("INSERT INTO Users (name) VALUES (\"{0}\")", param); // Noncompliant } } + + // https://github.com/SonarSource/sonar-dotnet/issues/9602 + class Repro_9602 + { + public void ConstantQuery(SqliteConnection connection, bool onlyEnabled) + { + string query = "SELECT id FROM users"; + if(onlyEnabled) + query += " WHERE enabled = 1"; + string query2 = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Secondary [c2, c3] + + var command = new SqliteCommand(query, connection); // Compliant + command.CommandText = query; // Compliant + + var command2 = new SqliteCommand(query2, connection); // Noncompliant [c2] - FP + command2.CommandText = query2; // Noncompliant [c3] - FP + + var command3 = new SqliteCommand($"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}", connection); // Noncompliant - FP + command3.CommandText = $"SELECT id FROM users {(onlyEnabled ? "WHERE enabled = 1" : "")}"; // Noncompliant - FP + } + } } diff --git a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.vb b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.vb index 38a5530f800..2d89b1a51d1 100644 --- a/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.vb +++ b/analyzers/tests/SonarAnalyzer.Test/TestCases/Hotspots/ExecutingSqlQueries.Net46.vb @@ -276,6 +276,25 @@ Namespace Tests.Diagnostics y = sensitiveQuery ' Secondary [4] {{SQL query is assigned to y.}} ^13#1 command.CommandText = y ' Noncompliant [4] End Sub + End Class + + ' https://github.com/SonarSource/sonar-dotnet/issues/9602 + Class Repro_9602 + Public Sub ConstantBuiltQuery(connection As MSSqlite.SqliteConnection, onlyEnabled As Boolean) + Dim query As String = "SELECT id FROM users" + If onlyEnabled Then + query += " WHERE enabled = 1" + End If + Dim query2 As String = $"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}" ' Secondary [c2, c3] + + Dim command As New MSSqlite.SqliteCommand(query, connection) ' Compliant + command.CommandText = query ' Compliant + Dim command2 As New MSSqlite.SqliteCommand(query2, connection) ' Noncompliant [c2] - FP + command2.CommandText = query2 ' Noncompliant [c3] - FP + + Dim command3 As New MSSqlite.SqliteCommand($"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}", connection) ' Noncompliant - FP + command3.CommandText = $"SELECT id FROM users {(If(onlyEnabled, "WHERE enabled = 1", ""))}" ' Noncompliant - FP + End Sub End Class End Namespace