diff --git a/src/EFCore.PG/Extensions/NpgsqlNetworkExtensions.cs b/src/EFCore.PG/Extensions/NpgsqlNetworkExtensions.cs
new file mode 100644
index 000000000..4f28c218a
--- /dev/null
+++ b/src/EFCore.PG/Extensions/NpgsqlNetworkExtensions.cs
@@ -0,0 +1,1090 @@
+#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.Net;
+using System.Net.NetworkInformation;
+using System.Runtime.CompilerServices;
+using JetBrains.Annotations;
+
+// ReSharper disable once CheckNamespace
+namespace Microsoft.EntityFrameworkCore
+{
+ ///
+ /// Provides extension methods supporting operator translation for PostgreSQL network types.
+ ///
+ ///
+ /// See: https://www.postgresql.org/docs/current/static/functions-net.html
+ ///
+ public static class NpgsqlNetworkExtensions
+ {
+ #region RelationalOperators
+
+ ///
+ /// Determines whether an is less than another .
+ ///
+ /// The instance.
+ /// The left-hand inet.
+ /// The right-hand inet.
+ ///
+ /// True if the is less than the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool LessThan([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) is less than another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The left-hand cidr.
+ /// The right-hand cidr.
+ ///
+ /// True if the (IPAddress Address, int Subnet) is less than the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool LessThan([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is less than another .
+ ///
+ /// The instance.
+ /// The left-hand macaddr.
+ /// The right-hand macaddr.
+ ///
+ /// True if the is less than the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool LessThan([CanBeNull] this DbFunctions _, PhysicalAddress macaddr, PhysicalAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is less than or equal to another .
+ ///
+ /// The instance.
+ /// The left-hand inet.
+ /// The right-hand inet.
+ ///
+ /// True if the is less than or equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool LessThanOrEqual([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) is less than or equal to another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The left-hand cidr.
+ /// The right-hand cidr.
+ ///
+ /// True if the (IPAddress Address, int Subnet) is less than or equal to the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool LessThanOrEqual([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is less than or equal to another .
+ ///
+ /// The instance.
+ /// The left-hand macaddr.
+ /// The right-hand macaddr.
+ ///
+ /// True if the is less than or equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool LessThanOrEqual([CanBeNull] this DbFunctions _, PhysicalAddress macaddr, PhysicalAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is greater than or equal to another .
+ ///
+ /// The instance.
+ /// The left-hand inet.
+ /// The right-hand inet.
+ ///
+ /// True if the is greater than or equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool GreaterThanOrEqual([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) is greater than or equal to another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The left-hand cidr.
+ /// The right-hand cidr.
+ ///
+ /// True if the (IPAddress Address, int Subnet) is greater than or equal to the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool GreaterThanOrEqual([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is greater than or equal to another .
+ ///
+ /// The instance.
+ /// The left-hand macaddr.
+ /// The right-hand macaddr.
+ ///
+ /// True if the is greater than or equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool GreaterThanOrEqual([CanBeNull] this DbFunctions _, PhysicalAddress macaddr, PhysicalAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is greater than another .
+ ///
+ /// The instance.
+ /// The left-hand inet.
+ /// The right-hand inet.
+ ///
+ /// True if the is greater than the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool GreaterThan([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) is greater than another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The left-hand cidr.
+ /// The right-hand cidr.
+ ///
+ /// True if the (IPAddress Address, int Subnet) is greater than the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool GreaterThan([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is greater than another .
+ ///
+ /// The instance.
+ /// The left-hand macaddr.
+ /// The right-hand macaddr.
+ ///
+ /// True if the is greater than the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool GreaterThan([CanBeNull] this DbFunctions _, PhysicalAddress macaddr, PhysicalAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ #endregion
+
+ #region ContainmentOperators
+
+ ///
+ /// Determines whether an is contained within another .
+ ///
+ /// The instance.
+ /// The inet to locate.
+ /// The inet to search.
+ ///
+ /// True if the is contained within the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainedBy([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is contained within a network.
+ ///
+ /// The instance.
+ /// The inet to locate.
+ /// The cidr to search.
+ ///
+ /// True if the is contained within the network; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainedBy([CanBeNull] this DbFunctions _, IPAddress inet, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) is contained within another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr to locate.
+ /// The cidr to search.
+ ///
+ /// True if the (IPAddress Address, int Subnet) is contained within the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainedBy([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is contained within or equal to another .
+ ///
+ /// The instance.
+ /// The inet to locate.
+ /// The inet to search.
+ ///
+ /// True if the is contained within or equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainedByOrEqual([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an is contained within or equal to a network.
+ ///
+ /// The instance.
+ /// The inet to locate.
+ /// The cidr to search.
+ ///
+ /// True if the is contained within or equal to the network; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainedByOrEqual([CanBeNull] this DbFunctions _, IPAddress inet, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) is contained within or equal to another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr to locate.
+ /// The cidr to search.
+ ///
+ /// True if the (IPAddress Address, int Subnet) is contained within or equal to the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainedByOrEqual([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an contains another .
+ ///
+ /// The instance.
+ /// The IP address to search.
+ /// The IP address to locate.
+ ///
+ /// True if the contains the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool Contains([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether a network contains another .
+ ///
+ /// The instance.
+ /// The network to search.
+ /// The IP address to locate.
+ ///
+ /// True if the network contains the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool Contains([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) contains another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr to search.
+ /// The cidr to locate.
+ ///
+ /// True if the (IPAddress Address, int Subnet) contains the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool Contains([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an contains or is equal to another .
+ ///
+ /// The instance.
+ /// The IP address to search.
+ /// The IP address to locate.
+ ///
+ /// True if the contains or is equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrEqual([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether a network contains or is equal to another .
+ ///
+ /// The instance.
+ /// The network to search.
+ /// The IP address to locate.
+ ///
+ /// True if the network contains or is equal to the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrEqual([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) contains or is equal to another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr to search.
+ /// The cidr to locate.
+ ///
+ /// True if the (IPAddress Address, int Subnet) contains or is equal to the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrEqual([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an contains or is contained by another .
+ ///
+ /// The instance.
+ /// The IP address to search.
+ /// The IP address to locate.
+ ///
+ /// True if the contains or is contained by the other ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrContainedBy([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether a network contains or is contained by an .
+ ///
+ /// The instance.
+ /// The network to search.
+ /// The IP address to locate.
+ ///
+ /// True if the network contains or is contained by the ; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrContainedBy([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an contains or is contained by a network.
+ ///
+ /// The instance.
+ /// The IP address to search.
+ /// The network to locate.
+ ///
+ /// True if the contains or is contained by the network; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrContainedBy([CanBeNull] this DbFunctions _, IPAddress inet, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Determines whether an (IPAddress Address, int Subnet) contains or is contained by another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr to search.
+ /// The cidr to locate.
+ ///
+ /// True if the (IPAddress Address, int Subnet) contains or is contained by the other (IPAddress Address, int Subnet); otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool ContainsOrContainedBy([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ #endregion
+
+ #region BitwiseOperators
+
+ ///
+ /// Computes the bitwise NOT operation on an .
+ ///
+ /// The instance.
+ /// The inet to negate.
+ ///
+ /// The result of the bitwise NOT operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress BitwiseNot([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise NOT operation on an (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr to negate.
+ ///
+ /// The result of the bitwise NOT operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) BitwiseNot([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise NOT operation on an .
+ ///
+ /// The instance.
+ /// The macaddr to negate.
+ ///
+ /// The result of the bitwise NOT operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static PhysicalAddress BitwiseNot([CanBeNull] this DbFunctions _, PhysicalAddress macaddr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise AND of two instances.
+ ///
+ /// The instance.
+ /// The left-hand inet.
+ /// The right-hand inet.
+ ///
+ /// The result of the bitwise AND operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress BitwiseAnd([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise AND of two (IPAddress Address, int Subnet) instances.
+ ///
+ /// The instance.
+ /// The left-hand cidr.
+ /// The right-hand cidr.
+ ///
+ /// The result of the bitwise AND operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) BitwiseAnd([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise AND of two instances.
+ ///
+ /// The instance.
+ /// The left-hand macaddr.
+ /// The right-hand macaddr.
+ ///
+ /// The result of the bitwise AND operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static PhysicalAddress BitwiseAnd([CanBeNull] this DbFunctions _, PhysicalAddress macaddr, PhysicalAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise OR of two instances.
+ ///
+ /// The instance.
+ /// The left-hand inet.
+ /// The right-hand inet.
+ ///
+ /// The result of the bitwise OR operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress BitwiseOr([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise OR of two (IPAddress Address, int Subnet) instances.
+ ///
+ /// The instance.
+ /// The left-hand cidr.
+ /// The right-hand cidr.
+ ///
+ /// The result of the bitwise OR operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) BitwiseOr([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Computes the bitwise OR of two instances.
+ ///
+ /// The instance.
+ /// The left-hand macaddr.
+ /// The right-hand macaddr.
+ ///
+ /// The result of the bitwise OR operation.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static PhysicalAddress BitwiseOr([CanBeNull] this DbFunctions _, PhysicalAddress macaddr, PhysicalAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ #endregion
+
+ #region ArithmeticOperators
+
+ ///
+ /// Adds the to the .
+ ///
+ /// The instance.
+ /// The inet.
+ /// The value to add.
+ ///
+ /// The augmented by the .
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Add([CanBeNull] this DbFunctions _, IPAddress inet, int value)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Adds the to the (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr.
+ /// The value to add.
+ ///
+ /// The (IPAddress Address, int Subnet) augmented by the .
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Add([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, int value)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Subtracts the from the .
+ ///
+ /// The instance.
+ /// The inet.
+ /// The value to subtract.
+ ///
+ /// The augmented by the .
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Subtract([CanBeNull] this DbFunctions _, IPAddress inet, int value)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Subtracts the from the (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The inet.
+ /// The value to subtract.
+ ///
+ /// The (IPAddress Address, int Subnet) augmented by the .
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Subtract([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, int value)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Subtracts one from another .
+ ///
+ /// The instance.
+ /// The inet from which to subtract.
+ /// The inet to subtract.
+ ///
+ /// The augmented by the .
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Subtract([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Subtracts one (IPAddress Address, int Subnet) from another (IPAddress Address, int Subnet).
+ ///
+ /// The instance.
+ /// The cidr from which to subtract.
+ /// The cidr to subtract.
+ ///
+ /// The (IPAddress Address, int Subnet) augmented by the .
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Subtract([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ #endregion
+
+ #region Functions
+
+ ///
+ /// Returns the abbreviated display format as text.
+ ///
+ /// The instance.
+ /// The inet to abbreviate.
+ ///
+ /// The abbreviated display format as text.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static string Abbreviate([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Returns the abbreviated display format as text.
+ ///
+ /// The instance.
+ /// The cidr to abbreviate.
+ ///
+ /// The abbreviated display format as text.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static string Abbreviate([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Returns the broadcast address for a network.
+ ///
+ /// The instance.
+ /// The inet used to derive the broadcast address.
+ ///
+ /// The broadcast address for a network.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Broadcast([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Returns the broadcast address for a network.
+ ///
+ /// The instance.
+ /// The cidr used to derive the broadcast address.
+ ///
+ /// The broadcast address for a network.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Broadcast([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the family of an address; 4 for IPv4, 6 for IPv6.
+ ///
+ /// The instance.
+ /// The inet used to derive the family.
+ ///
+ /// The family of an address; 4 for IPv4, 6 for IPv6.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static int Family([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the family of an address; 4 for IPv4, 6 for IPv6.
+ ///
+ /// The instance.
+ /// The cidr used to derive the family.
+ ///
+ /// The family of an address; 4 for IPv4, 6 for IPv6.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static int Family([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the host (i.e. the IP address) as text.
+ ///
+ /// The instance.
+ /// The inet from which to extract the host.
+ ///
+ /// The host (i.e. the IP address) as text.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static string Host([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the host (i.e. the IP address) as text.
+ ///
+ /// The instance.
+ /// The cidr from which to extract the host.
+ ///
+ /// The host (i.e. the IP address) as text.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static string Host([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Constructs the host mask for the network.
+ ///
+ /// The instance.
+ /// The inet used to construct the host mask.
+ ///
+ /// The constructed host mask.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress HostMask([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Constructs the host mask for the network.
+ ///
+ /// The instance.
+ /// The cidr used to construct the host mask.
+ ///
+ /// The constructed host mask.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress HostMask([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the length of the subnet mask.
+ ///
+ /// The instance.
+ /// The inet used to extract the subnet length.
+ ///
+ /// The length of the subnet mask.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static int MaskLength([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the length of the subnet mask.
+ ///
+ /// The instance.
+ /// The cidr used to extract the subnet length.
+ ///
+ /// The length of the subnet mask.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static int MaskLength([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Constructs the subnet mask for the network.
+ ///
+ /// The instance.
+ /// The inet used to construct the subnet mask.
+ ///
+ /// The subnet mask for the network.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Netmask([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Constructs the subnet mask for the network.
+ ///
+ /// The instance.
+ /// The cidr used to construct the subnet mask.
+ ///
+ /// The subnet mask for the network.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress Netmask([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the network part of the address.
+ ///
+ /// The instance.
+ /// The inet used to extract the network.
+ ///
+ /// The network part of the address.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Network([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the network part of the address.
+ ///
+ /// The instance.
+ /// The cidr used to extract the network.
+ ///
+ /// The network part of the address.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Network([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Sets the length of the subnet mask.
+ ///
+ /// The instance.
+ /// The inet to modify.
+ /// The subnet mask length to set.
+ ///
+ /// The network with a subnet mask of the specified length.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static IPAddress SetMaskLength([CanBeNull] this DbFunctions _, IPAddress inet, int length)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Sets the length of the subnet mask.
+ ///
+ /// The instance.
+ /// The cidr to modify.
+ /// The subnet mask length to set.
+ ///
+ /// The network with a subnet mask of the specified length.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) SetMaskLength([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, int length)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the IP address and subnet mask as text.
+ ///
+ /// The instance.
+ /// The inet to extract as text.
+ ///
+ /// The IP address and subnet mask as text.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static string Text([CanBeNull] this DbFunctions _, IPAddress inet)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Extracts the IP address and subnet mask as text.
+ ///
+ /// The instance.
+ /// The cidr to extract as text.
+ ///
+ /// The IP address and subnet mask as text.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static string Text([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Tests if the addresses are in the same family.
+ ///
+ /// The instance.
+ /// The primary inet.
+ /// The other inet.
+ ///
+ /// True if the addresses are in the same family; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool SameFamily([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Tests if the addresses are in the same family.
+ ///
+ /// The instance.
+ /// The primary cidr.
+ /// The other cidr.
+ ///
+ /// True if the addresses are in the same family; otherwise, false.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static bool SameFamily([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Constructs the smallest network which includes both of the given networks.
+ ///
+ /// The instance.
+ /// The first inet.
+ /// The second inet.
+ ///
+ /// The smallest network which includes both of the given networks.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Merge([CanBeNull] this DbFunctions _, IPAddress inet, IPAddress other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Constructs the smallest network which includes both of the given networks.
+ ///
+ /// The instance.
+ /// The first cidr.
+ /// The second cidr.
+ ///
+ /// The smallest network which includes both of the given networks.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static (IPAddress Address, int Subnet) Merge([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Sets the last 3 bytes of the MAC address to zero. For macaddr8, the last 5 bytes are set to zero.
+ ///
+ /// The instance.
+ /// The MAC address to truncate.
+ ///
+ /// The MAC address with the last 3 bytes set to zero. For macaddr8, the last 5 bytes are set to zero.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static PhysicalAddress Truncate([CanBeNull] this DbFunctions _, PhysicalAddress macAddress)
+ => throw ClientEvaluationNotSupportedException();
+
+ ///
+ /// Sets the 7th bit to one, also known as modified EUI-64, for inclusion in an IPv6 address.
+ ///
+ /// The instance.
+ /// The MAC address to modify.
+ ///
+ /// The MAC address with the 7th bit set to one.
+ ///
+ ///
+ /// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
+ ///
+ public static PhysicalAddress Set7BitMac8([CanBeNull] this DbFunctions _, PhysicalAddress macAddress)
+ => throw ClientEvaluationNotSupportedException();
+
+ #endregion
+
+ #region Utilities
+
+ ///
+ /// Helper method to throw a with the name of the throwing method.
+ ///
+ /// The method that throws the exception.
+ ///
+ /// A .
+ ///
+ [NotNull]
+ static NotSupportedException ClientEvaluationNotSupportedException([CallerMemberName] string method = default)
+ => new NotSupportedException($"{method} is only intended for use via SQL translation as part of an EF Core LINQ query.");
+
+ #endregion
+ }
+}
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs
index 709e65836..131ac6988 100644
--- a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlCompositeMethodCallTranslator.cs
@@ -59,7 +59,8 @@ public class NpgsqlCompositeMethodCallTranslator : RelationalCompositeMethodCall
new NpgsqlStringTrimStartTranslator(),
new NpgsqlRegexIsMatchTranslator(),
new NpgsqlFullTextSearchMethodTranslator(),
- new NpgsqlRangeTranslator()
+ new NpgsqlRangeTranslator(),
+ new NpgsqlNetworkTranslator()
};
///
diff --git a/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlNetworkTranslator.cs b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlNetworkTranslator.cs
new file mode 100644
index 000000000..a9fd81a0e
--- /dev/null
+++ b/src/EFCore.PG/Query/ExpressionTranslators/Internal/NpgsqlNetworkTranslator.cs
@@ -0,0 +1,143 @@
+#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 System.Net;
+using System.Net.NetworkInformation;
+using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Query.Expressions;
+using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Query.Expressions.Internal;
+
+namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal
+{
+ ///
+ /// Provides translation services for operators and functions of PostgreSQL network typess (cidr, inet, macaddr, macaddr8).
+ ///
+ ///
+ /// See: https://www.postgresql.org/docs/current/static/functions-net.html
+ ///
+ public class NpgsqlNetworkTranslator : IMethodCallTranslator
+ {
+ ///
+ [CanBeNull]
+ public Expression Translate(MethodCallExpression expression)
+ {
+ if (expression.Method.DeclaringType != typeof(NpgsqlNetworkExtensions))
+ return null;
+
+ switch (expression.Method.Name)
+ {
+ case nameof(NpgsqlNetworkExtensions.LessThan):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "<", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.LessThanOrEqual):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "<=", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.GreaterThanOrEqual):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], ">=", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.GreaterThan):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], ">", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.ContainedBy):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "<<", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.ContainedByOrEqual):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "<<=", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.Contains):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], ">>", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.ContainsOrEqual):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], ">>=", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.ContainsOrContainedBy):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "&&", typeof(bool));
+
+ case nameof(NpgsqlNetworkExtensions.BitwiseNot):
+ return new CustomUnaryExpression(expression.Arguments[1], "~", expression.Arguments[1].Type);
+
+ case nameof(NpgsqlNetworkExtensions.BitwiseAnd):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "&", expression.Arguments[1].Type);
+
+ case nameof(NpgsqlNetworkExtensions.BitwiseOr):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "|", expression.Arguments[1].Type);
+
+ case nameof(NpgsqlNetworkExtensions.Add):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "+", expression.Arguments[1].Type);
+
+ case nameof(NpgsqlNetworkExtensions.Subtract):
+ return new CustomBinaryExpression(expression.Arguments[1], expression.Arguments[2], "-", expression.Arguments[1].Type);
+
+ case nameof(NpgsqlNetworkExtensions.Abbreviate):
+ return new SqlFunctionExpression("abbrev", typeof(string), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.Broadcast):
+ return new SqlFunctionExpression("broadcast", typeof(IPAddress), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.Family):
+ return new SqlFunctionExpression("family", typeof(int), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.Host):
+ return new SqlFunctionExpression("host", typeof(string), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.HostMask):
+ return new SqlFunctionExpression("hostmask", typeof(IPAddress), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.MaskLength):
+ return new SqlFunctionExpression("masklen", typeof(int), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.Netmask):
+ return new SqlFunctionExpression("netmask", typeof(IPAddress), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.Network):
+ return new SqlFunctionExpression("network", typeof((IPAddress Address, int Subnet)), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.SetMaskLength):
+ return new SqlFunctionExpression("set_masklen", expression.Arguments[1].Type, new[] { expression.Arguments[1], expression.Arguments[2] });
+
+ case nameof(NpgsqlNetworkExtensions.Text):
+ return new SqlFunctionExpression("text", typeof(string), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.SameFamily):
+ return new SqlFunctionExpression("inet_same_family", typeof(bool), new[] { expression.Arguments[1], expression.Arguments[2] });
+
+ case nameof(NpgsqlNetworkExtensions.Merge):
+ return new SqlFunctionExpression("inet_merge", typeof((IPAddress Address, int Subnet)), new[] { expression.Arguments[1], expression.Arguments[2] });
+
+ case nameof(NpgsqlNetworkExtensions.Truncate):
+ return new SqlFunctionExpression("trunc", typeof(PhysicalAddress), new[] { expression.Arguments[1] });
+
+ case nameof(NpgsqlNetworkExtensions.Set7BitMac8):
+ return new SqlFunctionExpression("macaddr8_set7bit", typeof(PhysicalAddress), new[] { expression.Arguments[1] });
+
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj b/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
index 995cdaa61..31000562e 100644
--- a/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
+++ b/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj
@@ -7,6 +7,7 @@
../../Npgsql.snk
true
true
+ latest
diff --git a/test/EFCore.PG.FunctionalTests/Query/NetworkQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NetworkQueryNpgsqlTest.cs
new file mode 100644
index 000000000..51468ca9c
--- /dev/null
+++ b/test/EFCore.PG.FunctionalTests/Query/NetworkQueryNpgsqlTest.cs
@@ -0,0 +1,1616 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.TestUtilities;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Npgsql.EntityFrameworkCore.PostgreSQL.TestUtilities;
+using Xunit;
+
+namespace Npgsql.EntityFrameworkCore.PostgreSQL.Query
+{
+ ///
+ /// Provides unit tests for network address operator and function translations.
+ ///
+ ///
+ /// See: https://www.postgresql.org/docs/current/static/functions-net.html
+ ///
+ public class NetworkQueryNpgsqlTest : IClassFixture
+ {
+ #region Setup
+
+ ///
+ /// Provides resources for unit tests.
+ ///
+ NetworkAddressQueryNpgsqlFixture Fixture { get; }
+
+ ///
+ /// Initializes resources for unit tests.
+ ///
+ /// The fixture of resources for testing.
+ public NetworkQueryNpgsqlTest(NetworkAddressQueryNpgsqlFixture fixture)
+ {
+ Fixture = fixture;
+ Fixture.TestSqlLoggerFactory.Clear();
+ }
+
+ #endregion
+
+ #region BugTests
+
+ ///
+ /// Demonstrates parameter duplication.
+ ///
+ [Fact(Skip = nameof(NetworkQueryNpgsqlTest))]
+ public void Demonstrate_ValueTypeParametersAreDuplicated()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ bool[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrEqual(x.Cidr, cidr))
+ .Select(x => x.Cidr.Equals(cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT x.\"Cidr\" = @__cidr_1 = TRUE");
+ AssertContainsSql("WHERE x.\"Cidr\" >>= @__cidr_1 = TRUE");
+ }
+ }
+
+ #endregion
+
+ #region RelationalOperatorTests
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_LessThan_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThan(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" < @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_LessThan_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThan(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" < @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_LessThan_macaddr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress macaddr = new PhysicalAddress(new byte[6]);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThan(x.Macaddr, macaddr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr\" < @__macaddr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_LessThan_macaddr8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThan(x.Macaddr8, x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr8\" < x.\"Macaddr8\") = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_LessThanOrEqual_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThanOrEqual(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" <= @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_LessThanOrEqual_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThanOrEqual(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" <= @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_LessThanOrEqual_macaddr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress macaddr = new PhysicalAddress(new byte[6]);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThanOrEqual(x.Macaddr, macaddr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr\" <= @__macaddr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_LessThanOrEqual_macaddr8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.LessThanOrEqual(x.Macaddr8, x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr8\" <= x.\"Macaddr8\") = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_GreaterThanOrEqual_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThanOrEqual(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" >= @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_GreaterThanOrEqual_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThanOrEqual(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" >= @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_GreaterThanOrEqual_macaddr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress macaddr = new PhysicalAddress(new byte[6]);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThanOrEqual(x.Macaddr, macaddr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr\" >= @__macaddr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_GreaterThanOrEqual_macaddr8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThanOrEqual(x.Macaddr8, x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr8\" >= x.\"Macaddr8\") = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_GreaterThan_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThan(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" > @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_GreaterThan_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThan(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" > @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_GreaterThan_macaddr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress macaddr = new PhysicalAddress(new byte[6]);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThan(x.Macaddr, macaddr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr\" > @__macaddr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_GreaterThan_macaddr8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.GreaterThan(x.Macaddr8, x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Macaddr8\" > x.\"Macaddr8\") = TRUE");
+ }
+ }
+
+ #endregion
+
+ #region ContainmentOperatorTests
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainedBy_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainedBy(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" << @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainedBy_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainedBy(x.Inet, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" << @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_ContainedBy_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainedBy(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" << @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainedByOrEqual_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainedByOrEqual(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" <<= @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainedByOrEqual_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainedByOrEqual(x.Inet, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" <<= @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_ContainedByOrEqual_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainedByOrEqual(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" <<= @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Contains_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.Contains(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" >> @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Contains_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.Contains(x.Cidr, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" >> @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Contains_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.Contains(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" >> @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainsOrEqual_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrEqual(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" >>= @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_ContainsOrEqual_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrEqual(x.Cidr, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" >>= @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_ContainsOrEqual_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrEqual(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" >>= @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainsOrContainedBy_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrContainedBy(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" && @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_ContainsOrContainedBy_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrContainedBy(x.Inet, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Inet\" && @__cidr_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_ContainsOrContainedBy_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrContainedBy(x.Cidr, inet))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" && @__inet_1) = TRUE");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_ContainsOrContainedBy_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ NetTestEntity[] _ =
+ context.NetTestEntities
+ .Where(x => EF.Functions.ContainsOrContainedBy(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("WHERE (x.\"Cidr\" && @__cidr_1) = TRUE");
+ }
+ }
+
+ #endregion
+
+ #region BitwiseOperatorTests
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_BitwiseNot()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseNot(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT ~x.\"Inet\"");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_BitwiseNot()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseNot(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT ~x.\"Cidr\"");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_BitwiseNot()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseNot(x.Macaddr))
+ .ToArray();
+
+ AssertContainsSql("SELECT ~x.\"Macaddr\"");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_BitwiseNot()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseNot(x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("SELECT ~x.\"Macaddr8\"");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_BitwiseAnd_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseAnd(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Inet\" & @__inet_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_BitwiseAnd_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseAnd(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Cidr\" & @__cidr_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_BitwiseAnd_macaddr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress macaddr = new PhysicalAddress(new byte[6]);
+
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseAnd(x.Macaddr, macaddr))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Macaddr\" & @__macaddr_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_BitwiseAnd_macaddr8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseAnd(x.Macaddr8, x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Macaddr8\" & x.\"Macaddr8\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_BitwiseOr_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseOr(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Inet\" | @__inet_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_BitwiseOr_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseOr(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Cidr\" | @__cidr_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_BitwiseOr_macaddr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress macaddr = new PhysicalAddress(new byte[6]);
+
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseOr(x.Macaddr, macaddr))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Macaddr\" | @__macaddr_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_BitwiseOr_macaddr8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.BitwiseOr(x.Macaddr8, x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Macaddr8\" | x.\"Macaddr8\")");
+ }
+ }
+
+ #endregion
+
+ #region ArithmeticOperatorTests
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Add_int()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Add(x.Inet, 1))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Inet\" + 1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Add_int()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Add(x.Cidr, 1))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Cidr\" + 1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Subtract_int()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Subtract(x.Inet, 1))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Inet\" - 1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Subtract_int()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Subtract(x.Cidr, 1))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Cidr\" - 1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Subtract_inet()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Subtract(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Inet\" - @__inet_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Subtract_cidr()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Subtract(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT (x.\"Cidr\" - @__cidr_1)");
+ }
+ }
+
+ #endregion
+
+ #region FunctionTests
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Abbreviate()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ string[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Abbreviate(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT abbrev(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Abbrebiate()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ string[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Abbreviate(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT abbrev(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Broadcast()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Broadcast(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT broadcast(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Broadcast()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Broadcast(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT broadcast(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Family()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ int[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Family(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT family(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Family()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ int[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Family(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT family(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Host()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ string[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Host(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT host(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Host()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ string[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Host(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT host(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_HostMask()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.HostMask(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT hostmask(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_HostMask()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.HostMask(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT hostmask(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_MaskLength()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ int[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.MaskLength(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT masklen(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_MaskLength()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ int[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.MaskLength(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT masklen(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Netmask()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Netmask(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT netmask(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Netmask()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Netmask(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT netmask(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Network()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Network(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT network(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Network()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Network(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT network(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_SetMaskLength()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.SetMaskLength(x.Inet, default))
+ .ToArray();
+
+ AssertContainsSql("SELECT set_masklen(x.\"Inet\", 0)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_SetMaskLength()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.SetMaskLength(x.Cidr, default))
+ .ToArray();
+
+ AssertContainsSql("SELECT set_masklen(x.\"Cidr\", 0)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Text()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ string[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Text(x.Inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT text(x.\"Inet\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Text()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ string[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Text(x.Cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT text(x.\"Cidr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_SameFamily()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ bool[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.SameFamily(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT inet_same_family(x.\"Inet\", @__inet_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_SameFamily()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ bool[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.SameFamily(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT inet_same_family(x.\"Cidr\", @__cidr_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void IPAddress_inet_Merge()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ IPAddress inet = IPAddress.Any;
+
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Merge(x.Inet, inet))
+ .ToArray();
+
+ AssertContainsSql("SELECT inet_merge(x.\"Inet\", @__inet_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void ValueTuple_cidr_Merge()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ (IPAddress Address, int Subnet) cidr = (IPAddress.Any, default);
+
+ (IPAddress Address, int Subnet)[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Merge(x.Cidr, cidr))
+ .ToArray();
+
+ AssertContainsSql("SELECT inet_merge(x.\"Cidr\", @__cidr_1)");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr_Truncate()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ var _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Truncate(x.Macaddr))
+ .ToArray();
+
+ AssertContainsSql("SELECT trunc(x.\"Macaddr\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_Truncate()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ var _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Truncate(x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("SELECT trunc(x.\"Macaddr8\")");
+ }
+ }
+
+ ///
+ /// Tests translation for .
+ ///
+ [Fact]
+ public void PhysicalAddress_macaddr8_Set7BitMac8()
+ {
+ using (NetContext context = Fixture.CreateContext())
+ {
+ PhysicalAddress[] _ =
+ context.NetTestEntities
+ .Select(x => EF.Functions.Set7BitMac8(x.Macaddr8))
+ .ToArray();
+
+ AssertContainsSql("SELECT macaddr8_set7bit(x.\"Macaddr8\")");
+ }
+ }
+
+ #endregion
+
+ #region Fixtures
+
+ ///
+ /// Represents a fixture suitable for testing network address operators.
+ ///
+ public class NetworkAddressQueryNpgsqlFixture : IDisposable
+ {
+ ///
+ /// The used for testing.
+ ///
+ private readonly NpgsqlTestStore _testStore;
+
+ ///
+ /// The used for testing.
+ ///
+ private readonly DbContextOptions _options;
+
+ ///
+ /// The logger factory used for testing.
+ ///
+ public TestSqlLoggerFactory TestSqlLoggerFactory { get; }
+
+ ///
+ /// Initializes a .
+ ///
+ // ReSharper disable once UnusedMember.Global
+ public NetworkAddressQueryNpgsqlFixture()
+ {
+ TestSqlLoggerFactory = new TestSqlLoggerFactory();
+
+ _testStore = NpgsqlTestStore.CreateScratch();
+
+ _options =
+ new DbContextOptionsBuilder()
+ .UseNpgsql(_testStore.ConnectionString, b => b.ApplyConfiguration())
+ .UseInternalServiceProvider(
+ new ServiceCollection()
+ .AddEntityFrameworkNpgsql()
+ .AddSingleton(TestSqlLoggerFactory)
+ .BuildServiceProvider())
+ .Options;
+
+ using (NetContext context = CreateContext())
+ {
+ context.Database.EnsureCreated();
+
+// BUG: This throws for some reason
+// for (int i = 0; i < 10; i++)
+// {
+// context.NetTestEntities
+// .Add(
+// new NetTestEntity
+// {
+// Id = i,
+// Inet = new IPAddress(i),
+// Cidr = (IPAddress: new IPAddress(i), Subnet: i)
+// });
+// }
+
+ context.SaveChanges();
+ }
+ }
+
+ ///
+ /// Creates a new .
+ ///
+ ///
+ /// A for testing.
+ ///
+ public NetContext CreateContext() => new NetContext(_options);
+
+ ///
+ public void Dispose() => _testStore.Dispose();
+ }
+
+ ///
+ /// Represents an entity suitable for testing network address operators.
+ ///
+ public class NetTestEntity
+ {
+ ///
+ /// The primary key.
+ ///
+ [Key]
+ public int Id { get; set; }
+
+ ///
+ /// The network address.
+ ///
+ public IPAddress Inet { get; set; }
+
+ ///
+ /// The network address.
+ ///
+ public (IPAddress Address, int Subnet) Cidr { get; set; }
+
+ ///
+ /// The MAC address.
+ ///
+ public PhysicalAddress Macaddr { get; set; }
+
+ ///
+ /// The MAC address.
+ ///
+ [Column(TypeName = "macaddr8")]
+ public PhysicalAddress Macaddr8 { get; set; }
+ }
+
+ ///
+ /// Represents a database suitable for testing network address operators.
+ ///
+ public class NetContext : DbContext
+ {
+ ///
+ /// Represents a set of entities with properties.
+ ///
+ public DbSet NetTestEntities { get; set; }
+
+ ///
+ /// Initializes a .
+ ///
+ ///
+ /// The options to be used for configuration.
+ ///
+ public NetContext(DbContextOptions options) : base(options) { }
+ }
+
+ #endregion
+
+ #region Helpers
+
+ ///
+ /// Asserts that the SQL fragment appears in the logs.
+ ///
+ /// The SQL statement or fragment to search for in the logs.
+ public void AssertContainsSql(string sql) => Assert.Contains(sql, Fixture.TestSqlLoggerFactory.Sql);
+
+ #endregion
+ }
+}