-
Notifications
You must be signed in to change notification settings - Fork 228
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
Changes from 3 commits
4e1820d
403908a
35f7d00
7fb701c
ed0b754
fc9ff22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
#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 Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators; | ||
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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.Contains)] | ||
public static bool Contains<T>(this NpgsqlRange<T> range, T value) where T : IComparable<T> => throw new NotImplementedException(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should throw |
||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.Contains)] | ||
public static bool Contains<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.ContainedBy)] | ||
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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.Overlaps)] | ||
public static bool Overlaps<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.IsStrictlyLeftOf)] | ||
public static bool IsStrictlyLeftOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.IsStrictlyRightOf)] | ||
public static bool IsStrictlyRightOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.DoesNotExtendLeftOf)] | ||
public static bool DoesNotExtendLeftOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.DoesNotExtendRightOf)] | ||
public static bool DoesNotExtendRightOf<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.IsAdjacentTo)] | ||
public static bool IsAdjacentTo<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.Union)] | ||
public static NpgsqlRange<T> Union<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.Intersection)] | ||
public static NpgsqlRange<T> Intersect<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
|
||
/// <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> | ||
[NpgsqlRangeOperator(NpgsqlRangeOperatorType.Difference)] | ||
public static NpgsqlRange<T> Except<T>(this NpgsqlRange<T> a, NpgsqlRange<T> b) where T : IComparable<T> => throw new NotImplementedException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#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 System.Linq.Expressions; | ||
using JetBrains.Annotations; | ||
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal; | ||
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities; | ||
|
||
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal | ||
{ | ||
/// <summary> | ||
/// Represents information about a PostgreSQL operator. | ||
/// </summary> | ||
/// <remarks> | ||
/// This attribute stores metadata describing the representation of a binary operator | ||
/// in PostgreSQL on enum members representing the available binary operators for a PostgreSQL type. | ||
/// </remarks> | ||
[AttributeUsage(AttributeTargets.Field)] | ||
internal class NpgsqlBinaryOperatorAttribute : Attribute | ||
{ | ||
/// <summary> | ||
/// The operator symbol. | ||
/// </summary> | ||
[NotNull] | ||
public string Symbol { get; set; } = string.Empty; | ||
|
||
/// <summary> | ||
/// The operator represented by the method. | ||
/// </summary> | ||
[NotNull] | ||
public Type ReturnType { get; set; } = typeof(void); | ||
|
||
/// <summary> | ||
/// Creates a <see cref="CustomBinaryExpression"/> representing the operator. | ||
/// </summary> | ||
/// <param name="left"> | ||
/// The left-hand expression. | ||
/// </param> | ||
/// <param name="right"> | ||
/// The right-hand expression. | ||
/// </param> | ||
/// <returns> | ||
/// A <see cref="CustomBinaryExpression"/> representing the operator. | ||
/// </returns> | ||
/// <exception cref="ArgumentNullException"/> | ||
[NotNull] | ||
public Expression Create([NotNull] Expression left, [NotNull] Expression right) | ||
{ | ||
Check.NotNull(left, nameof(left)); | ||
Check.NotNull(right, nameof(right)); | ||
|
||
// TODO: will the left type arguments always be valid? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my general comment about the architecture. Simply moving all the logic into the translator makes this go away, as you'd be translating each operation separately and can make this decision on a per-operation basis. |
||
Type type = ReturnType.IsGenericType ? ReturnType.MakeGenericType(left.Type.GetGenericArguments()) : ReturnType; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: please use |
||
|
||
return new CustomBinaryExpression(left, right, Symbol, type); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: here and below, why not put the
<param>
and<typeparam>
in a single line:/// <param name="range">The range in which to locate the value</param>
This seems to be standard in the .NET / EF Core code bases and reduces lots of useless lines