Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[automated] Merge branch 'release/8.0' => 'main' #33694

Merged
11 commits merged into from
May 15, 2024
Merged
2 changes: 2 additions & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<clear />
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
<!-- Begin: Package sources from dotnet-runtime -->
<add key="darc-int-dotnet-runtime-087e153" value="https://pkgs.dev.azure.com/dnceng/internal/_packaging/darc-int-dotnet-runtime-087e1532/nuget/v3/index.json" />
<!-- End: Package sources from dotnet-runtime -->
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
Expand All @@ -18,6 +19,7 @@
<clear />
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
<!-- Begin: Package sources from dotnet-runtime -->
<add key="darc-int-dotnet-runtime-087e153" value="true" />
<!-- End: Package sources from dotnet-runtime -->
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
</disabledPackageSources>
Expand Down
16 changes: 8 additions & 8 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>5535e31a712343a63f5d7d796cd874e563e5ac14</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="8.0.4-servicing.24169.9">
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="8.0.5-servicing.24216.15">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>2d7eea252964e69be94cb9c847b371b23e4dd470</Sha>
<Sha>087e15321bb712ef6fe8b0ba6f8bd12facf92629</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging" Version="8.0.0">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
Expand All @@ -41,18 +41,18 @@
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>9f4b1f5d664afdfc80e1508ab7ed099dff210fbd</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Ref" Version="8.0.4">
<Dependency Name="Microsoft.NETCore.App.Ref" Version="8.0.5">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>2d7eea252964e69be94cb9c847b371b23e4dd470</Sha>
<Sha>087e15321bb712ef6fe8b0ba6f8bd12facf92629</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="8.0.4">
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="8.0.5">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>2d7eea252964e69be94cb9c847b371b23e4dd470</Sha>
<Sha>087e15321bb712ef6fe8b0ba6f8bd12facf92629</Sha>
</Dependency>
<!-- NB: Using BrowserDebugHost to represent the nonshipping version of Microsoft.NETCore.App -->
<Dependency Name="Microsoft.NETCore.BrowserDebugHost.Transport" Version="8.0.4-servicing.24169.9">
<Dependency Name="Microsoft.NETCore.BrowserDebugHost.Transport" Version="8.0.5-servicing.24216.15">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>2d7eea252964e69be94cb9c847b371b23e4dd470</Sha>
<Sha>087e15321bb712ef6fe8b0ba6f8bd12facf92629</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
Expand Down
8 changes: 4 additions & 4 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
<MicrosoftExtensionsConfigurationJsonVersion>8.0.0</MicrosoftExtensionsConfigurationJsonVersion>
<MicrosoftExtensionsDependencyInjectionVersion>8.0.0</MicrosoftExtensionsDependencyInjectionVersion>
<MicrosoftExtensionsDependencyModelVersion>8.0.0</MicrosoftExtensionsDependencyModelVersion>
<MicrosoftExtensionsHostFactoryResolverSourcesVersion>8.0.4-servicing.24169.9</MicrosoftExtensionsHostFactoryResolverSourcesVersion>
<MicrosoftExtensionsHostFactoryResolverSourcesVersion>8.0.5-servicing.24216.15</MicrosoftExtensionsHostFactoryResolverSourcesVersion>
<MicrosoftExtensionsLoggingVersion>8.0.0</MicrosoftExtensionsLoggingVersion>
<SystemTextJsonVersion>8.0.3</SystemTextJsonVersion>
<MicrosoftNETCoreAppRefVersion>8.0.4</MicrosoftNETCoreAppRefVersion>
<MicrosoftNETCoreAppRuntimewinx64Version>8.0.4</MicrosoftNETCoreAppRuntimewinx64Version>
<MicrosoftNETCoreBrowserDebugHostTransportVersion>8.0.4-servicing.24169.9</MicrosoftNETCoreBrowserDebugHostTransportVersion>
<MicrosoftNETCoreAppRefVersion>8.0.5</MicrosoftNETCoreAppRefVersion>
<MicrosoftNETCoreAppRuntimewinx64Version>8.0.5</MicrosoftNETCoreAppRuntimewinx64Version>
<MicrosoftNETCoreBrowserDebugHostTransportVersion>8.0.5-servicing.24216.15</MicrosoftNETCoreBrowserDebugHostTransportVersion>
</PropertyGroup>
<PropertyGroup Label="Dependencies from dotnet/arcade">
<MicrosoftDotNetBuildTasksTemplatingVersion>8.0.0-beta.24204.3</MicrosoftDotNetBuildTasksTemplatingVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ namespace Microsoft.EntityFrameworkCore.Query;
/// </summary>
public class RelationalStructuralTypeShaperExpression : StructuralTypeShaperExpression
{
private static readonly bool UseOldBehavior33547 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue33547", out var enabled33547) && enabled33547;

/// <summary>
/// Creates a new instance of the <see cref="RelationalStructuralTypeShaperExpression" /> class.
/// </summary>
Expand Down Expand Up @@ -156,10 +159,30 @@ public override StructuralTypeShaperExpression WithType(ITypeBase type)

/// <inheritdoc />
public override StructuralTypeShaperExpression MakeNullable(bool nullable = true)
=> IsNullable != nullable
// Marking nullable requires re-computation of Discriminator condition
? new RelationalStructuralTypeShaperExpression(StructuralType, ValueBufferExpression, true)
: this;
{
if (IsNullable == nullable)
{
return this;
}

var newValueBufferExpression = ValueBufferExpression;
if (!UseOldBehavior33547
&& StructuralType is IComplexType
&& ValueBufferExpression is StructuralTypeProjectionExpression structuralTypeProjectionExpression)
{
// for complex types we also need to go inside and mark all properties there as nullable
// so that when they get extracted during apply projection, they have correct nullabilities
// for entity types (containing complex types) we are ok - if the pushdown already happened we iterate over all complex shaper
// and call MakeNullable, so we get here. If pushdown hasn't happened yet (so the complex cache is not populated yet)
// it's enough to mark shaper itself as nullable - when we eventually create shapers for the complex types
// in GenerateComplexPropertyShaperExpression, we generate the columns as nullable if the shaper itself is nullable
// see issue #33547 for more details
newValueBufferExpression = structuralTypeProjectionExpression.MakeNullable();
}

// Marking nullable requires re-computation of Discriminator condition
return new RelationalStructuralTypeShaperExpression(StructuralType, newValueBufferExpression, true);
}

/// <inheritdoc />
public override StructuralTypeShaperExpression Update(Expression valueBufferExpression)
Expand Down
30 changes: 30 additions & 0 deletions test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,36 @@ public virtual Task Same_complex_type_projected_twice_with_pushdown_as_part_of_a
AssertEqual(e.Complex?.Two, a.Complex?.Two);
});

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Projecting_property_of_complex_type_using_left_join_with_pushdown(bool async)
=> AssertQuery(
async,
ss => from cg in ss.Set<CustomerGroup>()
join c in ss.Set<Customer>().Where(x => x.Id > 5) on cg.Id equals c.Id into grouping
from c in grouping.DefaultIfEmpty()
select c == null ? null : (int?)c.BillingAddress.ZipCode);

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Projecting_complex_from_optional_navigation_using_conditional(bool async)
=> AssertQuery(
async,
ss => ss.Set<CustomerGroup>().Select(x => x.OptionalCustomer == null ? null : x.OptionalCustomer.ShippingAddress)
.OrderBy(x => x!.ZipCode).Take(20).Distinct().Select(x => (int?)x!.ZipCode),
ss => ss.Set<CustomerGroup>().Select(x => x.OptionalCustomer == null ? null : x.OptionalCustomer.ShippingAddress)
.OrderBy(x => x.MaybeScalar(xx => xx!.ZipCode)).Take(20).Distinct().Select(x => x.MaybeScalar(xx => xx!.ZipCode)));

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Project_entity_with_complex_type_pushdown_and_then_left_join(bool async)
=> AssertQuery(
async,
ss => from c1 in ss.Set<Customer>().OrderBy(x => x.Id).Take(20).Distinct()
join c2 in ss.Set<Customer>().OrderByDescending(x => x.Id).Take(30).Distinct() on c1.Id equals c2.Id into grouping
from c2 in grouping.DefaultIfEmpty()
select new { Zip1 = c1.BillingAddress.ZipCode, Zip2 = c2.ShippingAddress.ZipCode });

protected DbContext CreateContext()
=> Fixture.CreateContext();
}
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,72 @@ public override async Task Same_complex_type_projected_twice_with_pushdown_as_pa
AssertSql("");
}

public override async Task Projecting_property_of_complex_type_using_left_join_with_pushdown(bool async)
{
await base.Projecting_property_of_complex_type_using_left_join_with_pushdown(async);

AssertSql(
"""
SELECT [t].[BillingAddress_ZipCode]
FROM [CustomerGroup] AS [c]
LEFT JOIN (
SELECT [c0].[Id], [c0].[BillingAddress_ZipCode]
FROM [Customer] AS [c0]
WHERE [c0].[Id] > 5
) AS [t] ON [c].[Id] = [t].[Id]
""");
}

public override async Task Projecting_complex_from_optional_navigation_using_conditional(bool async)
{
await base.Projecting_complex_from_optional_navigation_using_conditional(async);

AssertSql(
"""
@__p_0='20'

SELECT [t0].[ShippingAddress_ZipCode]
FROM (
SELECT DISTINCT [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName]
FROM (
SELECT TOP(@__p_0) [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName]
FROM [CustomerGroup] AS [c]
LEFT JOIN [Customer] AS [c0] ON [c].[OptionalCustomerId] = [c0].[Id]
ORDER BY [c0].[ShippingAddress_ZipCode]
) AS [t]
) AS [t0]
""");
}

public override async Task Project_entity_with_complex_type_pushdown_and_then_left_join(bool async)
{
await base.Project_entity_with_complex_type_pushdown_and_then_left_join(async);

AssertSql(
"""
@__p_0='20'
@__p_1='30'

SELECT [t0].[BillingAddress_ZipCode] AS [Zip1], [t1].[ShippingAddress_ZipCode] AS [Zip2]
FROM (
SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName]
FROM (
SELECT TOP(@__p_0) [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName]
FROM [Customer] AS [c]
ORDER BY [c].[Id]
) AS [t]
) AS [t0]
LEFT JOIN (
SELECT DISTINCT [t2].[Id], [t2].[Name], [t2].[BillingAddress_AddressLine1], [t2].[BillingAddress_AddressLine2], [t2].[BillingAddress_ZipCode], [t2].[BillingAddress_Country_Code], [t2].[BillingAddress_Country_FullName], [t2].[ShippingAddress_AddressLine1], [t2].[ShippingAddress_AddressLine2], [t2].[ShippingAddress_ZipCode], [t2].[ShippingAddress_Country_Code], [t2].[ShippingAddress_Country_FullName]
FROM (
SELECT TOP(@__p_1) [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName]
FROM [Customer] AS [c0]
ORDER BY [c0].[Id] DESC
) AS [t2]
) AS [t1] ON [t0].[Id] = [t1].[Id]
""");
}

[ConditionalFact]
public virtual void Check_all_tests_overridden()
=> TestHelpers.AssertAllMethodsOverridden(GetType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,75 @@ public override async Task Same_complex_type_projected_twice_with_pushdown_as_pa
(await Assert.ThrowsAsync<InvalidOperationException>(
() => base.Same_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(async))).Message);

public override async Task Projecting_property_of_complex_type_using_left_join_with_pushdown(bool async)
{
await base.Projecting_property_of_complex_type_using_left_join_with_pushdown(async);

AssertSql(
"""
SELECT "t"."BillingAddress_ZipCode"
FROM "CustomerGroup" AS "c"
LEFT JOIN (
SELECT "c0"."Id", "c0"."BillingAddress_ZipCode"
FROM "Customer" AS "c0"
WHERE "c0"."Id" > 5
) AS "t" ON "c"."Id" = "t"."Id"
""");
}

public override async Task Projecting_complex_from_optional_navigation_using_conditional(bool async)
{
await base.Projecting_complex_from_optional_navigation_using_conditional(async);

AssertSql(
"""
@__p_0='20'

SELECT "t0"."ShippingAddress_ZipCode"
FROM (
SELECT DISTINCT "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName"
FROM (
SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName"
FROM "CustomerGroup" AS "c"
LEFT JOIN "Customer" AS "c0" ON "c"."OptionalCustomerId" = "c0"."Id"
ORDER BY "c0"."ShippingAddress_ZipCode"
LIMIT @__p_0
) AS "t"
) AS "t0"
""");
}

public override async Task Project_entity_with_complex_type_pushdown_and_then_left_join(bool async)
{
await base.Project_entity_with_complex_type_pushdown_and_then_left_join(async);

AssertSql(
"""
@__p_0='20'
@__p_1='30'

SELECT "t0"."BillingAddress_ZipCode" AS "Zip1", "t1"."ShippingAddress_ZipCode" AS "Zip2"
FROM (
SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName"
FROM (
SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName"
FROM "Customer" AS "c"
ORDER BY "c"."Id"
LIMIT @__p_0
) AS "t"
) AS "t0"
LEFT JOIN (
SELECT DISTINCT "t2"."Id", "t2"."Name", "t2"."BillingAddress_AddressLine1", "t2"."BillingAddress_AddressLine2", "t2"."BillingAddress_ZipCode", "t2"."BillingAddress_Country_Code", "t2"."BillingAddress_Country_FullName", "t2"."ShippingAddress_AddressLine1", "t2"."ShippingAddress_AddressLine2", "t2"."ShippingAddress_ZipCode", "t2"."ShippingAddress_Country_Code", "t2"."ShippingAddress_Country_FullName"
FROM (
SELECT "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName"
FROM "Customer" AS "c0"
ORDER BY "c0"."Id" DESC
LIMIT @__p_1
) AS "t2"
) AS "t1" ON "t0"."Id" = "t1"."Id"
""");
}

[ConditionalFact]
public virtual void Check_all_tests_overridden()
=> TestHelpers.AssertAllMethodsOverridden(GetType());
Expand Down