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: Convert MaterializeCollectionNavigation to expression from met… #16363

Merged
merged 3 commits into from
Jul 1, 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
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,16 @@ public class CosmosShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingE
private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _logger;

public CosmosShapedQueryCompilingExpressionVisitor(
QueryCompilationContext queryCompilationContext,
IEntityMaterializerSource entityMaterializerSource,
ISqlExpressionFactory sqlExpressionFactory,
IQuerySqlGeneratorFactory querySqlGeneratorFactory,
Type contextType,
IDiagnosticsLogger<DbLoggerCategory.Query> logger,
bool trackQueryResults,
bool async)
: base(entityMaterializerSource, trackQueryResults, async)
IQuerySqlGeneratorFactory querySqlGeneratorFactory)
: base(queryCompilationContext, entityMaterializerSource)
{
_sqlExpressionFactory = sqlExpressionFactory;
_querySqlGeneratorFactory = querySqlGeneratorFactory;
_contextType = contextType;
_logger = logger;
_contextType = queryCompilationContext.ContextType;
_logger = queryCompilationContext.Logger;
}

protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ public CosmosShapedQueryCompilingExpressionVisitorFactory(IEntityMaterializerSou
public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext)
{
return new CosmosShapedQueryCompilingExpressionVisitor(
queryCompilationContext,
_entityMaterializerSource,
_sqlExpressionFactory,
_querySqlGeneratorFactory,
queryCompilationContext.ContextType,
queryCompilationContext.Logger,
queryCompilationContext.TrackQueryResults,
queryCompilationContext.Async);
_querySqlGeneratorFactory);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ public class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQueryCompilin
private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _logger;

public InMemoryShapedQueryCompilingExpressionVisitor(
IEntityMaterializerSource entityMaterializerSource,
Type contextType,
IDiagnosticsLogger<DbLoggerCategory.Query> logger,
bool trackQueryResults, bool async)
: base(entityMaterializerSource, trackQueryResults, async)
QueryCompilationContext queryCompilationContext,
IEntityMaterializerSource entityMaterializerSource)
: base(queryCompilationContext, entityMaterializerSource)
{
_contextType = contextType;
_logger = logger;
_contextType = queryCompilationContext.ContextType;
_logger = queryCompilationContext.Logger;
}

protected override Expression VisitExtension(Expression extensionExpression)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@ public InMemoryShapedQueryCompilingExpressionVisitorFactory(IEntityMaterializerS
public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext)
{
return new InMemoryShapedQueryCompilingExpressionVisitor(
_entityMaterializerSource,
queryCompilationContext.ContextType,
queryCompilationContext.Logger,
queryCompilationContext.TrackQueryResults,
queryCompilationContext.Async);
queryCompilationContext,
_entityMaterializerSource);
}
}

Expand Down
42 changes: 38 additions & 4 deletions src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions;
Expand Down Expand Up @@ -55,14 +56,46 @@ public virtual IRelationalCommand GetCommand(SelectExpression selectExpression)
}
else
{
GenerateTagsHeaderComment(selectExpression);

VisitSelect(selectExpression);
}

return _relationalCommandBuilder.Build();
}

/// <summary>
/// The default alias separator.
/// </summary>
protected virtual string AliasSeparator { get; } = " AS ";

/// <summary>
/// The default single line comment prefix.
/// </summary>
protected virtual string SingleLineCommentToken { get; } = "--";

protected virtual IRelationalCommandBuilder Sql => _relationalCommandBuilder;

protected virtual void GenerateTagsHeaderComment(SelectExpression selectExpression)
{
if (selectExpression.Tags.Count > 0)
{
foreach (var tag in selectExpression.Tags)
{
using (var reader = new StringReader(tag))
{
string line;
while ((line = reader.ReadLine()) != null)
{
_relationalCommandBuilder.Append(SingleLineCommentToken).Append(" ").AppendLine(line);
}
}

_relationalCommandBuilder.AppendLine();
}
}
}

protected override Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression)
{
_relationalCommandBuilder.Append(sqlFragmentExpression.Sql);
Expand Down Expand Up @@ -94,7 +127,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression)
subQueryIndent.Dispose();

_relationalCommandBuilder.AppendLine()
.Append(") AS " + _sqlGenerationHelper.DelimitIdentifier(selectExpression.Alias));
.Append(")" + AliasSeparator + _sqlGenerationHelper.DelimitIdentifier(selectExpression.Alias));
}

return selectExpression;
Expand Down Expand Up @@ -193,7 +226,7 @@ protected override Expression VisitProjection(ProjectionExpression projectionExp
&& !(projectionExpression.Expression is ColumnExpression column
&& string.Equals(column.Name, projectionExpression.Alias)))
{
_relationalCommandBuilder.Append(" AS " + _sqlGenerationHelper.DelimitIdentifier(projectionExpression.Alias));
_relationalCommandBuilder.Append(AliasSeparator + _sqlGenerationHelper.DelimitIdentifier(projectionExpression.Alias));
}

return projectionExpression;
Expand Down Expand Up @@ -248,7 +281,7 @@ protected override Expression VisitTable(TableExpression tableExpression)
{
_relationalCommandBuilder
.Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Table, tableExpression.Schema))
.Append(" AS ")
.Append(AliasSeparator)
.Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Alias));

return tableExpression;
Expand Down Expand Up @@ -297,7 +330,8 @@ protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression)
GenerateFromSql(fromSqlExpression);
}

_relationalCommandBuilder.Append(") AS ")
_relationalCommandBuilder.Append(")")
.Append(AliasSeparator)
.Append(_sqlGenerationHelper.DelimitIdentifier(fromSqlExpression.Alias));

return fromSqlExpression;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,16 @@ public override Expression Visit(Expression expression)
Expression.Constant(parameterExpression.Name));
}

if (expression is MethodCallExpression methodCallExpression)
if (expression is MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression)
{
if (methodCallExpression.Method.Name == "MaterializeCollectionNavigation")
{
var result = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression.Arguments[0]);
var navigation = (INavigation)((ConstantExpression)methodCallExpression.Arguments[1]).Value;

return _selectExpression.AddCollectionProjection(result, navigation, null);
}
return _selectExpression.AddCollectionProjection(
_queryableMethodTranslatingExpressionVisitor.TranslateSubquery(
materializeCollectionNavigationExpression.Subquery),
materializeCollectionNavigationExpression.Navigation, null);
}

if (expression is MethodCallExpression methodCallExpression)
{
if (methodCallExpression.Method.IsGenericMethod
&& methodCallExpression.Method.DeclaringType == typeof(Enumerable)
&& methodCallExpression.Method.Name == nameof(Enumerable.ToList))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,28 @@ public partial class RelationalShapedQueryCompilingExpressionVisitor : ShapedQue
private readonly IParameterNameGeneratorFactory _parameterNameGeneratorFactory;
private readonly Type _contextType;
private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _logger;
private readonly ISet<string> _tags;

public RelationalShapedQueryCompilingExpressionVisitor(
QueryCompilationContext queryCompilationContext,
IEntityMaterializerSource entityMaterializerSource,
IQuerySqlGeneratorFactory querySqlGeneratorFactory,
ISqlExpressionFactory sqlExpressionFactory,
IParameterNameGeneratorFactory parameterNameGeneratorFactory,
Type contextType,
IDiagnosticsLogger<DbLoggerCategory.Query> logger,
bool trackQueryResults,
bool async)
: base(entityMaterializerSource, trackQueryResults, async)
IParameterNameGeneratorFactory parameterNameGeneratorFactory)
: base(queryCompilationContext, entityMaterializerSource)
{
_querySqlGeneratorFactory = querySqlGeneratorFactory;
_sqlExpressionFactory = sqlExpressionFactory;
_parameterNameGeneratorFactory = parameterNameGeneratorFactory;
_contextType = contextType;
_logger = logger;
_contextType = queryCompilationContext.ContextType;
_logger = queryCompilationContext.Logger;
_tags = queryCompilationContext.Tags;
}

protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression)
{
var selectExpression = (SelectExpression)shapedQueryExpression.QueryExpression;
selectExpression.ApplyTags(_tags);

var dataReaderParameter = Expression.Parameter(typeof(DbDataReader), "dataReader");
var resultCoordinatorParameter = Expression.Parameter(typeof(ResultCoordinator), "resultCoordinator");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ public RelationalShapedQueryCompilingExpressionVisitorFactory(
public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext)
{
return new RelationalShapedQueryCompilingExpressionVisitor(
queryCompilationContext,
_entityMaterializerSource,
_querySqlGeneratorFactory,
_sqlExpressionFactory,
_parameterNameGeneratorFactory,
queryCompilationContext.ContextType,
queryCompilationContext.Logger,
queryCompilationContext.TrackQueryResults,
queryCompilationContext.Async);
_parameterNameGeneratorFactory);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
Expand All @@ -34,11 +31,17 @@ private readonly IDictionary<EntityProjectionExpression, IDictionary<IProperty,
public IReadOnlyList<ProjectionExpression> Projection => _projection;
public IReadOnlyList<TableExpressionBase> Tables => _tables;
public IReadOnlyList<OrderingExpression> Orderings => _orderings;
public ISet<string> Tags { get; private set; } = new HashSet<string>();
public SqlExpression Predicate { get; private set; }
public SqlExpression Limit { get; private set; }
public SqlExpression Offset { get; private set; }
public bool IsDistinct { get; private set; }

public void ApplyTags(ISet<string> tags)
{
Tags = tags;
}

/// <summary>
/// Marks this <see cref="SelectExpression"/> as representing an SQL set operation, such as a UNION.
/// For regular SQL SELECT expressions, contains <c>None</c>.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Query.Expressions.Internal;
using Microsoft.EntityFrameworkCore.Query.Internal;

namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion
{
public class MaterializeCollectionNavigationExpression : Expression, IPrintable
{
public MaterializeCollectionNavigationExpression(Expression subquery, INavigation navigation)
{
Subquery = subquery;
Navigation = navigation;
}

public virtual Expression Subquery { get; }
public virtual INavigation Navigation { get; }

public override ExpressionType NodeType => ExpressionType.Extension;
public override Type Type => Navigation.ClrType;

public virtual void Print(ExpressionPrinter expressionPrinter)
{
expressionPrinter.StringBuilder.Append($"MaterializeCollectionNavigation({Navigation}, ");
expressionPrinter.Visit(Subquery);
expressionPrinter.StringBuilder.Append(")");
}

protected override Expression VisitChildren(ExpressionVisitor visitor)
{
var subquery = visitor.Visit(Subquery);

return subquery != Subquery
? new MaterializeCollectionNavigationExpression(subquery, Navigation)
: this;
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ private NavigationExpansionExpressionState ReplaceNavigationExpansionExpressionS
newPendingOrderings,
newPendingIncludeChain,
State.PendingCardinalityReducingOperator,
State.PendingTags,
State.CustomRootMappings,
State.MaterializeCollectionNavigation);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ public NavigationExpansionExpressionState(
List<(MethodInfo method, LambdaExpression keySelector)> pendingOrderings,
NavigationBindingExpression pendingIncludeChain,
MethodInfo pendingCardinalityReducingOperator,
List<string> pendingTags,
List<List<string>> customRootMappings,
INavigation materializeCollectionNavigation)
{
Expand All @@ -29,7 +28,6 @@ public NavigationExpansionExpressionState(
PendingOrderings = pendingOrderings;
PendingIncludeChain = pendingIncludeChain;
PendingCardinalityReducingOperator = pendingCardinalityReducingOperator;
PendingTags = pendingTags;
CustomRootMappings = customRootMappings;
MaterializeCollectionNavigation = materializeCollectionNavigation;
}
Expand All @@ -41,7 +39,6 @@ public NavigationExpansionExpressionState(
public virtual List<(MethodInfo method, LambdaExpression keySelector)> PendingOrderings { get; set; }
public virtual NavigationBindingExpression PendingIncludeChain { get; set; }
public virtual MethodInfo PendingCardinalityReducingOperator { get; set; }
public virtual List<string> PendingTags { get; set; }
public virtual List<List<string>> CustomRootMappings { get; set; }
public virtual INavigation MaterializeCollectionNavigation { get; set; }
}
Expand Down
16 changes: 0 additions & 16 deletions src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Reflection;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query.Expressions.Internal;
using Microsoft.EntityFrameworkCore.Query.Internal;

Expand Down Expand Up @@ -49,7 +48,6 @@ public static NavigationExpansionExpression CreateNavigationExpansionRoot(
new List<(MethodInfo method, LambdaExpression keySelector)>(),
pendingIncludeChain: null,
pendingCardinalityReducingOperator: null,
pendingTags: new List<string>(),
customRootMappings: new List<List<string>>(),
materializeCollectionNavigation),
materializeCollectionNavigation?.ClrType ?? operand.Type);
Expand Down Expand Up @@ -276,19 +274,5 @@ public static Expression CreateNullKeyExpression(Type resultType, int keyCount)
Expression.Constant(null),
keyCount)))
: (Expression)Expression.Constant(null);

public static readonly MethodInfo MaterializeCollectionNavigationMethodInfo
= typeof(NavigationExpansionHelpers).GetTypeInfo()
.GetDeclaredMethod(nameof(MaterializeCollectionNavigation));

public static TResult MaterializeCollectionNavigation<TResult, TEntity>(
IEnumerable<object> elements,
INavigation navigation)
where TResult : IEnumerable<TEntity>
{
var collection = navigation.GetCollectionAccessor().Create(elements);

return (TResult)collection;
}
}
}
Loading