From 1d44c174303db7d71291fa3682985fadba1e25e1 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Sun, 16 Jun 2024 11:32:09 +0200 Subject: [PATCH 1/6] Fix nullability of `group_concat` and `STRING_AGG` --- .../Translators/SqlServerStringAggregateMethodTranslator.cs | 2 +- .../Translators/SqliteStringAggregateMethodTranslator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs index f2bb4a7d19d..3e51f1f3275 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerStringAggregateMethodTranslator.cs @@ -101,7 +101,7 @@ public SqlServerStringAggregateMethodTranslator( source, enumerableArgumentIndex: 0, nullable: true, - argumentsPropagateNullability: new[] { false, true }, + argumentsPropagateNullability: new[] { false, false }, typeof(string)), _sqlExpressionFactory.Constant(string.Empty, typeof(string)), resultTypeMapping); diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs index b588eaa7fdf..98aaa2518ff 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteStringAggregateMethodTranslator.cs @@ -93,7 +93,7 @@ public SqliteStringAggregateMethodTranslator(ISqlExpressionFactory sqlExpression sqlExpression.TypeMapping) }, nullable: true, - argumentsPropagateNullability: new[] { false, true }, + argumentsPropagateNullability: new[] { false, false }, typeof(string)), _sqlExpressionFactory.Constant(string.Empty, typeof(string)), sqlExpression.TypeMapping); From 91c269a21ed3b614f6e41286c76435e9426ebd65 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Mon, 1 Jul 2024 11:59:46 +0200 Subject: [PATCH 2/6] Simplify `SqlFunctionExpression.IsNiladic` Redefined it based on `Arguments`, consistent with its annotation. --- .../SqlExpressions/SqlFunctionExpression.cs | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index ff782b9a80e..75548081f8e 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -88,7 +88,7 @@ private SqlFunctionExpression( Type type, RelationalTypeMapping? typeMapping) : this( - instance, schema, name, niladic: true, arguments: null, nullable, instancePropagatesNullability, + instance, schema, name, arguments: null, nullable, instancePropagatesNullability, argumentsPropagateNullability: null, builtIn, type, typeMapping) { } @@ -165,24 +165,6 @@ public SqlFunctionExpression( { } - private SqlFunctionExpression( - SqlExpression? instance, - string? schema, - string name, - IEnumerable arguments, - bool nullable, - bool? instancePropagatesNullability, - IEnumerable argumentsPropagateNullability, - bool builtIn, - Type type, - RelationalTypeMapping? typeMapping) - : this( - instance, schema, name, niladic: false, arguments, nullable, - instancePropagatesNullability, argumentsPropagateNullability, builtIn, - type, typeMapping) - { - } - /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -194,7 +176,6 @@ public SqlFunctionExpression( SqlExpression? instance, string? schema, string name, - bool niladic, IEnumerable? arguments, bool nullable, bool? instancePropagatesNullability, @@ -207,7 +188,6 @@ public SqlFunctionExpression( Instance = instance; Name = name; Schema = schema; - IsNiladic = niladic; IsBuiltIn = builtIn; Arguments = arguments?.ToList(); IsNullable = nullable; @@ -240,7 +220,7 @@ public SqlFunctionExpression( /// A bool value indicating if the function is niladic. /// [MemberNotNullWhen(false, nameof(Arguments), nameof(ArgumentsPropagateNullability))] - public virtual bool IsNiladic { get; } + public virtual bool IsNiladic => Arguments is null; /// /// A bool value indicating if the function is built-in. @@ -295,7 +275,6 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) instance, Schema, Name, - IsNiladic, arguments, IsNullable, InstancePropagatesNullability, @@ -316,7 +295,6 @@ public virtual SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping? typ Instance, Schema, Name, - IsNiladic, Arguments, IsNullable, InstancePropagatesNullability, @@ -353,13 +331,12 @@ public override Expression Quote() => New( _quotingConstructor ??= typeof(SqlFunctionExpression).GetConstructor( [ - typeof(SqlExpression), typeof(string), typeof(string), typeof(bool), typeof(IEnumerable), + typeof(SqlExpression), typeof(string), typeof(string), typeof(IEnumerable), typeof(bool), typeof(bool), typeof(IEnumerable), typeof(bool), typeof(Type), typeof(RelationalTypeMapping) ])!, RelationalExpressionQuotingUtilities.QuoteOrNull(Instance), Constant(Schema, typeof(string)), Constant(Name), - Constant(IsNiladic), Arguments is null ? Constant(null, typeof(IEnumerable)) : NewArrayInit(typeof(SqlExpression), initializers: Arguments.Select(a => a.Quote())), @@ -408,7 +385,6 @@ public override bool Equals(object? obj) private bool Equals(SqlFunctionExpression sqlFunctionExpression) => base.Equals(sqlFunctionExpression) - && IsNiladic == sqlFunctionExpression.IsNiladic && Name == sqlFunctionExpression.Name && Schema == sqlFunctionExpression.Schema && ((Instance == null && sqlFunctionExpression.Instance == null) From 88f596a750430e309a0a98a3d3756bef7cac8c03 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Thu, 27 Jun 2024 09:38:52 +0200 Subject: [PATCH 3/6] Add support for changing arity in `SqlFunctionExpression.Update` --- .../SqlExpressions/SqlFunctionExpression.cs | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs index 75548081f8e..0f9e2343055 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SqlFunctionExpression.cs @@ -311,20 +311,39 @@ public virtual SqlFunctionExpression ApplyTypeMapping(RelationalTypeMapping? typ /// The property of the result. /// This expression if no children changed, or an expression with the updated children. public virtual SqlFunctionExpression Update(SqlExpression? instance, IReadOnlyList? arguments) - => instance != Instance || (arguments != null && Arguments != null && !arguments.SequenceEqual(Arguments)) - ? new SqlFunctionExpression( + => Update(instance, arguments, ArgumentsPropagateNullability); + + /// + /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will + /// return this expression. + /// + /// The property of the result. + /// The property of the result. + /// The property of the result. If omitted, + /// the current ArgumentsPropagateNullability will be used. + /// This expression if no children changed, or an expression with the updated children. + public virtual SqlFunctionExpression Update( + SqlExpression? instance, + IReadOnlyList? arguments, + IReadOnlyList? argumentsPropagateNullability) + => instance == Instance + && ((arguments == Arguments) || (arguments != null && Arguments != null && arguments.SequenceEqual(Arguments))) + && ((argumentsPropagateNullability == ArgumentsPropagateNullability) + || (argumentsPropagateNullability != null + && ArgumentsPropagateNullability != null + && argumentsPropagateNullability.SequenceEqual(ArgumentsPropagateNullability))) + ? this + : new SqlFunctionExpression( instance, Schema, Name, - IsNiladic, arguments, IsNullable, InstancePropagatesNullability, - ArgumentsPropagateNullability, + argumentsPropagateNullability, IsBuiltIn, Type, - TypeMapping) - : this; + TypeMapping); /// public override Expression Quote() From f15220498c7ac7d0e22acc49913d42e40b701d3b Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Mon, 17 Jun 2024 11:13:01 +0200 Subject: [PATCH 4/6] Add test for `COALESCE` short-circuiting --- .../Query/NullSemanticsQueryTestBase.cs | 12 ++++++++ .../Query/NullSemanticsQuerySqlServerTest.cs | 30 +++++++++++++++++++ .../Query/NullSemanticsQuerySqliteTest.cs | 24 +++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs index 8f3c3ecd7df..e089e1927c6 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/NullSemanticsQueryTestBase.cs @@ -617,6 +617,18 @@ public virtual Task Where_multiple_ands_with_nullable_parameter_and_constant_not public virtual Task Where_coalesce(bool async) => AssertQueryScalar(async, ss => ss.Set().Where(e => e.NullableBoolA ?? true).Select(e => e.Id)); + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_coalesce_shortcircuit(bool async) + => AssertQueryScalar(async, ss => ss.Set().Where(e => (bool?)(e.BoolA | e.BoolB) ?? e.NullableBoolA ?? true) + .Select(e => e.Id)); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Where_coalesce_shortcircuit_many(bool async) + => AssertQueryScalar(async, ss => ss.Set().Where(e => e.NullableBoolA ?? (bool?)(e.BoolA | e.BoolB) ?? e.NullableBoolB ?? e.BoolB) + .Select(e => e.Id)); + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Where_equal_nullable_with_null_value_parameter(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs index 0a8052fa749..c20050ddb2f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs @@ -2194,6 +2194,36 @@ WHERE COALESCE([e].[NullableBoolA], CAST(1 AS bit)) = CAST(1 AS bit) """); } + public override async Task Where_coalesce_shortcircuit(bool async) + { + await base.Where_coalesce_shortcircuit(async); + + AssertSql( + """ +SELECT [e].[Id] +FROM [Entities1] AS [e] +WHERE COALESCE(CASE + WHEN [e].[BoolA] = CAST(1 AS bit) OR [e].[BoolB] = CAST(1 AS bit) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END, [e].[NullableBoolA], CAST(1 AS bit)) = CAST(1 AS bit) +"""); + } + + public override async Task Where_coalesce_shortcircuit_many(bool async) + { + await base.Where_coalesce_shortcircuit_many(async); + + AssertSql( + """ +SELECT [e].[Id] +FROM [Entities1] AS [e] +WHERE COALESCE([e].[NullableBoolA], CASE + WHEN [e].[BoolA] = CAST(1 AS bit) OR [e].[BoolB] = CAST(1 AS bit) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END, [e].[NullableBoolB], [e].[BoolB]) = CAST(1 AS bit) +"""); + } + public override async Task Where_equal_nullable_with_null_value_parameter(bool async) { await base.Where_equal_nullable_with_null_value_parameter(async); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs index a1c45c915cc..38527ac3797 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs @@ -909,6 +909,30 @@ public override async Task Rewrite_compare_bool_with_bool(bool async) """); } + public override async Task Where_coalesce_shortcircuit(bool async) + { + await base.Where_coalesce_shortcircuit(async); + + AssertSql( + """ +SELECT "e"."Id" +FROM "Entities1" AS "e" +WHERE COALESCE("e"."BoolA" OR "e"."BoolB", "e"."NullableBoolA", 1) +"""); + } + + public override async Task Where_coalesce_shortcircuit_many(bool async) + { + await base.Where_coalesce_shortcircuit_many(async); + + AssertSql( + """ +SELECT "e"."Id" +FROM "Entities1" AS "e" +WHERE COALESCE("e"."NullableBoolA", "e"."BoolA" OR "e"."BoolB", "e"."NullableBoolB", "e"."BoolB") +"""); + } + public override async Task Join_uses_database_semantics(bool async) { await base.Join_uses_database_semantics(async); From 8861ada7fa1e3b8594ea36457af98727e07aabd5 Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Sun, 16 Jun 2024 11:32:09 +0200 Subject: [PATCH 5/6] Simplify `COALESCE` Drop all of the arguments after the first non-nullable sub-expressions. Simplify unary `COALESCE` to its argument. --- .../Query/SqlNullabilityProcessor.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index 4b2b44773c1..53db438fb7d 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -1422,12 +1422,22 @@ protected virtual SqlExpression VisitSqlFunction( foreach (var argument in sqlFunctionExpression.Arguments) { coalesceArguments.Add(Visit(argument, out var argumentNullable)); - coalesceNullable = coalesceNullable && argumentNullable; + if (!argumentNullable) + { + coalesceNullable = false; + break; + } } nullable = coalesceNullable; - return sqlFunctionExpression.Update(sqlFunctionExpression.Instance, coalesceArguments); + return coalesceArguments.Count == 1 + ? coalesceArguments[0] + : sqlFunctionExpression.Update( + sqlFunctionExpression.Instance, + coalesceArguments, + argumentsPropagateNullability: coalesceArguments.Select(_ => false).ToArray() + ); } var useNullabilityPropagation = sqlFunctionExpression is { InstancePropagatesNullability: true }; From 6a3488afa6162c666d3941bb719978929c05972e Mon Sep 17 00:00:00 2001 From: Andrea Canciani Date: Sun, 16 Jun 2024 11:32:09 +0200 Subject: [PATCH 6/6] Update test baselines --- .../Query/GearsOfWarQuerySqlServerTest.cs | 10 +++++----- .../Query/NorthwindFunctionsQuerySqlServerTest.cs | 2 +- .../Query/NullSemanticsQuerySqlServerTest.cs | 7 ++----- .../Query/TPCGearsOfWarQuerySqlServerTest.cs | 10 +++++----- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 10 +++++----- .../Query/TemporalGearsOfWarQuerySqlServerTest.cs | 10 +++++----- .../Query/GearsOfWarQuerySqliteTest.cs | 8 ++++---- .../Query/NullSemanticsQuerySqliteTest.cs | 4 ++-- 8 files changed, 29 insertions(+), 32 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index e970afe5674..5c3d15a8229 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -1215,10 +1215,10 @@ public override async Task Select_null_propagation_negative9(bool async) AssertSql( """ SELECT CASE - WHEN [g].[LeaderNickname] IS NOT NULL THEN COALESCE(CASE + WHEN [g].[LeaderNickname] IS NOT NULL THEN CASE WHEN CAST(LEN([g].[Nickname]) AS int) = 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) - END, CAST(0 AS bit)) + END ELSE NULL END FROM [Gears] AS [g] @@ -4033,7 +4033,7 @@ public override async Task ToString_enum_property_projection(bool async) await base.ToString_enum_property_projection(async); AssertSql( -""" + """ SELECT CASE [g].[Rank] WHEN 0 THEN N'None' WHEN 1 THEN N'Private' @@ -4044,7 +4044,7 @@ WHEN 16 THEN N'Captain' WHEN 32 THEN N'Major' WHEN 64 THEN N'Colonel' WHEN 128 THEN N'General' - ELSE COALESCE(CAST([g].[Rank] AS nvarchar(max)), N'') + ELSE CAST([g].[Rank] AS nvarchar(max)) END FROM [Gears] AS [g] """); @@ -5759,7 +5759,7 @@ SELECT COALESCE(( SELECT TOP(1) [w].[Id] FROM [Weapons] AS [w] WHERE [g].[FullName] = [w].[OwnerFullName] - ORDER BY [w].[Id]), 0, 42) + ORDER BY [w].[Id]), 0) FROM [Gears] AS [g] """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs index 76af10c51bf..7b6b52694d4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindFunctionsQuerySqlServerTest.cs @@ -420,7 +420,7 @@ public override async Task String_Join_non_aggregate(bool async) SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] -WHERE CONCAT_WS(N'|', [c].[CompanyName], COALESCE(@__foo_0, N''), N'', N'bar') = N'Around the Horn|foo||bar' +WHERE CONCAT_WS(N'|', [c].[CompanyName], @__foo_0, N'', N'bar') = N'Around the Horn|foo||bar' """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs index c20050ddb2f..66f69d3fb5b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NullSemanticsQuerySqlServerTest.cs @@ -2202,10 +2202,7 @@ public override async Task Where_coalesce_shortcircuit(bool async) """ SELECT [e].[Id] FROM [Entities1] AS [e] -WHERE COALESCE(CASE - WHEN [e].[BoolA] = CAST(1 AS bit) OR [e].[BoolB] = CAST(1 AS bit) THEN CAST(1 AS bit) - ELSE CAST(0 AS bit) -END, [e].[NullableBoolA], CAST(1 AS bit)) = CAST(1 AS bit) +WHERE [e].[BoolA] = CAST(1 AS bit) OR [e].[BoolB] = CAST(1 AS bit) """); } @@ -2220,7 +2217,7 @@ FROM [Entities1] AS [e] WHERE COALESCE([e].[NullableBoolA], CASE WHEN [e].[BoolA] = CAST(1 AS bit) OR [e].[BoolB] = CAST(1 AS bit) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END, [e].[NullableBoolB], [e].[BoolB]) = CAST(1 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 af2b5cb528d..e52b1f77174 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs @@ -1709,10 +1709,10 @@ public override async Task Select_null_propagation_negative9(bool async) AssertSql( """ SELECT CASE - WHEN [u].[LeaderNickname] IS NOT NULL THEN COALESCE(CASE + WHEN [u].[LeaderNickname] IS NOT NULL THEN CASE WHEN CAST(LEN([u].[Nickname]) AS int) = 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) - END, CAST(0 AS bit)) + END ELSE NULL END FROM ( @@ -5414,7 +5414,7 @@ public override async Task ToString_enum_property_projection(bool async) await base.ToString_enum_property_projection(async); AssertSql( -""" + """ SELECT CASE [u].[Rank] WHEN 0 THEN N'None' WHEN 1 THEN N'Private' @@ -5425,7 +5425,7 @@ WHEN 16 THEN N'Captain' WHEN 32 THEN N'Major' WHEN 64 THEN N'Colonel' WHEN 128 THEN N'General' - ELSE COALESCE(CAST([u].[Rank] AS nvarchar(max)), N'') + ELSE CAST([u].[Rank] AS nvarchar(max)) END FROM ( SELECT [g].[Rank] @@ -7861,7 +7861,7 @@ SELECT COALESCE(( SELECT TOP(1) [w].[Id] FROM [Weapons] AS [w] WHERE [u].[FullName] = [w].[OwnerFullName] - ORDER BY [w].[Id]), 0, 42) + ORDER BY [w].[Id]), 0) FROM ( SELECT [g].[FullName] FROM [Gears] AS [g] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 6e857565770..296cac03743 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -1449,10 +1449,10 @@ public override async Task Select_null_propagation_negative9(bool async) AssertSql( """ SELECT CASE - WHEN [g].[LeaderNickname] IS NOT NULL THEN COALESCE(CASE + WHEN [g].[LeaderNickname] IS NOT NULL THEN CASE WHEN CAST(LEN([g].[Nickname]) AS int) = 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) - END, CAST(0 AS bit)) + END ELSE NULL END FROM [Gears] AS [g] @@ -4692,7 +4692,7 @@ public override async Task ToString_enum_property_projection(bool async) await base.ToString_enum_property_projection(async); AssertSql( -""" + """ SELECT CASE [g].[Rank] WHEN 0 THEN N'None' WHEN 1 THEN N'Private' @@ -4703,7 +4703,7 @@ WHEN 16 THEN N'Captain' WHEN 32 THEN N'Major' WHEN 64 THEN N'Colonel' WHEN 128 THEN N'General' - ELSE COALESCE(CAST([g].[Rank] AS nvarchar(max)), N'') + ELSE CAST([g].[Rank] AS nvarchar(max)) END FROM [Gears] AS [g] """); @@ -6618,7 +6618,7 @@ SELECT COALESCE(( SELECT TOP(1) [w].[Id] FROM [Weapons] AS [w] WHERE [g].[FullName] = [w].[OwnerFullName] - ORDER BY [w].[Id]), 0, 42) + ORDER BY [w].[Id]), 0) FROM [Gears] AS [g] """); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs index 7ee56fa0222..4e6a3b8333b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs @@ -851,7 +851,7 @@ SELECT COALESCE(( SELECT TOP(1) [w].[Id] FROM [Weapons] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [w] WHERE [g].[FullName] = [w].[OwnerFullName] - ORDER BY [w].[Id]), 0, 42) + ORDER BY [w].[Id]), 0) FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g] """); } @@ -2660,10 +2660,10 @@ public override async Task Select_null_propagation_negative9(bool async) AssertSql( """ SELECT CASE - WHEN [g].[LeaderNickname] IS NOT NULL THEN COALESCE(CASE + WHEN [g].[LeaderNickname] IS NOT NULL THEN CASE WHEN CAST(LEN([g].[Nickname]) AS int) = 5 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) - END, CAST(0 AS bit)) + END ELSE NULL END FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g] @@ -4803,7 +4803,7 @@ public override async Task ToString_enum_property_projection(bool async) await base.ToString_enum_property_projection(async); AssertSql( -""" + """ SELECT CASE [g].[Rank] WHEN 0 THEN N'None' WHEN 1 THEN N'Private' @@ -4814,7 +4814,7 @@ WHEN 16 THEN N'Captain' WHEN 32 THEN N'Major' WHEN 64 THEN N'Colonel' WHEN 128 THEN N'General' - ELSE COALESCE(CAST([g].[Rank] AS nvarchar(max)), N'') + ELSE CAST([g].[Rank] AS nvarchar(max)) END FROM [Gears] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [g] """); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs index 7edb07d101a..9aaab7bc43b 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs @@ -3312,7 +3312,7 @@ public override async Task Select_null_propagation_negative9(bool async) AssertSql( """ SELECT CASE - WHEN "g"."LeaderNickname" IS NOT NULL THEN COALESCE(length("g"."Nickname") = 5, 0) + WHEN "g"."LeaderNickname" IS NOT NULL THEN length("g"."Nickname") = 5 ELSE NULL END FROM "Gears" AS "g" @@ -3440,7 +3440,7 @@ public override async Task ToString_enum_property_projection(bool async) await base.ToString_enum_property_projection(async); AssertSql( -""" + """ SELECT CASE "g"."Rank" WHEN 0 THEN 'None' WHEN 1 THEN 'Private' @@ -3451,7 +3451,7 @@ WHEN 16 THEN 'Captain' WHEN 32 THEN 'Major' WHEN 64 THEN 'Colonel' WHEN 128 THEN 'General' - ELSE COALESCE(CAST("g"."Rank" AS TEXT), '') + ELSE CAST("g"."Rank" AS TEXT) END FROM "Gears" AS "g" """); @@ -5629,7 +5629,7 @@ SELECT COALESCE(( FROM "Weapons" AS "w" WHERE "g"."FullName" = "w"."OwnerFullName" ORDER BY "w"."Id" - LIMIT 1), 0, 42) + LIMIT 1), 0) FROM "Gears" AS "g" """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs index 38527ac3797..ae0b1342950 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NullSemanticsQuerySqliteTest.cs @@ -917,7 +917,7 @@ public override async Task Where_coalesce_shortcircuit(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE COALESCE("e"."BoolA" OR "e"."BoolB", "e"."NullableBoolA", 1) +WHERE "e"."BoolA" OR "e"."BoolB" """); } @@ -929,7 +929,7 @@ public override async Task Where_coalesce_shortcircuit_many(bool async) """ SELECT "e"."Id" FROM "Entities1" AS "e" -WHERE COALESCE("e"."NullableBoolA", "e"."BoolA" OR "e"."BoolB", "e"."NullableBoolB", "e"."BoolB") +WHERE COALESCE("e"."NullableBoolA", "e"."BoolA" OR "e"."BoolB") """); }