Skip to content

Commit

Permalink
Remove quirks (#27258)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers authored Jan 25, 2022
1 parent c604749 commit 511b6b8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 106 deletions.
160 changes: 66 additions & 94 deletions src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -851,130 +851,102 @@ 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)
{
// If there are no initial table then this is not correlated grouping subquery
// 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++)
Expand Down
14 changes: 2 additions & 12 deletions src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1309,26 +1309,16 @@ 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)
.Select(e => sqlExpressionFactory.Equal(e.First, e.Second))
.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)))
{
Expand Down

0 comments on commit 511b6b8

Please sign in to comment.