From 2abab27581d75bb097b2c31a5ad99e3fd4e0cc3c Mon Sep 17 00:00:00 2001 From: maumar Date: Tue, 15 Dec 2020 20:45:21 -0800 Subject: [PATCH] Fix to #23472 - !boolean in query should convert to boolean == false rather than boolean != true where possible When comparing something to bool constant, which is later negated we now flip the constant true -> false and false -> true, rather than flipping the operation from == to != --- .../Query/SqlNullabilityProcessor.cs | 28 ++++++++ ...rchConditionConvertingExpressionVisitor.cs | 42 +++++++++-- .../CustomConvertersCosmosTest.cs | 11 +++ .../CustomConvertersTestBase.cs | 10 +++ .../CustomConvertersSqlServerTest.cs | 13 +++- .../Query/GearsOfWarQuerySqlServerTest.cs | 70 +++++++++---------- .../NorthwindDbFunctionsQuerySqlServerTest.cs | 2 +- .../Query/NorthwindWhereQuerySqlServerTest.cs | 10 +-- .../Query/QueryBugsTest.cs | 4 +- .../QueryFilterFuncletizationSqlServerTest.cs | 6 +- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 70 +++++++++---------- .../CustomConvertersSqliteTest.cs | 13 +++- 12 files changed, 189 insertions(+), 90 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index ae66ec72efb..0e3e46bc8a6 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -1490,6 +1490,34 @@ private SqlExpression OptimizeNonNullableNotExpression(SqlUnaryExpression sqlUna sqlBinaryOperand.TypeMapping)!); } + // use equality where possible + // !(a == true) -> a == false + // !(a == false) -> a == true + // !(true == a) -> false == a + // !(false == a) -> true == a + if (sqlBinaryOperand.OperatorType == ExpressionType.Equal) + { + if (sqlBinaryOperand.Left is SqlConstantExpression leftConstant + && leftConstant.Type == typeof(bool)) + { + return _sqlExpressionFactory.MakeBinary( + ExpressionType.Equal, + _sqlExpressionFactory.Constant(!(bool)leftConstant.Value!, leftConstant.TypeMapping), + sqlBinaryOperand.Right, + sqlBinaryOperand.TypeMapping)!; + } + + if (sqlBinaryOperand.Right is SqlConstantExpression rightConstant + && rightConstant.Type == typeof(bool)) + { + return _sqlExpressionFactory.MakeBinary( + ExpressionType.Equal, + sqlBinaryOperand.Left, + _sqlExpressionFactory.Constant(!(bool)rightConstant.Value!, rightConstant.TypeMapping), + sqlBinaryOperand.TypeMapping)!; + } + } + // !(a == b) -> a != b // !(a != b) -> a == b // !(a > b) -> a <= b diff --git a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs index 36fe2dc7adc..c44f17028d0 100644 --- a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs @@ -74,22 +74,50 @@ private SqlExpression BuildCompareToExpression(SqlExpression sqlExpression) sqlExpression, _sqlExpressionFactory.Constant(true)); - // !(a == b) -> (a != b) - // !(a != b) -> (a == b) + private SqlExpression SimplifyNegatedBinary(SqlExpression sqlExpression) - => sqlExpression is SqlUnaryExpression sqlUnaryExpression + { + if (sqlExpression is SqlUnaryExpression sqlUnaryExpression && sqlUnaryExpression.OperatorType == ExpressionType.Not && sqlUnaryExpression.Type == typeof(bool) && sqlUnaryExpression.Operand is SqlBinaryExpression sqlBinaryOperand - && (sqlBinaryOperand.OperatorType == ExpressionType.Equal || sqlBinaryOperand.OperatorType == ExpressionType.NotEqual) - ? _sqlExpressionFactory.MakeBinary( + && (sqlBinaryOperand.OperatorType == ExpressionType.Equal || sqlBinaryOperand.OperatorType == ExpressionType.NotEqual)) + { + if (sqlBinaryOperand.Left.Type == typeof(bool) + && sqlBinaryOperand.Right.Type == typeof(bool) + && (sqlBinaryOperand.Left is SqlConstantExpression + || sqlBinaryOperand.Right is SqlConstantExpression)) + { + var constant = sqlBinaryOperand.Left as SqlConstantExpression ?? (SqlConstantExpression)sqlBinaryOperand.Right; + if (sqlBinaryOperand.Left is SqlConstantExpression) + { + return _sqlExpressionFactory.MakeBinary( + ExpressionType.Equal, + _sqlExpressionFactory.Constant(!(bool)constant.Value!, constant.TypeMapping), + sqlBinaryOperand.Right, + sqlBinaryOperand.TypeMapping)!; + } + else + { + return _sqlExpressionFactory.MakeBinary( + ExpressionType.Equal, + sqlBinaryOperand.Left, + _sqlExpressionFactory.Constant(!(bool)constant.Value!, constant.TypeMapping), + sqlBinaryOperand.TypeMapping)!; + } + } + + return _sqlExpressionFactory.MakeBinary( sqlBinaryOperand.OperatorType == ExpressionType.Equal ? ExpressionType.NotEqual : ExpressionType.Equal, sqlBinaryOperand.Left, sqlBinaryOperand.Right, - sqlBinaryOperand.TypeMapping)! - : sqlExpression; + sqlBinaryOperand.TypeMapping)!; + } + + return sqlExpression; + } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs index a5de655b073..23cc9345e91 100644 --- a/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs @@ -112,6 +112,17 @@ FROM root c WHERE (c[""Discriminator""] IN (""Blog"", ""RssBlog"") AND (c[""IsVisible""] = ""Y""))"); } + [ConditionalFact] + public override void Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used() + { + base.Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used(); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Blog"", ""RssBlog"") AND NOT((c[""IsVisible""] = ""Y"")))"); + } + [ConditionalFact] public override void Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty() { diff --git a/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs b/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs index ab699f0082c..f4babd35efd 100644 --- a/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs +++ b/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs @@ -488,6 +488,16 @@ public virtual void Where_bool_gets_converted_to_equality_when_value_conversion_ Assert.Equal("http://blog.com", result.Url); } + [ConditionalFact] + public virtual void Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used() + { + using var context = CreateContext(); + var query = context.Set().Where(b => !b.IsVisible).ToList(); + + var result = Assert.Single(query); + Assert.Equal("http://rssblog.com", result.Url); + } + [ConditionalFact] public virtual void Where_bool_with_value_conversion_inside_comparison_doesnt_get_converted_twice() { diff --git a/test/EFCore.SqlServer.FunctionalTests/CustomConvertersSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/CustomConvertersSqlServerTest.cs index 6e09af4dca5..9a417c96987 100644 --- a/test/EFCore.SqlServer.FunctionalTests/CustomConvertersSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/CustomConvertersSqlServerTest.cs @@ -243,6 +243,17 @@ FROM [Blog] AS [b] WHERE [b].[IsVisible] = N'Y'"); } + [ConditionalFact] + public override void Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used() + { + base.Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used(); + + AssertSql( + @"SELECT [b].[BlogId], [b].[Discriminator], [b].[IndexerVisible], [b].[IsVisible], [b].[Url], [b].[RssUrl] +FROM [Blog] AS [b] +WHERE [b].[IsVisible] = N'N'"); + } + public override void Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty() { base.Where_bool_gets_converted_to_equality_when_value_conversion_is_used_using_EFProperty(); @@ -260,7 +271,7 @@ public override void Where_bool_gets_converted_to_equality_when_value_conversion AssertSql( @"SELECT [b].[BlogId], [b].[Discriminator], [b].[IndexerVisible], [b].[IsVisible], [b].[Url], [b].[RssUrl] FROM [Blog] AS [b] -WHERE [b].[IndexerVisible] <> N'Aye'"); +WHERE [b].[IndexerVisible] = N'Nay'"); } public override void Object_to_string_conversion() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index daef3dbbf75..49b8aa3eeb7 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -672,7 +672,7 @@ public override async Task Select_inverted_boolean(bool async) AssertSql( @"SELECT [w].[Id], CASE - WHEN [w].[IsAutomatic] <> CAST(1 AS bit) THEN CAST(1 AS bit) + WHEN [w].[IsAutomatic] = CAST(0 AS bit) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [Manual] FROM [Weapons] AS [w] @@ -741,7 +741,7 @@ public override async Task Select_ternary_operation_with_inverted_boolean(bool a AssertSql( @"SELECT [w].[Id], CASE - WHEN [w].[IsAutomatic] <> CAST(1 AS bit) THEN 1 + WHEN [w].[IsAutomatic] = CAST(0 AS bit) THEN 1 ELSE 0 END AS [Num] FROM [Weapons] AS [w]"); @@ -778,7 +778,7 @@ public override async Task Select_ternary_operation_multiple_conditions_2(bool a AssertSql( @"SELECT [w].[Id], CASE - WHEN ([w].[IsAutomatic] <> CAST(1 AS bit)) AND ([w].[SynergyWithId] = 1) THEN N'Yes' + WHEN ([w].[IsAutomatic] = CAST(0 AS bit)) AND ([w].[SynergyWithId] = 1) THEN N'Yes' ELSE N'No' END AS [IsCartridge] FROM [Weapons] AS [w]"); @@ -790,7 +790,7 @@ public override async Task Select_multiple_conditions(bool async) AssertSql( @"SELECT [w].[Id], CASE - WHEN ([w].[IsAutomatic] <> CAST(1 AS bit)) AND (([w].[SynergyWithId] = 1) AND [w].[SynergyWithId] IS NOT NULL) THEN CAST(1 AS bit) + WHEN ([w].[IsAutomatic] = CAST(0 AS bit)) AND (([w].[SynergyWithId] = 1) AND [w].[SynergyWithId] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [IsCartridge] FROM [Weapons] AS [w]"); @@ -802,7 +802,7 @@ public override async Task Select_nested_ternary_operations(bool async) AssertSql( @"SELECT [w].[Id], CASE - WHEN [w].[IsAutomatic] <> CAST(1 AS bit) THEN CASE + WHEN [w].[IsAutomatic] = CAST(0 AS bit) THEN CASE WHEN [w].[AmmunitionType] = 1 THEN N'ManualCartridge' ELSE N'Manual' END @@ -1425,7 +1425,7 @@ SELECT TOP(1) [t].[IsAutomatic] FROM [Weapons] AS [w] WHERE [g].[FullName] = [w].[OwnerFullName] ) AS [t] - ORDER BY [t].[Id] DESC) <> CAST(1 AS bit) + ORDER BY [t].[Id] DESC) = CAST(0 AS bit) ORDER BY [g].[Nickname]"); } @@ -1436,7 +1436,7 @@ public override async Task Where_subquery_distinct_last_boolean(bool async) AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] FROM [Gears] AS [g] -WHERE ([g].[HasSoulPatch] <> CAST(1 AS bit)) AND (( +WHERE ([g].[HasSoulPatch] = CAST(0 AS bit)) AND (( SELECT TOP(1) [t].[IsAutomatic] FROM ( SELECT DISTINCT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -1638,7 +1638,7 @@ FROM [Weapons] AS [w0] WHERE [g].[FullName] = [w0].[OwnerFullName] ) AS [t]) FROM [Gears] AS [g] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit)"); +WHERE [g].[HasSoulPatch] = CAST(0 AS bit)"); } public override async Task Concat_with_collection_navigations(bool async) @@ -2116,7 +2116,7 @@ public override async Task Optional_navigation_type_compensation_works_with_pred @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[IssueDate], [t].[Note] FROM [Tags] AS [t] LEFT JOIN [Gears] AS [g] ON ([t].[GearNickName] = [g].[Nickname]) AND ([t].[GearSquadId] = [g].[SquadId]) -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit)"); +WHERE [g].[HasSoulPatch] = CAST(0 AS bit)"); } public override async Task Optional_navigation_type_compensation_works_with_predicate_negated_complex1(bool async) @@ -2130,7 +2130,7 @@ LEFT JOIN [Gears] AS [g] ON ([t].[GearNickName] = [g].[Nickname]) AND ([t].[Gear WHERE CASE WHEN [g].[HasSoulPatch] = CAST(1 AS bit) THEN CAST(1 AS bit) ELSE [g].[HasSoulPatch] -END <> CAST(1 AS bit)"); +END = CAST(0 AS bit)"); } public override async Task Optional_navigation_type_compensation_works_with_predicate_negated_complex2(bool async) @@ -2142,9 +2142,9 @@ public override async Task Optional_navigation_type_compensation_works_with_pred FROM [Tags] AS [t] LEFT JOIN [Gears] AS [g] ON ([t].[GearNickName] = [g].[Nickname]) AND ([t].[GearSquadId] = [g].[SquadId]) WHERE CASE - WHEN [g].[HasSoulPatch] <> CAST(1 AS bit) THEN CAST(0 AS bit) + WHEN [g].[HasSoulPatch] = CAST(0 AS bit) THEN CAST(0 AS bit) ELSE [g].[HasSoulPatch] -END <> CAST(1 AS bit)"); +END = CAST(0 AS bit)"); } public override async Task Optional_navigation_type_compensation_works_with_conditional_expression(bool async) @@ -2263,7 +2263,7 @@ WHEN NOT EXISTS ( SELECT 1 FROM [Tags] AS [t] LEFT JOIN [Gears] AS [g] ON ([t].[GearNickName] = [g].[Nickname]) AND ([t].[GearSquadId] = [g].[SquadId]) - WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([g].[HasSoulPatch] <> CAST(1 AS bit))) THEN CAST(1 AS bit) + WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([g].[HasSoulPatch] = CAST(0 AS bit))) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END"); } @@ -2276,7 +2276,7 @@ public override async Task Optional_navigation_type_compensation_works_with_nega @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[IssueDate], [t].[Note] FROM [Tags] AS [t] LEFT JOIN [Gears] AS [g] ON ([t].[GearNickName] = [g].[Nickname]) AND ([t].[GearSquadId] = [g].[SquadId]) -WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([g].[HasSoulPatch] <> CAST(1 AS bit))"); +WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([g].[HasSoulPatch] = CAST(0 AS bit))"); } public override async Task Optional_navigation_type_compensation_works_with_contains(bool async) @@ -2704,7 +2704,7 @@ public override async Task Complex_predicate_with_AndAlso_and_nullable_bool_prop @"SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Weapons] AS [w] LEFT JOIN [Gears] AS [g] ON [w].[OwnerFullName] = [g].[FullName] -WHERE ([w].[Id] <> 50) AND ([g].[HasSoulPatch] <> CAST(1 AS bit))"); +WHERE ([w].[Id] <> 50) AND ([g].[HasSoulPatch] = CAST(0 AS bit))"); } public override async Task Distinct_with_optional_navigation_is_translated_to_sql(bool async) @@ -2808,7 +2808,7 @@ public override async Task Multiple_order_bys_are_properly_lifted_from_subquery_ AssertSql( @"SELECT [g].[FullName] FROM [Gears] AS [g] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) +WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName]"); } @@ -2819,7 +2819,7 @@ public override async Task Order_by_is_properly_lifted_from_subquery_with_same_o AssertSql( @"SELECT [g].[FullName] FROM [Gears] AS [g] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) +WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName]"); } @@ -2831,7 +2831,7 @@ public override async Task Where_is_properly_lifted_from_subquery_created_by_inc @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[IssueDate], [t].[Note] FROM [Gears] AS [g] LEFT JOIN [Tags] AS [t] ON ([g].[Nickname] = [t].[GearNickName]) AND ([g].[SquadId] = [t].[GearSquadId]) -WHERE ([g].[FullName] <> N'Augustus Cole') AND ([g].[HasSoulPatch] <> CAST(1 AS bit)) +WHERE ([g].[FullName] <> N'Augustus Cole') AND ([g].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[FullName]"); } @@ -2843,7 +2843,7 @@ public override async Task Subquery_is_lifted_from_main_from_clause_of_SelectMan @"SELECT [g].[FullName] AS [Name1], [g0].[FullName] AS [Name2] FROM [Gears] AS [g] CROSS JOIN [Gears] AS [g0] -WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([g0].[HasSoulPatch] <> CAST(1 AS bit)) +WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([g0].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[FullName]"); } @@ -2905,7 +2905,7 @@ FROM [Gears] AS [g] WHERE EXISTS ( SELECT 1 FROM [Weapons] AS [w] - WHERE [g].[FullName] = [w].[OwnerFullName]) AND ([g].[HasSoulPatch] <> CAST(1 AS bit)) + WHERE [g].[FullName] = [w].[OwnerFullName]) AND ([g].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[Nickname]"); } @@ -2920,7 +2920,7 @@ CROSS JOIN ( SELECT [g0].[FullName], [g0].[HasSoulPatch] FROM [Gears] AS [g0] ) AS [t] -WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([t].[HasSoulPatch] <> CAST(1 AS bit)) +WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([t].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[FullName]"); } @@ -2935,7 +2935,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName] ) AS [t] ORDER BY [t].[Rank]"); @@ -2952,7 +2952,7 @@ SELECT [t].[FullName] FROM ( SELECT [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName] OFFSET @__p_0 ROWS ) AS [t] @@ -2970,7 +2970,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ORDER BY [t].[Rank]"); } @@ -2986,7 +2986,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ORDER BY [t].[Rank]"); } @@ -3002,7 +3002,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ORDER BY [t].[FullName], [t].[Rank]"); } @@ -3721,7 +3721,7 @@ FROM [Gears] AS [g] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[FullName], [g0].[SquadId], [g0].[LeaderNickname], [g0].[LeaderSquadId] FROM [Gears] AS [g0] - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ON ([g].[Nickname] = [t].[LeaderNickname]) AND ([g].[SquadId] = [t].[LeaderSquadId]) WHERE ([g].[Discriminator] = N'Officer') AND ([g].[Nickname] <> N'Foo') ORDER BY [g].[Nickname], [g].[SquadId], [t].[Nickname], [t].[SquadId]"); @@ -3923,7 +3923,7 @@ FROM [Weapons] AS [w] LEFT JOIN ( SELECT [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Weapons] AS [w0] - WHERE [w0].[IsAutomatic] <> CAST(1 AS bit) + WHERE [w0].[IsAutomatic] = CAST(0 AS bit) ) AS [t0] ON [g].[FullName] = [t0].[OwnerFullName] ORDER BY [g].[Rank], [g].[Nickname], [g].[SquadId], [t].[OwnerFullName], [t].[Id], [t0].[IsAutomatic], [t0].[Id]"); } @@ -4159,7 +4159,7 @@ FROM [Weapons] AS [w] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] FROM [Gears] AS [g0] - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t0] ON [s].[Id] = [t0].[SquadId] WHERE [g].[HasSoulPatch] = CAST(1 AS bit) ORDER BY [g].[Nickname], [s].[Id] DESC, [g].[SquadId], [t].[Id], [t0].[Nickname], [t0].[SquadId]"); @@ -4252,7 +4252,7 @@ public override async Task Correlated_collections_on_left_join_with_predicate(bo FROM [Tags] AS [t] LEFT JOIN [Gears] AS [g] ON [t].[GearNickName] = [g].[Nickname] LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) +WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [t].[Id], [g].[Nickname], [g].[SquadId], [w].[Id]"); } @@ -4321,7 +4321,7 @@ FROM [Gears] AS [g0] LEFT JOIN ( SELECT [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Weapons] AS [w0] - WHERE [w0].[IsAutomatic] <> CAST(1 AS bit) + WHERE [w0].[IsAutomatic] = CAST(0 AS bit) ) AS [t] ON [g0].[FullName] = [t].[OwnerFullName] ) AS [t0] ON [s].[Id] = [t0].[SquadId] ORDER BY [w].[Name], [w].[Id], [g].[Nickname], [g].[SquadId], [s].[Id], [t0].[FullName] DESC, [t0].[Nickname], [t0].[SquadId], [t0].[Id]"); @@ -4611,7 +4611,7 @@ public override async Task Negated_bool_ternary_inside_anonymous_type_in_project WHEN CASE WHEN [g].[HasSoulPatch] = CAST(1 AS bit) THEN CAST(1 AS bit) ELSE COALESCE([g].[HasSoulPatch], CAST(1 AS bit)) - END <> CAST(1 AS bit) THEN CAST(1 AS bit) + END = CAST(0 AS bit) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [c] FROM [Tags] AS [t] @@ -4783,7 +4783,7 @@ ORDER BY [g].[Nickname] LEFT JOIN ( SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Weapons] AS [w] - WHERE [w].[IsAutomatic] <> CAST(1 AS bit) + WHERE [w].[IsAutomatic] = CAST(0 AS bit) ) AS [t0] ON [t].[FullName] = [t0].[OwnerFullName] ORDER BY [t].[Nickname], [t].[SquadId], [t0].[Id]"); } @@ -5034,7 +5034,7 @@ FROM [Gears] AS [g] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] FROM [Gears] AS [g0] - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ON ([g].[Nickname] = [t].[LeaderNickname]) AND ([g].[SquadId] = [t].[LeaderSquadId]) WHERE [g].[Discriminator] = N'Officer' ORDER BY ( @@ -5053,7 +5053,7 @@ FROM [Gears] AS [g] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] FROM [Gears] AS [g0] - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ON ([g].[Nickname] = [t].[LeaderNickname]) AND ([g].[SquadId] = [t].[LeaderSquadId]) WHERE [g].[Discriminator] = N'Officer' ORDER BY ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs index a6e9f41e6ee..cd2f3438b33 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindDbFunctionsQuerySqlServerTest.cs @@ -695,7 +695,7 @@ await AssertQueryScalar( AssertSql( @"SELECT CAST(ISDATE([o].[CustomerID]) AS bit) FROM [Orders] AS [o] -WHERE CAST(ISDATE([o].[CustomerID]) AS bit) <> CAST(1 AS bit)"); +WHERE CAST(ISDATE([o].[CustomerID]) AS bit) = CAST(0 AS bit)"); } [ConditionalTheory] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs index 24ed2f1cd56..107867fbc3f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs @@ -1038,7 +1038,7 @@ public override async Task Where_bool_member_false(bool async) AssertSql( @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] FROM [Products] AS [p] -WHERE [p].[Discontinued] <> CAST(1 AS bit)"); +WHERE [p].[Discontinued] = CAST(0 AS bit)"); } public override async Task Where_bool_member_negated_twice(bool async) @@ -1068,7 +1068,7 @@ public override async Task Where_bool_member_false_shadow(bool async) AssertSql( @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] FROM [Products] AS [p] -WHERE [p].[Discontinued] <> CAST(1 AS bit)"); +WHERE [p].[Discontinued] = CAST(0 AS bit)"); } public override async Task Where_bool_member_equals_constant(bool async) @@ -1194,7 +1194,7 @@ public override async Task Where_de_morgan_or_optimized(bool async) AssertSql( @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] FROM [Products] AS [p] -WHERE ([p].[Discontinued] <> CAST(1 AS bit)) AND ([p].[ProductID] >= 20)"); +WHERE ([p].[Discontinued] = CAST(0 AS bit)) AND ([p].[ProductID] >= 20)"); } public override async Task Where_de_morgan_and_optimized(bool async) @@ -1204,7 +1204,7 @@ public override async Task Where_de_morgan_and_optimized(bool async) AssertSql( @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] FROM [Products] AS [p] -WHERE ([p].[Discontinued] <> CAST(1 AS bit)) OR ([p].[ProductID] >= 20)"); +WHERE ([p].[Discontinued] = CAST(0 AS bit)) OR ([p].[ProductID] >= 20)"); } public override async Task Where_complex_negated_expression_optimized(bool async) @@ -1214,7 +1214,7 @@ public override async Task Where_complex_negated_expression_optimized(bool async AssertSql( @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] FROM [Products] AS [p] -WHERE (([p].[Discontinued] <> CAST(1 AS bit)) AND ([p].[ProductID] < 60)) AND ([p].[ProductID] > 30)"); +WHERE (([p].[Discontinued] = CAST(0 AS bit)) AND ([p].[ProductID] < 60)) AND ([p].[ProductID] > 30)"); } public override async Task Where_short_member_comparison(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 2a95c7d9868..e28bd2af506 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -2845,7 +2845,7 @@ public virtual void Conditional_expression_with_conditions_does_not_collapse_if_ AssertSql( @"SELECT CASE WHEN [c0].[Id] IS NOT NULL THEN CASE - WHEN [c0].[Processed] <> CAST(1 AS bit) THEN CAST(1 AS bit) + WHEN [c0].[Processed] = CAST(0 AS bit) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END ELSE NULL @@ -5385,7 +5385,7 @@ public virtual void Expression_tree_constructed_via_interface_works_17276() AssertSql( @"SELECT [r].[Id], [r].[IsRemoved], [r].[Removed], [r].[RemovedByUser], [r].[OwnedEntity_OwnedValue] FROM [RemovableEntities] AS [r] -WHERE [r].[IsRemoved] <> CAST(1 AS bit)"); +WHERE [r].[IsRemoved] = CAST(0 AS bit)"); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryFilterFuncletizationSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryFilterFuncletizationSqlServerTest.cs index 331a1550fa0..11f11398703 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryFilterFuncletizationSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryFilterFuncletizationSqlServerTest.cs @@ -194,20 +194,20 @@ public override void DbContext_property_based_filter_does_not_short_circuit() SELECT [s].[Id], [s].[IsDeleted], [s].[IsModerated] FROM [ShortCircuitFilter] AS [s] -WHERE ([s].[IsDeleted] <> CAST(1 AS bit)) AND ((@__ef_filter__p_0 = CAST(1 AS bit)) OR (@__ef_filter__IsModerated_1 = [s].[IsModerated]))", +WHERE ([s].[IsDeleted] = CAST(0 AS bit)) AND ((@__ef_filter__p_0 = CAST(1 AS bit)) OR (@__ef_filter__IsModerated_1 = [s].[IsModerated]))", // @"@__ef_filter__p_0='False' @__ef_filter__IsModerated_1='False' (Nullable = true) SELECT [s].[Id], [s].[IsDeleted], [s].[IsModerated] FROM [ShortCircuitFilter] AS [s] -WHERE ([s].[IsDeleted] <> CAST(1 AS bit)) AND ((@__ef_filter__p_0 = CAST(1 AS bit)) OR (@__ef_filter__IsModerated_1 = [s].[IsModerated]))", +WHERE ([s].[IsDeleted] = CAST(0 AS bit)) AND ((@__ef_filter__p_0 = CAST(1 AS bit)) OR (@__ef_filter__IsModerated_1 = [s].[IsModerated]))", // @"@__ef_filter__p_0='True' SELECT [s].[Id], [s].[IsDeleted], [s].[IsModerated] FROM [ShortCircuitFilter] AS [s] -WHERE ([s].[IsDeleted] <> CAST(1 AS bit)) AND (@__ef_filter__p_0 = CAST(1 AS bit))"); +WHERE ([s].[IsDeleted] = CAST(0 AS bit)) AND (@__ef_filter__p_0 = CAST(1 AS bit))"); } public override void EntityTypeConfiguration_DbContext_field_is_parameterized() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 9a593b71c22..5917ebc7d5b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -874,7 +874,7 @@ public override async Task Select_inverted_boolean(bool async) AssertSql( @"SELECT [w].[Id], CASE - WHEN [w].[IsAutomatic] <> CAST(1 AS bit) THEN CAST(1 AS bit) + WHEN [w].[IsAutomatic] = CAST(0 AS bit) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [Manual] FROM [Weapons] AS [w] @@ -943,7 +943,7 @@ public override async Task Select_ternary_operation_with_inverted_boolean(bool a AssertSql( @"SELECT [w].[Id], CASE - WHEN [w].[IsAutomatic] <> CAST(1 AS bit) THEN 1 + WHEN [w].[IsAutomatic] = CAST(0 AS bit) THEN 1 ELSE 0 END AS [Num] FROM [Weapons] AS [w]"); @@ -980,7 +980,7 @@ public override async Task Select_ternary_operation_multiple_conditions_2(bool a AssertSql( @"SELECT [w].[Id], CASE - WHEN ([w].[IsAutomatic] <> CAST(1 AS bit)) AND ([w].[SynergyWithId] = 1) THEN N'Yes' + WHEN ([w].[IsAutomatic] = CAST(0 AS bit)) AND ([w].[SynergyWithId] = 1) THEN N'Yes' ELSE N'No' END AS [IsCartridge] FROM [Weapons] AS [w]"); @@ -992,7 +992,7 @@ public override async Task Select_multiple_conditions(bool async) AssertSql( @"SELECT [w].[Id], CASE - WHEN ([w].[IsAutomatic] <> CAST(1 AS bit)) AND (([w].[SynergyWithId] = 1) AND [w].[SynergyWithId] IS NOT NULL) THEN CAST(1 AS bit) + WHEN ([w].[IsAutomatic] = CAST(0 AS bit)) AND (([w].[SynergyWithId] = 1) AND [w].[SynergyWithId] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [IsCartridge] FROM [Weapons] AS [w]"); @@ -1004,7 +1004,7 @@ public override async Task Select_nested_ternary_operations(bool async) AssertSql( @"SELECT [w].[Id], CASE - WHEN [w].[IsAutomatic] <> CAST(1 AS bit) THEN CASE + WHEN [w].[IsAutomatic] = CAST(0 AS bit) THEN CASE WHEN [w].[AmmunitionType] = 1 THEN N'ManualCartridge' ELSE N'Manual' END @@ -1729,7 +1729,7 @@ SELECT TOP(1) [t].[IsAutomatic] FROM [Weapons] AS [w] WHERE [g].[FullName] = [w].[OwnerFullName] ) AS [t] - ORDER BY [t].[Id] DESC) <> CAST(1 AS bit) + ORDER BY [t].[Id] DESC) = CAST(0 AS bit) ORDER BY [g].[Nickname]"); } @@ -1743,7 +1743,7 @@ WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' END AS [Discriminator] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) -WHERE ([g].[HasSoulPatch] <> CAST(1 AS bit)) AND (( +WHERE ([g].[HasSoulPatch] = CAST(0 AS bit)) AND (( SELECT TOP(1) [t].[IsAutomatic] FROM ( SELECT DISTINCT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -1983,7 +1983,7 @@ FROM [Weapons] AS [w0] WHERE [g].[FullName] = [w0].[OwnerFullName] ) AS [t]) FROM [Gears] AS [g] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit)"); +WHERE [g].[HasSoulPatch] = CAST(0 AS bit)"); } public override async Task Concat_with_collection_navigations(bool async) @@ -2535,7 +2535,7 @@ LEFT JOIN ( SELECT [g].[Nickname], [g].[SquadId], [g].[HasSoulPatch] FROM [Gears] AS [g] ) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) -WHERE [t0].[HasSoulPatch] <> CAST(1 AS bit)"); +WHERE [t0].[HasSoulPatch] = CAST(0 AS bit)"); } public override async Task Optional_navigation_type_compensation_works_with_predicate_negated_complex1(bool async) @@ -2552,7 +2552,7 @@ FROM [Gears] AS [g] WHERE CASE WHEN [t0].[HasSoulPatch] = CAST(1 AS bit) THEN CAST(1 AS bit) ELSE [t0].[HasSoulPatch] -END <> CAST(1 AS bit)"); +END = CAST(0 AS bit)"); } public override async Task Optional_navigation_type_compensation_works_with_predicate_negated_complex2(bool async) @@ -2567,9 +2567,9 @@ LEFT JOIN ( FROM [Gears] AS [g] ) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) WHERE CASE - WHEN [t0].[HasSoulPatch] <> CAST(1 AS bit) THEN CAST(0 AS bit) + WHEN [t0].[HasSoulPatch] = CAST(0 AS bit) THEN CAST(0 AS bit) ELSE [t0].[HasSoulPatch] -END <> CAST(1 AS bit)"); +END = CAST(0 AS bit)"); } public override async Task Optional_navigation_type_compensation_works_with_conditional_expression(bool async) @@ -2721,7 +2721,7 @@ END AS [Discriminator] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) ) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) - WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([t0].[HasSoulPatch] <> CAST(1 AS bit))) THEN CAST(1 AS bit) + WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([t0].[HasSoulPatch] = CAST(0 AS bit))) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END"); } @@ -2737,7 +2737,7 @@ LEFT JOIN ( SELECT [g].[Nickname], [g].[SquadId], [g].[HasSoulPatch] FROM [Gears] AS [g] ) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) -WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([t0].[HasSoulPatch] <> CAST(1 AS bit))"); +WHERE (([t].[Note] <> N'K.I.A.') OR [t].[Note] IS NULL) AND ([t0].[HasSoulPatch] = CAST(0 AS bit))"); } public override async Task Optional_navigation_type_compensation_works_with_contains(bool async) @@ -3200,7 +3200,7 @@ LEFT JOIN ( SELECT [g].[FullName], [g].[HasSoulPatch] FROM [Gears] AS [g] ) AS [t] ON [w].[OwnerFullName] = [t].[FullName] -WHERE ([w].[Id] <> 50) AND ([t].[HasSoulPatch] <> CAST(1 AS bit))"); +WHERE ([w].[Id] <> 50) AND ([t].[HasSoulPatch] = CAST(0 AS bit))"); } public override async Task Distinct_with_optional_navigation_is_translated_to_sql(bool async) @@ -3312,7 +3312,7 @@ public override async Task Multiple_order_bys_are_properly_lifted_from_subquery_ AssertSql( @"SELECT [g].[FullName] FROM [Gears] AS [g] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) +WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName]"); } @@ -3323,7 +3323,7 @@ public override async Task Order_by_is_properly_lifted_from_subquery_with_same_o AssertSql( @"SELECT [g].[FullName] FROM [Gears] AS [g] -WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) +WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName]"); } @@ -3338,7 +3338,7 @@ WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) LEFT JOIN [Tags] AS [t] ON ([g].[Nickname] = [t].[GearNickName]) AND ([g].[SquadId] = [t].[GearSquadId]) -WHERE ([g].[FullName] <> N'Augustus Cole') AND ([g].[HasSoulPatch] <> CAST(1 AS bit)) +WHERE ([g].[FullName] <> N'Augustus Cole') AND ([g].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[FullName]"); } @@ -3353,7 +3353,7 @@ CROSS JOIN ( SELECT [g0].[FullName], [g0].[HasSoulPatch] FROM [Gears] AS [g0] ) AS [t] -WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([t].[HasSoulPatch] <> CAST(1 AS bit)) +WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([t].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[FullName]"); } @@ -3418,7 +3418,7 @@ LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[Squad WHERE EXISTS ( SELECT 1 FROM [Weapons] AS [w] - WHERE [g].[FullName] = [w].[OwnerFullName]) AND ([g].[HasSoulPatch] <> CAST(1 AS bit)) + WHERE [g].[FullName] = [w].[OwnerFullName]) AND ([g].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[Nickname]"); } @@ -3433,7 +3433,7 @@ CROSS JOIN ( SELECT [g0].[FullName], [g0].[HasSoulPatch] FROM [Gears] AS [g0] ) AS [t] -WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([t].[HasSoulPatch] <> CAST(1 AS bit)) +WHERE ([g].[HasSoulPatch] = CAST(1 AS bit)) AND ([t].[HasSoulPatch] = CAST(0 AS bit)) ORDER BY [g].[FullName]"); } @@ -3448,7 +3448,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName] ) AS [t] ORDER BY [t].[Rank]"); @@ -3465,7 +3465,7 @@ SELECT [t].[FullName] FROM ( SELECT [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [g].[FullName] OFFSET @__p_0 ROWS ) AS [t] @@ -3483,7 +3483,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ORDER BY [t].[Rank]"); } @@ -3499,7 +3499,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ORDER BY [t].[Rank]"); } @@ -3515,7 +3515,7 @@ SELECT [t].[FullName] FROM ( SELECT TOP(@__p_0) [g].[FullName], [g].[Rank] FROM [Gears] AS [g] - WHERE [g].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ORDER BY [t].[FullName], [t].[Rank]"); } @@ -4490,7 +4490,7 @@ LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[Squad LEFT JOIN ( SELECT [g0].[Nickname], [g0].[FullName], [g0].[SquadId], [g0].[LeaderNickname], [g0].[LeaderSquadId] FROM [Gears] AS [g0] - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ON ([g].[Nickname] = [t].[LeaderNickname]) AND ([g].[SquadId] = [t].[LeaderSquadId]) WHERE [o].[Nickname] IS NOT NULL AND ([g].[Nickname] <> N'Foo') ORDER BY [g].[Nickname], [g].[SquadId], [t].[Nickname], [t].[SquadId]"); @@ -4696,7 +4696,7 @@ FROM [Weapons] AS [w] LEFT JOIN ( SELECT [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Weapons] AS [w0] - WHERE [w0].[IsAutomatic] <> CAST(1 AS bit) + WHERE [w0].[IsAutomatic] = CAST(0 AS bit) ) AS [t0] ON [g].[FullName] = [t0].[OwnerFullName] ORDER BY [g].[Rank], [g].[Nickname], [g].[SquadId], [t].[OwnerFullName], [t].[Id], [t0].[IsAutomatic], [t0].[Id]"); } @@ -4977,7 +4977,7 @@ WHEN [o0].[Nickname] IS NOT NULL THEN N'Officer' END AS [Discriminator] FROM [Gears] AS [g0] LEFT JOIN [Officers] AS [o0] ON ([g0].[Nickname] = [o0].[Nickname]) AND ([g0].[SquadId] = [o0].[SquadId]) - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t0] ON [s].[Id] = [t0].[SquadId] WHERE [g].[HasSoulPatch] = CAST(1 AS bit) ORDER BY [g].[Nickname], [s].[Id] DESC, [g].[SquadId], [t].[Id], [t0].[Nickname], [t0].[SquadId]"); @@ -5077,7 +5077,7 @@ LEFT JOIN ( FROM [Gears] AS [g] ) AS [t0] ON [t].[GearNickName] = [t0].[Nickname] LEFT JOIN [Weapons] AS [w] ON [t0].[FullName] = [w].[OwnerFullName] -WHERE [t0].[HasSoulPatch] <> CAST(1 AS bit) +WHERE [t0].[HasSoulPatch] = CAST(0 AS bit) ORDER BY [t].[Id], [t0].[Nickname], [t0].[SquadId], [w].[Id]"); } @@ -5159,7 +5159,7 @@ FROM [Gears] AS [g0] LEFT JOIN ( SELECT [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Weapons] AS [w0] - WHERE [w0].[IsAutomatic] <> CAST(1 AS bit) + WHERE [w0].[IsAutomatic] = CAST(0 AS bit) ) AS [t0] ON [g0].[FullName] = [t0].[OwnerFullName] ) AS [t1] ON [s].[Id] = [t1].[SquadId] ORDER BY [w].[Name], [w].[Id], [t].[Nickname], [t].[SquadId], [s].[Id], [t1].[FullName] DESC, [t1].[Nickname], [t1].[SquadId], [t1].[Id]"); @@ -5494,7 +5494,7 @@ public override async Task Negated_bool_ternary_inside_anonymous_type_in_project WHEN CASE WHEN [t0].[HasSoulPatch] = CAST(1 AS bit) THEN CAST(1 AS bit) ELSE COALESCE([t0].[HasSoulPatch], CAST(1 AS bit)) - END <> CAST(1 AS bit) THEN CAST(1 AS bit) + END = CAST(0 AS bit) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END AS [c] FROM [Tags] AS [t] @@ -5689,7 +5689,7 @@ ORDER BY [g].[Nickname] LEFT JOIN ( SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Weapons] AS [w] - WHERE [w].[IsAutomatic] <> CAST(1 AS bit) + WHERE [w].[IsAutomatic] = CAST(0 AS bit) ) AS [t0] ON [t].[FullName] = [t0].[OwnerFullName] ORDER BY [t].[Nickname], [t].[SquadId], [t0].[Id]"); } @@ -5982,7 +5982,7 @@ WHEN [o0].[Nickname] IS NOT NULL THEN N'Officer' END AS [Discriminator] FROM [Gears] AS [g0] LEFT JOIN [Officers] AS [o0] ON ([g0].[Nickname] = [o0].[Nickname]) AND ([g0].[SquadId] = [o0].[SquadId]) - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ON ([g].[Nickname] = [t].[LeaderNickname]) AND ([g].[SquadId] = [t].[LeaderSquadId]) WHERE [o].[Nickname] IS NOT NULL ORDER BY ( @@ -6005,7 +6005,7 @@ WHEN [o0].[Nickname] IS NOT NULL THEN N'Officer' END AS [Discriminator] FROM [Gears] AS [g0] LEFT JOIN [Officers] AS [o0] ON ([g0].[Nickname] = [o0].[Nickname]) AND ([g0].[SquadId] = [o0].[SquadId]) - WHERE [g0].[HasSoulPatch] <> CAST(1 AS bit) + WHERE [g0].[HasSoulPatch] = CAST(0 AS bit) ) AS [t] ON ([g].[Nickname] = [t].[LeaderNickname]) AND ([g].[SquadId] = [t].[LeaderSquadId]) WHERE [o].[Nickname] IS NOT NULL ORDER BY ( diff --git a/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs index e80b5ec0388..296bde454d3 100644 --- a/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs @@ -59,6 +59,17 @@ public override void Where_bool_gets_converted_to_equality_when_value_conversion WHERE ""b"".""IsVisible"" = 'Y'"); } + [ConditionalFact] + public override void Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used() + { + base.Where_negated_bool_gets_converted_to_equality_when_value_conversion_is_used(); + + AssertSql( + @"SELECT ""b"".""BlogId"", ""b"".""Discriminator"", ""b"".""IndexerVisible"", ""b"".""IsVisible"", ""b"".""Url"", ""b"".""RssUrl"" +FROM ""Blog"" AS ""b"" +WHERE ""b"".""IsVisible"" = 'N'"); + } + public override void Where_bool_with_value_conversion_inside_comparison_doesnt_get_converted_twice() { base.Where_bool_with_value_conversion_inside_comparison_doesnt_get_converted_twice(); @@ -101,7 +112,7 @@ public override void Where_bool_gets_converted_to_equality_when_value_conversion AssertSql( @"SELECT ""b"".""BlogId"", ""b"".""Discriminator"", ""b"".""IndexerVisible"", ""b"".""IsVisible"", ""b"".""Url"", ""b"".""RssUrl"" FROM ""Blog"" AS ""b"" -WHERE ""b"".""IndexerVisible"" <> 'Aye'"); +WHERE ""b"".""IndexerVisible"" = 'Nay'"); } private void AssertSql(params string[] expected)