Skip to content

Commit

Permalink
Add hooks for expression fragments and visitors
Browse files Browse the repository at this point in the history
Creates Npgsql implementations of `IExpressionFragmentTranslator`
and `IQueryOptimizer` to support more complex translations.

These classes make it easier to inject new fragment translations
and expression rewrites into the EF Core translation process.

This is split out from #431. Working examples can be found there.
  • Loading branch information
austindrenski committed Jul 22, 2018
1 parent d60631b commit 2bea785
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/EFCore.PG/Extensions/NpgsqlServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
{
// ReSharper disable once UnusedMember.Global
public static class NpgsqlEntityFrameworkServicesBuilderExtensions
{
/// <summary>
Expand Down Expand Up @@ -106,6 +107,8 @@ public static IServiceCollection AddEntityFrameworkNpgsql([NotNull] this IServic
.TryAdd<IQueryCompilationContextFactory, NpgsqlQueryCompilationContextFactory>()
.TryAdd<IMemberTranslator, NpgsqlCompositeMemberTranslator>()
.TryAdd<ICompositeMethodCallTranslator, NpgsqlCompositeMethodCallTranslator>()
.TryAdd<IExpressionFragmentTranslator, NpgsqlCompositeExpressionFragmentTranslator>()
.TryAdd<IQueryOptimizer, NpgsqlQueryOptimizer>()
.TryAdd<IQuerySqlGeneratorFactory, NpgsqlQuerySqlGeneratorFactory>()
.TryAdd<ISqlTranslatingExpressionVisitorFactory, NpgsqlSqlTranslatingExpressionVisitorFactory>()
.TryAdd<ISingletonOptions, INpgsqlOptions>(p => p.GetService<INpgsqlOptions>())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#region License

// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph and the following two paragraphs appear in all copies.
//
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

#endregion

using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal
{
/// <summary>
/// A composite expression fragment translator that dispatches to multiple specialized translators specific to Npgsql.
/// </summary>
public class NpgsqlCompositeExpressionFragmentTranslator : RelationalCompositeExpressionFragmentTranslator
{
/// <summary>
/// The default expression fragment translators registered by the Npgsql provider.
/// </summary>
[NotNull] [ItemNotNull] static readonly IExpressionFragmentTranslator[] ExpressionFragmentTranslators = {};

/// <inheritdoc />
public NpgsqlCompositeExpressionFragmentTranslator(
[NotNull] RelationalCompositeExpressionFragmentTranslatorDependencies dependencies)
: base(dependencies)
{
// ReSharper disable once DoNotCallOverridableMethodsInConstructor
AddTranslators(ExpressionFragmentTranslators);
}

/// <summary>
/// Adds additional dispatches to the translators list.
/// </summary>
/// <param name="translators">The translators.</param>
public new virtual void AddTranslators([NotNull] IEnumerable<IExpressionFragmentTranslator> translators)
=> base.AddTranslators(translators);
}
}
55 changes: 55 additions & 0 deletions src/EFCore.PG/Query/Internal/NpgsqlQueryOptimizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#region License

// The PostgreSQL License
//
// Copyright (C) 2016 The Npgsql Development Team
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph and the following two paragraphs appear in all copies.
//
// IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY
// FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
// INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
// DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
// ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

#endregion

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

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.Internal
{
/// <summary>
/// The default relational LINQ query optimizer for Npgsql.
/// </summary>
public class NpgsqlQueryOptimizer : QueryOptimizer
{
/// <summary>
/// The default expression visitors registered by the Npgsql provider.
/// </summary>
[NotNull] [ItemNotNull] static readonly ExpressionVisitor[] ExpressionVisitors = {};

/// <inheritdoc />
public override void Optimize(QueryCompilationContext queryCompilationContext, QueryModel queryModel)
{
base.Optimize(queryCompilationContext, queryModel);

for (int i = 0; i < ExpressionVisitors.Length; i++)
{
queryModel.TransformExpressions(ExpressionVisitors[i].Visit);
}
}
}
}

0 comments on commit 2bea785

Please sign in to comment.