diff --git a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs index 90d76aa7b10..0f9e25cd343 100644 --- a/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs @@ -215,6 +215,6 @@ internal static IQueryable FromSqlOnQueryable( [NotParameterized] string sql, [NotNull] params object[] parameters) where TEntity : class - => throw new NotSupportedException(); + => throw new InvalidOperationException(); } } diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 25bc34b2bf2..84bb6ee8ae7 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -193,6 +193,16 @@ protected virtual void GenerateSetOperation(SelectExpression setOperationExpress Debug.Assert(setOperationExpression.Tables.Count == 2, $"{nameof(SelectExpression)} with {setOperationExpression.Tables.Count} tables, must be 2"); + static string GenerateSetOperationType(SetOperationType setOperationType) + => setOperationType switch + { + SetOperationType.Union => "UNION", + SetOperationType.UnionAll => "UNION ALL", + SetOperationType.Intersect => "INTERSECT", + SetOperationType.Except => "EXCEPT", + _ => throw new InvalidOperationException($"Invalid {nameof(SetOperationType)}: {setOperationType}") + }; + GenerateSetOperationOperand(setOperationExpression, (SelectExpression)setOperationExpression.Tables[0]); _relationalCommandBuilder @@ -205,16 +215,6 @@ protected virtual void GenerateSetOperation(SelectExpression setOperationExpress GenerateLimitOffset(setOperationExpression); } - private static string GenerateSetOperationType(SetOperationType setOperationType) - => setOperationType switch - { - SetOperationType.Union => "UNION", - SetOperationType.UnionAll => "UNION ALL", - SetOperationType.Intersect => "INTERSECT", - SetOperationType.Except => "EXCEPT", - _ => throw new NotSupportedException($"Invalid {nameof(SetOperationType)}: {setOperationType}") - }; - protected virtual void GenerateSetOperationOperand( SelectExpression setOperationExpression, SelectExpression operandExpression) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index dc5ac987be4..cc51c7371d3 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -959,51 +959,35 @@ private bool ContainsTableReference(TableExpressionBase table) ? ((SelectExpression)Tables[0]).ContainsTableReference(table) : Tables.Any(te => ReferenceEquals(te is JoinExpressionBase jeb ? jeb.Table : te, table)); - public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) + private enum JoinType { - if (Limit != null || Offset != null || IsDistinct || IsSetOperation || GroupBy.Count > 1) - { - joinPredicate = new SqlRemappingVisitor(PushdownIntoSubquery(), (SelectExpression)Tables[0]) - .Remap(joinPredicate); - } - - // TODO: write a test which has distinct on outer so that we can verify pushdown - if (innerSelectExpression.Orderings.Any() - || innerSelectExpression.Limit != null - || innerSelectExpression.Offset != null - || innerSelectExpression.IsDistinct - // TODO: Predicate can be lifted in inner join - || innerSelectExpression.Predicate != null - || innerSelectExpression.Tables.Count > 1 - || innerSelectExpression.GroupBy.Count > 1) - { - joinPredicate = new SqlRemappingVisitor( - innerSelectExpression.PushdownIntoSubquery(), (SelectExpression)innerSelectExpression.Tables[0]) - .Remap(joinPredicate); - } - - _identifier.AddRange(innerSelectExpression._identifier); - var joinTable = new InnerJoinExpression(innerSelectExpression.Tables.Single(), joinPredicate); - _tables.Add(joinTable); - - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var projectionMapping = new Dictionary(); - foreach (var projection in _projectionMapping) - { - projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; - } + InnerJoin, + LeftJoin, + CrossJoin, + InnerJoinLateral, + LeftJoinLateral + } - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); - foreach (var projection in innerSelectExpression._projectionMapping) + private void AddJoin( + JoinType joinType, + SelectExpression innerSelectExpression, + Type transparentIdentifierType, + SqlExpression joinPredicate = null) + { + // Try to convert lateral join to normal join + if (joinType == JoinType.InnerJoinLateral || joinType == JoinType.LeftJoinLateral) { - projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projection.Value; + joinPredicate = TryExtractJoinKey(innerSelectExpression); + // TODO: Make sure that innerSelectExpression does not contain any reference from this SelectExpression + if (joinPredicate != null) + { + AddJoin(joinType == JoinType.InnerJoinLateral ? JoinType.InnerJoin : JoinType.LeftJoin, + innerSelectExpression, transparentIdentifierType, joinPredicate); + return; + } } - _projectionMapping = projectionMapping; - } - - public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) - { + // Verify what are the cases of pushdown for inner & outer both sides if (Limit != null || Offset != null || IsDistinct || IsSetOperation || GroupBy.Count > 1) { joinPredicate = new SqlRemappingVisitor(PushdownIntoSubquery(), (SelectExpression)Tables[0]) @@ -1023,7 +1007,21 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo .Remap(joinPredicate); } - var joinTable = new LeftJoinExpression(innerSelectExpression.Tables.Single(), joinPredicate); + if (joinType != JoinType.LeftJoin) + { + _identifier.AddRange(innerSelectExpression._identifier); + } + var innerTable = innerSelectExpression.Tables.Single(); + var joinTable = (TableExpressionBase)(joinType switch + { + JoinType.InnerJoin => new InnerJoinExpression(innerTable, joinPredicate), + JoinType.LeftJoin => new LeftJoinExpression(innerTable, joinPredicate), + JoinType.CrossJoin => new CrossJoinExpression(innerTable), + JoinType.InnerJoinLateral => new InnerJoinLateralExpression(innerTable), + JoinType.LeftJoinLateral => new LeftJoinLateralExpression(innerTable), + _ => throw new InvalidOperationException($"Invalid {nameof(joinType)}: {joinType}") + }); + _tables.Add(joinTable); if (transparentIdentifierType != null) @@ -1036,18 +1034,21 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo } var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + var innerNullable = joinType == JoinType.LeftJoin || joinType == JoinType.LeftJoinLateral; foreach (var projection in innerSelectExpression._projectionMapping) { var projectionToAdd = projection.Value; - if (projectionToAdd is EntityProjectionExpression entityProjection) - { - projectionToAdd = entityProjection.MakeNullable(); - } - else if (projectionToAdd is ColumnExpression column) + if (innerNullable) { - projectionToAdd = column.MakeNullable(); + if (projectionToAdd is EntityProjectionExpression entityProjection) + { + projectionToAdd = entityProjection.MakeNullable(); + } + else if (projectionToAdd is ColumnExpression column) + { + projectionToAdd = column.MakeNullable(); + } } - projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projectionToAdd; } @@ -1055,146 +1056,29 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo } } - public void AddCrossJoin(SelectExpression innerSelectExpression, Type transparentIdentifierType) + public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) { - if (Limit != null || Offset != null || IsDistinct || Predicate != null || IsSetOperation || GroupBy.Count > 1) - { - PushdownIntoSubquery(); - } - - if (innerSelectExpression.Orderings.Any() - || innerSelectExpression.Limit != null - || innerSelectExpression.Offset != null - || innerSelectExpression.IsDistinct - || innerSelectExpression.Predicate != null - || innerSelectExpression.Tables.Count > 1 - || innerSelectExpression.GroupBy.Count > 1) - { - innerSelectExpression.PushdownIntoSubquery(); - } - - _identifier.AddRange(innerSelectExpression._identifier); - var joinTable = new CrossJoinExpression(innerSelectExpression.Tables.Single()); - _tables.Add(joinTable); - - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var projectionMapping = new Dictionary(); - foreach (var projection in _projectionMapping) - { - projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; - } + AddJoin(JoinType.InnerJoin, innerSelectExpression, transparentIdentifierType, joinPredicate); + } - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); - foreach (var projection in innerSelectExpression._projectionMapping) - { - projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projection.Value; - } + public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) + { + AddJoin(JoinType.LeftJoin, innerSelectExpression, transparentIdentifierType, joinPredicate); + } - _projectionMapping = projectionMapping; + public void AddCrossJoin(SelectExpression innerSelectExpression, Type transparentIdentifierType) + { + AddJoin(JoinType.CrossJoin, innerSelectExpression, transparentIdentifierType); } public void AddInnerJoinLateral(SelectExpression innerSelectExpression, Type transparentIdentifierType) { - var joinPredicate = TryExtractJoinKey(innerSelectExpression); - if (joinPredicate != null) - { - // TODO: Make sure that innerSelectExpression does not contain any reference from this SelectExpression - AddInnerJoin(innerSelectExpression, joinPredicate, transparentIdentifierType); - return; - } - - if (Limit != null || Offset != null || IsDistinct || Predicate != null || IsSetOperation || GroupBy.Count > 1) - { - innerSelectExpression = new SqlRemappingVisitor( - PushdownIntoSubquery(), (SelectExpression)Tables[0]).Remap(innerSelectExpression); - } - - if (innerSelectExpression.Orderings.Any() - || innerSelectExpression.Limit != null - || innerSelectExpression.Offset != null - || innerSelectExpression.IsDistinct - || innerSelectExpression.Predicate != null - || innerSelectExpression.Tables.Count > 1 - || innerSelectExpression.GroupBy.Count > 1) - { - innerSelectExpression.PushdownIntoSubquery(); - } - - _identifier.AddRange(innerSelectExpression._identifier); - var joinTable = new InnerJoinLateralExpression(innerSelectExpression.Tables.Single()); - _tables.Add(joinTable); - - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var projectionMapping = new Dictionary(); - foreach (var projection in _projectionMapping) - { - projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; - } - - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); - foreach (var projection in innerSelectExpression._projectionMapping) - { - projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projection.Value; - } - - _projectionMapping = projectionMapping; + AddJoin(JoinType.InnerJoinLateral, innerSelectExpression, transparentIdentifierType); } public void AddLeftJoinLateral(SelectExpression innerSelectExpression, Type transparentIdentifierType) { - var joinPredicate = TryExtractJoinKey(innerSelectExpression); - if (joinPredicate != null) - { - // TODO: Make sure that innerSelectExpression does not contain any reference from this SelectExpression - AddLeftJoin(innerSelectExpression, joinPredicate, transparentIdentifierType); - return; - } - - if (Limit != null || Offset != null || IsDistinct || Predicate != null || IsSetOperation || GroupBy.Count > 1) - { - innerSelectExpression = new SqlRemappingVisitor( - PushdownIntoSubquery(), (SelectExpression)Tables[0]).Remap(innerSelectExpression); - } - - if (innerSelectExpression.Orderings.Any() - || innerSelectExpression.Limit != null - || innerSelectExpression.Offset != null - || innerSelectExpression.IsDistinct - || innerSelectExpression.Predicate != null - || innerSelectExpression.Tables.Count > 1 - || innerSelectExpression.GroupBy.Count > 1) - { - innerSelectExpression.PushdownIntoSubquery(); - } - - _identifier.AddRange(innerSelectExpression._identifier); - var joinTable = new LeftJoinLateralExpression(innerSelectExpression.Tables.Single()); - _tables.Add(joinTable); - - var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); - var projectionMapping = new Dictionary(); - foreach (var projection in _projectionMapping) - { - projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; - } - - var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); - foreach (var projection in innerSelectExpression._projectionMapping) - { - var projectionToAdd = projection.Value; - if (projectionToAdd is EntityProjectionExpression entityProjection) - { - projectionToAdd = entityProjection.MakeNullable(); - } - else if (projectionToAdd is ColumnExpression column) - { - projectionToAdd = column.MakeNullable(); - } - - projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projectionToAdd; - } - - _projectionMapping = projectionMapping; + AddJoin(JoinType.LeftJoinLateral, innerSelectExpression, transparentIdentifierType); } private class SqlRemappingVisitor : ExpressionVisitor diff --git a/src/EFCore/Query/ExpressionPrinter.cs b/src/EFCore/Query/ExpressionPrinter.cs index df78b208811..ad5221fd824 100644 --- a/src/EFCore/Query/ExpressionPrinter.cs +++ b/src/EFCore/Query/ExpressionPrinter.cs @@ -515,7 +515,6 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp } else { - ////throw new NotSupportedException(CoreStrings.InvalidMemberInitBinding); AppendLine(CoreStrings.InvalidMemberInitBinding); } } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Where.cs b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Where.cs index 95bc80a6a8c..11777fd8bc0 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Where.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Where.cs @@ -1737,6 +1737,7 @@ FROM root c WHERE (((c[""Discriminator""] = ""Order"") AND (c[""CustomerID""] = ""QUICK"")) AND (c[""OrderDate""] > ""1998-01-01T00:00:00""))"); } + [ConditionalFact(Skip = "Issue #14935")] public override void Where_navigation_contains() { base.Where_navigation_contains(); diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.SetOperations.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.SetOperations.cs index 91408e93c14..cf97c7cdcfb 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.SetOperations.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.SetOperations.cs @@ -379,19 +379,19 @@ static Func, IQueryable> ExpressionGenerator(string ex case "ScalarSubquery": return os => os.Select(o => (object)o.OrderDetails.Count()); default: - throw new NotSupportedException(); + throw new InvalidOperationException(); } } } private static IEnumerable GetSetOperandTestCases() => from async in new[] { true, false } - from leftType in SupportedOperandExpressionType - from rightType in SupportedOperandExpressionType + from leftType in _supportedOperandExpressionType + from rightType in _supportedOperandExpressionType select new object[] { async, leftType, rightType }; // ReSharper disable once StaticMemberInGenericType - private static readonly string[] SupportedOperandExpressionType = + private static readonly string[] _supportedOperandExpressionType = { "Column", "Function", "Constant", "Unary", "Binary", "ScalarSubquery" }; diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Where.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Where.cs index 92727b0148c..7501de200be 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Where.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Where.cs @@ -559,7 +559,7 @@ public virtual Task Where_bitwise_and(bool isAsync) cs => cs.Where(c => c.CustomerID == "ALFKI" & c.CustomerID == "ANATR")); } - [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'where (([c].CustomerID == \"ALFKI\") ^ True)'")] + [ConditionalTheory(Skip = "Issue #16645. Cannot eval 'where (([c].CustomerID == \"ALFKI\") ^ True)'")] [InlineData(false)] public virtual Task Where_bitwise_xor(bool isAsync) { @@ -1895,10 +1895,11 @@ public virtual Task Where_chain(bool isAsync) isAsync, order => order .Where(o => o.CustomerID == "QUICK") - .Where(o => o.OrderDate > new DateTime(1998, 1, 1)), entryCount: 8); + .Where(o => o.OrderDate > new DateTime(1998, 1, 1)), + entryCount: 8); } - [ConditionalFact(Skip = "Issue #14935. Cannot eval 'Contains(Property([od], \"OrderID\"))'")] + [ConditionalFact] public virtual void Where_navigation_contains() { using (var context = CreateContext()) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 903336923ff..40ee9635649 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -12,8 +12,11 @@ public class GearsOfWarQuerySqlServerTest : GearsOfWarQueryTestBase N'foo') OR [w].[Name] IS NULL) -) AS [t0] ON [t].[FullName] = [t0].[OwnerFullName] +) AS [t] ON [g].[FullName] = [t].[OwnerFullName] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOrBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] FROM [Gears] AS [g0] WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') AND ([g0].[HasSoulPatch] <> CAST(1 AS bit)) -) AS [t1] ON [s].[Id] = [t1].[SquadId] -WHERE [t].[HasSoulPatch] = CAST(1 AS bit) -ORDER BY [t].[Nickname], [s].[Id] DESC, [t].[SquadId], [t0].[Id], [t1].[Nickname], [t1].[SquadId]"); +) AS [t0] ON [s].[Id] = [t0].[SquadId] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[HasSoulPatch] = CAST(1 AS bit)) +ORDER BY [g].[Nickname], [s].[Id] DESC, [g].[SquadId], [t].[Id], [t0].[Nickname], [t0].[SquadId]"); } public override async Task Correlated_collections_with_Skip(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs index bf8fe7d1271..e2302d88515 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs @@ -19,26 +19,22 @@ public override void Query_with_owned_entity_equality_operator() base.Query_with_owned_entity_equality_operator(); AssertSql( - @"SELECT [t].[Id], [t].[Discriminator], [o0].[Id], [o1].[Id], [o1].[PersonAddress_Country_Name], [o1].[PersonAddress_Country_PlanetId], [o2].[Id], [o3].[Id], [o3].[BranchAddress_Country_Name], [o3].[BranchAddress_Country_PlanetId], [o4].[Id], [o5].[Id], [o5].[LeafAAddress_Country_Name], [o5].[LeafAAddress_Country_PlanetId], [t0].[Id], [o7].[ClientId], [o7].[Id] -FROM ( - SELECT [o].[Id], [o].[Discriminator] - FROM [OwnedPerson] AS [o] - WHERE [o].[Discriminator] = N'LeafA' -) AS [t] + @"SELECT [o].[Id], [o].[Discriminator], [o0].[Id], [o1].[Id], [o1].[PersonAddress_Country_Name], [o1].[PersonAddress_Country_PlanetId], [o2].[Id], [o3].[Id], [o3].[BranchAddress_Country_Name], [o3].[BranchAddress_Country_PlanetId], [o4].[Id], [o5].[Id], [o5].[LeafAAddress_Country_Name], [o5].[LeafAAddress_Country_PlanetId], [t].[Id], [o7].[ClientId], [o7].[Id] +FROM [OwnedPerson] AS [o] CROSS JOIN ( SELECT [o6].[Id], [o6].[Discriminator] FROM [OwnedPerson] AS [o6] WHERE [o6].[Discriminator] = N'LeafB' -) AS [t0] -LEFT JOIN [OwnedPerson] AS [o0] ON [t].[Id] = [o0].[Id] +) AS [t] +LEFT JOIN [OwnedPerson] AS [o0] ON [o].[Id] = [o0].[Id] LEFT JOIN [OwnedPerson] AS [o1] ON [o0].[Id] = [o1].[Id] -LEFT JOIN [OwnedPerson] AS [o2] ON [t].[Id] = [o2].[Id] +LEFT JOIN [OwnedPerson] AS [o2] ON [o].[Id] = [o2].[Id] LEFT JOIN [OwnedPerson] AS [o3] ON [o2].[Id] = [o3].[Id] -LEFT JOIN [OwnedPerson] AS [o4] ON [t].[Id] = [o4].[Id] +LEFT JOIN [OwnedPerson] AS [o4] ON [o].[Id] = [o4].[Id] LEFT JOIN [OwnedPerson] AS [o5] ON [o4].[Id] = [o5].[Id] -LEFT JOIN [Order] AS [o7] ON [t].[Id] = [o7].[ClientId] +LEFT JOIN [Order] AS [o7] ON [o].[Id] = [o7].[ClientId] WHERE CAST(0 AS bit) = CAST(1 AS bit) -ORDER BY [t].[Id], [t0].[Id], [o7].[ClientId], [o7].[Id]"); +ORDER BY [o].[Id], [t].[Id], [o7].[ClientId], [o7].[Id]"); } public override void Query_for_base_type_loads_all_owned_navs() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryNavigationsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryNavigationsSqlServerTest.cs index e659f827fc6..991714597ce 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryNavigationsSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryNavigationsSqlServerTest.cs @@ -412,20 +412,16 @@ public override async Task Select_Where_Navigation_Scalar_Equals_Navigation_Scal await base.Select_Where_Navigation_Scalar_Equals_Navigation_Scalar(isAsync); AssertSql( - @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate] -FROM ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] - FROM [Orders] AS [o] - WHERE [o].[OrderID] < 10300 -) AS [t] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate] +FROM [Orders] AS [o] CROSS JOIN ( SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Orders] AS [o0] WHERE [o0].[OrderID] < 10400 -) AS [t0] -LEFT JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID] -LEFT JOIN [Customers] AS [c0] ON [t0].[CustomerID] = [c0].[CustomerID] -WHERE (([c].[City] = [c0].[City]) AND ([c].[City] IS NOT NULL AND [c0].[City] IS NOT NULL)) OR ([c].[City] IS NULL AND [c0].[City] IS NULL)"); +) AS [t] +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] +LEFT JOIN [Customers] AS [c0] ON [t].[CustomerID] = [c0].[CustomerID] +WHERE ([o].[OrderID] < 10300) AND ((([c].[City] = [c0].[City]) AND ([c].[City] IS NOT NULL AND [c0].[City] IS NOT NULL)) OR ([c].[City] IS NULL AND [c0].[City] IS NULL))"); } public override async Task Select_Where_Navigation_Scalar_Equals_Navigation_Scalar_Projected(bool isAsync) @@ -433,20 +429,16 @@ public override async Task Select_Where_Navigation_Scalar_Equals_Navigation_Scal await base.Select_Where_Navigation_Scalar_Equals_Navigation_Scalar_Projected(isAsync); AssertSql( - @"SELECT [t].[CustomerID], [t0].[CustomerID] AS [C2] -FROM ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] - FROM [Orders] AS [o] - WHERE [o].[OrderID] < 10300 -) AS [t] + @"SELECT [o].[CustomerID], [t].[CustomerID] AS [C2] +FROM [Orders] AS [o] CROSS JOIN ( SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Orders] AS [o0] WHERE [o0].[OrderID] < 10400 -) AS [t0] -LEFT JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID] -LEFT JOIN [Customers] AS [c0] ON [t0].[CustomerID] = [c0].[CustomerID] -WHERE (([c].[City] = [c0].[City]) AND ([c].[City] IS NOT NULL AND [c0].[City] IS NOT NULL)) OR ([c].[City] IS NULL AND [c0].[City] IS NULL)"); +) AS [t] +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] +LEFT JOIN [Customers] AS [c0] ON [t].[CustomerID] = [c0].[CustomerID] +WHERE ([o].[OrderID] < 10300) AND ((([c].[City] = [c0].[City]) AND ([c].[City] IS NOT NULL AND [c0].[City] IS NOT NULL)) OR ([c].[City] IS NULL AND [c0].[City] IS NULL))"); } public override async Task Select_Where_Navigation_Equals_Navigation(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs index 65068922c7a..51bd59ef4c9 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs @@ -51,17 +51,14 @@ public override void Tags_on_subquery() -- Laurel -SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region] -FROM ( - SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] - FROM [Customers] AS [c] - WHERE [c].[CustomerID] = N'ALFKI' -) AS [t] +SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] CROSS JOIN ( SELECT TOP(5) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] ORDER BY [o].[OrderID] -) AS [t0]"); +) AS [t] +WHERE [c].[CustomerID] = N'ALFKI'"); } public override void Duplicate_tags() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.SetOperations.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.SetOperations.cs index ca6696aeae5..78e8b20c0b1 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.SetOperations.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.SetOperations.cs @@ -392,7 +392,7 @@ FROM [Order Details] AS [o] WHERE [o0].[OrderID] = [o].[OrderID]) FROM [Orders] AS [o0]"; default: - throw new NotSupportedException(); + throw new InvalidOperationException(); } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Where.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Where.cs index a8d1716c9a0..96ea736e337 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Where.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Where.cs @@ -1638,23 +1638,19 @@ public override void Where_navigation_contains() base.Where_navigation_contains(); AssertSql( - @"SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]", + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] +ORDER BY [t].[CustomerID], [o].[OrderID]", // - @"SELECT [od].[OrderID], [od].[ProductID], [od].[Discount], [od].[Quantity], [od].[UnitPrice] -FROM [Order Details] AS [od]"); + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +WHERE [o0].[OrderID] IN (10643, 10692, 10702, 10835, 10952, 11011)"); } public override async Task Where_array_index(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs index 3cd96c7a9e9..d7d02d035a6 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs @@ -1893,13 +1893,10 @@ public override async Task Where_select_many(bool isAsync) await base.Where_select_many(isAsync); AssertSql( - @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region] -FROM ( - SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] - FROM [Customers] AS [c] - WHERE [c].[CustomerID] = N'ALFKI' -) AS [t] -CROSS JOIN [Orders] AS [o]"); + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +CROSS JOIN [Orders] AS [o] +WHERE [c].[CustomerID] = N'ALFKI'"); } public override async Task Where_orderby_select_many(bool isAsync) @@ -1907,14 +1904,11 @@ public override async Task Where_orderby_select_many(bool isAsync) await base.Where_orderby_select_many(isAsync); AssertSql( - @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region] -FROM ( - SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] - FROM [Customers] AS [c] - WHERE [c].[CustomerID] = N'ALFKI' -) AS [t] + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] CROSS JOIN [Orders] AS [o] -ORDER BY [t].[CustomerID]"); +WHERE [c].[CustomerID] = N'ALFKI' +ORDER BY [c].[CustomerID]"); } public override async Task SelectMany_cartesian_product_with_ordering(bool isAsync) @@ -3508,14 +3502,10 @@ public override async Task DefaultIfEmpty_in_subquery_nested(bool isAsync) await base.DefaultIfEmpty_in_subquery_nested(isAsync); AssertSql( - @"SELECT [t].[CustomerID], [t1].[OrderID], [o0].[OrderDate] -FROM ( - SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] - FROM [Customers] AS [c] - WHERE ([c].[City] = N'Seattle') AND [c].[City] IS NOT NULL -) AS [t] + @"SELECT [c].[CustomerID], [t0].[OrderID], [o0].[OrderDate] +FROM [Customers] AS [c] CROSS JOIN ( - SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[OrderID] AS [OrderID0] + SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[OrderID] AS [OrderID0] FROM ( SELECT NULL AS [empty] ) AS [empty] @@ -3523,11 +3513,11 @@ LEFT JOIN ( SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] WHERE [o].[OrderID] > 15000 - ) AS [t0] ON 1 = 1 -) AS [t1] -LEFT JOIN [Orders] AS [o0] ON [t].[CustomerID] = [o0].[CustomerID] -WHERE [t1].[OrderID] IS NOT NULL AND [o0].[OrderID] IS NOT NULL -ORDER BY [t1].[OrderID], [o0].[OrderDate]"); + ) AS [t] ON 1 = 1 +) AS [t0] +LEFT JOIN [Orders] AS [o0] ON [c].[CustomerID] = [o0].[CustomerID] +WHERE (([c].[City] = N'Seattle') AND [c].[City] IS NOT NULL) AND ([t0].[OrderID] IS NOT NULL AND [o0].[OrderID] IS NOT NULL) +ORDER BY [t0].[OrderID], [o0].[OrderDate]"); } [SqlServerCondition(SqlServerCondition.SupportsOffset)]