diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs index bc205a7faa1..a7afc248320 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs @@ -851,118 +851,93 @@ public GroupByAggregateLiftingExpressionVisitor(SelectExpression selectExpressio { var initialTableCounts = 0; - if (AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue27163", out var enabled27163) && enabled27163) - { + initialTableCounts = _selectExpression._groupingParentSelectExpressionTableCount!.Value; var potentialTableCount = Math.Min(_selectExpression._tables.Count, subquery._tables.Count); - for (var i = 0; i < potentialTableCount; i++) + // First verify that subquery has same structure for initial tables, + // If not then subquery may have different root than grouping element. + for (var i = 0; i < initialTableCounts; i++) { if (!string.Equals( - _selectExpression._tableReferences[i].Alias, - subquery._tableReferences[i].Alias, - StringComparison.OrdinalIgnoreCase)) + _selectExpression._tableReferences[i].Alias, + subquery._tableReferences[i].Alias, StringComparison.OrdinalIgnoreCase)) { + initialTableCounts = 0; break; } - - if (_selectExpression._tables[i] is SelectExpression originalNestedSelectExpression - && subquery._tables[i] is SelectExpression subqueryNestedSelectExpression) - { - CopyOverOwnedJoinInSameTable(originalNestedSelectExpression, subqueryNestedSelectExpression); - } - - initialTableCounts++; } - } - else + + if (initialTableCounts > 0) + { + // If initial table structure matches and + // Parent has additional joins lifted already one of them is a subquery join + // Then we abort lifting if any of the joins from the subquery to lift are a subquery join + if (_selectExpression._tables.Skip(initialTableCounts) + .Select(e => UnwrapJoinExpression(e)) + .Any(e => e is SelectExpression)) { - initialTableCounts = _selectExpression._groupingParentSelectExpressionTableCount!.Value; - var potentialTableCount = Math.Min(_selectExpression._tables.Count, subquery._tables.Count); - // First verify that subquery has same structure for initial tables, - // If not then subquery may have different root than grouping element. - for (var i = 0; i < initialTableCounts; i++) + for (var i = initialTableCounts; i < subquery._tables.Count; i++) { - if (!string.Equals( - _selectExpression._tableReferences[i].Alias, - subquery._tableReferences[i].Alias, StringComparison.OrdinalIgnoreCase)) + if (UnwrapJoinExpression(subquery._tables[i]) is SelectExpression) { + // If any of the join is to subquery then we abort the lifting group by term altogether. initialTableCounts = 0; break; } } + } + } - if (initialTableCounts > 0) + if (initialTableCounts > 0) + { + // We need to copy over owned join which are coming from same initial tables. + for (var i = 0; i < initialTableCounts; i++) + { + if (_selectExpression._tables[i] is SelectExpression originalNestedSelectExpression + && subquery._tables[i] is SelectExpression subqueryNestedSelectExpression) { - // If initial table structure matches and - // Parent has additional joins lifted already one of them is a subquery join - // Then we abort lifting if any of the joins from the subquery to lift are a subquery join - if (_selectExpression._tables.Skip(initialTableCounts) - .Select(e => UnwrapJoinExpression(e)) - .Any(e => e is SelectExpression)) - { - for (var i = initialTableCounts; i < subquery._tables.Count; i++) - { - if (UnwrapJoinExpression(subquery._tables[i]) is SelectExpression) - { - // If any of the join is to subquery then we abort the lifting group by term altogether. - initialTableCounts = 0; - break; - } - } - } + CopyOverOwnedJoinInSameTable(originalNestedSelectExpression, subqueryNestedSelectExpression); } + } - if (initialTableCounts > 0) + + for (var i = initialTableCounts; i < potentialTableCount; i++) + { + // Try to match additional tables for the cases where we can match exact so we can avoid lifting + // same joins to parent + if (!string.Equals( + _selectExpression._tableReferences[i].Alias, + subquery._tableReferences[i].Alias, StringComparison.OrdinalIgnoreCase)) { - // We need to copy over owned join which are coming from same initial tables. - for (var i = 0; i < initialTableCounts; i++) - { - if (_selectExpression._tables[i] is SelectExpression originalNestedSelectExpression - && subquery._tables[i] is SelectExpression subqueryNestedSelectExpression) - { - CopyOverOwnedJoinInSameTable(originalNestedSelectExpression, subqueryNestedSelectExpression); - } - } + break; + } + var outerTableExpressionBase = _selectExpression._tables[i]; + var innerTableExpressionBase = subquery._tables[i]; - for (var i = initialTableCounts; i < potentialTableCount; i++) - { - // Try to match additional tables for the cases where we can match exact so we can avoid lifting - // same joins to parent - if (!string.Equals( - _selectExpression._tableReferences[i].Alias, - subquery._tableReferences[i].Alias, StringComparison.OrdinalIgnoreCase)) - { - break; - } - - var outerTableExpressionBase = _selectExpression._tables[i]; - var innerTableExpressionBase = subquery._tables[i]; - - if (outerTableExpressionBase is InnerJoinExpression outerInnerJoin - && innerTableExpressionBase is InnerJoinExpression innerInnerJoin) - { - outerTableExpressionBase = outerInnerJoin.Table as TableExpression; - innerTableExpressionBase = innerInnerJoin.Table as TableExpression; - } - else if (outerTableExpressionBase is LeftJoinExpression outerLeftJoin - && innerTableExpressionBase is LeftJoinExpression innerLeftJoin) - { - outerTableExpressionBase = outerLeftJoin.Table as TableExpression; - innerTableExpressionBase = innerLeftJoin.Table as TableExpression; - } - - if (outerTableExpressionBase is TableExpression outerTable - && innerTableExpressionBase is TableExpression innerTable - && !(string.Equals(outerTable.Name, innerTable.Name, StringComparison.OrdinalIgnoreCase) - && string.Equals(outerTable.Schema, innerTable.Schema, StringComparison.OrdinalIgnoreCase))) - { - break; - } - - initialTableCounts++; - } + if (outerTableExpressionBase is InnerJoinExpression outerInnerJoin + && innerTableExpressionBase is InnerJoinExpression innerInnerJoin) + { + outerTableExpressionBase = outerInnerJoin.Table as TableExpression; + innerTableExpressionBase = innerInnerJoin.Table as TableExpression; + } + else if (outerTableExpressionBase is LeftJoinExpression outerLeftJoin + && innerTableExpressionBase is LeftJoinExpression innerLeftJoin) + { + outerTableExpressionBase = outerLeftJoin.Table as TableExpression; + innerTableExpressionBase = innerLeftJoin.Table as TableExpression; } + + if (outerTableExpressionBase is TableExpression outerTable + && innerTableExpressionBase is TableExpression innerTable + && !(string.Equals(outerTable.Name, innerTable.Name, StringComparison.OrdinalIgnoreCase) + && string.Equals(outerTable.Schema, innerTable.Schema, StringComparison.OrdinalIgnoreCase))) + { + break; + } + + initialTableCounts++; } + } if (initialTableCounts > 0) { @@ -970,11 +945,8 @@ public GroupByAggregateLiftingExpressionVisitor(SelectExpression selectExpressio // We only replace columns from initial tables. // Additional tables may have been added to outer from other terms which may end up matching on table alias var columnExpressionReplacingExpressionVisitor = - AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue27083", out var enabled27083) && enabled27083 - ? new ColumnExpressionReplacingExpressionVisitor( - subquery, _selectExpression._tableReferences) - : new ColumnExpressionReplacingExpressionVisitor( - subquery, _selectExpression._tableReferences.Take(initialTableCounts)); + new ColumnExpressionReplacingExpressionVisitor( + subquery, _selectExpression._tableReferences.Take(initialTableCounts)); { // If subquery has more tables then we expanded join on it. for (var i = initialTableCounts; i < subquery._tables.Count; i++) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 7793d151650..4b0c2083cc3 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -1309,10 +1309,7 @@ public GroupByShaperExpression ApplyGrouping( // We generate the cloned expression before changing identifier for this SelectExpression // because we are going to erase grouping for cloned expression. - if (!(AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue27094", out var enabled27094) && enabled27094)) - { - _groupingParentSelectExpressionId = Guid.NewGuid(); - } + _groupingParentSelectExpressionId = Guid.NewGuid(); var clonedSelectExpression = Clone(); var correlationPredicate = groupByTerms.Zip(clonedSelectExpression._groupBy) @@ -1320,15 +1317,8 @@ public GroupByShaperExpression ApplyGrouping( .Aggregate((l, r) => sqlExpressionFactory.AndAlso(l, r)); clonedSelectExpression._groupBy.Clear(); clonedSelectExpression.ApplyPredicate(correlationPredicate); - if (!(AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue27102", out var enabled27102) && enabled27102)) - { clonedSelectExpression._groupingCorrelationPredicate = clonedSelectExpression.Predicate; - } - if (!(AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue27163", out var enabled27163) && enabled27163)) - { - _groupingParentSelectExpressionTableCount = _tables.Count; - - } + _groupingParentSelectExpressionTableCount = _tables.Count; if (!_identifier.All(e => _groupBy.Contains(e.Column))) {