Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Query: Rename Lateral joins to Cross/Outer Apply #17358

Merged
merged 1 commit into from
Aug 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/EFCore.Relational/Query/QuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -674,20 +674,20 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres
return crossJoinExpression;
}

protected override Expression VisitInnerJoinLateral(InnerJoinLateralExpression innerJoinLateralExpression)
protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression)
{
_relationalCommandBuilder.Append("INNER JOIN LATERAL ");
Visit(innerJoinLateralExpression.Table);
_relationalCommandBuilder.Append("CROSS APPLY ");
Visit(crossApplyExpression.Table);

return innerJoinLateralExpression;
return crossApplyExpression;
}

protected override Expression VisitLeftJoinLateral(LeftJoinLateralExpression leftJoinLateralExpression)
protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression)
{
_relationalCommandBuilder.Append("LEFT JOIN LATERAL ");
Visit(leftJoinLateralExpression.Table);
_relationalCommandBuilder.Append("OUTER APPLY ");
Visit(outerApplyExpression.Table);

return leftJoinLateralExpression;
return outerApplyExpression;
}

protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -742,13 +742,13 @@ protected override ShapedQueryExpression TranslateSelectMany(
var innerShaperExpression = inner.ShaperExpression;
if (defaultIfEmpty)
{
((SelectExpression)source.QueryExpression).AddLeftJoinLateral(
((SelectExpression)source.QueryExpression).AddOuterApply(
(SelectExpression)inner.QueryExpression, transparentIdentifierType);
innerShaperExpression = MarkShaperNullable(innerShaperExpression);
}
else
{
((SelectExpression)source.QueryExpression).AddInnerJoinLateral(
((SelectExpression)source.QueryExpression).AddCrossApply(
(SelectExpression)inner.QueryExpression, transparentIdentifierType);
}

Expand Down
12 changes: 6 additions & 6 deletions src/EFCore.Relational/Query/SqlExpressionVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ protected override Expression VisitExtension(Expression extensionExpression)
case CrossJoinExpression crossJoinExpression:
return VisitCrossJoin(crossJoinExpression);

case InnerJoinLateralExpression innerJoinLateralExpression:
return VisitInnerJoinLateral(innerJoinLateralExpression);
case CrossApplyExpression crossApplyExpression:
return VisitCrossApply(crossApplyExpression);

case LeftJoinLateralExpression leftJoinLateralExpression:
return VisitLeftJoinLateral(leftJoinLateralExpression);
case OuterApplyExpression outerApplyExpression:
return VisitOuterApply(outerApplyExpression);

case ExistsExpression existsExpression:
return VisitExists(existsExpression);
Expand Down Expand Up @@ -101,8 +101,8 @@ protected override Expression VisitExtension(Expression extensionExpression)
protected abstract Expression VisitExists(ExistsExpression existsExpression);
protected abstract Expression VisitIn(InExpression inExpression);
protected abstract Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression);
protected abstract Expression VisitInnerJoinLateral(InnerJoinLateralExpression innerJoinLateralExpression);
protected abstract Expression VisitLeftJoinLateral(LeftJoinLateralExpression leftJoinLateralExpression);
protected abstract Expression VisitCrossApply(CrossApplyExpression crossApplyExpression);
protected abstract Expression VisitOuterApply(OuterApplyExpression outerApplyExpression);
protected abstract Expression VisitFromSql(FromSqlExpression fromSqlExpression);
protected abstract Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression);
protected abstract Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,35 @@

namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions
{
public class LeftJoinLateralExpression : JoinExpressionBase
public class CrossApplyExpression : JoinExpressionBase
{
public LeftJoinLateralExpression(TableExpressionBase table)
public CrossApplyExpression(TableExpressionBase table)
: base(table)
{
}

protected override Expression VisitChildren(ExpressionVisitor visitor)
=> Update((TableExpressionBase)visitor.Visit(Table));

public virtual LeftJoinLateralExpression Update(TableExpressionBase table)
public virtual CrossApplyExpression Update(TableExpressionBase table)
=> table != Table
? new LeftJoinLateralExpression(table)
? new CrossApplyExpression(table)
: this;

public override void Print(ExpressionPrinter expressionPrinter)
{
expressionPrinter.Append("LEFT JOIN LATERAL ");
expressionPrinter.Append("CROSS APPLY ");
expressionPrinter.Visit(Table);
}

public override bool Equals(object obj)
=> obj != null
&& (ReferenceEquals(this, obj)
|| obj is LeftJoinLateralExpression leftJoinLateralExpression
&& Equals(leftJoinLateralExpression));
|| obj is CrossApplyExpression crossApplyExpression
&& Equals(crossApplyExpression));

private bool Equals(LeftJoinLateralExpression leftJoinLateralExpression)
=> base.Equals(leftJoinLateralExpression);
private bool Equals(CrossApplyExpression crossApplyExpression)
=> base.Equals(crossApplyExpression);

public override int GetHashCode() => base.GetHashCode();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,35 @@

namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions
{
public class InnerJoinLateralExpression : JoinExpressionBase
public class OuterApplyExpression : JoinExpressionBase
{
public InnerJoinLateralExpression(TableExpressionBase table)
public OuterApplyExpression(TableExpressionBase table)
: base(table)
{
}

protected override Expression VisitChildren(ExpressionVisitor visitor)
=> Update((TableExpressionBase)visitor.Visit(Table));

public virtual InnerJoinLateralExpression Update(TableExpressionBase table)
public virtual OuterApplyExpression Update(TableExpressionBase table)
=> table != Table
? new InnerJoinLateralExpression(table)
? new OuterApplyExpression(table)
: this;

public override void Print(ExpressionPrinter expressionPrinter)
{
expressionPrinter.Append("INNER JOIN LATERAL ");
expressionPrinter.Append("OUTER APPLY ");
expressionPrinter.Visit(Table);
}

public override bool Equals(object obj)
=> obj != null
&& (ReferenceEquals(this, obj)
|| obj is InnerJoinLateralExpression innerJoinLateralExpression
&& Equals(innerJoinLateralExpression));
|| obj is OuterApplyExpression outerApplyExpression
&& Equals(outerApplyExpression));

private bool Equals(InnerJoinLateralExpression innerJoinLateralExpression)
=> base.Equals(innerJoinLateralExpression);
private bool Equals(OuterApplyExpression outerApplyExpression)
=> base.Equals(outerApplyExpression);

public override int GetHashCode() => base.GetHashCode();
}
Expand Down
28 changes: 14 additions & 14 deletions src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ public Expression AddSingleProjection(ShapedQueryExpression shapedQueryExpressio
var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression;
innerSelectExpression.ApplyProjection();
var projectionCount = innerSelectExpression.Projection.Count;
AddLeftJoinLateral(innerSelectExpression, null);
AddOuterApply(innerSelectExpression, null);

// Joined SelectExpression may different based on left join or outer apply
// And it will always be SelectExpression because of presence of Take(1)
Expand Down Expand Up @@ -786,7 +786,7 @@ public Expression ApplyCollectionJoin(
}

var joinExpression = joinPredicate == null
? (TableExpressionBase)new LeftJoinLateralExpression(innerSelectExpression.Tables.Single())
? (TableExpressionBase)new OuterApplyExpression(innerSelectExpression.Tables.Single())
: new LeftJoinExpression(innerSelectExpression.Tables.Single(), joinPredicate);
_tables.Add(joinExpression);

Expand Down Expand Up @@ -1028,8 +1028,8 @@ private enum JoinType
InnerJoin,
LeftJoin,
CrossJoin,
InnerJoinLateral,
LeftJoinLateral
CrossApply,
OuterApply
}

private void AddJoin(
Expand All @@ -1038,8 +1038,8 @@ private void AddJoin(
Type transparentIdentifierType,
SqlExpression joinPredicate = null)
{
// Try to convert lateral join to normal join
if (joinType == JoinType.InnerJoinLateral || joinType == JoinType.LeftJoinLateral)
// Try to convert Apply to normal join
if (joinType == JoinType.CrossApply || joinType == JoinType.OuterApply)
{
// Doing for limit only since limit + offset may need sum
var limit = innerSelectExpression.Limit;
Expand Down Expand Up @@ -1080,7 +1080,7 @@ private void AddJoin(
innerSelectExpression.ApplyPredicate(predicate);
}

AddJoin(joinType == JoinType.InnerJoinLateral ? JoinType.InnerJoin : JoinType.LeftJoin,
AddJoin(joinType == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftJoin,
innerSelectExpression, transparentIdentifierType, joinPredicate);
return;
}
Expand Down Expand Up @@ -1122,8 +1122,8 @@ private void AddJoin(
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),
JoinType.CrossApply => new CrossApplyExpression(innerTable),
JoinType.OuterApply => new OuterApplyExpression(innerTable),
_ => throw new InvalidOperationException($"Invalid {nameof(joinType)}: {joinType}")
});

Expand All @@ -1139,7 +1139,7 @@ private void AddJoin(
}

var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner");
var innerNullable = joinType == JoinType.LeftJoin || joinType == JoinType.LeftJoinLateral;
var innerNullable = joinType == JoinType.LeftJoin || joinType == JoinType.OuterApply;
foreach (var projection in innerSelectExpression._projectionMapping)
{
var projectionToAdd = projection.Value;
Expand Down Expand Up @@ -1170,11 +1170,11 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo
public void AddCrossJoin(SelectExpression innerSelectExpression, Type transparentIdentifierType)
=> AddJoin(JoinType.CrossJoin, innerSelectExpression, transparentIdentifierType);

public void AddInnerJoinLateral(SelectExpression innerSelectExpression, Type transparentIdentifierType)
=> AddJoin(JoinType.InnerJoinLateral, innerSelectExpression, transparentIdentifierType);
public void AddCrossApply(SelectExpression innerSelectExpression, Type transparentIdentifierType)
=> AddJoin(JoinType.CrossApply, innerSelectExpression, transparentIdentifierType);

public void AddLeftJoinLateral(SelectExpression innerSelectExpression, Type transparentIdentifierType)
=> AddJoin(JoinType.LeftJoinLateral, innerSelectExpression, transparentIdentifierType);
public void AddOuterApply(SelectExpression innerSelectExpression, Type transparentIdentifierType)
=> AddJoin(JoinType.OuterApply, innerSelectExpression, transparentIdentifierType);

private class SqlRemappingVisitor : ExpressionVisitor
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres
return crossJoinExpression.Update(table);
}

protected override Expression VisitInnerJoinLateral(InnerJoinLateralExpression crossApplyExpression)
protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression)
{
var parentSearchCondition = _isSearchCondition;
_isSearchCondition = false;
Expand All @@ -319,7 +319,7 @@ protected override Expression VisitInnerJoinLateral(InnerJoinLateralExpression c
return crossApplyExpression.Update(table);
}

protected override Expression VisitLeftJoinLateral(LeftJoinLateralExpression outerApplyExpression)
protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression)
{
var parentSearchCondition = _isSearchCondition;
_isSearchCondition = false;
Expand Down
16 changes: 0 additions & 16 deletions src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,5 @@ protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunction

return base.VisitSqlFunction(sqlFunctionExpression);
}

protected override Expression VisitInnerJoinLateral(InnerJoinLateralExpression innerJoinLateralExpression)
{
Sql.Append("CROSS APPLY ");
Visit(innerJoinLateralExpression.Table);

return innerJoinLateralExpression;
}

protected override Expression VisitLeftJoinLateral(LeftJoinLateralExpression leftJoinLateralExpression)
{
Sql.Append("OUTER APPLY ");
Visit(leftJoinLateralExpression.Table);

return leftJoinLateralExpression;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public override async Task DateTimeOffset_Contains_Less_than_Greater_than(bool i
private string RemoveNewLines(string message)
=> message.Replace("\n", "").Replace("\r", "");

// Sqlite does not support lateral joins
// Sqlite does not support cross/outer apply
public override Task Correlated_collections_inner_subquery_predicate_references_outer_qsre(bool isAsync) => null;

public override Task Correlated_collections_inner_subquery_selector_references_outer_qsre(bool isAsync) => null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,7 @@ LIMIT @__p_0
public override Task Project_single_element_from_collection_with_multiple_OrderBys_Take_and_FirstOrDefault_2(bool isAsync)
=> base.Project_single_element_from_collection_with_multiple_OrderBys_Take_and_FirstOrDefault_2(isAsync);

// Sqlite does not support lateral joins
// Sqlite does not support cross/outer apply
public override void Select_nested_collection_multi_level()
{
}
Expand Down