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

Map range operations for NpgsqlRange<T> #323

Merged
merged 6 commits into from
May 15, 2018
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
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 @@ -50,7 +50,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