Skip to content

Commit

Permalink
Map range operations for NpgsqlRange<T> (#323)
Browse files Browse the repository at this point in the history
  • Loading branch information
austindrenski authored and roji committed May 15, 2018
1 parent 5655b1c commit 502ce2a
Show file tree
Hide file tree
Showing 5 changed files with 947 additions and 2 deletions.
168 changes: 168 additions & 0 deletions src/EFCore.PG/NpgsqlRangeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#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;
using NpgsqlTypes;

namespace Npgsql.EntityFrameworkCore.PostgreSQL
{
/// <summary>
/// Provides extension methods for <see cref="NpgsqlRange{T}"/> supporting PostgreSQL translation.
/// </summary>
public static class NpgsqlRangeExtensions
{
/// <summary>
/// Determines whether a range contains a specified value.
/// </summary>
/// <param name="range">The range in which to locate the value.</param>
/// <param name="value">The value to locate in the range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="range"/>.</typeparam>
/// <returns>
/// <value>true</value> if the range contains the specified value; otherwise, <value>false</value>.
/// </returns>
public static bool Contains<T>(this NpgsqlRange<T> range, T value) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range contains a specified range.
/// </summary>
/// <param name="a">The range in which to locate the specified range.</param>
/// <param name="b">The specified range to locate in the range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the range contains the specified range; otherwise, <value>false</value>.
/// </returns>
public static bool Contains<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range is contained by a specified range.
/// </summary>
/// <param name="a">The specified range to locate in the range.</param>
/// <param name="b">The range in which to locate the specified range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the range contains the specified range; otherwise, <value>false</value>.
/// </returns>
public static bool ContainedBy<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => b.Contains(a);

/// <summary>
/// Determines whether a range overlaps another range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the ranges overlap (share points in common); otherwise, <value>false</value>.
/// </returns>
public static bool Overlaps<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range is strictly to the left of another range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the first range is strictly to the left of the second; otherwise, <value>false</value>.
/// </returns>
public static bool IsStrictlyLeftOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range is strictly to the right of another range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the first range is strictly to the right of the second; otherwise, <value>false</value>.
/// </returns>
public static bool IsStrictlyRightOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range does not extend to the left of another range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the first range does not extend to the left of the second; otherwise, <value>false</value>.
/// </returns>
public static bool DoesNotExtendLeftOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range does not extend to the right of another range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the first range does not extend to the right of the second; otherwise, <value>false</value>.
/// </returns>
public static bool DoesNotExtendRightOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Determines whether a range is adjacent to another range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// <value>true</value> if the ranges are adjacent; otherwise, <value>false</value>.
/// </returns>
public static bool IsAdjacentTo<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Returns the set union, which means unique elements that appear in either of two ranges.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// The unique elements that appear in either range.
/// </returns>
public static NpgsqlRange<T> Union<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Returns the set intersection, which means elements that appear in each of two ranges.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// The elements that appear in both ranges.
/// </returns>
public static NpgsqlRange<T> Intersect<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();

/// <summary>
/// Returns the set difference, which means the elements of one range that do not appear in a second range.
/// </summary>
/// <param name="a">The first range.</param>
/// <param name="b">The second range.</param>
/// <typeparam name="T">The type of the elements of <paramref name="a"/>.</typeparam>
/// <returns>
/// The elements that appear in the first range, but not the second range.
/// </returns>
public static NpgsqlRange<T> Except<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotSupportedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public class NpgsqlCompositeMethodCallTranslator : RelationalCompositeMethodCall
new NpgsqlStringTrimEndTranslator(),
new NpgsqlStringTrimStartTranslator(),
new NpgsqlRegexIsMatchTranslator(),
new NpgsqlFullTextSearchMethodTranslator()
new NpgsqlFullTextSearchMethodTranslator(),
new NpgsqlRangeTranslator()
};

public NpgsqlCompositeMethodCallTranslator(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#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.ExpressionTranslators;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal
{
/// <summary>
/// Provides translation services for PostgreSQL range operators.
/// </summary>
/// <remarks>
/// See: https://www.postgresql.org/docs/current/static/functions-range.html
/// </remarks>
public class NpgsqlRangeTranslator : IMethodCallTranslator
{
/// <inheritdoc />
[CanBeNull]
public Expression Translate(MethodCallExpression expression)
{
switch (expression.Method.Name)
{
case nameof(NpgsqlRangeExtensions.Contains):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "@>", typeof(bool));

case nameof(NpgsqlRangeExtensions.ContainedBy):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "<@", typeof(bool));

case nameof(NpgsqlRangeExtensions.Overlaps):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "&&", typeof(bool));

case nameof(NpgsqlRangeExtensions.IsStrictlyLeftOf):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "<<", typeof(bool));

case nameof(NpgsqlRangeExtensions.IsStrictlyRightOf):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], ">>", typeof(bool));

case nameof(NpgsqlRangeExtensions.DoesNotExtendRightOf):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "&<", typeof(bool));

case nameof(NpgsqlRangeExtensions.DoesNotExtendLeftOf):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "&>", typeof(bool));

case nameof(NpgsqlRangeExtensions.IsAdjacentTo):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "-|-", typeof(bool));

case nameof(NpgsqlRangeExtensions.Union):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "+", expression.Arguments[0].Type);

case nameof(NpgsqlRangeExtensions.Intersect):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "*", expression.Arguments[0].Type);

case nameof(NpgsqlRangeExtensions.Except):
return new CustomBinaryExpression(expression.Arguments[0], expression.Arguments[1], "-", expression.Arguments[0].Type);

default:
return null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.1.0-rtm-30736" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.1.0-rtm-30736" />
</ItemGroup>
</Project>
</Project>
Loading

0 comments on commit 502ce2a

Please sign in to comment.