diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs b/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
index ef2563253..08621113e 100644
--- a/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
+++ b/src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs
@@ -460,13 +460,11 @@ protected virtual Expression VisitPostgresBinary(PostgresBinaryExpression binary
.Append(binaryExpression.OperatorType switch
{
PostgresExpressionType.Contains
- when binaryExpression.Left.TypeMapping is NpgsqlInetTypeMapping ||
- binaryExpression.Left.TypeMapping is NpgsqlCidrTypeMapping
+ when binaryExpression.Left.TypeMapping is NpgsqlInetTypeMapping
=> ">>",
PostgresExpressionType.ContainedBy
- when binaryExpression.Left.TypeMapping is NpgsqlInetTypeMapping ||
- binaryExpression.Left.TypeMapping is NpgsqlCidrTypeMapping
+ when binaryExpression.Left.TypeMapping is NpgsqlInetTypeMapping
=> "<<",
PostgresExpressionType.Contains => "@>",
diff --git a/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlNetworkTypeMappings.cs b/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlNetworkTypeMappings.cs
index 0232b291a..b2da33182 100644
--- a/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlNetworkTypeMappings.cs
+++ b/src/EFCore.PG/Storage/Internal/Mapping/NpgsqlNetworkTypeMappings.cs
@@ -114,7 +114,7 @@ public override Expression GenerateCodeLiteral(object value)
}
///
-/// The type mapping for the PostgreSQL inet type.
+/// The type mapping for the PostgreSQL inet and cidr types.
///
///
/// See: https://www.postgresql.org/docs/current/static/datatype-net-types.html#DATATYPE-INET
@@ -127,7 +127,7 @@ public class NpgsqlInetTypeMapping : NpgsqlTypeMapping
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- public NpgsqlInetTypeMapping() : base("inet", typeof(IPAddress), NpgsqlDbType.Inet) {}
+ public NpgsqlInetTypeMapping(string storeType, Type clrType, NpgsqlDbType npgsqlDbType) : base(storeType, clrType, npgsqlDbType) {}
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -135,8 +135,8 @@ public NpgsqlInetTypeMapping() : base("inet", typeof(IPAddress), NpgsqlDbType.In
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
- protected NpgsqlInetTypeMapping(RelationalTypeMappingParameters parameters)
- : base(parameters, NpgsqlDbType.Inet) {}
+ protected NpgsqlInetTypeMapping(RelationalTypeMappingParameters parameters, NpgsqlDbType npgsqlDbType)
+ : base(parameters, npgsqlDbType) {}
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -145,62 +145,7 @@ protected NpgsqlInetTypeMapping(RelationalTypeMappingParameters parameters)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
///
protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
- => new NpgsqlInetTypeMapping(parameters);
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- protected override string GenerateNonNullSqlLiteral(object value)
- => $"INET '{(IPAddress)value}'";
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- public override Expression GenerateCodeLiteral(object value)
- => Expression.Call(ParseMethod, Expression.Constant(((IPAddress)value).ToString()));
-
- private static readonly MethodInfo ParseMethod = typeof(IPAddress).GetMethod("Parse", new[] { typeof(string) })!;
-}
-
-///
-/// The type mapping for the PostgreSQL cidr type.
-///
-///
-/// See: https://www.postgresql.org/docs/current/static/datatype-net-types.html#DATATYPE-CIDR
-///
-public class NpgsqlCidrTypeMapping : NpgsqlTypeMapping
-{
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- public NpgsqlCidrTypeMapping() : base("cidr", typeof((IPAddress, int)), NpgsqlDbType.Cidr) {}
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- protected NpgsqlCidrTypeMapping(RelationalTypeMappingParameters parameters)
- : base(parameters, NpgsqlDbType.Cidr) {}
-
- ///
- /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
- /// the same compatibility standards as public APIs. It may be changed or removed without notice in
- /// any release. You should only use it directly in your code with extreme caution and knowing that
- /// doing so can result in application failures when updating to a new Entity Framework Core release.
- ///
- protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters parameters)
- => new NpgsqlCidrTypeMapping(parameters);
+ => new NpgsqlInetTypeMapping(parameters, NpgsqlDbType);
///
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -210,8 +155,18 @@ protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters p
///
protected override string GenerateNonNullSqlLiteral(object value)
{
- var cidr = ((IPAddress Address, int Subnet))value;
- return $"CIDR '{cidr.Address}/{cidr.Subnet}'";
+ switch (value)
+ {
+ case (IPAddress address, int subnet):
+ return $"{StoreType.ToUpperInvariant()} '{address}/{subnet}'";
+
+ case IPAddress address:
+ return $"INET '{address}'";
+
+ default:
+ throw new InvalidCastException(
+ $"Attempted to generate {StoreType} literal for type {value.GetType()}");
+ }
}
///
@@ -222,15 +177,18 @@ protected override string GenerateNonNullSqlLiteral(object value)
///
public override Expression GenerateCodeLiteral(object value)
{
- var cidr = ((IPAddress Address, int Subnet))value;
- return Expression.New(
- Constructor,
- Expression.Call(ParseMethod, Expression.Constant(cidr.Address.ToString())),
- Expression.Constant(cidr.Subnet));
+ if (value is (IPAddress address, int subnet))
+ {
+ return Expression.New(
+ MaskConstructor,
+ Expression.Call(ParseMethod, Expression.Constant(address.ToString())),
+ Expression.Constant(subnet));
+ }
+
+ return Expression.Call(ParseMethod, Expression.Constant(((IPAddress)value).ToString()));
}
private static readonly MethodInfo ParseMethod = typeof(IPAddress).GetMethod("Parse", new[] { typeof(string) })!;
-
- private static readonly ConstructorInfo Constructor =
+ private static readonly ConstructorInfo MaskConstructor =
typeof((IPAddress, int)).GetConstructor(new[] { typeof(IPAddress), typeof(int) })!;
}
diff --git a/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs b/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs
index b0cbf226a..0778f9cf9 100644
--- a/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs
+++ b/src/EFCore.PG/Storage/Internal/NpgsqlTypeMappingSource.cs
@@ -117,8 +117,9 @@ static NpgsqlTypeMappingSource()
// Network address types
private readonly NpgsqlMacaddrTypeMapping _macaddr = new();
private readonly NpgsqlMacaddr8TypeMapping _macaddr8 = new();
- private readonly NpgsqlInetTypeMapping _inet = new();
- private readonly NpgsqlCidrTypeMapping _cidr = new();
+ private readonly NpgsqlInetTypeMapping _inet = new("inet", typeof(IPAddress), NpgsqlDbType.Inet);
+ private readonly NpgsqlInetTypeMapping _inetMask = new("inet", typeof((IPAddress, int)), NpgsqlDbType.Inet);
+ private readonly NpgsqlInetTypeMapping _cidr = new("cidr", typeof((IPAddress, int)), NpgsqlDbType.Cidr);
// Built-in geometric types
private readonly NpgsqlPointTypeMapping _point = new();
@@ -316,7 +317,7 @@ public NpgsqlTypeMappingSource(
{ "macaddr", new[] { _macaddr } },
{ "macaddr8", new[] { _macaddr8 } },
- { "inet", new[] { _inet } },
+ { "inet", new[] { _inet, _inetMask } },
{ "cidr", new[] { _cidr } },
{ "point", new[] { _point } },
diff --git a/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs b/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs
index 854d88314..a9f67cf97 100644
--- a/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs
+++ b/test/EFCore.PG.Tests/Storage/NpgsqlTypeMappingTest.cs
@@ -253,6 +253,14 @@ public void GenerateSqlLiteral_returns_inet_literal()
public void GenerateCodeLiteral_returns_inet_literal()
=> Assert.Equal(@"System.Net.IPAddress.Parse(""192.168.1.1"")", CodeLiteral(IPAddress.Parse("192.168.1.1")));
+ [Fact]
+ public void GenerateSqlLiteral_returns_inet_masked_literal()
+ => Assert.Equal("INET '192.168.1.1/24'", GetMapping(typeof((IPAddress, int)), "inet").GenerateSqlLiteral((IPAddress.Parse("192.168.1.1"), 24)));
+
+ [Fact]
+ public void GenerateCodeLiteral_returns_inet_masked_literal()
+ => Assert.Equal(@"(System.Net.IPAddress.Parse(""192.168.1.1""), 24)", CodeLiteral((IPAddress.Parse("192.168.1.1"), 24)));
+
[Fact]
public void GenerateSqlLiteral_returns_cidr_literal()
=> Assert.Equal("CIDR '192.168.1.0/24'", GetMapping("cidr").GenerateSqlLiteral((IPAddress.Parse("192.168.1.0"), 24)));