diff --git a/src/EFCore.PG/NpgsqlRangeExtensions.cs b/src/EFCore.PG/NpgsqlRangeExtensions.cs
new file mode 100644
index 000000000..d50b555bf
--- /dev/null
+++ b/src/EFCore.PG/NpgsqlRangeExtensions.cs
@@ -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
+{
+ ///
+ /// Provides extension methods for supporting PostgreSQL translation.
+ ///
+ public static class NpgsqlRangeExtensions
+ {
+ ///
+ /// Determines whether a range contains a specified value.
+ ///
+ /// The range in which to locate the value.
+ /// The value to locate in the range.
+ /// The type of the elements of .
+ ///
+ /// true if the range contains the specified value; otherwise, false.
+ ///
+ public static bool Contains(this NpgsqlRange range, T value) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range contains a specified range.
+ ///
+ /// The range in which to locate the specified range.
+ /// The specified range to locate in the range.
+ /// The type of the elements of .
+ ///
+ /// true if the range contains the specified range; otherwise, false.
+ ///
+ public static bool Contains(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range is contained by a specified range.
+ ///
+ /// The specified range to locate in the range.
+ /// The range in which to locate the specified range.
+ /// The type of the elements of .
+ ///
+ /// true if the range contains the specified range; otherwise, false.
+ ///
+ public static bool ContainedBy(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => b.Contains(a);
+
+ ///
+ /// Determines whether a range overlaps another range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// true if the ranges overlap (share points in common); otherwise, false.
+ ///
+ public static bool Overlaps(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range is strictly to the left of another range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// true if the first range is strictly to the left of the second; otherwise, false.
+ ///
+ public static bool IsStrictlyLeftOf(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range is strictly to the right of another range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// true if the first range is strictly to the right of the second; otherwise, false.
+ ///
+ public static bool IsStrictlyRightOf(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range does not extend to the left of another range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// true if the first range does not extend to the left of the second; otherwise, false.
+ ///
+ public static bool DoesNotExtendLeftOf(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range does not extend to the right of another range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// true if the first range does not extend to the right of the second; otherwise, false.
+ ///
+ public static bool DoesNotExtendRightOf(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Determines whether a range is adjacent to another range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// true if the ranges are adjacent; otherwise, false.
+ ///
+ public static bool IsAdjacentTo(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Returns the set union, which means unique elements that appear in either of two ranges.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// The unique elements that appear in either range.
+ ///
+ public static NpgsqlRange Union(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Returns the set intersection, which means elements that appear in each of two ranges.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// The elements that appear in both ranges.
+ ///
+ public static NpgsqlRange Intersect(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+
+ ///
+ /// Returns the set difference, which means the elements of one range that do not appear in a second range.
+ ///
+ /// The first range.
+ /// The second range.
+ /// The type of the elements of .
+ ///
+ /// The elements that appear in the first range, but not the second range.
+ ///
+ public static NpgsqlRange Except(this NpgsqlRange a, NpgsqlRange b) where T : IComparable => throw new NotSupportedException();
+ }
+}
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs
index 54feb84ab..3011d4b67 100644
--- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs
@@ -50,7 +50,8 @@ public class NpgsqlCompositeMethodCallTranslator : RelationalCompositeMethodCall
new NpgsqlStringTrimEndTranslator(),
new NpgsqlStringTrimStartTranslator(),
new NpgsqlRegexIsMatchTranslator(),
- new NpgsqlFullTextSearchMethodTranslator()
+ new NpgsqlFullTextSearchMethodTranslator(),
+ new NpgsqlRangeTranslator()
};
public NpgsqlCompositeMethodCallTranslator(
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlRangeTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlRangeTranslator.cs
new file mode 100644
index 000000000..39127c444
--- /dev/null
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlRangeTranslator.cs
@@ -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
+{
+ ///
+ /// Provides translation services for PostgreSQL range operators.
+ ///
+ ///
+ /// See: https://www.postgresql.org/docs/current/static/functions-range.html
+ ///
+ public class NpgsqlRangeTranslator : IMethodCallTranslator
+ {
+ ///
+ [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;
+ }
+ }
+ }
+}
diff --git a/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj b/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
index 050106099..e6f2d8420 100644
--- a/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
+++ b/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
@@ -26,4 +26,4 @@
-
+
\ No newline at end of file
diff --git a/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs
new file mode 100644
index 000000000..c31d32016
--- /dev/null
+++ b/test/EFCore.PG.FunctionalTests/Query/RangeQueryNpgsqlTest.cs
@@ -0,0 +1,691 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.TestUtilities;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
+using NpgsqlTypes;
+using Xunit;
+
+namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query
+{
+ ///
+ /// Provides unit tests for range operator translations.
+ ///
+ public class RangeQueryNpgsqlTest : IClassFixture
+ {
+ ///
+ /// Provides resources for unit tests.
+ ///
+ RangeQueryNpgsqlFixture Fixture { get; }
+
+ ///
+ /// Initializes resources for unit tests.
+ ///
+ /// The fixture of resources for testing.
+ public RangeQueryNpgsqlTest(RangeQueryNpgsqlFixture fixture)
+ {
+ Fixture = fixture;
+ Fixture.TestSqlLoggerFactory.Clear();
+ }
+
+ #region Tests
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeContainsRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.Contains(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" @> @__range_0 = TRUE");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesNotContainRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.Contains(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" @> @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(IntegerTheoryData))]
+ public void RangeContainsValue(int value)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.Contains(value))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" @> @__value_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(IntegerTheoryData))]
+ public void RangeDoesNotContainValue(int value)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.Contains(value))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" @> @__value_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeContainedByRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => range.ContainedBy(x.Range))
+ .ToArray();
+
+ AssertContainsSql("WHERE @__range_0 <@ x.\"Range\" = TRUE");
+ }
+ }
+
+ ///
+ /// Tests inverse containment translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeNotContainedByRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !range.ContainedBy(x.Range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (@__range_0 <@ x.\"Range\" = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for via the symbolic operator.
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeEqualsRange_Operator(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range == range)
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" = @__range_0");
+ }
+ }
+
+ ///
+ /// Tests translation for via method call.
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeEqualsRange_Method(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.Equals(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" = @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for via symbolic operator.
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesNotEqualsRange_Operator(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range != range)
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" <> @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for via method call.
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesNotEqualsRange_Method(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.Equals(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" <> @__range_0");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeOvelapsRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.Overlaps(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" && @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesNotOvelapRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.Overlaps(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" && @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIsStrictlyLeftOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.IsStrictlyLeftOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" << @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIsNotStrictlyLeftOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.IsStrictlyLeftOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" << @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIsStrictlyRightOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.IsStrictlyRightOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" >> @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIsNotStrictlyRightOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.IsStrictlyRightOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" >> @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesNotExtendLeftOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.DoesNotExtendLeftOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" &> @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesExtendLeftOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.DoesNotExtendLeftOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" &> @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesNotExtendRightOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.DoesNotExtendRightOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" &< @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeDoesExtendRightOfRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.DoesNotExtendRightOf(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" &< @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIsAdjacentToRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => x.Range.IsAdjacentTo(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE x.\"Range\" -|- @__range_0");
+ }
+ }
+
+ ///
+ /// Tests inverse translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIsNotAdjacentToRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ RangeTestEntity[] _ =
+ context.RangeTestEntities
+ .Where(x => !x.Range.IsAdjacentTo(range))
+ .ToArray();
+
+ AssertContainsSql("WHERE NOT (x.\"Range\" -|- @__range_0 = TRUE)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeUnionRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ NpgsqlRange[] _ =
+ context.RangeTestEntities
+ .Select(x => x.Range.Union(range))
+ .ToArray();
+
+ AssertContainsSql("SELECT x.\"Range\" + @__range_0");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeIntersectsRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ NpgsqlRange[] _ =
+ context.RangeTestEntities
+ .Select(x => x.Range.Intersect(range))
+ .ToArray();
+
+ AssertContainsSql("SELECT x.\"Range\" * @__range_0");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Theory]
+ [MemberData(nameof(RangeTheoryData))]
+ public void RangeExceptRange(NpgsqlRange range)
+ {
+ using (RangeContext context = Fixture.CreateContext())
+ {
+ try
+ {
+ NpgsqlRange[] _ =
+ context.RangeTestEntities
+ .Select(x => x.Range.Except(range))
+ .ToArray();
+ }
+ catch (PostgresException)
+ {
+ // ignore: Npgsql.PostgresException : 22000: result of range difference would not be contiguous.
+ }
+
+ AssertContainsSql("SELECT x.\"Range\" - @__range_0");
+ }
+ }
+
+ #endregion Tests
+
+ #region TheoryData
+
+ ///
+ /// Provides theory data for integers.
+ ///
+ public static IEnumerable