From 9b31af9672dd4fb61da936e974172762afba45e9 Mon Sep 17 00:00:00 2001 From: maumar Date: Fri, 2 Feb 2024 13:47:51 -0800 Subject: [PATCH] Fix to #32911 - ComplexProperty with AsSplitQuery Problem was that when we lift structural type projection during pushdown, if that projection contains complex types with the same column names (e.g. cross join of same entities - it's perfectly fine to do in a vacuum, we just alias the columns whose names are repeated) we would lift the projection incorrectly. What we do is go through all the properties, apply the corresponding columns to the selectExpression if needed and generate StructuralTypeProjection object if the projection needs to be applied one level up. For complex types we would generate a shaper expression and then run it through the same process, BUT the nested complex properties would be added to a flat structure along with the primitive properties, rather than in separate cache dedicated for complex property shapers. This was wrong and not what we expected to see, when processing this structure one level up (i.e. when applying projection to the outer select) SELECT [applying_this_projection_was_wrong] FROM ( SELECT c.Id, c.Name, c.ComplexProp, o.ComplexProp as ComplexProp0 FROM Customers as c JOIN Orders as o ON ... ) as s i.e. applying projection once worked fine, but doing it second time did not. The reason why is that we expected to see information about the complex type shape in the complex property shaper cache, rather than flat structure for primitives, but it wasn't there. So we assumed this is the first time we the projection is being applied, so we conjure up the complex type shaper based on table alias and IColumn metadata. This results in a situation, where complex property that was aliased is never picked. So we end up with: SELECT s.Id, s.Name, s.ComplexProp -- we would also try to add s.ComplexProp again, instead of s.ComplexProp0 but of course we don't add same thing twice FROM ( SELECT c.Id, c.Name, c.ComplexProp, o.ComplexProp as ComplexProp0 FROM Customers as c JOIN Orders as o ON ... ) as s This leads to bad data - two different objects with distinct data in them are mapped to the same column in the database. Fix is to property build a complex type shaper structure when applying projection instead, so the structure we generate matches expectations. Also modified VisitChildren and MakeNullable methods on StructuralTypeProjectionExpression to process/preserve complex type cache information, which was previously gobbled up/ignored. Fixes #32911 --- .../Query/SqlExpressions/SelectExpression.cs | 159 +++++----- .../StructuralTypeProjectionExpression.cs | 72 ++++- ...AdvancedMappingsQueryRelationalTestBase.cs | 131 ++++++++ .../Query/ComplexTypeQueryTestBase.cs | 286 ++++++++++++++++++ ...AdHocAdvancedMappingsQuerySqlServerTest.cs | 51 ++++ .../Query/ComplexTypeQuerySqlServerTest.cs | 270 +++++++++++++++++ .../AdHocAdvancedMappingsQuerySqliteTest.cs | 2 - .../Query/ComplexTypeQuerySqliteTest.cs | 270 +++++++++++++++++ 8 files changed, 1162 insertions(+), 79 deletions(-) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 5aec06691c9..7d13924e0e5 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2077,20 +2077,21 @@ void HandleStructuralTypeProjection( projection1.StructuralType.DisplayName(), projection2.StructuralType.DisplayName())); } - var propertyExpressions = new Dictionary(); - - ProcessStructuralType(projection1, projection2); + var resultProjection = ProcessStructuralType(projection1, projection2); + _projectionMapping[projectionMember] = resultProjection; - void ProcessStructuralType( - StructuralTypeProjectionExpression nestedProjection1, - StructuralTypeProjectionExpression nestedProjection2) + StructuralTypeProjectionExpression ProcessStructuralType( + StructuralTypeProjectionExpression structuralProjection1, + StructuralTypeProjectionExpression structuralProjection2) { - var type = nestedProjection1.StructuralType; + var propertyExpressions = new Dictionary(); + var complexPropertyCache = new Dictionary(); + var type = structuralProjection1.StructuralType; foreach (var property in type.GetAllPropertiesInHierarchy()) { - var column1 = nestedProjection1.BindProperty(property); - var column2 = nestedProjection2.BindProperty(property); + var column1 = structuralProjection1.BindProperty(property); + var column2 = structuralProjection2.BindProperty(property); var alias = GenerateUniqueColumnAlias(column1.Name); var innerProjection = new ProjectionExpression(column1, alias); select1._projection.Add(innerProjection); @@ -2127,7 +2128,7 @@ void ProcessStructuralType( // If the top-level projection - not the current nested one - is a complex type and not an entity type, then add // all its columns to the "otherExpressions" list (i.e. columns not part of a an entity primary key). This is // the same as with a non-structural type projection. - else if (projection1.StructuralType is IComplexType) + else if (type is IComplexType) { var outerTypeMapping = column1.TypeMapping ?? column1.TypeMapping; if (outerTypeMapping == null) @@ -2141,52 +2142,62 @@ void ProcessStructuralType( } } - foreach (var complexProperty in GetAllComplexPropertiesInHierarchy(nestedProjection1.StructuralType)) + foreach (var complexProperty in GetAllComplexPropertiesInHierarchy(type)) { - ProcessStructuralType( - (StructuralTypeProjectionExpression)nestedProjection1.BindComplexProperty(complexProperty).ValueBufferExpression, - (StructuralTypeProjectionExpression)nestedProjection2.BindComplexProperty(complexProperty).ValueBufferExpression); - } - } + var complexPropertyShaper1 = structuralProjection1.BindComplexProperty(complexProperty); + var complexPropertyShaper2 = structuralProjection2.BindComplexProperty(complexProperty); - Check.DebugAssert( - projection1.TableMap.Count == projection2.TableMap.Count, - "Set operation over entity projections with different table map counts"); - Check.DebugAssert( - projection1.TableMap.Keys.All(t => projection2.TableMap.ContainsKey(t)), - "Set operation over entity projections with table map discrepancy"); + var resultComplexProjection = ProcessStructuralType( + (StructuralTypeProjectionExpression)complexPropertyShaper1.ValueBufferExpression, + (StructuralTypeProjectionExpression)complexPropertyShaper2.ValueBufferExpression); - var tableMap = projection1.TableMap.ToDictionary(kvp => kvp.Key, _ => setOperationAlias); + var resultComplexShaper = new RelationalStructuralTypeShaperExpression( + complexProperty.ComplexType, + resultComplexProjection, + resultComplexProjection.IsNullable); - var discriminatorExpression = projection1.DiscriminatorExpression; - if (projection1.DiscriminatorExpression != null - && projection2.DiscriminatorExpression != null) - { - var alias = GenerateUniqueColumnAlias(DiscriminatorColumnAlias); - var innerProjection = new ProjectionExpression(projection1.DiscriminatorExpression, alias); - select1._projection.Add(innerProjection); - select2._projection.Add(new ProjectionExpression(projection2.DiscriminatorExpression, alias)); - discriminatorExpression = CreateColumnExpression(innerProjection, setOperationAlias); - } + complexPropertyCache[complexProperty] = resultComplexShaper; + } - var outerProjection = new StructuralTypeProjectionExpression( - projection1.StructuralType, propertyExpressions, tableMap, nullable: false, discriminatorExpression); + Check.DebugAssert( + structuralProjection1.TableMap.Count == structuralProjection2.TableMap.Count, + "Set operation over entity projections with different table map counts"); + Check.DebugAssert( + structuralProjection1.TableMap.Keys.All(t => structuralProjection2.TableMap.ContainsKey(t)), + "Set operation over entity projections with table map discrepancy"); - if (outerIdentifiers.Length > 0 && outerProjection is { StructuralType: IEntityType entityType }) - { - var primaryKey = entityType.FindPrimaryKey(); + var tableMap = projection1.TableMap.ToDictionary(kvp => kvp.Key, _ => setOperationAlias); - // We know that there are existing identifiers (see condition above); we know we must have a key since a keyless - // entity type would have wiped the identifiers when generating the join. - Check.DebugAssert(primaryKey != null, "primary key is null."); - foreach (var property in primaryKey.Properties) + var discriminatorExpression = structuralProjection1.DiscriminatorExpression; + if (structuralProjection1.DiscriminatorExpression != null + && structuralProjection2.DiscriminatorExpression != null) { - entityProjectionIdentifiers.Add(outerProjection.BindProperty(property)); - entityProjectionValueComparers.Add(property.GetKeyValueComparer()); + var alias = GenerateUniqueColumnAlias(DiscriminatorColumnAlias); + var innerProjection = new ProjectionExpression(structuralProjection1.DiscriminatorExpression, alias); + select1._projection.Add(innerProjection); + select2._projection.Add(new ProjectionExpression(structuralProjection2.DiscriminatorExpression, alias)); + discriminatorExpression = CreateColumnExpression(innerProjection, setOperationAlias); } - } - _projectionMapping[projectionMember] = outerProjection; + var outerProjection = new StructuralTypeProjectionExpression( + type, propertyExpressions, complexPropertyCache, tableMap, nullable: false, discriminatorExpression); + + if (outerIdentifiers.Length > 0 && outerProjection is { StructuralType: IEntityType entityType }) + { + var primaryKey = entityType.FindPrimaryKey(); + + // We know that there are existing identifiers (see condition above); we know we must have a key since a keyless + // entity type would have wiped the identifiers when generating the join. + Check.DebugAssert(primaryKey != null, "primary key is null."); + foreach (var property in primaryKey.Properties) + { + entityProjectionIdentifiers.Add(outerProjection.BindProperty(property)); + entityProjectionValueComparers.Add(property.GetKeyValueComparer()); + } + } + + return outerProjection; + } } string GenerateUniqueColumnAlias(string baseAlias) @@ -2560,10 +2571,10 @@ public static StructuralTypeShaperExpression GenerateComplexPropertyShaperExpres // We do not support complex type splitting, so we will only ever have a single table/view mapping to it. // See Issue #32853 and Issue #31248 var complexTypeTable = complexProperty.ComplexType.GetViewOrTableMappings().Single().Table; - if (!containerProjection.TableMap.TryGetValue(complexTypeTable, out var tableReferenceExpression)) + if (!containerProjection.TableMap.TryGetValue(complexTypeTable, out var tableAlias)) { complexTypeTable = complexProperty.ComplexType.GetDefaultMappings().Single().Table; - tableReferenceExpression = containerProjection.TableMap[complexTypeTable]; + tableAlias = containerProjection.TableMap[complexTypeTable]; } var isComplexTypeNullable = containerProjection.IsNullable || complexProperty.IsNullable; @@ -2581,14 +2592,14 @@ public static StructuralTypeShaperExpression GenerateComplexPropertyShaperExpres // TODO: Reimplement EntityProjectionExpression via TableMap, and then use that here var column = complexTypeTable.FindColumn(property)!; propertyExpressionMap[property] = CreateColumnExpression( - property, column, tableReferenceExpression, isComplexTypeNullable || column.IsNullable); + property, column, tableAlias, isComplexTypeNullable || column.IsNullable); } // The table map of the target complex type should only ever contains a single table (no table splitting). // If the source is itself a complex type (nested complex type), its table map is already suitable and we can just pass it on. var newTableMap = containerProjection.TableMap.Count == 1 ? containerProjection.TableMap - : new Dictionary { [complexTypeTable] = tableReferenceExpression }; + : new Dictionary { [complexTypeTable] = tableAlias }; Check.DebugAssert(newTableMap.Single().Key == complexTypeTable, "Bad new table map"); @@ -3530,33 +3541,35 @@ StructuralTypeProjectionExpression LiftEntityProjectionFromSubquery( string subqueryAlias) { var propertyExpressions = new Dictionary(); + var complexPropertyCache = new Dictionary(); - HandleTypeProjection(projection); - - void HandleTypeProjection(StructuralTypeProjectionExpression typeProjection) + foreach (var property in projection.StructuralType.GetAllPropertiesInHierarchy()) { - foreach (var property in typeProjection.StructuralType.GetAllPropertiesInHierarchy()) + // json entity projection (i.e. JSON entity that was transformed into query root) may have synthesized keys + // but they don't correspond to any columns - we need to skip those + if (projection is { StructuralType: IEntityType entityType } + && entityType.IsMappedToJson() + && property.IsOrdinalKeyProperty()) { - // json entity projection (i.e. JSON entity that was transformed into query root) may have synthesized keys - // but they don't correspond to any columns - we need to skip those - if (typeProjection is { StructuralType: IEntityType entityType } - && entityType.IsMappedToJson() - && property.IsOrdinalKeyProperty()) - { - continue; - } - - var innerColumn = typeProjection.BindProperty(property); - var outerColumn = subquery.GenerateOuterColumn(subqueryAlias, innerColumn); - projectionMap[innerColumn] = outerColumn; - propertyExpressions[property] = outerColumn; + continue; } - foreach (var complexProperty in GetAllComplexPropertiesInHierarchy(typeProjection.StructuralType)) - { - HandleTypeProjection( - (StructuralTypeProjectionExpression)typeProjection.BindComplexProperty(complexProperty).ValueBufferExpression); - } + var innerColumn = projection.BindProperty(property); + var outerColumn = subquery.GenerateOuterColumn(subqueryAlias, innerColumn); + + projectionMap[innerColumn] = outerColumn; + propertyExpressions[property] = outerColumn; + } + + foreach (var complexProperty in GetAllComplexPropertiesInHierarchy(projection.StructuralType)) + { + var complexPropertyShaper = projection.BindComplexProperty(complexProperty); + + var complexTypeProjectionExpression = LiftEntityProjectionFromSubquery( + (StructuralTypeProjectionExpression)complexPropertyShaper.ValueBufferExpression, + subqueryAlias); + + complexPropertyCache[complexProperty] = complexPropertyShaper.Update(complexTypeProjectionExpression); } ColumnExpression? discriminatorExpression = null; @@ -3570,7 +3583,7 @@ void HandleTypeProjection(StructuralTypeProjectionExpression typeProjection) var tableMap = projection.TableMap.ToDictionary(kvp => kvp.Key, _ => subqueryAlias); var newEntityProjection = new StructuralTypeProjectionExpression( - projection.StructuralType, propertyExpressions, tableMap, nullable: false, discriminatorExpression); + projection.StructuralType, propertyExpressions, complexPropertyCache, tableMap, nullable: false, discriminatorExpression); if (projection.StructuralType is IEntityType entityType2) { diff --git a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs index de6b484dfa5..ff33d491091 100644 --- a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs +++ b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; namespace Microsoft.EntityFrameworkCore.Query; @@ -37,7 +36,33 @@ public StructuralTypeProjectionExpression( : this( type, propertyExpressionMap, - new Dictionary(), + [], + null, + tableMap, + nullable, + discriminatorExpression) + { + } + + /// + /// 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 + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public StructuralTypeProjectionExpression( + ITypeBase type, + IReadOnlyDictionary propertyExpressionMap, + Dictionary complexPropertyCache, + IReadOnlyDictionary tableMap, + bool nullable = false, + SqlExpression? discriminatorExpression = null) + : this( + type, + propertyExpressionMap, + [], + complexPropertyCache, tableMap, nullable, discriminatorExpression) @@ -48,6 +73,7 @@ private StructuralTypeProjectionExpression( ITypeBase type, IReadOnlyDictionary propertyExpressionMap, Dictionary ownedNavigationMap, + Dictionary? complexPropertyCache, IReadOnlyDictionary tableMap, bool nullable, SqlExpression? discriminatorExpression = null) @@ -55,6 +81,7 @@ private StructuralTypeProjectionExpression( StructuralType = type; _propertyExpressionMap = propertyExpressionMap; _ownedNavigationMap = ownedNavigationMap; + _complexPropertyCache = complexPropertyCache; TableMap = tableMap; IsNullable = nullable; DiscriminatorExpression = discriminatorExpression; @@ -124,6 +151,18 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) propertyExpressionMap[property] = newExpression; } + var complexPropertyCache = default(Dictionary); + if (_complexPropertyCache != null) + { + complexPropertyCache = new(); + foreach (var (complexProperty, complexShaper) in _complexPropertyCache) + { + var newComplexShaper = (StructuralTypeShaperExpression)visitor.Visit(complexShaper); + changed |= complexShaper != newComplexShaper; + complexPropertyCache[complexProperty] = newComplexShaper; + } + } + var discriminatorExpression = (SqlExpression?)visitor.Visit(DiscriminatorExpression); changed |= discriminatorExpression != DiscriminatorExpression; @@ -137,7 +176,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) return changed ? new StructuralTypeProjectionExpression( - StructuralType, propertyExpressionMap, ownedNavigationMap, TableMap, IsNullable, discriminatorExpression) + StructuralType, propertyExpressionMap, ownedNavigationMap, complexPropertyCache, TableMap, IsNullable, discriminatorExpression) : this; } @@ -153,6 +192,16 @@ public virtual StructuralTypeProjectionExpression MakeNullable() propertyExpressionMap[property] = columnExpression.MakeNullable(); } + var complexPropertyCache = default(Dictionary); + if (_complexPropertyCache != null) + { + complexPropertyCache = new(); + foreach (var (complexProperty, complexShaper) in _complexPropertyCache) + { + complexPropertyCache[complexProperty] = complexShaper.MakeNullable(); + } + } + var discriminatorExpression = DiscriminatorExpression; if (discriminatorExpression is ColumnExpression ce) { @@ -179,6 +228,7 @@ public virtual StructuralTypeProjectionExpression MakeNullable() StructuralType, propertyExpressionMap, ownedNavigationMap, + complexPropertyCache, TableMap, nullable: true, discriminatorExpression); @@ -213,6 +263,20 @@ public virtual StructuralTypeProjectionExpression UpdateEntityType(IEntityType d } } + var complexPropertyCache = default(Dictionary); + if (_complexPropertyCache != null) + { + complexPropertyCache = new(); + foreach (var (complexProperty, complexShaper) in _complexPropertyCache) + { + if (derivedType.IsAssignableFrom(complexProperty.DeclaringType) + || complexProperty.DeclaringType.IsAssignableFrom(derivedType)) + { + complexPropertyCache[complexProperty] = complexShaper; + } + } + } + var ownedNavigationMap = new Dictionary(); foreach (var (navigation, entityShaperExpression) in _ownedNavigationMap) { @@ -264,7 +328,7 @@ public virtual StructuralTypeProjectionExpression UpdateEntityType(IEntityType d } return new StructuralTypeProjectionExpression( - derivedType, propertyExpressionMap, ownedNavigationMap, newTableMap ?? TableMap, IsNullable, discriminatorExpression); + derivedType, propertyExpressionMap, ownedNavigationMap, complexPropertyCache, newTableMap ?? TableMap, IsNullable, discriminatorExpression); } /// diff --git a/test/EFCore.Relational.Specification.Tests/Query/AdHocAdvancedMappingsQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/AdHocAdvancedMappingsQueryRelationalTestBase.cs index 7c1e5190a25..0643e846e66 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/AdHocAdvancedMappingsQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/AdHocAdvancedMappingsQueryRelationalTestBase.cs @@ -14,6 +14,137 @@ protected void ClearLog() protected void AssertSql(params string[] expected) => TestSqlLoggerFactory.AssertBaseline(expected); + #region 32911 + + [ConditionalFact] + public virtual async Task Two_similar_complex_properties_projected_with_split_query1() + { + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using var context = contextFactory.CreateContext(); + var query = context.Offers + .Include(e => e.Variations) + .ThenInclude(v => v.Nested) + .AsSplitQuery() + .ToList(); + + var resultElement = query.Single(); + foreach (var variation in resultElement.Variations) + { + Assert.NotEqual(variation.Payment.Brutto, variation.Nested.Payment.Brutto); + Assert.NotEqual(variation.Payment.Netto, variation.Nested.Payment.Netto); + } + } + + [ConditionalFact] + public virtual async Task Two_similar_complex_properties_projected_with_split_query2() + { + var contextFactory = await InitializeAsync(seed: c => c.Seed()); + + using var context = contextFactory.CreateContext(); + var query = context.Offers + .Include(e => e.Variations) + .ThenInclude(v => v.Nested) + .AsSplitQuery() + .Single(x => x.Id == 1); + + foreach (var variation in query.Variations) + { + Assert.NotEqual(variation.Payment.Brutto, variation.Nested.Payment.Brutto); + Assert.NotEqual(variation.Payment.Netto, variation.Nested.Payment.Netto); + } + } + + protected class Context32911(DbContextOptions options) : DbContext(options) + { + public DbSet Offers { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); + modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); + modelBuilder.Entity().ComplexProperty(x => x.Payment, cpb => + { + cpb.IsRequired(); + cpb.Property(p => p.Netto).HasColumnName("payment_netto"); + cpb.Property(p => p.Brutto).HasColumnName("payment_brutto"); + }); + modelBuilder.Entity().Property(x => x.Id).ValueGeneratedNever(); + modelBuilder.Entity().ComplexProperty(x => x.Payment, cpb => + { + cpb.IsRequired(); + cpb.Property(p => p.Netto).HasColumnName("payment_netto"); + cpb.Property(p => p.Brutto).HasColumnName("payment_brutto"); + }); + } + + public void Seed() + { + var v1 = new Variation + { + Id = 1, + Payment = new Payment(1, 10), + Nested = new NestedEntity + { + Id = 1, + Payment = new Payment(10, 100) + } + }; + + var v2 = new Variation + { + Id = 2, + Payment = new Payment(2, 20), + Nested = new NestedEntity + { + Id = 2, + Payment = new Payment(20, 200) + } + }; + + var v3 = new Variation + { + Id = 3, + Payment = new Payment(3, 30), + Nested = new NestedEntity + { + Id = 3, + Payment = new Payment(30, 300) + } + }; + + Offers.Add(new Offer { Id = 1, Variations = new List { v1, v2, v3 } }); + + SaveChanges(); + } + + public abstract class EntityBase + { + public int Id { get; set; } + } + + public class Offer : EntityBase + { + public ICollection Variations { get; set; } + } + + public class Variation : EntityBase + { + public Payment Payment { get; set; } = new Payment(0, 0); + + public NestedEntity Nested { get; set; } + } + + public class NestedEntity : EntityBase + { + public Payment Payment { get; set; } = new Payment(0, 0); + } + + public record Payment(decimal Netto, decimal Brutto); + } + + #endregion + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Hierarchy_query_with_abstract_type_sibling_TPC(bool async) diff --git a/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs index c91a7ae046b..ae38af60bf3 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs @@ -528,6 +528,292 @@ public virtual Task Union_two_different_struct_complex_type(bool async) async, ss => ss.Set().Select(c => c.ShippingAddress).Union(ss.Set().Select(c => c.BillingAddress))); + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_nested_complex_type_twice_with_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .Distinct() + .Select(x => new { x.BA1, x.BA2 }), + elementSorter: e => (e.BA1.ZipCode, e.BA2.ZipCode), + elementAsserter: (e, a) => + { + AssertEqual(e.BA1, a.BA1); + AssertEqual(e.BA2, a.BA2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_entity_with_nested_complex_type_twice_with_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + select new { c1, c2 }) + .Distinct() + .Select(x => new { x.c1, x.c2 }), + elementSorter: e => (e.c1.Id, e.c2.Id), + elementAsserter: (e, a) => + { + AssertEqual(e.c1, a.c1); + AssertEqual(e.c2, a.c2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_nested_complex_type_twice_with_double_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .Take(50) + .Distinct() + .Select(x => new { x.BA1, x.BA2 }), + elementSorter: e => (e.BA1.ZipCode, e.BA2.ZipCode), + elementAsserter: (e, a) => + { + AssertEqual(e.BA1, a.BA1); + AssertEqual(e.BA2, a.BA2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_entity_with_nested_complex_type_twice_with_double_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { c1, c2 }) + .Take(50) + .Distinct() + .Select(x => new { x.c1, x.c2 }), + elementSorter: e => (e.c1.Id, e.c2.Id), + elementAsserter: (e, a) => + { + AssertEqual(e.c1, a.c1); + AssertEqual(e.c2, a.c2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_struct_nested_complex_type_twice_with_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .Distinct() + .Select(x => new { x.BA1, x.BA2 }), + elementSorter: e => (e.BA1.ZipCode, e.BA2.ZipCode), + elementAsserter: (e, a) => + { + AssertEqual(e.BA1, a.BA1); + AssertEqual(e.BA2, a.BA2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_entity_with_struct_nested_complex_type_twice_with_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + select new { c1, c2 }) + .Distinct() + .Select(x => new { x.c1, x.c2 }), + elementSorter: e => (e.c1.Id, e.c2.Id), + elementAsserter: (e, a) => + { + AssertEqual(e.c1, a.c1); + AssertEqual(e.c2, a.c2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_struct_nested_complex_type_twice_with_double_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .Take(50) + .Distinct() + .Select(x => new { x.BA1, x.BA2 }), + elementSorter: e => (e.BA1.ZipCode, e.BA2.ZipCode), + elementAsserter: (e, a) => + { + AssertEqual(e.BA1, a.BA1); + AssertEqual(e.BA2, a.BA2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Project_same_entity_with_struct_nested_complex_type_twice_with_double_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { c1, c2 }) + .Take(50) + .Distinct() + .Select(x => new { x.c1, x.c2 }), + elementSorter: e => (e.c1.Id, e.c2.Id), + elementAsserter: (e, a) => + { + AssertEqual(e.c1, a.c1); + AssertEqual(e.c2, a.c2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Union_of_same_entity_with_nested_complex_type_projected_twice_with_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { c1, c2 }) + .Union(from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { c1, c2 }) + .OrderBy(x => x.c1.Id).ThenBy(x => x.c2.Id) + .Take(50) + .Select(x => new { x.c1, x.c2 }), + assertOrder: true, + elementAsserter: (e, a) => + { + AssertEqual(e.c1, a.c1); + AssertEqual(e.c2, a.c2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Union_of_same_entity_with_nested_complex_type_projected_twice_with_double_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { c1, c2 }) + .Union(from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { c1, c2 }) + .OrderBy(x => x.c1.Id).ThenBy(x => x.c2.Id) + .Take(50) + .Select(x => new { x.c1, x.c2 }) + .Distinct() + .OrderBy(x => x.c1.Id).ThenBy(x => x.c2.Id) + .Take(50) + .Select(x => new { x.c1, x.c2 }), + assertOrder: true, + elementAsserter: (e, a) => + { + AssertEqual(e.c1, a.c1); + AssertEqual(e.c2, a.c2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Union_of_same_nested_complex_type_projected_twice_with_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .Union(from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .OrderBy(x => x.BA1.ZipCode).ThenBy(x => x.BA2.ZipCode) + .Take(50) + .Select(x => new { x.BA1, x.BA2 }), + assertOrder: true, + elementAsserter: (e, a) => + { + AssertEqual(e.BA1, a.BA1); + AssertEqual(e.BA2, a.BA2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Union_of_same_nested_complex_type_projected_twice_with_double_pushdown(bool async) + => AssertQuery( + async, + ss => (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .Union(from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id + select new { BA1 = c1.BillingAddress, BA2 = c2.BillingAddress }) + .OrderBy(x => x.BA1.ZipCode).ThenBy(x => x.BA2.ZipCode) + .Take(50) + .Select(x => new { x.BA1, x.BA2 }) + .Distinct() + .OrderBy(x => x.BA1.ZipCode).ThenBy(x => x.BA2.ZipCode) + .Take(50) + .Select(x => new { x.BA1, x.BA2 }), + assertOrder: true, + elementAsserter: (e, a) => + { + AssertEqual(e.BA1, a.BA1); + AssertEqual(e.BA2, a.BA2); + }); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Same_entity_with_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(bool async) + => AssertQuery( + async, + ss => ss.Set().Select(x => new + { + x.Id, + Complex = (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id descending + select new { One = c1, Two = c2 }).FirstOrDefault() + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Complex?.One, a.Complex?.One); + AssertEqual(e.Complex?.Two, a.Complex?.Two); + }); + + [ConditionalTheory(Skip = "issue #31376")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Same_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(bool async) + => AssertQuery( + async, + ss => ss.Set().Select(x => new + { + x.Id, + Complex = (from c1 in ss.Set() + from c2 in ss.Set() + orderby c1.Id, c2.Id descending + select new { One = c1.BillingAddress, Two = c2.BillingAddress }).FirstOrDefault() + }), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + AssertEqual(e.Id, a.Id); + AssertEqual(e.Complex?.One, a.Complex?.One); + AssertEqual(e.Complex?.Two, a.Complex?.Two); + }); + protected DbContext CreateContext() => Fixture.CreateContext(); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqlServerTest.cs index aaeaf5fc010..109f8a9bf66 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqlServerTest.cs @@ -231,6 +231,57 @@ UNION ALL FROM [Dogs] AS [d] ) AS [u] WHERE [u].[Species] LIKE N'F%' +"""); + } + + public override async Task Two_similar_complex_properties_projected_with_split_query1() + { + await base.Two_similar_complex_properties_projected_with_split_query1(); + + AssertSql( +""" +SELECT [o].[Id] +FROM [Offers] AS [o] +ORDER BY [o].[Id] +""", + // + """ +SELECT [s].[Id], [s].[NestedId], [s].[OfferId], [s].[payment_brutto], [s].[payment_netto], [s].[Id0], [s].[payment_brutto0], [s].[payment_netto0], [o].[Id] +FROM [Offers] AS [o] +INNER JOIN ( + SELECT [v].[Id], [v].[NestedId], [v].[OfferId], [v].[payment_brutto], [v].[payment_netto], [n].[Id] AS [Id0], [n].[payment_brutto] AS [payment_brutto0], [n].[payment_netto] AS [payment_netto0] + FROM [Variation] AS [v] + LEFT JOIN [NestedEntity] AS [n] ON [v].[NestedId] = [n].[Id] +) AS [s] ON [o].[Id] = [s].[OfferId] +ORDER BY [o].[Id] +"""); + } + + public override async Task Two_similar_complex_properties_projected_with_split_query2() + { + await base.Two_similar_complex_properties_projected_with_split_query2(); + + AssertSql( +""" +SELECT TOP(2) [o].[Id] +FROM [Offers] AS [o] +WHERE [o].[Id] = 1 +ORDER BY [o].[Id] +""", + // + """ +SELECT [s].[Id], [s].[NestedId], [s].[OfferId], [s].[payment_brutto], [s].[payment_netto], [s].[Id0], [s].[payment_brutto0], [s].[payment_netto0], [o0].[Id] +FROM ( + SELECT TOP(1) [o].[Id] + FROM [Offers] AS [o] + WHERE [o].[Id] = 1 +) AS [o0] +INNER JOIN ( + SELECT [v].[Id], [v].[NestedId], [v].[OfferId], [v].[payment_brutto], [v].[payment_netto], [n].[Id] AS [Id0], [n].[payment_brutto] AS [payment_brutto0], [n].[payment_netto] AS [payment_netto0] + FROM [Variation] AS [v] + LEFT JOIN [NestedEntity] AS [n] ON [v].[NestedId] = [n].[Id] +) AS [s] ON [o0].[Id] = [s].[OfferId] +ORDER BY [o0].[Id] """); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs index 9060eebbad9..56719f73de4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs @@ -859,6 +859,276 @@ FROM [Customer] AS [c] """).Select(c => c.ShippingAddress).Distinct(), ss => ss.Set().Select(c => c.ShippingAddress).Distinct()); + public override async Task Project_same_entity_with_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_entity_with_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT [s].[Id], [s].[Name], [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_Tags], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[ShippingAddress_AddressLine1], [s].[ShippingAddress_AddressLine2], [s].[ShippingAddress_Tags], [s].[ShippingAddress_ZipCode], [s].[ShippingAddress_Country_Code], [s].[ShippingAddress_Country_FullName], [s].[Id0], [s].[Name0], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_Tags0], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0], [s].[ShippingAddress_AddressLine10], [s].[ShippingAddress_AddressLine20], [s].[ShippingAddress_Tags0], [s].[ShippingAddress_ZipCode0], [s].[ShippingAddress_Country_Code0], [s].[ShippingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName], [c0].[Id] AS [Id0], [c0].[Name] AS [Name0], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c0].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c0].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c0].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c0].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c0].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c0].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] +) AS [s] +"""); + } + + public override async Task Project_same_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_Tags], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_Tags0], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] +) AS [s] +"""); + } + + public override async Task Project_same_entity_with_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_entity_with_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT [s0].[Id], [s0].[Name], [s0].[BillingAddress_AddressLine1], [s0].[BillingAddress_AddressLine2], [s0].[BillingAddress_Tags], [s0].[BillingAddress_ZipCode], [s0].[BillingAddress_Country_Code], [s0].[BillingAddress_Country_FullName], [s0].[ShippingAddress_AddressLine1], [s0].[ShippingAddress_AddressLine2], [s0].[ShippingAddress_Tags], [s0].[ShippingAddress_ZipCode], [s0].[ShippingAddress_Country_Code], [s0].[ShippingAddress_Country_FullName], [s0].[Id0], [s0].[Name0], [s0].[BillingAddress_AddressLine10], [s0].[BillingAddress_AddressLine20], [s0].[BillingAddress_Tags0], [s0].[BillingAddress_ZipCode0], [s0].[BillingAddress_Country_Code0], [s0].[BillingAddress_Country_FullName0], [s0].[ShippingAddress_AddressLine10], [s0].[ShippingAddress_AddressLine20], [s0].[ShippingAddress_Tags0], [s0].[ShippingAddress_ZipCode0], [s0].[ShippingAddress_Country_Code0], [s0].[ShippingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [s].[Id], [s].[Name], [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_Tags], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[ShippingAddress_AddressLine1], [s].[ShippingAddress_AddressLine2], [s].[ShippingAddress_Tags], [s].[ShippingAddress_ZipCode], [s].[ShippingAddress_Country_Code], [s].[ShippingAddress_Country_FullName], [s].[Id0], [s].[Name0], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_Tags0], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0], [s].[ShippingAddress_AddressLine10], [s].[ShippingAddress_AddressLine20], [s].[ShippingAddress_Tags0], [s].[ShippingAddress_ZipCode0], [s].[ShippingAddress_Country_Code0], [s].[ShippingAddress_Country_FullName0] + FROM ( + SELECT TOP(@__p_0) [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName], [c0].[Id] AS [Id0], [c0].[Name] AS [Name0], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c0].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c0].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c0].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c0].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c0].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c0].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] + ORDER BY [c].[Id], [c0].[Id] + ) AS [s] +) AS [s0] +"""); + } + + public override async Task Project_same_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT [s0].[BillingAddress_AddressLine1], [s0].[BillingAddress_AddressLine2], [s0].[BillingAddress_Tags], [s0].[BillingAddress_ZipCode], [s0].[BillingAddress_Country_Code], [s0].[BillingAddress_Country_FullName], [s0].[BillingAddress_AddressLine10], [s0].[BillingAddress_AddressLine20], [s0].[BillingAddress_Tags0], [s0].[BillingAddress_ZipCode0], [s0].[BillingAddress_Country_Code0], [s0].[BillingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_Tags], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_Tags0], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0] + FROM ( + SELECT TOP(@__p_0) [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] + ORDER BY [c].[Id], [c0].[Id] + ) AS [s] +) AS [s0] +"""); + } + + public override async Task Project_same_entity_with_struct_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_entity_with_struct_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT [s].[Id], [s].[Name], [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[ShippingAddress_AddressLine1], [s].[ShippingAddress_AddressLine2], [s].[ShippingAddress_ZipCode], [s].[ShippingAddress_Country_Code], [s].[ShippingAddress_Country_FullName], [s].[Id0], [s].[Name0], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0], [s].[ShippingAddress_AddressLine10], [s].[ShippingAddress_AddressLine20], [s].[ShippingAddress_ZipCode0], [s].[ShippingAddress_Country_Code0], [s].[ShippingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [v].[Id], [v].[Name], [v].[BillingAddress_AddressLine1], [v].[BillingAddress_AddressLine2], [v].[BillingAddress_ZipCode], [v].[BillingAddress_Country_Code], [v].[BillingAddress_Country_FullName], [v].[ShippingAddress_AddressLine1], [v].[ShippingAddress_AddressLine2], [v].[ShippingAddress_ZipCode], [v].[ShippingAddress_Country_Code], [v].[ShippingAddress_Country_FullName], [v0].[Id] AS [Id0], [v0].[Name] AS [Name0], [v0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [v0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [v0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [v0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [v0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [v0].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [v0].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [v0].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [v0].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [v0].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [ValuedCustomer] AS [v] + CROSS JOIN [ValuedCustomer] AS [v0] +) AS [s] +"""); + } + + public override async Task Project_same_struct_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_struct_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [v].[BillingAddress_AddressLine1], [v].[BillingAddress_AddressLine2], [v].[BillingAddress_ZipCode], [v].[BillingAddress_Country_Code], [v].[BillingAddress_Country_FullName], [v0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [v0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [v0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [v0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [v0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [ValuedCustomer] AS [v] + CROSS JOIN [ValuedCustomer] AS [v0] +) AS [s] +"""); + } + + public override async Task Project_same_entity_with_struct_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_entity_with_struct_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT [s0].[Id], [s0].[Name], [s0].[BillingAddress_AddressLine1], [s0].[BillingAddress_AddressLine2], [s0].[BillingAddress_ZipCode], [s0].[BillingAddress_Country_Code], [s0].[BillingAddress_Country_FullName], [s0].[ShippingAddress_AddressLine1], [s0].[ShippingAddress_AddressLine2], [s0].[ShippingAddress_ZipCode], [s0].[ShippingAddress_Country_Code], [s0].[ShippingAddress_Country_FullName], [s0].[Id0], [s0].[Name0], [s0].[BillingAddress_AddressLine10], [s0].[BillingAddress_AddressLine20], [s0].[BillingAddress_ZipCode0], [s0].[BillingAddress_Country_Code0], [s0].[BillingAddress_Country_FullName0], [s0].[ShippingAddress_AddressLine10], [s0].[ShippingAddress_AddressLine20], [s0].[ShippingAddress_ZipCode0], [s0].[ShippingAddress_Country_Code0], [s0].[ShippingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [s].[Id], [s].[Name], [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[ShippingAddress_AddressLine1], [s].[ShippingAddress_AddressLine2], [s].[ShippingAddress_ZipCode], [s].[ShippingAddress_Country_Code], [s].[ShippingAddress_Country_FullName], [s].[Id0], [s].[Name0], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0], [s].[ShippingAddress_AddressLine10], [s].[ShippingAddress_AddressLine20], [s].[ShippingAddress_ZipCode0], [s].[ShippingAddress_Country_Code0], [s].[ShippingAddress_Country_FullName0] + FROM ( + SELECT TOP(@__p_0) [v].[Id], [v].[Name], [v].[BillingAddress_AddressLine1], [v].[BillingAddress_AddressLine2], [v].[BillingAddress_ZipCode], [v].[BillingAddress_Country_Code], [v].[BillingAddress_Country_FullName], [v].[ShippingAddress_AddressLine1], [v].[ShippingAddress_AddressLine2], [v].[ShippingAddress_ZipCode], [v].[ShippingAddress_Country_Code], [v].[ShippingAddress_Country_FullName], [v0].[Id] AS [Id0], [v0].[Name] AS [Name0], [v0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [v0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [v0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [v0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [v0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [v0].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [v0].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [v0].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [v0].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [v0].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [ValuedCustomer] AS [v] + CROSS JOIN [ValuedCustomer] AS [v0] + ORDER BY [v].[Id], [v0].[Id] + ) AS [s] +) AS [s0] +"""); + } + + public override async Task Project_same_struct_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_struct_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT [s0].[BillingAddress_AddressLine1], [s0].[BillingAddress_AddressLine2], [s0].[BillingAddress_ZipCode], [s0].[BillingAddress_Country_Code], [s0].[BillingAddress_Country_FullName], [s0].[BillingAddress_AddressLine10], [s0].[BillingAddress_AddressLine20], [s0].[BillingAddress_ZipCode0], [s0].[BillingAddress_Country_Code0], [s0].[BillingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0] + FROM ( + SELECT TOP(@__p_0) [v].[BillingAddress_AddressLine1], [v].[BillingAddress_AddressLine2], [v].[BillingAddress_ZipCode], [v].[BillingAddress_Country_Code], [v].[BillingAddress_Country_FullName], [v0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [v0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [v0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [v0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [v0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [ValuedCustomer] AS [v] + CROSS JOIN [ValuedCustomer] AS [v0] + ORDER BY [v].[Id], [v0].[Id] + ) AS [s] +) AS [s0] +"""); + } + + public override async Task Union_of_same_entity_with_nested_complex_type_projected_twice_with_pushdown(bool async) + { + await base.Union_of_same_entity_with_nested_complex_type_projected_twice_with_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT TOP(@__p_0) [u].[Id], [u].[Name], [u].[BillingAddress_AddressLine1], [u].[BillingAddress_AddressLine2], [u].[BillingAddress_Tags], [u].[BillingAddress_ZipCode], [u].[BillingAddress_Country_Code], [u].[BillingAddress_Country_FullName], [u].[ShippingAddress_AddressLine1], [u].[ShippingAddress_AddressLine2], [u].[ShippingAddress_Tags], [u].[ShippingAddress_ZipCode], [u].[ShippingAddress_Country_Code], [u].[ShippingAddress_Country_FullName], [u].[Id0], [u].[Name0], [u].[BillingAddress_AddressLine10], [u].[BillingAddress_AddressLine20], [u].[BillingAddress_Tags0], [u].[BillingAddress_ZipCode0], [u].[BillingAddress_Country_Code0], [u].[BillingAddress_Country_FullName0], [u].[ShippingAddress_AddressLine10], [u].[ShippingAddress_AddressLine20], [u].[ShippingAddress_Tags0], [u].[ShippingAddress_ZipCode0], [u].[ShippingAddress_Country_Code0], [u].[ShippingAddress_Country_FullName0] +FROM ( + SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName], [c0].[Id] AS [Id0], [c0].[Name] AS [Name0], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c0].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c0].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c0].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c0].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c0].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c0].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] + UNION + SELECT [c1].[Id], [c1].[Name], [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_Tags], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c1].[ShippingAddress_AddressLine1], [c1].[ShippingAddress_AddressLine2], [c1].[ShippingAddress_Tags], [c1].[ShippingAddress_ZipCode], [c1].[ShippingAddress_Country_Code], [c1].[ShippingAddress_Country_FullName], [c2].[Id] AS [Id0], [c2].[Name] AS [Name0], [c2].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c2].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c2].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c2].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c2].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c2].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c2].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c2].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c2].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c2].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c2].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c2].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [Customer] AS [c1] + CROSS JOIN [Customer] AS [c2] +) AS [u] +ORDER BY [u].[Id], [u].[Id0] +"""); + } + + public override async Task Union_of_same_entity_with_nested_complex_type_projected_twice_with_double_pushdown(bool async) + { + await base.Union_of_same_entity_with_nested_complex_type_projected_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT TOP(@__p_0) [u1].[Id], [u1].[Name], [u1].[BillingAddress_AddressLine1], [u1].[BillingAddress_AddressLine2], [u1].[BillingAddress_Tags], [u1].[BillingAddress_ZipCode], [u1].[BillingAddress_Country_Code], [u1].[BillingAddress_Country_FullName], [u1].[ShippingAddress_AddressLine1], [u1].[ShippingAddress_AddressLine2], [u1].[ShippingAddress_Tags], [u1].[ShippingAddress_ZipCode], [u1].[ShippingAddress_Country_Code], [u1].[ShippingAddress_Country_FullName], [u1].[Id0], [u1].[Name0], [u1].[BillingAddress_AddressLine10], [u1].[BillingAddress_AddressLine20], [u1].[BillingAddress_Tags0], [u1].[BillingAddress_ZipCode0], [u1].[BillingAddress_Country_Code0], [u1].[BillingAddress_Country_FullName0], [u1].[ShippingAddress_AddressLine10], [u1].[ShippingAddress_AddressLine20], [u1].[ShippingAddress_Tags0], [u1].[ShippingAddress_ZipCode0], [u1].[ShippingAddress_Country_Code0], [u1].[ShippingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [u0].[Id], [u0].[Name], [u0].[BillingAddress_AddressLine1], [u0].[BillingAddress_AddressLine2], [u0].[BillingAddress_Tags], [u0].[BillingAddress_ZipCode], [u0].[BillingAddress_Country_Code], [u0].[BillingAddress_Country_FullName], [u0].[ShippingAddress_AddressLine1], [u0].[ShippingAddress_AddressLine2], [u0].[ShippingAddress_Tags], [u0].[ShippingAddress_ZipCode], [u0].[ShippingAddress_Country_Code], [u0].[ShippingAddress_Country_FullName], [u0].[Id0], [u0].[Name0], [u0].[BillingAddress_AddressLine10], [u0].[BillingAddress_AddressLine20], [u0].[BillingAddress_Tags0], [u0].[BillingAddress_ZipCode0], [u0].[BillingAddress_Country_Code0], [u0].[BillingAddress_Country_FullName0], [u0].[ShippingAddress_AddressLine10], [u0].[ShippingAddress_AddressLine20], [u0].[ShippingAddress_Tags0], [u0].[ShippingAddress_ZipCode0], [u0].[ShippingAddress_Country_Code0], [u0].[ShippingAddress_Country_FullName0] + FROM ( + SELECT TOP(@__p_0) [u].[Id], [u].[Name], [u].[BillingAddress_AddressLine1], [u].[BillingAddress_AddressLine2], [u].[BillingAddress_Tags], [u].[BillingAddress_ZipCode], [u].[BillingAddress_Country_Code], [u].[BillingAddress_Country_FullName], [u].[ShippingAddress_AddressLine1], [u].[ShippingAddress_AddressLine2], [u].[ShippingAddress_Tags], [u].[ShippingAddress_ZipCode], [u].[ShippingAddress_Country_Code], [u].[ShippingAddress_Country_FullName], [u].[Id0], [u].[Name0], [u].[BillingAddress_AddressLine10], [u].[BillingAddress_AddressLine20], [u].[BillingAddress_Tags0], [u].[BillingAddress_ZipCode0], [u].[BillingAddress_Country_Code0], [u].[BillingAddress_Country_FullName0], [u].[ShippingAddress_AddressLine10], [u].[ShippingAddress_AddressLine20], [u].[ShippingAddress_Tags0], [u].[ShippingAddress_ZipCode0], [u].[ShippingAddress_Country_Code0], [u].[ShippingAddress_Country_FullName0] + FROM ( + SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName], [c0].[Id] AS [Id0], [c0].[Name] AS [Name0], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c0].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c0].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c0].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c0].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c0].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c0].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] + UNION + SELECT [c1].[Id], [c1].[Name], [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_Tags], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c1].[ShippingAddress_AddressLine1], [c1].[ShippingAddress_AddressLine2], [c1].[ShippingAddress_Tags], [c1].[ShippingAddress_ZipCode], [c1].[ShippingAddress_Country_Code], [c1].[ShippingAddress_Country_FullName], [c2].[Id] AS [Id0], [c2].[Name] AS [Name0], [c2].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c2].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c2].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c2].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c2].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c2].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c2].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c2].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c2].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c2].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c2].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c2].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0] + FROM [Customer] AS [c1] + CROSS JOIN [Customer] AS [c2] + ) AS [u] + ORDER BY [u].[Id], [u].[Id0] + ) AS [u0] +) AS [u1] +ORDER BY [u1].[Id], [u1].[Id0] +"""); + } + + public override async Task Union_of_same_nested_complex_type_projected_twice_with_pushdown(bool async) + { + await base.Union_of_same_nested_complex_type_projected_twice_with_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT TOP(@__p_0) [u].[BillingAddress_AddressLine1], [u].[BillingAddress_AddressLine2], [u].[BillingAddress_Tags], [u].[BillingAddress_ZipCode], [u].[BillingAddress_Country_Code], [u].[BillingAddress_Country_FullName], [u].[BillingAddress_AddressLine10], [u].[BillingAddress_AddressLine20], [u].[BillingAddress_Tags0], [u].[BillingAddress_ZipCode0], [u].[BillingAddress_Country_Code0], [u].[BillingAddress_Country_FullName0] +FROM ( + SELECT [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] + UNION + SELECT [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_Tags], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c2].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c2].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c2].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c2].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c2].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c2].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [Customer] AS [c1] + CROSS JOIN [Customer] AS [c2] +) AS [u] +ORDER BY [u].[BillingAddress_ZipCode], [u].[BillingAddress_ZipCode0] +"""); + } + + public override async Task Union_of_same_nested_complex_type_projected_twice_with_double_pushdown(bool async) + { + await base.Union_of_same_nested_complex_type_projected_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT TOP(@__p_0) [u1].[BillingAddress_AddressLine1], [u1].[BillingAddress_AddressLine2], [u1].[BillingAddress_Tags], [u1].[BillingAddress_ZipCode], [u1].[BillingAddress_Country_Code], [u1].[BillingAddress_Country_FullName], [u1].[BillingAddress_AddressLine10], [u1].[BillingAddress_AddressLine20], [u1].[BillingAddress_Tags0], [u1].[BillingAddress_ZipCode0], [u1].[BillingAddress_Country_Code0], [u1].[BillingAddress_Country_FullName0] +FROM ( + SELECT DISTINCT [u0].[BillingAddress_AddressLine1], [u0].[BillingAddress_AddressLine2], [u0].[BillingAddress_Tags], [u0].[BillingAddress_ZipCode], [u0].[BillingAddress_Country_Code], [u0].[BillingAddress_Country_FullName], [u0].[BillingAddress_AddressLine10], [u0].[BillingAddress_AddressLine20], [u0].[BillingAddress_Tags0], [u0].[BillingAddress_ZipCode0], [u0].[BillingAddress_Country_Code0], [u0].[BillingAddress_Country_FullName0] + FROM ( + SELECT TOP(@__p_0) [u].[BillingAddress_AddressLine1], [u].[BillingAddress_AddressLine2], [u].[BillingAddress_Tags], [u].[BillingAddress_ZipCode], [u].[BillingAddress_Country_Code], [u].[BillingAddress_Country_FullName], [u].[BillingAddress_AddressLine10], [u].[BillingAddress_AddressLine20], [u].[BillingAddress_Tags0], [u].[BillingAddress_ZipCode0], [u].[BillingAddress_Country_Code0], [u].[BillingAddress_Country_FullName0] + FROM ( + SELECT [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c0].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c0].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c0].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c0].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c0].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c0].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [Customer] AS [c] + CROSS JOIN [Customer] AS [c0] + UNION + SELECT [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_Tags], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c2].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c2].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c2].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c2].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c2].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c2].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0] + FROM [Customer] AS [c1] + CROSS JOIN [Customer] AS [c2] + ) AS [u] + ORDER BY [u].[BillingAddress_ZipCode], [u].[BillingAddress_ZipCode0] + ) AS [u0] +) AS [u1] +ORDER BY [u1].[BillingAddress_ZipCode], [u1].[BillingAddress_ZipCode0] +"""); + } + + public override async Task Same_entity_with_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(bool async) + { + await base.Same_entity_with_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(async); + + AssertSql( +""" +SELECT [c].[Id], [s].[Id], [s].[Name], [s].[BillingAddress_AddressLine1], [s].[BillingAddress_AddressLine2], [s].[BillingAddress_Tags], [s].[BillingAddress_ZipCode], [s].[BillingAddress_Country_Code], [s].[BillingAddress_Country_FullName], [s].[ShippingAddress_AddressLine1], [s].[ShippingAddress_AddressLine2], [s].[ShippingAddress_Tags], [s].[ShippingAddress_ZipCode], [s].[ShippingAddress_Country_Code], [s].[ShippingAddress_Country_FullName], [s].[Id0], [s].[Name0], [s].[BillingAddress_AddressLine10], [s].[BillingAddress_AddressLine20], [s].[BillingAddress_Tags0], [s].[BillingAddress_ZipCode0], [s].[BillingAddress_Country_Code0], [s].[BillingAddress_Country_FullName0], [s].[ShippingAddress_AddressLine10], [s].[ShippingAddress_AddressLine20], [s].[ShippingAddress_Tags0], [s].[ShippingAddress_ZipCode0], [s].[ShippingAddress_Country_Code0], [s].[ShippingAddress_Country_FullName0], [s].[c] +FROM [Customer] AS [c] +OUTER APPLY ( + SELECT TOP(1) [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_Tags], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName], [c1].[Id] AS [Id0], [c1].[Name] AS [Name0], [c1].[BillingAddress_AddressLine1] AS [BillingAddress_AddressLine10], [c1].[BillingAddress_AddressLine2] AS [BillingAddress_AddressLine20], [c1].[BillingAddress_Tags] AS [BillingAddress_Tags0], [c1].[BillingAddress_ZipCode] AS [BillingAddress_ZipCode0], [c1].[BillingAddress_Country_Code] AS [BillingAddress_Country_Code0], [c1].[BillingAddress_Country_FullName] AS [BillingAddress_Country_FullName0], [c1].[ShippingAddress_AddressLine1] AS [ShippingAddress_AddressLine10], [c1].[ShippingAddress_AddressLine2] AS [ShippingAddress_AddressLine20], [c1].[ShippingAddress_Tags] AS [ShippingAddress_Tags0], [c1].[ShippingAddress_ZipCode] AS [ShippingAddress_ZipCode0], [c1].[ShippingAddress_Country_Code] AS [ShippingAddress_Country_Code0], [c1].[ShippingAddress_Country_FullName] AS [ShippingAddress_Country_FullName0], 1 AS [c] + FROM [Customer] AS [c0] + CROSS JOIN [Customer] AS [c1] + ORDER BY [c0].[Id], [c1].[Id] DESC +) AS [s] +"""); + } + + public override async Task Same_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(bool async) + { + await base.Same_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(async); + + AssertSql(""); + } + [ConditionalFact] public virtual void Check_all_tests_overridden() => TestHelpers.AssertAllMethodsOverridden(GetType()); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqliteTest.cs index 2e0852f0dbd..1807f23b4a2 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/AdHocAdvancedMappingsQuerySqliteTest.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.ComponentModel.DataAnnotations; - namespace Microsoft.EntityFrameworkCore.Query; public class AdHocAdvancedMappingsQuerySqliteTest : AdHocAdvancedMappingsQueryRelationalTestBase diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs index 0e2239a3b41..af256a93e2f 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Sqlite.Internal; + namespace Microsoft.EntityFrameworkCore.Query; public class ComplexTypeQuerySqliteTest : ComplexTypeQueryRelationalTestBase< @@ -742,6 +744,274 @@ public override async Task Union_two_different_struct_complex_type(bool async) AssertSql(); } + public override async Task Project_same_entity_with_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_entity_with_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT "s"."Id", "s"."Name", "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_Tags", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."ShippingAddress_AddressLine1", "s"."ShippingAddress_AddressLine2", "s"."ShippingAddress_Tags", "s"."ShippingAddress_ZipCode", "s"."ShippingAddress_Country_Code", "s"."ShippingAddress_Country_FullName", "s"."Id0", "s"."Name0", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_Tags0", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0", "s"."ShippingAddress_AddressLine10", "s"."ShippingAddress_AddressLine20", "s"."ShippingAddress_Tags0", "s"."ShippingAddress_ZipCode0", "s"."ShippingAddress_Country_Code0", "s"."ShippingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName", "c0"."Id" AS "Id0", "c0"."Name" AS "Name0", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "c0"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "c0"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "c0"."ShippingAddress_Tags" AS "ShippingAddress_Tags0", "c0"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "c0"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "c0"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" +) AS "s" +"""); + } + + public override async Task Project_same_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_Tags", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_Tags0", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" +) AS "s" +"""); + } + + public override async Task Project_same_entity_with_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_entity_with_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "s0"."Id", "s0"."Name", "s0"."BillingAddress_AddressLine1", "s0"."BillingAddress_AddressLine2", "s0"."BillingAddress_Tags", "s0"."BillingAddress_ZipCode", "s0"."BillingAddress_Country_Code", "s0"."BillingAddress_Country_FullName", "s0"."ShippingAddress_AddressLine1", "s0"."ShippingAddress_AddressLine2", "s0"."ShippingAddress_Tags", "s0"."ShippingAddress_ZipCode", "s0"."ShippingAddress_Country_Code", "s0"."ShippingAddress_Country_FullName", "s0"."Id0", "s0"."Name0", "s0"."BillingAddress_AddressLine10", "s0"."BillingAddress_AddressLine20", "s0"."BillingAddress_Tags0", "s0"."BillingAddress_ZipCode0", "s0"."BillingAddress_Country_Code0", "s0"."BillingAddress_Country_FullName0", "s0"."ShippingAddress_AddressLine10", "s0"."ShippingAddress_AddressLine20", "s0"."ShippingAddress_Tags0", "s0"."ShippingAddress_ZipCode0", "s0"."ShippingAddress_Country_Code0", "s0"."ShippingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "s"."Id", "s"."Name", "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_Tags", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."ShippingAddress_AddressLine1", "s"."ShippingAddress_AddressLine2", "s"."ShippingAddress_Tags", "s"."ShippingAddress_ZipCode", "s"."ShippingAddress_Country_Code", "s"."ShippingAddress_Country_FullName", "s"."Id0", "s"."Name0", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_Tags0", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0", "s"."ShippingAddress_AddressLine10", "s"."ShippingAddress_AddressLine20", "s"."ShippingAddress_Tags0", "s"."ShippingAddress_ZipCode0", "s"."ShippingAddress_Country_Code0", "s"."ShippingAddress_Country_FullName0" + FROM ( + SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName", "c0"."Id" AS "Id0", "c0"."Name" AS "Name0", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "c0"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "c0"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "c0"."ShippingAddress_Tags" AS "ShippingAddress_Tags0", "c0"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "c0"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "c0"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" + ORDER BY "c"."Id", "c0"."Id" + LIMIT @__p_0 + ) AS "s" +) AS "s0" +"""); + } + + public override async Task Project_same_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "s0"."BillingAddress_AddressLine1", "s0"."BillingAddress_AddressLine2", "s0"."BillingAddress_Tags", "s0"."BillingAddress_ZipCode", "s0"."BillingAddress_Country_Code", "s0"."BillingAddress_Country_FullName", "s0"."BillingAddress_AddressLine10", "s0"."BillingAddress_AddressLine20", "s0"."BillingAddress_Tags0", "s0"."BillingAddress_ZipCode0", "s0"."BillingAddress_Country_Code0", "s0"."BillingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_Tags", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_Tags0", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0" + FROM ( + SELECT "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" + ORDER BY "c"."Id", "c0"."Id" + LIMIT @__p_0 + ) AS "s" +) AS "s0" +"""); + } + + public override async Task Project_same_entity_with_struct_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_entity_with_struct_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT "s"."Id", "s"."Name", "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."ShippingAddress_AddressLine1", "s"."ShippingAddress_AddressLine2", "s"."ShippingAddress_ZipCode", "s"."ShippingAddress_Country_Code", "s"."ShippingAddress_Country_FullName", "s"."Id0", "s"."Name0", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0", "s"."ShippingAddress_AddressLine10", "s"."ShippingAddress_AddressLine20", "s"."ShippingAddress_ZipCode0", "s"."ShippingAddress_Country_Code0", "s"."ShippingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "v"."Id", "v"."Name", "v"."BillingAddress_AddressLine1", "v"."BillingAddress_AddressLine2", "v"."BillingAddress_ZipCode", "v"."BillingAddress_Country_Code", "v"."BillingAddress_Country_FullName", "v"."ShippingAddress_AddressLine1", "v"."ShippingAddress_AddressLine2", "v"."ShippingAddress_ZipCode", "v"."ShippingAddress_Country_Code", "v"."ShippingAddress_Country_FullName", "v0"."Id" AS "Id0", "v0"."Name" AS "Name0", "v0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "v0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "v0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "v0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "v0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "v0"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "v0"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "v0"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "v0"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "v0"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "ValuedCustomer" AS "v" + CROSS JOIN "ValuedCustomer" AS "v0" +) AS "s" +"""); + } + + public override async Task Project_same_struct_nested_complex_type_twice_with_pushdown(bool async) + { + await base.Project_same_struct_nested_complex_type_twice_with_pushdown(async); + + AssertSql( +""" +SELECT "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "v"."BillingAddress_AddressLine1", "v"."BillingAddress_AddressLine2", "v"."BillingAddress_ZipCode", "v"."BillingAddress_Country_Code", "v"."BillingAddress_Country_FullName", "v0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "v0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "v0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "v0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "v0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "ValuedCustomer" AS "v" + CROSS JOIN "ValuedCustomer" AS "v0" +) AS "s" +"""); + } + + public override async Task Project_same_entity_with_struct_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_entity_with_struct_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "s0"."Id", "s0"."Name", "s0"."BillingAddress_AddressLine1", "s0"."BillingAddress_AddressLine2", "s0"."BillingAddress_ZipCode", "s0"."BillingAddress_Country_Code", "s0"."BillingAddress_Country_FullName", "s0"."ShippingAddress_AddressLine1", "s0"."ShippingAddress_AddressLine2", "s0"."ShippingAddress_ZipCode", "s0"."ShippingAddress_Country_Code", "s0"."ShippingAddress_Country_FullName", "s0"."Id0", "s0"."Name0", "s0"."BillingAddress_AddressLine10", "s0"."BillingAddress_AddressLine20", "s0"."BillingAddress_ZipCode0", "s0"."BillingAddress_Country_Code0", "s0"."BillingAddress_Country_FullName0", "s0"."ShippingAddress_AddressLine10", "s0"."ShippingAddress_AddressLine20", "s0"."ShippingAddress_ZipCode0", "s0"."ShippingAddress_Country_Code0", "s0"."ShippingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "s"."Id", "s"."Name", "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."ShippingAddress_AddressLine1", "s"."ShippingAddress_AddressLine2", "s"."ShippingAddress_ZipCode", "s"."ShippingAddress_Country_Code", "s"."ShippingAddress_Country_FullName", "s"."Id0", "s"."Name0", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0", "s"."ShippingAddress_AddressLine10", "s"."ShippingAddress_AddressLine20", "s"."ShippingAddress_ZipCode0", "s"."ShippingAddress_Country_Code0", "s"."ShippingAddress_Country_FullName0" + FROM ( + SELECT "v"."Id", "v"."Name", "v"."BillingAddress_AddressLine1", "v"."BillingAddress_AddressLine2", "v"."BillingAddress_ZipCode", "v"."BillingAddress_Country_Code", "v"."BillingAddress_Country_FullName", "v"."ShippingAddress_AddressLine1", "v"."ShippingAddress_AddressLine2", "v"."ShippingAddress_ZipCode", "v"."ShippingAddress_Country_Code", "v"."ShippingAddress_Country_FullName", "v0"."Id" AS "Id0", "v0"."Name" AS "Name0", "v0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "v0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "v0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "v0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "v0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "v0"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "v0"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "v0"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "v0"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "v0"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "ValuedCustomer" AS "v" + CROSS JOIN "ValuedCustomer" AS "v0" + ORDER BY "v"."Id", "v0"."Id" + LIMIT @__p_0 + ) AS "s" +) AS "s0" +"""); + } + + public override async Task Project_same_struct_nested_complex_type_twice_with_double_pushdown(bool async) + { + await base.Project_same_struct_nested_complex_type_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "s0"."BillingAddress_AddressLine1", "s0"."BillingAddress_AddressLine2", "s0"."BillingAddress_ZipCode", "s0"."BillingAddress_Country_Code", "s0"."BillingAddress_Country_FullName", "s0"."BillingAddress_AddressLine10", "s0"."BillingAddress_AddressLine20", "s0"."BillingAddress_ZipCode0", "s0"."BillingAddress_Country_Code0", "s0"."BillingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "s"."BillingAddress_AddressLine1", "s"."BillingAddress_AddressLine2", "s"."BillingAddress_ZipCode", "s"."BillingAddress_Country_Code", "s"."BillingAddress_Country_FullName", "s"."BillingAddress_AddressLine10", "s"."BillingAddress_AddressLine20", "s"."BillingAddress_ZipCode0", "s"."BillingAddress_Country_Code0", "s"."BillingAddress_Country_FullName0" + FROM ( + SELECT "v"."BillingAddress_AddressLine1", "v"."BillingAddress_AddressLine2", "v"."BillingAddress_ZipCode", "v"."BillingAddress_Country_Code", "v"."BillingAddress_Country_FullName", "v0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "v0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "v0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "v0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "v0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "ValuedCustomer" AS "v" + CROSS JOIN "ValuedCustomer" AS "v0" + ORDER BY "v"."Id", "v0"."Id" + LIMIT @__p_0 + ) AS "s" +) AS "s0" +"""); + } + + public override async Task Union_of_same_entity_with_nested_complex_type_projected_twice_with_pushdown(bool async) + { + await base.Union_of_same_entity_with_nested_complex_type_projected_twice_with_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "u"."Id", "u"."Name", "u"."BillingAddress_AddressLine1", "u"."BillingAddress_AddressLine2", "u"."BillingAddress_Tags", "u"."BillingAddress_ZipCode", "u"."BillingAddress_Country_Code", "u"."BillingAddress_Country_FullName", "u"."ShippingAddress_AddressLine1", "u"."ShippingAddress_AddressLine2", "u"."ShippingAddress_Tags", "u"."ShippingAddress_ZipCode", "u"."ShippingAddress_Country_Code", "u"."ShippingAddress_Country_FullName", "u"."Id0", "u"."Name0", "u"."BillingAddress_AddressLine10", "u"."BillingAddress_AddressLine20", "u"."BillingAddress_Tags0", "u"."BillingAddress_ZipCode0", "u"."BillingAddress_Country_Code0", "u"."BillingAddress_Country_FullName0", "u"."ShippingAddress_AddressLine10", "u"."ShippingAddress_AddressLine20", "u"."ShippingAddress_Tags0", "u"."ShippingAddress_ZipCode0", "u"."ShippingAddress_Country_Code0", "u"."ShippingAddress_Country_FullName0" +FROM ( + SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName", "c0"."Id" AS "Id0", "c0"."Name" AS "Name0", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "c0"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "c0"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "c0"."ShippingAddress_Tags" AS "ShippingAddress_Tags0", "c0"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "c0"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "c0"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" + UNION + SELECT "c1"."Id", "c1"."Name", "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_Tags", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c1"."ShippingAddress_AddressLine1", "c1"."ShippingAddress_AddressLine2", "c1"."ShippingAddress_Tags", "c1"."ShippingAddress_ZipCode", "c1"."ShippingAddress_Country_Code", "c1"."ShippingAddress_Country_FullName", "c2"."Id" AS "Id0", "c2"."Name" AS "Name0", "c2"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c2"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c2"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c2"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c2"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c2"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "c2"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "c2"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "c2"."ShippingAddress_Tags" AS "ShippingAddress_Tags0", "c2"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "c2"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "c2"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "Customer" AS "c1" + CROSS JOIN "Customer" AS "c2" +) AS "u" +ORDER BY "u"."Id", "u"."Id0" +LIMIT @__p_0 +"""); + } + + public override async Task Union_of_same_entity_with_nested_complex_type_projected_twice_with_double_pushdown(bool async) + { + await base.Union_of_same_entity_with_nested_complex_type_projected_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "u1"."Id", "u1"."Name", "u1"."BillingAddress_AddressLine1", "u1"."BillingAddress_AddressLine2", "u1"."BillingAddress_Tags", "u1"."BillingAddress_ZipCode", "u1"."BillingAddress_Country_Code", "u1"."BillingAddress_Country_FullName", "u1"."ShippingAddress_AddressLine1", "u1"."ShippingAddress_AddressLine2", "u1"."ShippingAddress_Tags", "u1"."ShippingAddress_ZipCode", "u1"."ShippingAddress_Country_Code", "u1"."ShippingAddress_Country_FullName", "u1"."Id0", "u1"."Name0", "u1"."BillingAddress_AddressLine10", "u1"."BillingAddress_AddressLine20", "u1"."BillingAddress_Tags0", "u1"."BillingAddress_ZipCode0", "u1"."BillingAddress_Country_Code0", "u1"."BillingAddress_Country_FullName0", "u1"."ShippingAddress_AddressLine10", "u1"."ShippingAddress_AddressLine20", "u1"."ShippingAddress_Tags0", "u1"."ShippingAddress_ZipCode0", "u1"."ShippingAddress_Country_Code0", "u1"."ShippingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "u0"."Id", "u0"."Name", "u0"."BillingAddress_AddressLine1", "u0"."BillingAddress_AddressLine2", "u0"."BillingAddress_Tags", "u0"."BillingAddress_ZipCode", "u0"."BillingAddress_Country_Code", "u0"."BillingAddress_Country_FullName", "u0"."ShippingAddress_AddressLine1", "u0"."ShippingAddress_AddressLine2", "u0"."ShippingAddress_Tags", "u0"."ShippingAddress_ZipCode", "u0"."ShippingAddress_Country_Code", "u0"."ShippingAddress_Country_FullName", "u0"."Id0", "u0"."Name0", "u0"."BillingAddress_AddressLine10", "u0"."BillingAddress_AddressLine20", "u0"."BillingAddress_Tags0", "u0"."BillingAddress_ZipCode0", "u0"."BillingAddress_Country_Code0", "u0"."BillingAddress_Country_FullName0", "u0"."ShippingAddress_AddressLine10", "u0"."ShippingAddress_AddressLine20", "u0"."ShippingAddress_Tags0", "u0"."ShippingAddress_ZipCode0", "u0"."ShippingAddress_Country_Code0", "u0"."ShippingAddress_Country_FullName0" + FROM ( + SELECT "u"."Id", "u"."Name", "u"."BillingAddress_AddressLine1", "u"."BillingAddress_AddressLine2", "u"."BillingAddress_Tags", "u"."BillingAddress_ZipCode", "u"."BillingAddress_Country_Code", "u"."BillingAddress_Country_FullName", "u"."ShippingAddress_AddressLine1", "u"."ShippingAddress_AddressLine2", "u"."ShippingAddress_Tags", "u"."ShippingAddress_ZipCode", "u"."ShippingAddress_Country_Code", "u"."ShippingAddress_Country_FullName", "u"."Id0", "u"."Name0", "u"."BillingAddress_AddressLine10", "u"."BillingAddress_AddressLine20", "u"."BillingAddress_Tags0", "u"."BillingAddress_ZipCode0", "u"."BillingAddress_Country_Code0", "u"."BillingAddress_Country_FullName0", "u"."ShippingAddress_AddressLine10", "u"."ShippingAddress_AddressLine20", "u"."ShippingAddress_Tags0", "u"."ShippingAddress_ZipCode0", "u"."ShippingAddress_Country_Code0", "u"."ShippingAddress_Country_FullName0" + FROM ( + SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName", "c0"."Id" AS "Id0", "c0"."Name" AS "Name0", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "c0"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "c0"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "c0"."ShippingAddress_Tags" AS "ShippingAddress_Tags0", "c0"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "c0"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "c0"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" + UNION + SELECT "c1"."Id", "c1"."Name", "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_Tags", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c1"."ShippingAddress_AddressLine1", "c1"."ShippingAddress_AddressLine2", "c1"."ShippingAddress_Tags", "c1"."ShippingAddress_ZipCode", "c1"."ShippingAddress_Country_Code", "c1"."ShippingAddress_Country_FullName", "c2"."Id" AS "Id0", "c2"."Name" AS "Name0", "c2"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c2"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c2"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c2"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c2"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c2"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0", "c2"."ShippingAddress_AddressLine1" AS "ShippingAddress_AddressLine10", "c2"."ShippingAddress_AddressLine2" AS "ShippingAddress_AddressLine20", "c2"."ShippingAddress_Tags" AS "ShippingAddress_Tags0", "c2"."ShippingAddress_ZipCode" AS "ShippingAddress_ZipCode0", "c2"."ShippingAddress_Country_Code" AS "ShippingAddress_Country_Code0", "c2"."ShippingAddress_Country_FullName" AS "ShippingAddress_Country_FullName0" + FROM "Customer" AS "c1" + CROSS JOIN "Customer" AS "c2" + ) AS "u" + ORDER BY "u"."Id", "u"."Id0" + LIMIT @__p_0 + ) AS "u0" +) AS "u1" +ORDER BY "u1"."Id", "u1"."Id0" +LIMIT @__p_0 +"""); + } + + public override async Task Union_of_same_nested_complex_type_projected_twice_with_pushdown(bool async) + { + await base.Union_of_same_nested_complex_type_projected_twice_with_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "u"."BillingAddress_AddressLine1", "u"."BillingAddress_AddressLine2", "u"."BillingAddress_Tags", "u"."BillingAddress_ZipCode", "u"."BillingAddress_Country_Code", "u"."BillingAddress_Country_FullName", "u"."BillingAddress_AddressLine10", "u"."BillingAddress_AddressLine20", "u"."BillingAddress_Tags0", "u"."BillingAddress_ZipCode0", "u"."BillingAddress_Country_Code0", "u"."BillingAddress_Country_FullName0" +FROM ( + SELECT "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" + UNION + SELECT "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_Tags", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c2"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c2"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c2"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c2"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c2"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c2"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "Customer" AS "c1" + CROSS JOIN "Customer" AS "c2" +) AS "u" +ORDER BY "u"."BillingAddress_ZipCode", "u"."BillingAddress_ZipCode0" +LIMIT @__p_0 +"""); + } + + public override async Task Union_of_same_nested_complex_type_projected_twice_with_double_pushdown(bool async) + { + await base.Union_of_same_nested_complex_type_projected_twice_with_double_pushdown(async); + + AssertSql( +""" +@__p_0='50' + +SELECT "u1"."BillingAddress_AddressLine1", "u1"."BillingAddress_AddressLine2", "u1"."BillingAddress_Tags", "u1"."BillingAddress_ZipCode", "u1"."BillingAddress_Country_Code", "u1"."BillingAddress_Country_FullName", "u1"."BillingAddress_AddressLine10", "u1"."BillingAddress_AddressLine20", "u1"."BillingAddress_Tags0", "u1"."BillingAddress_ZipCode0", "u1"."BillingAddress_Country_Code0", "u1"."BillingAddress_Country_FullName0" +FROM ( + SELECT DISTINCT "u0"."BillingAddress_AddressLine1", "u0"."BillingAddress_AddressLine2", "u0"."BillingAddress_Tags", "u0"."BillingAddress_ZipCode", "u0"."BillingAddress_Country_Code", "u0"."BillingAddress_Country_FullName", "u0"."BillingAddress_AddressLine10", "u0"."BillingAddress_AddressLine20", "u0"."BillingAddress_Tags0", "u0"."BillingAddress_ZipCode0", "u0"."BillingAddress_Country_Code0", "u0"."BillingAddress_Country_FullName0" + FROM ( + SELECT "u"."BillingAddress_AddressLine1", "u"."BillingAddress_AddressLine2", "u"."BillingAddress_Tags", "u"."BillingAddress_ZipCode", "u"."BillingAddress_Country_Code", "u"."BillingAddress_Country_FullName", "u"."BillingAddress_AddressLine10", "u"."BillingAddress_AddressLine20", "u"."BillingAddress_Tags0", "u"."BillingAddress_ZipCode0", "u"."BillingAddress_Country_Code0", "u"."BillingAddress_Country_FullName0" + FROM ( + SELECT "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c0"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c0"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c0"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c0"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c0"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c0"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "Customer" AS "c" + CROSS JOIN "Customer" AS "c0" + UNION + SELECT "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_Tags", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c2"."BillingAddress_AddressLine1" AS "BillingAddress_AddressLine10", "c2"."BillingAddress_AddressLine2" AS "BillingAddress_AddressLine20", "c2"."BillingAddress_Tags" AS "BillingAddress_Tags0", "c2"."BillingAddress_ZipCode" AS "BillingAddress_ZipCode0", "c2"."BillingAddress_Country_Code" AS "BillingAddress_Country_Code0", "c2"."BillingAddress_Country_FullName" AS "BillingAddress_Country_FullName0" + FROM "Customer" AS "c1" + CROSS JOIN "Customer" AS "c2" + ) AS "u" + ORDER BY "u"."BillingAddress_ZipCode", "u"."BillingAddress_ZipCode0" + LIMIT @__p_0 + ) AS "u0" +) AS "u1" +ORDER BY "u1"."BillingAddress_ZipCode", "u1"."BillingAddress_ZipCode0" +LIMIT @__p_0 +"""); + } + + public override async Task Same_entity_with_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Same_entity_with_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(async))).Message); + + public override async Task Same_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Same_complex_type_projected_twice_with_pushdown_as_part_of_another_projection(async))).Message); + [ConditionalFact] public virtual void Check_all_tests_overridden() => TestHelpers.AssertAllMethodsOverridden(GetType());