From 35fc423ba39630b3bf883e9e06c4ee4ea038ae3e Mon Sep 17 00:00:00 2001 From: maumar Date: Tue, 31 Dec 2024 22:21:44 -0800 Subject: [PATCH 1/4] Fix to #35393 - GroupJoin in EF Core 9 Returns Null for Joined Entities Problem was that in EF9 we moved some optimizations from sql nullability processor to SqlExpressionFactory (so that we optimize things early). One of the optimizations: ``` !(true == a) -> false == a !(false == a) -> true == a ``` is not safe to do when a is a constant or parameter null value, because it evaluates to true IS NULL (two value logic). Fix is to remove this optimization from SqlExpressionFactory and instead put it back into OptimizeNotExpression, once we've converted everything we could to IS NULL checks already. Fixes #35393 --- .../Query/SqlExpressionFactory.cs | 12 +---- .../Query/SqlNullabilityProcessor.cs | 54 +++++++++++++------ .../Query/NullSemanticsQueryTestBase.cs | 19 +++++++ .../Query/NorthwindJoinQueryTestBase.cs | 18 +++++++ .../Query/GearsOfWarQuerySqlServerTest.cs | 6 +-- .../Query/NorthwindJoinQuerySqlServerTest.cs | 16 ++++++ .../Query/NullSemanticsQuerySqlServerTest.cs | 24 +++++++++ .../Query/TPCGearsOfWarQuerySqlServerTest.cs | 6 +-- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 10 ++-- .../TemporalGearsOfWarQuerySqlServerTest.cs | 6 +-- .../Query/GearsOfWarQuerySqliteTest.cs | 6 +-- .../Query/NorthwindJoinQuerySqliteTest.cs | 6 +++ 12 files changed, 139 insertions(+), 44 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 064e97cbe74..333f58c7079 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -660,20 +660,10 @@ private SqlExpression Not(SqlExpression operand, SqlExpression? existingExpressi SqlBinaryExpression { OperatorType: ExpressionType.OrElse } binary => AndAlso(Not(binary.Left), Not(binary.Right)), - // use equality where possible - // !(a == true) -> a == false - // !(a == false) -> a == true - SqlBinaryExpression { OperatorType: ExpressionType.Equal, Right: SqlConstantExpression { Value: bool } } binary - => Equal(binary.Left, Not(binary.Right)), - - // !(true == a) -> false == a - // !(false == a) -> true == a - SqlBinaryExpression { OperatorType: ExpressionType.Equal, Left: SqlConstantExpression { Value: bool } } binary - => Equal(Not(binary.Left), binary.Right), - // !(a == b) -> a != b SqlBinaryExpression { OperatorType: ExpressionType.Equal } sqlBinaryOperand => NotEqual( sqlBinaryOperand.Left, sqlBinaryOperand.Right), + // !(a != b) -> a == b SqlBinaryExpression { OperatorType: ExpressionType.NotEqual } sqlBinaryOperand => Equal( sqlBinaryOperand.Left, sqlBinaryOperand.Right), diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index a05a69773f8..59b72f7a552 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -1124,7 +1124,7 @@ protected virtual SqlExpression VisitSqlBinary( // we assume that NullSemantics rewrite is only needed (on the current level) // if the optimization didn't make any changes. // Reason is that optimization can/will change the nullability of the resulting expression - // and that inforation is not tracked/stored anywhere + // and that information is not tracked/stored anywhere // so we can no longer rely on nullabilities that we computed earlier (leftNullable, rightNullable) // when performing null semantics rewrite. // It should be fine because current optimizations *radically* change the expression @@ -1590,10 +1590,10 @@ private SqlExpression RewriteNullSemantics( } var leftIsNull = ProcessNullNotNull(_sqlExpressionFactory.IsNull(left), leftNullable); - var leftIsNotNull = _sqlExpressionFactory.Not(leftIsNull); + var leftIsNotNull = OptimizeNotExpression(_sqlExpressionFactory.Not(leftIsNull)); var rightIsNull = ProcessNullNotNull(_sqlExpressionFactory.IsNull(right), rightNullable); - var rightIsNotNull = _sqlExpressionFactory.Not(rightIsNull); + var rightIsNotNull = OptimizeNotExpression(_sqlExpressionFactory.Not(rightIsNull)); SqlExpression body; if (leftNegated == rightNegated) @@ -1625,7 +1625,7 @@ private SqlExpression RewriteNullSemantics( if (sqlBinaryExpression.OperatorType == ExpressionType.NotEqual) { // the factory takes care of simplifying using DeMorgan - body = _sqlExpressionFactory.Not(body); + body = OptimizeNotExpression(_sqlExpressionFactory.Not(body)); } return body; @@ -1643,18 +1643,40 @@ protected virtual SqlExpression OptimizeNotExpression(SqlExpression expression) return expression; } - // !(a > b) -> a <= b - // !(a >= b) -> a < b - // !(a < b) -> a >= b - // !(a <= b) -> a > b - if (sqlUnaryExpression.Operand is SqlBinaryExpression sqlBinaryOperand - && TryNegate(sqlBinaryOperand.OperatorType, out var negated)) + if (sqlUnaryExpression.Operand is SqlBinaryExpression sqlBinaryOperand) { - return _sqlExpressionFactory.MakeBinary( - negated, - sqlBinaryOperand.Left, - sqlBinaryOperand.Right, - sqlBinaryOperand.TypeMapping)!; + // !(a > b) -> a <= b + // !(a >= b) -> a < b + // !(a < b) -> a >= b + // !(a <= b) -> a > b + if (TryNegate(sqlBinaryOperand.OperatorType, out var negated)) + { + return _sqlExpressionFactory.MakeBinary( + negated, + sqlBinaryOperand.Left, + sqlBinaryOperand.Right, + sqlBinaryOperand.TypeMapping)!; + } + + // use equality where possible - at this point (true == null) and (false == null) have been converted to + // IS NULL / IS NOT NULL (i.e. false), so this optimization is safe to do. See #35393 + // !(a == true) -> a == false + // !(a == false) -> a == true + if (sqlBinaryOperand is { OperatorType: ExpressionType.Equal, Right: SqlConstantExpression { Value: bool } }) + { + return _sqlExpressionFactory.Equal( + sqlBinaryOperand.Left, + OptimizeNotExpression(_sqlExpressionFactory.Not(sqlBinaryOperand.Right))); + } + + // !(true == a) -> false == a + // !(false == a) -> true == a + if (sqlBinaryOperand is { OperatorType: ExpressionType.Equal, Left: SqlConstantExpression { Value: bool } }) + { + return _sqlExpressionFactory.Equal( + OptimizeNotExpression(_sqlExpressionFactory.Not(sqlBinaryOperand.Left)), + sqlBinaryOperand.Right); + } } // the factory can optimize most `NOT` expressions @@ -2039,7 +2061,7 @@ private SqlExpression ProcessNullNotNull(SqlExpression sqlExpression, bool opera return result; } } - break; + break; } return sqlUnaryExpression; diff --git a/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs index 6ce93abfd78..c20257949ad 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs @@ -2459,6 +2459,25 @@ await AssertQueryScalar( ss => ss.Set().Where(e => true).Select(e => e.Id)); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Compare_constant_true_to_nullable_column_negated(bool async) + => await AssertQueryScalar( + async, + ss => ss.Set().Where(x => !(true == x.NullableBoolA)).Select(x => x.Id)); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Compare_constant_true_to_expression_which_evaluates_to_null(bool async) + { + var prm = default(bool?); + + await AssertQueryScalar( + async, + ss => ss.Set().Where(x => x.NullableBoolA != null + && !object.Equals(true, x.NullableBoolA == null ? null : prm)).Select(x => x.Id)); + } + // We can't client-evaluate Like (for the expected results). // However, since the test data has no LIKE wildcards, it effectively functions like equality - except that 'null like null' returns // false instead of true. So we have this "lite" implementation which doesn't support wildcards. diff --git a/test/EFCore.Specification.Tests/Query/NorthwindJoinQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindJoinQueryTestBase.cs index 4e602af3a4f..6b7cb03fb2a 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindJoinQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindJoinQueryTestBase.cs @@ -703,6 +703,24 @@ public virtual Task GroupJoin_aggregate_nested_anonymous_key_selectors(bool asyn (c, g) => new { c.CustomerID, Sum = g.Sum(x => x.CustomerID.Length) }), elementSorter: e => e.CustomerID)); + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupJoin_on_true_equal_true(bool async) + => AssertQuery( + async, + ss => ss.Set().GroupJoin( + ss.Set(), + x => true, + x => true, + (c, g) => new { c, g }) + .Select(x => new { x.c.CustomerID, Orders = x.g }), + elementSorter: e => e.CustomerID, + elementAsserter: (e, a) => + { + Assert.Equal(e.CustomerID, a.CustomerID); + AssertCollection(e.Orders, a.Orders, elementSorter: ee => ee.OrderID); + }); + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Inner_join_with_tautology_predicate_converts_to_cross_join(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index d12c45997f3..64543299028 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -4452,7 +4452,7 @@ INNER JOIN ( FROM [Factions] AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL """); } @@ -4469,7 +4469,7 @@ LEFT JOIN ( FROM [Factions] AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL """); } @@ -6978,7 +6978,7 @@ FROM [LocustLeaders] AS [l] INNER JOIN [Factions] AS [f] ON [l].[Name] = [f].[CommanderName] WHERE CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) -END = CAST(0 AS bit) OR CASE +END <> CAST(1 AS bit) OR CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs index c8486b8e9f9..0515e690f8c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs @@ -616,6 +616,22 @@ public override async Task GroupJoin_aggregate_nested_anonymous_key_selectors(bo AssertSql(); } + public override async Task GroupJoin_on_true_equal_true(bool async) + { + await base.GroupJoin_on_true_equal_true(async); + + AssertSql( +""" +SELECT [c].[CustomerID], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +FROM [Customers] AS [c] +OUTER APPLY ( + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] + FROM [Orders] AS [o] +) AS [o0] +ORDER BY [c].[CustomerID] +"""); + } + public override async Task Inner_join_with_tautology_predicate_converts_to_cross_join(bool async) { await base.Inner_join_with_tautology_predicate_converts_to_cross_join(async); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs index d771cc25f85..2b01f4dfb81 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs @@ -4568,6 +4568,30 @@ FROM [Entities1] AS [e] """); } + public async override Task Compare_constant_true_to_nullable_column_negated(bool async) + { + await base.Compare_constant_true_to_nullable_column_negated(async); + + AssertSql( + """ +SELECT [e].[Id] +FROM [Entities1] AS [e] +WHERE CAST(1 AS bit) <> [e].[NullableBoolA] OR [e].[NullableBoolA] IS NULL +"""); + } + + public override async Task Compare_constant_true_to_expression_which_evaluates_to_null(bool async) + { + await base.Compare_constant_true_to_expression_which_evaluates_to_null(async); + + AssertSql( +""" +SELECT [e].[Id] +FROM [Entities1] AS [e] +WHERE [e].[NullableBoolA] IS NOT NULL +"""); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs index 182be105b6d..4956f88de2d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs @@ -6051,7 +6051,7 @@ INNER JOIN ( FROM [LocustHordes] AS [l1] WHERE [l1].[Name] = N'Swarm' ) AS [l2] ON [u].[Name] = [l2].[CommanderName] -WHERE [l2].[Eradicated] = CAST(0 AS bit) OR [l2].[Eradicated] IS NULL +WHERE [l2].[Eradicated] <> CAST(1 AS bit) OR [l2].[Eradicated] IS NULL """); } @@ -6074,7 +6074,7 @@ LEFT JOIN ( FROM [LocustHordes] AS [l1] WHERE [l1].[Name] = N'Swarm' ) AS [l2] ON [u].[Name] = [l2].[CommanderName] -WHERE [l2].[Eradicated] = CAST(0 AS bit) OR [l2].[Eradicated] IS NULL +WHERE [l2].[Eradicated] <> CAST(1 AS bit) OR [l2].[Eradicated] IS NULL """); } @@ -9333,7 +9333,7 @@ FROM [LocustCommanders] AS [l0] INNER JOIN [LocustHordes] AS [l1] ON [u].[Name] = [l1].[CommanderName] WHERE CASE WHEN [l1].[Name] = N'Locust' THEN CAST(1 AS bit) -END = CAST(0 AS bit) OR CASE +END <> CAST(1 AS bit) OR CASE WHEN [l1].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 62be1d75c6a..3a613a9fbc6 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -5129,7 +5129,7 @@ public override async Task Null_semantics_on_nullable_bool_from_inner_join_subqu await base.Null_semantics_on_nullable_bool_from_inner_join_subquery_is_fully_applied(async); AssertSql( - """ +""" SELECT [s].[Id], [s].[CapitalName], [s].[Name], [s].[ServerAddress], [s].[CommanderName], [s].[Eradicated], [s].[Discriminator] FROM [LocustLeaders] AS [l] INNER JOIN ( @@ -5140,7 +5140,7 @@ FROM [Factions] AS [f] LEFT JOIN [LocustHordes] AS [l0] ON [f].[Id] = [l0].[Id] WHERE [l0].[Id] IS NOT NULL AND [f].[Name] = N'Swarm' ) AS [s] ON [l].[Name] = [s].[CommanderName] -WHERE [s].[Eradicated] = CAST(0 AS bit) OR [s].[Eradicated] IS NULL +WHERE [s].[Eradicated] <> CAST(1 AS bit) OR [s].[Eradicated] IS NULL """); } @@ -5160,7 +5160,7 @@ FROM [Factions] AS [f] LEFT JOIN [LocustHordes] AS [l0] ON [f].[Id] = [l0].[Id] WHERE [l0].[Id] IS NOT NULL AND [f].[Name] = N'Swarm' ) AS [s] ON [l].[Name] = [s].[CommanderName] -WHERE [s].[Eradicated] = CAST(0 AS bit) OR [s].[Eradicated] IS NULL +WHERE [s].[Eradicated] <> CAST(1 AS bit) OR [s].[Eradicated] IS NULL """); } @@ -7918,7 +7918,7 @@ public override async Task Join_inner_source_custom_projection_followed_by_filte await base.Join_inner_source_custom_projection_followed_by_filter(async); AssertSql( - """ +""" SELECT CASE WHEN [s].[Name] = N'Locust' THEN CAST(1 AS bit) END AS [IsEradicated], [s].[CommanderName], [s].[Name] @@ -7931,7 +7931,7 @@ WHERE [l0].[Id] IS NOT NULL ) AS [s] ON [l].[Name] = [s].[CommanderName] WHERE CASE WHEN [s].[Name] = N'Locust' THEN CAST(1 AS bit) -END = CAST(0 AS bit) OR CASE +END <> CAST(1 AS bit) OR CASE WHEN [s].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs index 727f120e502..c9f431d57d9 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs @@ -2160,7 +2160,7 @@ SELECT CASE INNER JOIN [Factions] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] ON [l].[Name] = [f].[CommanderName] WHERE CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) -END = CAST(0 AS bit) OR CASE +END <> CAST(1 AS bit) OR CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); @@ -3962,7 +3962,7 @@ INNER JOIN ( FROM [Factions] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL """); } @@ -5676,7 +5676,7 @@ LEFT JOIN ( FROM [Factions] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs index 6038f2f2c53..2c4e238cd00 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs @@ -2314,7 +2314,7 @@ SELECT CASE INNER JOIN "Factions" AS "f" ON "l"."Name" = "f"."CommanderName" WHERE CASE WHEN "f"."Name" = 'Locust' THEN 1 -END = 0 OR CASE +END <> 1 OR CASE WHEN "f"."Name" = 'Locust' THEN 1 END IS NULL """); @@ -4692,7 +4692,7 @@ LEFT JOIN ( FROM "Factions" AS "f" WHERE "f"."Name" = 'Swarm' ) AS "f0" ON "l"."Name" = "f0"."CommanderName" -WHERE "f0"."Eradicated" = 0 OR "f0"."Eradicated" IS NULL +WHERE "f0"."Eradicated" <> 1 OR "f0"."Eradicated" IS NULL """); } @@ -4760,7 +4760,7 @@ INNER JOIN ( FROM "Factions" AS "f" WHERE "f"."Name" = 'Swarm' ) AS "f0" ON "l"."Name" = "f0"."CommanderName" -WHERE "f0"."Eradicated" = 0 OR "f0"."Eradicated" IS NULL +WHERE "f0"."Eradicated" <> 1 OR "f0"."Eradicated" IS NULL """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindJoinQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindJoinQuerySqliteTest.cs index 7051721f131..f032b5b7bcd 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindJoinQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindJoinQuerySqliteTest.cs @@ -57,4 +57,10 @@ public override async Task Take_in_collection_projection_with_FirstOrDefault_on_ SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Take_in_collection_projection_with_FirstOrDefault_on_top_level(async))).Message); + + public override async Task GroupJoin_on_true_equal_true(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.GroupJoin_on_true_equal_true(async))).Message); } From 50078f2e985123cff7e227e8d412592dd9914add Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Fri, 5 Jul 2024 12:06:08 +0200 Subject: [PATCH 2/4] Prefer equality in boolean comparisons They can take advantage of indexing. --- .../Query/SqlNullabilityProcessor.cs | 89 ++++++++++--------- 1 file changed, 49 insertions(+), 40 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index 59b72f7a552..3176f5f5968 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -166,6 +166,7 @@ SqlExpression ProcessJoinPredicate(SqlExpression predicate) right, leftNullable, rightNullable, + optimize: true, out _); return result; @@ -1107,6 +1108,7 @@ protected virtual SqlExpression VisitSqlBinary( right, leftNullable, rightNullable, + optimize, out nullable); if (optimized is SqlUnaryExpression { Operand: ColumnExpression optimizedUnaryColumnOperand } optimizedUnary) @@ -1451,6 +1453,7 @@ private SqlExpression OptimizeComparison( SqlExpression right, bool leftNullable, bool rightNullable, + bool optimize, out bool nullable) { var leftNullValue = leftNullable && left is SqlConstantExpression or SqlParameterExpression; @@ -1531,32 +1534,8 @@ private SqlExpression OptimizeComparison( && !rightNullable && sqlBinaryExpression.OperatorType is ExpressionType.Equal or ExpressionType.NotEqual) { - var leftUnary = left as SqlUnaryExpression; - var rightUnary = right as SqlUnaryExpression; - - var leftNegated = IsLogicalNot(leftUnary); - var rightNegated = IsLogicalNot(rightUnary); - - if (leftNegated) - { - left = leftUnary!.Operand; - } - - if (rightNegated) - { - right = rightUnary!.Operand; - } - - // a == b <=> !a == !b -> a == b - // !a == b <=> a == !b -> a != b - // a != b <=> !a != !b -> a != b - // !a != b <=> a != !b -> a == b - nullable = false; - - return sqlBinaryExpression.OperatorType == ExpressionType.Equal ^ leftNegated == rightNegated - ? _sqlExpressionFactory.NotEqual(left, right) - : _sqlExpressionFactory.Equal(left, right); + return OptimizeBooleanComparison(sqlBinaryExpression, left, right, optimize); } nullable = false; @@ -1564,14 +1543,11 @@ private SqlExpression OptimizeComparison( return sqlBinaryExpression.Update(left, right); } - private SqlExpression RewriteNullSemantics( + private SqlExpression OptimizeBooleanComparison( SqlBinaryExpression sqlBinaryExpression, SqlExpression left, SqlExpression right, - bool leftNullable, - bool rightNullable, - bool optimize, - out bool nullable) + bool optimize) { var leftUnary = left as SqlUnaryExpression; var rightUnary = right as SqlUnaryExpression; @@ -1589,22 +1565,49 @@ private SqlExpression RewriteNullSemantics( right = rightUnary!.Operand; } + var notEqual = sqlBinaryExpression.OperatorType == ExpressionType.Equal ^ leftNegated == rightNegated; + + // prefer equality in predicates + if (optimize && notEqual && left.Type == typeof(bool)) + { + if (right is ColumnExpression && (left is not ColumnExpression || leftNegated)) + { + left = _sqlExpressionFactory.Not(left); + } + else + { + right = _sqlExpressionFactory.Not(right); + } + + return _sqlExpressionFactory.Equal(left, right); + } + + // a == b <=> !a == !b -> a == b + // !a == b <=> a == !b -> a != b + // a != b <=> !a != !b -> a != b + // !a != b <=> a != !b -> a == b + + return notEqual + ? _sqlExpressionFactory.NotEqual(left, right) + : _sqlExpressionFactory.Equal(left, right); + } + + private SqlExpression RewriteNullSemantics( + SqlBinaryExpression sqlBinaryExpression, + SqlExpression left, + SqlExpression right, + bool leftNullable, + bool rightNullable, + bool optimize, + out bool nullable) + { var leftIsNull = ProcessNullNotNull(_sqlExpressionFactory.IsNull(left), leftNullable); var leftIsNotNull = OptimizeNotExpression(_sqlExpressionFactory.Not(leftIsNull)); var rightIsNull = ProcessNullNotNull(_sqlExpressionFactory.IsNull(right), rightNullable); var rightIsNotNull = OptimizeNotExpression(_sqlExpressionFactory.Not(rightIsNull)); - SqlExpression body; - if (leftNegated == rightNegated) - { - body = _sqlExpressionFactory.Equal(left, right); - } - else - { - // a == !b and !a == b in SQL evaluate the same as a != b - body = _sqlExpressionFactory.NotEqual(left, right); - } + var body = OptimizeBooleanComparison(sqlBinaryExpression, left, right, optimize); // optimized expansion which doesn't distinguish between null and false if (optimize && sqlBinaryExpression.OperatorType == ExpressionType.Equal) @@ -1617,6 +1620,12 @@ private SqlExpression RewriteNullSemantics( // doing a full null semantics rewrite - removing all nulls from truth table nullable = false; + if (sqlBinaryExpression.OperatorType == ExpressionType.NotEqual) + { + // the factory takes care of simplifying equal <-> not-equal + body = _sqlExpressionFactory.Not(body); + } + // (a == b && (a != null && b != null)) || (a == null && b == null) body = _sqlExpressionFactory.OrElse( _sqlExpressionFactory.AndAlso(body, _sqlExpressionFactory.AndAlso(leftIsNotNull, rightIsNotNull)), From aae5e3440119aa3505f9e132493594c1ba93d29c Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Fri, 5 Jul 2024 12:30:56 +0200 Subject: [PATCH 3/4] Update baselines --- .../Query/FunkyDataQueryAzureSynapseTest.cs | 4 +- .../Query/FunkyDataQuerySqlServerTest.cs | 4 +- .../Query/GearsOfWarQuerySqlServerTest.cs | 6 +- .../Query/NorthwindWhereQuerySqlServerTest.cs | 4 +- .../Query/NullSemanticsQuerySqlServerTest.cs | 224 +++++++++--------- .../Query/TPCGearsOfWarQuerySqlServerTest.cs | 6 +- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 6 +- .../TemporalGearsOfWarQuerySqlServerTest.cs | 6 +- .../CustomConvertersSqliteTest.cs | 2 +- .../Query/GearsOfWarQuerySqliteTest.cs | 6 +- .../Query/NullSemanticsQuerySqliteTest.cs | 82 +++---- 11 files changed, 175 insertions(+), 175 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQueryAzureSynapseTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQueryAzureSynapseTest.cs index 81db1893717..792590d945c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQueryAzureSynapseTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQueryAzureSynapseTest.cs @@ -556,9 +556,9 @@ public override async Task String_ends_with_not_equals_nullable_column(bool asyn FROM [FunkyCustomers] AS [f] CROSS JOIN [FunkyCustomers] AS [f0] WHERE CASE - WHEN [f].[FirstName] IS NOT NULL AND [f0].[LastName] IS NOT NULL AND RIGHT([f].[FirstName], LEN([f0].[LastName])) = [f0].[LastName] THEN CAST(1 AS bit) + WHEN [f].[FirstName] IS NULL OR [f0].[LastName] IS NULL OR RIGHT([f].[FirstName], LEN([f0].[LastName])) <> [f0].[LastName] THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> [f].[NullableBool] OR [f].[NullableBool] IS NULL +END = [f].[NullableBool] OR [f].[NullableBool] IS NULL """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQuerySqlServerTest.cs index 1cf8bdb95a3..8dad1faf508 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/FunkyDataQuerySqlServerTest.cs @@ -556,9 +556,9 @@ public override async Task String_ends_with_not_equals_nullable_column(bool asyn FROM [FunkyCustomers] AS [f] CROSS JOIN [FunkyCustomers] AS [f0] WHERE CASE - WHEN [f].[FirstName] IS NOT NULL AND [f0].[LastName] IS NOT NULL AND RIGHT([f].[FirstName], LEN([f0].[LastName])) = [f0].[LastName] THEN CAST(1 AS bit) + WHEN [f].[FirstName] IS NULL OR [f0].[LastName] IS NULL OR RIGHT([f].[FirstName], LEN([f0].[LastName])) <> [f0].[LastName] THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> [f].[NullableBool] OR [f].[NullableBool] IS NULL +END = [f].[NullableBool] OR [f].[NullableBool] IS NULL """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 64543299028..000f56f65d8 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -6217,7 +6217,7 @@ FROM [Gears] AS [g] LEFT JOIN ( SELECT [w].[Id], [w].[OwnerFullName] FROM [Weapons] AS [w] - WHERE [w].[IsAutomatic] <> @isAutomatic + WHERE [w].[IsAutomatic] = ~@isAutomatic ) AS [w0] ON [g].[FullName] = [w0].[OwnerFullName] """); } @@ -6941,7 +6941,7 @@ public override async Task Logical_operation_with_non_null_parameter_optimizes_n 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] <> @prm +WHERE [g].[HasSoulPatch] = ~@prm """, // """ @@ -6949,7 +6949,7 @@ WHERE [g].[HasSoulPatch] <> @prm 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] <> @prm +WHERE [g].[HasSoulPatch] = ~@prm """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs index c8baa1104c4..00ab68efe41 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs @@ -1091,7 +1091,7 @@ public override async Task Where_not_bool_member_compared_to_binary_expression(b """ SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] FROM [Products] AS [p] -WHERE [p].[Discontinued] <> CASE +WHERE [p].[Discontinued] = ~CASE WHEN [p].[ProductID] > 50 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END @@ -1125,7 +1125,7 @@ FROM [Products] AS [p] WHERE CASE WHEN [p].[ProductID] > 50 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> @prm +END = ~@prm """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs index 2b01f4dfb81..dd6ff81fd71 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs @@ -272,7 +272,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ @@ -286,7 +286,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE ~[e].[BoolA] = [e].[NullableBoolB] """, // """ @@ -328,7 +328,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE ~[e].[NullableBoolA] = [e].[BoolB] """, // """ @@ -342,7 +342,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE ~[e].[NullableBoolA] = [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """, // """ @@ -353,7 +353,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ @@ -367,7 +367,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE [e].[BoolA] = ~[e].[NullableBoolB] """, // """ @@ -406,7 +406,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE [e].[NullableBoolA] = ~[e].[BoolB] """, // """ @@ -420,7 +420,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE [e].[NullableBoolA] = ~[e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """, // """ @@ -459,7 +459,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ @@ -473,7 +473,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE [e].[BoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ @@ -512,7 +512,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE [e].[NullableBoolA] = ~[e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ @@ -526,7 +526,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """, // """ @@ -590,7 +590,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ @@ -604,7 +604,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE ~[e].[BoolA] = [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ @@ -646,7 +646,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE ~[e].[NullableBoolA] = [e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ @@ -660,7 +660,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE (~[e].[NullableBoolA] = [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """, // """ @@ -671,7 +671,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ @@ -685,7 +685,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE [e].[BoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ @@ -724,7 +724,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE [e].[NullableBoolA] = ~[e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ @@ -738,7 +738,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """, // """ @@ -802,7 +802,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ @@ -816,7 +816,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE ~[e].[BoolA] = [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ @@ -858,7 +858,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE ~[e].[NullableBoolA] = [e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ @@ -872,7 +872,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE (~[e].[NullableBoolA] = [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """, // """ @@ -908,7 +908,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ @@ -922,7 +922,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE ~[e].[BoolA] = [e].[NullableBoolB] """, // """ @@ -964,7 +964,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE ~[e].[NullableBoolA] = [e].[BoolB] """, // """ @@ -978,7 +978,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE ~[e].[NullableBoolA] = [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """, // """ @@ -989,7 +989,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ @@ -1003,7 +1003,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE [e].[BoolA] = ~[e].[NullableBoolB] """, // """ @@ -1042,7 +1042,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE [e].[NullableBoolA] = ~[e].[BoolB] """, // """ @@ -1056,7 +1056,7 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE [e].[NullableBoolA] = ~[e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """, // """ @@ -1126,25 +1126,25 @@ public override async Task Compare_negated_bool_with_bool_equal(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE ~[e].[BoolA] = [e].[NullableBoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE ~[e].[NullableBoolA] = [e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE ~[e].[NullableBoolA] = [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """); } @@ -1156,25 +1156,25 @@ public override async Task Compare_bool_with_negated_bool_equal(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE [e].[BoolA] = ~[e].[NullableBoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE [e].[NullableBoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE [e].[NullableBoolA] = ~[e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """); } @@ -1216,25 +1216,25 @@ public override async Task Compare_bool_with_bool_equal_negated(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE [e].[BoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE [e].[NullableBoolA] = ~[e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """); } @@ -1306,25 +1306,25 @@ public override async Task Compare_negated_bool_with_negated_bool_equal_negated( """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE ~[e].[BoolA] = [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE ~[e].[NullableBoolA] = [e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE (~[e].[NullableBoolA] = [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """); } @@ -1336,25 +1336,25 @@ public override async Task Compare_bool_with_bool_not_equal(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE [e].[BoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE [e].[NullableBoolA] = ~[e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """); } @@ -1426,25 +1426,25 @@ public override async Task Compare_negated_bool_with_negated_bool_not_equal(bool """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE ~[e].[BoolA] = [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE ~[e].[NullableBoolA] = [e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE (~[e].[NullableBoolA] = [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """); } @@ -1486,25 +1486,25 @@ public override async Task Compare_negated_bool_with_bool_not_equal_negated(bool """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE ~[e].[BoolA] = [e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE ~[e].[BoolA] = [e].[NullableBoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE ~[e].[NullableBoolA] = [e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE ~[e].[NullableBoolA] = [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """); } @@ -1516,25 +1516,25 @@ public override async Task Compare_bool_with_negated_bool_not_equal_negated(bool """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] +WHERE [e].[BoolA] = ~[e].[NullableBoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] +WHERE [e].[NullableBoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) +WHERE [e].[NullableBoolA] = ~[e].[NullableBoolB] OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) """); } @@ -1636,25 +1636,25 @@ public override async Task Compare_equals_method_negated(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE [e].[BoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE [e].[NullableBoolA] = ~[e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """); } @@ -1666,25 +1666,25 @@ public override async Task Compare_equals_method_negated_static(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[BoolB] +WHERE [e].[BoolA] = ~[e].[BoolB] """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL +WHERE [e].[BoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL +WHERE [e].[NullableBoolA] = ~[e].[BoolB] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) """); } @@ -1732,7 +1732,7 @@ public override async Task Compare_complex_equal_not_equal_equal(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] ^ [e].[BoolB] <> CAST([e].[IntA] ^ [e].[IntB] AS bit) +WHERE ~([e].[BoolA] ^ [e].[BoolB]) = CAST([e].[IntA] ^ [e].[IntB] AS bit) """, // """ @@ -1741,8 +1741,8 @@ FROM [Entities1] AS [e] WHERE CASE WHEN [e].[NullableBoolA] = [e].[BoolB] AND [e].[NullableBoolA] IS NOT NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> CASE - WHEN [e].[IntA] = [e].[NullableIntB] AND [e].[NullableIntB] IS NOT NULL THEN CAST(1 AS bit) +END = CASE + WHEN [e].[IntA] <> [e].[NullableIntB] OR [e].[NullableIntB] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """, @@ -1753,8 +1753,8 @@ FROM [Entities1] AS [e] WHERE CASE WHEN ([e].[NullableBoolA] = [e].[NullableBoolB] AND [e].[NullableBoolA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL) OR ([e].[NullableBoolA] IS NULL AND [e].[NullableBoolB] IS NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> CASE - WHEN ([e].[NullableIntA] = [e].[NullableIntB] AND [e].[NullableIntA] IS NOT NULL AND [e].[NullableIntB] IS NOT NULL) OR ([e].[NullableIntA] IS NULL AND [e].[NullableIntB] IS NULL) THEN CAST(1 AS bit) +END = CASE + WHEN ([e].[NullableIntA] <> [e].[NullableIntB] OR [e].[NullableIntA] IS NULL OR [e].[NullableIntB] IS NULL) AND ([e].[NullableIntA] IS NOT NULL OR [e].[NullableIntB] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """); @@ -1804,7 +1804,7 @@ public override async Task Compare_complex_not_equal_not_equal_equal(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] ^ [e].[BoolB] <> ~CAST([e].[IntA] ^ [e].[IntB] AS bit) +WHERE [e].[BoolA] ^ [e].[BoolB] = CAST([e].[IntA] ^ [e].[IntB] AS bit) """, // """ @@ -1813,8 +1813,8 @@ FROM [Entities1] AS [e] WHERE CASE WHEN [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> CASE - WHEN [e].[IntA] = [e].[NullableIntB] AND [e].[NullableIntB] IS NOT NULL THEN CAST(1 AS bit) +END = CASE + WHEN [e].[IntA] <> [e].[NullableIntB] OR [e].[NullableIntB] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """, @@ -1825,8 +1825,8 @@ FROM [Entities1] AS [e] WHERE CASE WHEN ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> CASE - WHEN ([e].[NullableIntA] = [e].[NullableIntB] AND [e].[NullableIntA] IS NOT NULL AND [e].[NullableIntB] IS NOT NULL) OR ([e].[NullableIntA] IS NULL AND [e].[NullableIntB] IS NULL) THEN CAST(1 AS bit) +END = CASE + WHEN ([e].[NullableIntA] <> [e].[NullableIntB] OR [e].[NullableIntA] IS NULL OR [e].[NullableIntB] IS NULL) AND ([e].[NullableIntA] IS NOT NULL OR [e].[NullableIntB] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """); @@ -1876,7 +1876,7 @@ public override async Task Compare_complex_not_equal_not_equal_not_equal(bool as """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[BoolA] ^ [e].[BoolB] <> CAST([e].[IntA] ^ [e].[IntB] AS bit) +WHERE [e].[BoolA] ^ [e].[BoolB] = ~CAST([e].[IntA] ^ [e].[IntB] AS bit) """, // """ @@ -1885,8 +1885,8 @@ FROM [Entities1] AS [e] WHERE CASE WHEN [e].[NullableBoolA] <> [e].[BoolB] OR [e].[NullableBoolA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> CASE - WHEN [e].[IntA] <> [e].[NullableIntB] OR [e].[NullableIntB] IS NULL THEN CAST(1 AS bit) +END = CASE + WHEN [e].[IntA] = [e].[NullableIntB] AND [e].[NullableIntB] IS NOT NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """, @@ -1897,8 +1897,8 @@ FROM [Entities1] AS [e] WHERE CASE WHEN ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END <> CASE - WHEN ([e].[NullableIntA] <> [e].[NullableIntB] OR [e].[NullableIntA] IS NULL OR [e].[NullableIntB] IS NULL) AND ([e].[NullableIntA] IS NOT NULL OR [e].[NullableIntB] IS NOT NULL) THEN CAST(1 AS bit) +END = CASE + WHEN ([e].[NullableIntA] = [e].[NullableIntB] AND [e].[NullableIntA] IS NOT NULL AND [e].[NullableIntB] IS NOT NULL) OR ([e].[NullableIntA] IS NULL AND [e].[NullableIntB] IS NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """); @@ -2779,13 +2779,13 @@ FROM [Entities1] AS [e] """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE COALESCE([e].[NullableBoolB], [e].[BoolC]) <> [e].[NullableBoolA] OR [e].[NullableBoolA] IS NULL +WHERE ~COALESCE([e].[NullableBoolB], [e].[BoolC]) = [e].[NullableBoolA] OR [e].[NullableBoolA] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE (COALESCE([e].[NullableBoolB], [e].[NullableBoolC]) <> [e].[NullableBoolA] OR ([e].[NullableBoolB] IS NULL AND [e].[NullableBoolC] IS NULL) OR [e].[NullableBoolA] IS NULL) AND ([e].[NullableBoolB] IS NOT NULL OR [e].[NullableBoolC] IS NOT NULL OR [e].[NullableBoolA] IS NOT NULL) +WHERE (~COALESCE([e].[NullableBoolB], [e].[NullableBoolC]) = [e].[NullableBoolA] OR ([e].[NullableBoolB] IS NULL AND [e].[NullableBoolC] IS NULL) OR [e].[NullableBoolA] IS NULL) AND ([e].[NullableBoolB] IS NOT NULL OR [e].[NullableBoolC] IS NOT NULL OR [e].[NullableBoolA] IS NOT NULL) """); } @@ -2807,7 +2807,7 @@ ELSE [e].[NullableBoolC] SELECT [e].[Id] FROM [Entities1] AS [e] WHERE CASE - WHEN ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) THEN [e].[BoolB] + WHEN ([e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) THEN [e].[BoolB] ELSE [e].[BoolC] END = [e].[BoolA] """, @@ -2816,13 +2816,13 @@ ELSE [e].[BoolC] SELECT [e].[Id] FROM [Entities1] AS [e] WHERE CASE - WHEN CASE + WHEN ~CASE WHEN [e].[BoolA] = CAST(1 AS bit) THEN CASE WHEN ([e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolB] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END ELSE [e].[BoolC] - END <> [e].[BoolB] THEN [e].[BoolA] + END = [e].[BoolB] THEN [e].[BoolA] WHEN [e].[NullableBoolB] = [e].[NullableBoolC] OR ([e].[NullableBoolB] IS NULL AND [e].[NullableBoolC] IS NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END = CAST(1 AS bit) @@ -3503,13 +3503,13 @@ public override async Task Null_semantics_with_null_check_complex2(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL AND ([e].[NullableBoolB] <> [e].[NullableBoolA] OR [e].[NullableBoolC] IS NOT NULL) AND ([e].[NullableBoolC] <> [e].[NullableBoolB] OR [e].[NullableBoolC] IS NULL)) OR [e].[NullableBoolC] <> [e].[BoolB] OR [e].[NullableBoolC] IS NULL +WHERE ([e].[NullableBoolA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL AND ([e].[NullableBoolB] = ~[e].[NullableBoolA] OR [e].[NullableBoolC] IS NOT NULL) AND ([e].[NullableBoolC] = ~[e].[NullableBoolB] OR [e].[NullableBoolC] IS NULL)) OR [e].[NullableBoolC] = ~[e].[BoolB] OR [e].[NullableBoolC] IS NULL """, // """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE ([e].[NullableBoolA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL AND ([e].[NullableBoolB] <> [e].[NullableBoolA] OR [e].[NullableBoolC] IS NOT NULL) AND ([e].[NullableBoolC] <> [e].[NullableBoolB] OR [e].[NullableBoolC] IS NULL)) OR [e].[NullableBoolB] <> [e].[BoolB] OR [e].[NullableBoolB] IS NULL +WHERE ([e].[NullableBoolA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL AND ([e].[NullableBoolB] = ~[e].[NullableBoolA] OR [e].[NullableBoolC] IS NOT NULL) AND ([e].[NullableBoolC] = ~[e].[NullableBoolB] OR [e].[NullableBoolC] IS NULL)) OR [e].[NullableBoolB] = ~[e].[BoolB] OR [e].[NullableBoolB] IS NULL """); } @@ -3728,7 +3728,7 @@ public override async Task Nullable_column_info_doesnt_propagate_between_differe SELECT [e].[Id] FROM [Entities1] AS [e] INNER JOIN [Entities1] AS [e0] ON [e].[NullableBoolA] IS NULL -WHERE ([e].[NullableBoolA] <> [e0].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e0].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e0].[NullableBoolB] IS NOT NULL) +WHERE ([e].[NullableBoolA] = ~[e0].[NullableBoolB] OR [e].[NullableBoolA] IS NULL OR [e0].[NullableBoolB] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e0].[NullableBoolB] IS NOT NULL) """); } @@ -3740,7 +3740,7 @@ public override async Task Nullable_column_info_propagation_complex(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE [e].[NullableStringA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL AND [e].[NullableStringC] IS NOT NULL AND ([e].[NullableBoolB] <> [e].[NullableBoolC] OR [e].[NullableBoolC] IS NULL) +WHERE [e].[NullableStringA] IS NOT NULL AND [e].[NullableBoolB] IS NOT NULL AND [e].[NullableStringC] IS NOT NULL AND ([e].[NullableBoolB] = ~[e].[NullableBoolC] OR [e].[NullableBoolC] IS NULL) """); } @@ -4145,8 +4145,8 @@ WHERE [e].[NullableBoolA] IS NULL SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] FROM [Entities1] AS [e] -WHERE @prm <> CASE - WHEN [e].[NullableBoolA] IS NOT NULL THEN CAST(1 AS bit) +WHERE @prm = CASE + WHEN [e].[NullableBoolA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """, @@ -4154,8 +4154,8 @@ ELSE CAST(0 AS bit) """ SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] FROM [Entities1] AS [e] -WHERE [e].[BoolB] <> CASE - WHEN [e].[NullableBoolA] IS NOT NULL THEN CAST(1 AS bit) +WHERE [e].[BoolB] = CASE + WHEN [e].[NullableBoolA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """); @@ -4177,8 +4177,8 @@ WHERE [e].[NullableIntA] IS NULL SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] FROM [Entities1] AS [e] -WHERE @prm <> CASE - WHEN [e].[NullableIntA] IS NOT NULL THEN CAST(1 AS bit) +WHERE @prm = CASE + WHEN [e].[NullableIntA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """, @@ -4186,8 +4186,8 @@ ELSE CAST(0 AS bit) """ SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] FROM [Entities1] AS [e] -WHERE [e].[BoolB] <> CASE - WHEN [e].[NullableIntA] IS NOT NULL THEN CAST(1 AS bit) +WHERE [e].[BoolB] = CASE + WHEN [e].[NullableIntA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """); @@ -4209,8 +4209,8 @@ WHERE [e].[NullableBoolA] IS NOT NULL SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] FROM [Entities1] AS [e] -WHERE @prm <> CASE - WHEN [e].[NullableBoolA] IS NOT NULL THEN CAST(1 AS bit) +WHERE @prm = CASE + WHEN [e].[NullableBoolA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """); @@ -4247,8 +4247,8 @@ public override async Task Comparison_compared_to_null_check_on_bool(bool async) """ SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC] FROM [Entities1] AS [e] -WHERE ~CAST([e].[IntA] ^ [e].[IntB] AS bit) <> CASE - WHEN [e].[NullableBoolA] IS NOT NULL THEN CAST(1 AS bit) +WHERE ~CAST([e].[IntA] ^ [e].[IntB] AS bit) = CASE + WHEN [e].[NullableBoolA] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END """, @@ -4381,10 +4381,10 @@ public override async Task Is_null_on_column_followed_by_OrElse_optimizes_nullab FROM [Entities1] AS [e] WHERE [e].[NullableBoolA] IS NULL OR CASE WHEN [e].[NullableBoolB] IS NULL THEN CASE - WHEN [e].[NullableBoolB] <> [e].[NullableBoolA] OR [e].[NullableBoolB] IS NULL THEN CAST(1 AS bit) + WHEN [e].[NullableBoolB] = ~[e].[NullableBoolA] OR [e].[NullableBoolB] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END - WHEN [e].[NullableBoolA] <> [e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL THEN CAST(1 AS bit) + WHEN [e].[NullableBoolA] = ~[e].[NullableBoolB] OR [e].[NullableBoolB] IS NULL THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END = CAST(1 AS bit) """); @@ -4402,10 +4402,10 @@ FROM [Entities1] AS [e] WHERE CASE WHEN [e].[NullableBoolA] IS NULL THEN ~([e].[BoolA] ^ [e].[BoolB]) WHEN [e].[NullableBoolC] IS NULL THEN CASE - WHEN ([e].[NullableBoolA] <> [e].[NullableBoolC] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolC] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolC] IS NOT NULL) THEN CAST(1 AS bit) + WHEN ([e].[NullableBoolA] = ~[e].[NullableBoolC] OR [e].[NullableBoolA] IS NULL OR [e].[NullableBoolC] IS NULL) AND ([e].[NullableBoolA] IS NOT NULL OR [e].[NullableBoolC] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END - WHEN ([e].[NullableBoolC] <> [e].[NullableBoolA] OR [e].[NullableBoolC] IS NULL OR [e].[NullableBoolA] IS NULL) AND ([e].[NullableBoolC] IS NOT NULL OR [e].[NullableBoolA] IS NOT NULL) THEN CAST(1 AS bit) + WHEN ([e].[NullableBoolC] = ~[e].[NullableBoolA] OR [e].[NullableBoolC] IS NULL OR [e].[NullableBoolA] IS NULL) AND ([e].[NullableBoolC] IS NOT NULL OR [e].[NullableBoolA] IS NOT NULL) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END = CAST(1 AS bit) """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs index 4956f88de2d..cbcf4611e77 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs @@ -9285,7 +9285,7 @@ UNION ALL SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOfBirthName], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank], N'Officer' AS [Discriminator] FROM [Officers] AS [o] ) AS [u] -WHERE [u].[HasSoulPatch] <> @prm +WHERE [u].[HasSoulPatch] = ~@prm """, // """ @@ -9299,7 +9299,7 @@ UNION ALL SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOfBirthName], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank], N'Officer' AS [Discriminator] FROM [Officers] AS [o] ) AS [u] -WHERE [u].[HasSoulPatch] <> @prm +WHERE [u].[HasSoulPatch] = ~@prm """); } @@ -11060,7 +11060,7 @@ FROM [Officers] AS [o] LEFT JOIN ( SELECT [w].[Id], [w].[OwnerFullName] FROM [Weapons] AS [w] - WHERE [w].[IsAutomatic] <> @isAutomatic + WHERE [w].[IsAutomatic] = ~@isAutomatic ) AS [w0] ON [u].[FullName] = [w0].[OwnerFullName] """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 3a613a9fbc6..43d5bf2714c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -7885,7 +7885,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] <> @prm +WHERE [g].[HasSoulPatch] = ~@prm """, // """ @@ -7896,7 +7896,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] <> @prm +WHERE [g].[HasSoulPatch] = ~@prm """); } @@ -9358,7 +9358,7 @@ FROM [Gears] AS [g] LEFT JOIN ( SELECT [w].[Id], [w].[OwnerFullName] FROM [Weapons] AS [w] - WHERE [w].[IsAutomatic] <> @isAutomatic + WHERE [w].[IsAutomatic] = ~@isAutomatic ) AS [w0] ON [g].[FullName] = [w0].[OwnerFullName] """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs index c9f431d57d9..ae099f694c4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs @@ -1482,7 +1482,7 @@ END AS [Collection] LEFT JOIN ( SELECT [w].[Id], [w].[OwnerFullName] FROM [Weapons] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [w] - WHERE [w].[IsAutomatic] <> @isAutomatic + WHERE [w].[IsAutomatic] = ~@isAutomatic ) AS [w0] ON [g].[FullName] = [w0].[OwnerFullName] """); } @@ -2020,7 +2020,7 @@ public override async Task Logical_operation_with_non_null_parameter_optimizes_n SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[PeriodEnd], [g].[PeriodStart], [g].[Rank] FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g] -WHERE [g].[HasSoulPatch] <> @prm +WHERE [g].[HasSoulPatch] = ~@prm """, // """ @@ -2028,7 +2028,7 @@ WHERE [g].[HasSoulPatch] <> @prm SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[PeriodEnd], [g].[PeriodStart], [g].[Rank] FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g] -WHERE [g].[HasSoulPatch] <> @prm +WHERE [g].[HasSoulPatch] = ~@prm """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs index fc64367a6c3..e59ee370231 100644 --- a/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/CustomConvertersSqliteTest.cs @@ -87,7 +87,7 @@ public override async Task Where_bool_with_value_conversion_inside_comparison_do """ SELECT "b"."BlogId", "b"."Discriminator", "b"."IndexerVisible", "b"."IsVisible", "b"."Url", "b"."RssUrl" FROM "Blog" AS "b" -WHERE "b"."IsVisible" <> 'Y' +WHERE "b"."IsVisible" = 'N' """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs index 2c4e238cd00..13b73ce1fd8 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs @@ -414,7 +414,7 @@ public override async Task Logical_operation_with_non_null_parameter_optimizes_n 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" <> @prm +WHERE "g"."HasSoulPatch" = (NOT (@prm)) """, // """ @@ -422,7 +422,7 @@ public override async Task Logical_operation_with_non_null_parameter_optimizes_n 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" <> @prm +WHERE "g"."HasSoulPatch" = (NOT (@prm)) """); } @@ -7086,7 +7086,7 @@ public override async Task SelectMany_Where_DefaultIfEmpty_with_navigation_in_th LEFT JOIN ( SELECT "w"."Id", "w"."OwnerFullName" FROM "Weapons" AS "w" - WHERE "w"."IsAutomatic" <> @isAutomatic + WHERE "w"."IsAutomatic" = (NOT (@isAutomatic)) ) AS "w0" ON "g"."FullName" = "w0"."OwnerFullName" """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs index 5a1487ffb76..2ad71f39ae9 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs @@ -232,7 +232,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE (NOT ("e"."BoolA")) = "e"."BoolB" """, // """ @@ -243,7 +243,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" +WHERE (NOT ("e"."BoolA")) = "e"."NullableBoolB" """, // """ @@ -276,7 +276,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" +WHERE (NOT ("e"."NullableBoolA")) = "e"."BoolB" """, // """ @@ -287,7 +287,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."NullableBoolB" OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) +WHERE (NOT ("e"."NullableBoolA")) = "e"."NullableBoolB" OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) """, // """ @@ -298,7 +298,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE "e"."BoolA" = (NOT ("e"."BoolB")) """, // """ @@ -309,7 +309,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" +WHERE "e"."BoolA" = (NOT ("e"."NullableBoolB")) """, // """ @@ -342,7 +342,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" +WHERE "e"."NullableBoolA" = (NOT ("e"."BoolB")) """, // """ @@ -353,7 +353,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."NullableBoolB" OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) +WHERE "e"."NullableBoolA" = (NOT ("e"."NullableBoolB")) OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) """, // """ @@ -386,7 +386,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE "e"."BoolA" = (NOT ("e"."BoolB")) """, // """ @@ -397,7 +397,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolB" IS NULL +WHERE "e"."BoolA" = (NOT ("e"."NullableBoolB")) OR "e"."NullableBoolB" IS NULL """, // """ @@ -430,7 +430,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" OR "e"."NullableBoolA" IS NULL +WHERE "e"."NullableBoolA" = (NOT ("e"."BoolB")) OR "e"."NullableBoolA" IS NULL """, // """ @@ -441,7 +441,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) +WHERE ("e"."NullableBoolA" = (NOT ("e"."NullableBoolB")) OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) """, // """ @@ -496,7 +496,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE (NOT ("e"."BoolA")) = "e"."BoolB" """, // """ @@ -507,7 +507,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolB" IS NULL +WHERE (NOT ("e"."BoolA")) = "e"."NullableBoolB" OR "e"."NullableBoolB" IS NULL """, // """ @@ -540,7 +540,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" OR "e"."NullableBoolA" IS NULL +WHERE (NOT ("e"."NullableBoolA")) = "e"."BoolB" OR "e"."NullableBoolA" IS NULL """, // """ @@ -551,7 +551,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) +WHERE ((NOT ("e"."NullableBoolA")) = "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) """, // """ @@ -562,7 +562,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE "e"."BoolA" = (NOT ("e"."BoolB")) """, // """ @@ -573,7 +573,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolB" IS NULL +WHERE "e"."BoolA" = (NOT ("e"."NullableBoolB")) OR "e"."NullableBoolB" IS NULL """, // """ @@ -606,7 +606,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" OR "e"."NullableBoolA" IS NULL +WHERE "e"."NullableBoolA" = (NOT ("e"."BoolB")) OR "e"."NullableBoolA" IS NULL """, // """ @@ -617,7 +617,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) +WHERE ("e"."NullableBoolA" = (NOT ("e"."NullableBoolB")) OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) """, // """ @@ -672,7 +672,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE (NOT ("e"."BoolA")) = "e"."BoolB" """, // """ @@ -683,7 +683,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolB" IS NULL +WHERE (NOT ("e"."BoolA")) = "e"."NullableBoolB" OR "e"."NullableBoolB" IS NULL """, // """ @@ -716,7 +716,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" OR "e"."NullableBoolA" IS NULL +WHERE (NOT ("e"."NullableBoolA")) = "e"."BoolB" OR "e"."NullableBoolA" IS NULL """, // """ @@ -727,7 +727,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) +WHERE ((NOT ("e"."NullableBoolA")) = "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) """, // """ @@ -760,7 +760,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE (NOT ("e"."BoolA")) = "e"."BoolB" """, // """ @@ -771,7 +771,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" +WHERE (NOT ("e"."BoolA")) = "e"."NullableBoolB" """, // """ @@ -804,7 +804,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" +WHERE (NOT ("e"."NullableBoolA")) = "e"."BoolB" """, // """ @@ -815,7 +815,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."NullableBoolB" OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) +WHERE (NOT ("e"."NullableBoolA")) = "e"."NullableBoolB" OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) """, // """ @@ -826,7 +826,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."BoolB" +WHERE "e"."BoolA" = (NOT ("e"."BoolB")) """, // """ @@ -837,7 +837,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."BoolA" <> "e"."NullableBoolB" +WHERE "e"."BoolA" = (NOT ("e"."NullableBoolB")) """, // """ @@ -870,7 +870,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."BoolB" +WHERE "e"."NullableBoolA" = (NOT ("e"."BoolB")) """, // """ @@ -881,7 +881,7 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE "e"."NullableBoolA" <> "e"."NullableBoolB" OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) +WHERE "e"."NullableBoolA" = (NOT ("e"."NullableBoolB")) OR ("e"."NullableBoolA" IS NULL AND "e"."NullableBoolB" IS NULL) """, // """ @@ -973,7 +973,7 @@ public override async Task Null_semantics_conditional(bool async) SELECT "e"."Id" FROM "Entities1" AS "e" WHERE CASE - WHEN ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) THEN "e"."BoolB" + WHEN ("e"."NullableBoolA" = (NOT ("e"."NullableBoolB")) OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) THEN "e"."BoolB" ELSE "e"."BoolC" END = "e"."BoolA" """, @@ -982,10 +982,10 @@ WHERE CASE SELECT "e"."Id" FROM "Entities1" AS "e" WHERE CASE - WHEN CASE + WHEN (NOT (CASE WHEN "e"."BoolA" THEN ("e"."NullableBoolA" <> "e"."NullableBoolB" OR "e"."NullableBoolA" IS NULL OR "e"."NullableBoolB" IS NULL) AND ("e"."NullableBoolA" IS NOT NULL OR "e"."NullableBoolB" IS NOT NULL) ELSE "e"."BoolC" - END <> "e"."BoolB" THEN "e"."BoolA" + END)) = "e"."BoolB" THEN "e"."BoolA" ELSE "e"."NullableBoolB" = "e"."NullableBoolC" OR ("e"."NullableBoolB" IS NULL AND "e"."NullableBoolC" IS NULL) END """, @@ -1262,13 +1262,13 @@ public override async Task Bool_not_equal_nullable_bool_HasValue(bool async) SELECT "e"."Id", "e"."BoolA", "e"."BoolB", "e"."BoolC", "e"."IntA", "e"."IntB", "e"."IntC", "e"."NullableBoolA", "e"."NullableBoolB", "e"."NullableBoolC", "e"."NullableIntA", "e"."NullableIntB", "e"."NullableIntC", "e"."NullableStringA", "e"."NullableStringB", "e"."NullableStringC", "e"."StringA", "e"."StringB", "e"."StringC" FROM "Entities1" AS "e" -WHERE @prm <> ("e"."NullableBoolA" IS NOT NULL) +WHERE @prm = ("e"."NullableBoolA" IS NULL) """, // """ SELECT "e"."Id", "e"."BoolA", "e"."BoolB", "e"."BoolC", "e"."IntA", "e"."IntB", "e"."IntC", "e"."NullableBoolA", "e"."NullableBoolB", "e"."NullableBoolC", "e"."NullableIntA", "e"."NullableIntB", "e"."NullableIntC", "e"."NullableStringA", "e"."NullableStringB", "e"."NullableStringC", "e"."StringA", "e"."StringB", "e"."StringC" FROM "Entities1" AS "e" -WHERE "e"."BoolB" <> ("e"."NullableBoolA" IS NOT NULL) +WHERE "e"."BoolB" = ("e"."NullableBoolA" IS NULL) """); } @@ -1288,13 +1288,13 @@ public override async Task Bool_not_equal_nullable_int_HasValue(bool async) SELECT "e"."Id", "e"."BoolA", "e"."BoolB", "e"."BoolC", "e"."IntA", "e"."IntB", "e"."IntC", "e"."NullableBoolA", "e"."NullableBoolB", "e"."NullableBoolC", "e"."NullableIntA", "e"."NullableIntB", "e"."NullableIntC", "e"."NullableStringA", "e"."NullableStringB", "e"."NullableStringC", "e"."StringA", "e"."StringB", "e"."StringC" FROM "Entities1" AS "e" -WHERE @prm <> ("e"."NullableIntA" IS NOT NULL) +WHERE @prm = ("e"."NullableIntA" IS NULL) """, // """ SELECT "e"."Id", "e"."BoolA", "e"."BoolB", "e"."BoolC", "e"."IntA", "e"."IntB", "e"."IntC", "e"."NullableBoolA", "e"."NullableBoolB", "e"."NullableBoolC", "e"."NullableIntA", "e"."NullableIntB", "e"."NullableIntC", "e"."NullableStringA", "e"."NullableStringB", "e"."NullableStringC", "e"."StringA", "e"."StringB", "e"."StringC" FROM "Entities1" AS "e" -WHERE "e"."BoolB" <> ("e"."NullableIntA" IS NOT NULL) +WHERE "e"."BoolB" = ("e"."NullableIntA" IS NULL) """); } @@ -1314,7 +1314,7 @@ public override async Task Bool_not_equal_nullable_bool_compared_to_null(bool as SELECT "e"."Id", "e"."BoolA", "e"."BoolB", "e"."BoolC", "e"."IntA", "e"."IntB", "e"."IntC", "e"."NullableBoolA", "e"."NullableBoolB", "e"."NullableBoolC", "e"."NullableIntA", "e"."NullableIntB", "e"."NullableIntC", "e"."NullableStringA", "e"."NullableStringB", "e"."NullableStringC", "e"."StringA", "e"."StringB", "e"."StringC" FROM "Entities1" AS "e" -WHERE @prm <> ("e"."NullableBoolA" IS NOT NULL) +WHERE @prm = ("e"."NullableBoolA" IS NULL) """); } @@ -1437,7 +1437,7 @@ public override async Task Comparison_compared_to_null_check_on_bool(bool async) """ SELECT "e"."Id", "e"."BoolA", "e"."BoolB", "e"."BoolC", "e"."IntA", "e"."IntB", "e"."IntC", "e"."NullableBoolA", "e"."NullableBoolB", "e"."NullableBoolC", "e"."NullableIntA", "e"."NullableIntB", "e"."NullableIntC", "e"."NullableStringA", "e"."NullableStringB", "e"."NullableStringC", "e"."StringA", "e"."StringB", "e"."StringC" FROM "Entities1" AS "e" -WHERE ("e"."IntA" = "e"."IntB") <> ("e"."NullableBoolA" IS NOT NULL) +WHERE ("e"."IntA" = "e"."IntB") = ("e"."NullableBoolA" IS NULL) """, // """ From 0eb325a82744f3d92fd6d0a767c5a7bcc2f80e3f Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Wed, 1 Jan 2025 12:18:09 +0100 Subject: [PATCH 4/4] Update baselines These are the baselines regenerated after a rebase on top of 35fc423ba39630b3bf883e9e06c4ee4ea038ae3e. --- .../Query/ComplexNavigationsQuerySqlServer160Test.cs | 12 ++++++------ ...plexNavigationsSharedTypeQuerySqlServer160Test.cs | 12 ++++++------ .../Query/GearsOfWarQuerySqlServerTest.cs | 6 +++--- .../Query/NullSemanticsQuerySqlServerTest.cs | 2 +- .../Query/TPCGearsOfWarQuerySqlServerTest.cs | 6 +++--- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 10 +++++----- .../Query/TemporalGearsOfWarQuerySqlServerTest.cs | 6 +++--- .../Query/GearsOfWarQuerySqliteTest.cs | 6 +++--- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServer160Test.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServer160Test.cs index 69f02149536..14af7a25c2d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServer160Test.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServer160Test.cs @@ -1369,10 +1369,10 @@ public override async Task Where_navigation_property_to_collection(bool async) SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] FROM [LevelOne] AS [l] LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Required_Id] -WHERE ( - SELECT COUNT(*) +WHERE EXISTS ( + SELECT 1 FROM [LevelThree] AS [l1] - WHERE [l0].[Id] IS NOT NULL AND [l0].[Id] = [l1].[OneToMany_Optional_Inverse3Id]) > 0 + WHERE [l0].[Id] IS NOT NULL AND [l0].[Id] = [l1].[OneToMany_Optional_Inverse3Id]) """); } @@ -1385,10 +1385,10 @@ public override async Task Where_navigation_property_to_collection2(bool async) SELECT [l].[Id], [l].[Level2_Optional_Id], [l].[Level2_Required_Id], [l].[Name], [l].[OneToMany_Optional_Inverse3Id], [l].[OneToMany_Optional_Self_Inverse3Id], [l].[OneToMany_Required_Inverse3Id], [l].[OneToMany_Required_Self_Inverse3Id], [l].[OneToOne_Optional_PK_Inverse3Id], [l].[OneToOne_Optional_Self3Id] FROM [LevelThree] AS [l] INNER JOIN [LevelTwo] AS [l0] ON [l].[Level2_Required_Id] = [l0].[Id] -WHERE ( - SELECT COUNT(*) +WHERE EXISTS ( + SELECT 1 FROM [LevelThree] AS [l1] - WHERE [l0].[Id] = [l1].[OneToMany_Optional_Inverse3Id]) > 0 + WHERE [l0].[Id] = [l1].[OneToMany_Optional_Inverse3Id]) """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServer160Test.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServer160Test.cs index 075eaf6fffa..0a59d9aed93 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServer160Test.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqlServer160Test.cs @@ -5055,8 +5055,8 @@ WHERE [l4].[OneToOne_Required_PK_Date] IS NOT NULL AND [l4].[Level1_Required_Id] ) AS [l5] ON [l3].[Level2_Required_Id] = CASE WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] END -WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l3].[Level2_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse3Id] IS NOT NULL AND ( - SELECT COUNT(*) +WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l3].[Level2_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse3Id] IS NOT NULL AND EXISTS ( + SELECT 1 FROM [Level1] AS [l6] WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL AND CASE WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] @@ -5064,7 +5064,7 @@ END IS NOT NULL AND (CASE WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] END = [l6].[OneToMany_Optional_Inverse3Id] OR (CASE WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] - END IS NULL AND [l6].[OneToMany_Optional_Inverse3Id] IS NULL))) > 0 + END IS NULL AND [l6].[OneToMany_Optional_Inverse3Id] IS NULL))) """); } @@ -6255,8 +6255,8 @@ LEFT JOIN ( FROM [Level1] AS [l0] WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL ) AS [l1] ON [l].[Id] = [l1].[Level1_Required_Id] -WHERE ( - SELECT COUNT(*) +WHERE EXISTS ( + SELECT 1 FROM [Level1] AS [l2] WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND CASE WHEN [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l1].[Id] @@ -6264,7 +6264,7 @@ END IS NOT NULL AND (CASE WHEN [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l1].[Id] END = [l2].[OneToMany_Optional_Inverse3Id] OR (CASE WHEN [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l1].[Id] - END IS NULL AND [l2].[OneToMany_Optional_Inverse3Id] IS NULL))) > 0 + END IS NULL AND [l2].[OneToMany_Optional_Inverse3Id] IS NULL))) """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 000f56f65d8..d3b75332e92 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -4452,7 +4452,7 @@ INNER JOIN ( FROM [Factions] AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL """); } @@ -4469,7 +4469,7 @@ LEFT JOIN ( FROM [Factions] AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL """); } @@ -6978,7 +6978,7 @@ FROM [LocustLeaders] AS [l] INNER JOIN [Factions] AS [f] ON [l].[Name] = [f].[CommanderName] WHERE CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) -END <> CAST(1 AS bit) OR CASE +END = CAST(0 AS bit) OR CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs index dd6ff81fd71..6346d1acc3e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs @@ -4576,7 +4576,7 @@ public async override Task Compare_constant_true_to_nullable_column_negated(bool """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE CAST(1 AS bit) <> [e].[NullableBoolA] OR [e].[NullableBoolA] IS NULL +WHERE CAST(0 AS bit) = [e].[NullableBoolA] OR [e].[NullableBoolA] IS NULL """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs index cbcf4611e77..bf8a99c63ea 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs @@ -6051,7 +6051,7 @@ INNER JOIN ( FROM [LocustHordes] AS [l1] WHERE [l1].[Name] = N'Swarm' ) AS [l2] ON [u].[Name] = [l2].[CommanderName] -WHERE [l2].[Eradicated] <> CAST(1 AS bit) OR [l2].[Eradicated] IS NULL +WHERE [l2].[Eradicated] = CAST(0 AS bit) OR [l2].[Eradicated] IS NULL """); } @@ -6074,7 +6074,7 @@ LEFT JOIN ( FROM [LocustHordes] AS [l1] WHERE [l1].[Name] = N'Swarm' ) AS [l2] ON [u].[Name] = [l2].[CommanderName] -WHERE [l2].[Eradicated] <> CAST(1 AS bit) OR [l2].[Eradicated] IS NULL +WHERE [l2].[Eradicated] = CAST(0 AS bit) OR [l2].[Eradicated] IS NULL """); } @@ -9333,7 +9333,7 @@ FROM [LocustCommanders] AS [l0] INNER JOIN [LocustHordes] AS [l1] ON [u].[Name] = [l1].[CommanderName] WHERE CASE WHEN [l1].[Name] = N'Locust' THEN CAST(1 AS bit) -END <> CAST(1 AS bit) OR CASE +END = CAST(0 AS bit) OR CASE WHEN [l1].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 43d5bf2714c..8d39cefb6db 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -5129,7 +5129,7 @@ public override async Task Null_semantics_on_nullable_bool_from_inner_join_subqu await base.Null_semantics_on_nullable_bool_from_inner_join_subquery_is_fully_applied(async); AssertSql( -""" + """ SELECT [s].[Id], [s].[CapitalName], [s].[Name], [s].[ServerAddress], [s].[CommanderName], [s].[Eradicated], [s].[Discriminator] FROM [LocustLeaders] AS [l] INNER JOIN ( @@ -5140,7 +5140,7 @@ FROM [Factions] AS [f] LEFT JOIN [LocustHordes] AS [l0] ON [f].[Id] = [l0].[Id] WHERE [l0].[Id] IS NOT NULL AND [f].[Name] = N'Swarm' ) AS [s] ON [l].[Name] = [s].[CommanderName] -WHERE [s].[Eradicated] <> CAST(1 AS bit) OR [s].[Eradicated] IS NULL +WHERE [s].[Eradicated] = CAST(0 AS bit) OR [s].[Eradicated] IS NULL """); } @@ -5160,7 +5160,7 @@ FROM [Factions] AS [f] LEFT JOIN [LocustHordes] AS [l0] ON [f].[Id] = [l0].[Id] WHERE [l0].[Id] IS NOT NULL AND [f].[Name] = N'Swarm' ) AS [s] ON [l].[Name] = [s].[CommanderName] -WHERE [s].[Eradicated] <> CAST(1 AS bit) OR [s].[Eradicated] IS NULL +WHERE [s].[Eradicated] = CAST(0 AS bit) OR [s].[Eradicated] IS NULL """); } @@ -7918,7 +7918,7 @@ public override async Task Join_inner_source_custom_projection_followed_by_filte await base.Join_inner_source_custom_projection_followed_by_filter(async); AssertSql( -""" + """ SELECT CASE WHEN [s].[Name] = N'Locust' THEN CAST(1 AS bit) END AS [IsEradicated], [s].[CommanderName], [s].[Name] @@ -7931,7 +7931,7 @@ WHERE [l0].[Id] IS NOT NULL ) AS [s] ON [l].[Name] = [s].[CommanderName] WHERE CASE WHEN [s].[Name] = N'Locust' THEN CAST(1 AS bit) -END <> CAST(1 AS bit) OR CASE +END = CAST(0 AS bit) OR CASE WHEN [s].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs index ae099f694c4..d612b504201 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs @@ -2160,7 +2160,7 @@ SELECT CASE INNER JOIN [Factions] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] ON [l].[Name] = [f].[CommanderName] WHERE CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) -END <> CAST(1 AS bit) OR CASE +END = CAST(0 AS bit) OR CASE WHEN [f].[Name] = N'Locust' THEN CAST(1 AS bit) END IS NULL """); @@ -3962,7 +3962,7 @@ INNER JOIN ( FROM [Factions] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL """); } @@ -5676,7 +5676,7 @@ LEFT JOIN ( FROM [Factions] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] WHERE [f].[Name] = N'Swarm' ) AS [f0] ON [l].[Name] = [f0].[CommanderName] -WHERE [f0].[Eradicated] <> CAST(1 AS bit) OR [f0].[Eradicated] IS NULL +WHERE [f0].[Eradicated] = CAST(0 AS bit) OR [f0].[Eradicated] IS NULL """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs index 13b73ce1fd8..3deb2933052 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs @@ -2314,7 +2314,7 @@ SELECT CASE INNER JOIN "Factions" AS "f" ON "l"."Name" = "f"."CommanderName" WHERE CASE WHEN "f"."Name" = 'Locust' THEN 1 -END <> 1 OR CASE +END = 0 OR CASE WHEN "f"."Name" = 'Locust' THEN 1 END IS NULL """); @@ -4692,7 +4692,7 @@ LEFT JOIN ( FROM "Factions" AS "f" WHERE "f"."Name" = 'Swarm' ) AS "f0" ON "l"."Name" = "f0"."CommanderName" -WHERE "f0"."Eradicated" <> 1 OR "f0"."Eradicated" IS NULL +WHERE "f0"."Eradicated" = 0 OR "f0"."Eradicated" IS NULL """); } @@ -4760,7 +4760,7 @@ INNER JOIN ( FROM "Factions" AS "f" WHERE "f"."Name" = 'Swarm' ) AS "f0" ON "l"."Name" = "f0"."CommanderName" -WHERE "f0"."Eradicated" <> 1 OR "f0"."Eradicated" IS NULL +WHERE "f0"."Eradicated" = 0 OR "f0"."Eradicated" IS NULL """); }