Skip to content

Commit

Permalink
Adds MAC address (macaddr and macaddr8) functions for translation
Browse files Browse the repository at this point in the history
- Maps macaddr and macaddr8 functions to CLR extension methods.
  - macaddr: https://www.postgresql.org/docs/current/static/functions-net.html#MACADDR-FUNCTIONS-TABLE
  - macaddr8: https://www.postgresql.org/docs/current/static/functions-net.html#MACADDR8-FUNCTIONS-TABLE

- Includes functional tests covering translation.

- TODO:
  - Map the standard relational operators and bitwise arithmetic operators.
  • Loading branch information
austindrenski committed May 26, 2018
1 parent b860f0a commit 8b5f37a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/EFCore.PG/Extensions/NpgsqlNetworkAddressExtensions.cs
Expand Up @@ -24,6 +24,7 @@
#endregion

using System.Net;
using System.Net.NetworkInformation;
using JetBrains.Annotations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Utilities;

Expand Down Expand Up @@ -799,5 +800,31 @@ public static class NpgsqlNetworkAddressExtensions
/// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
/// </exception>
public static (IPAddress Address, int Subnet) Merge([CanBeNull] this DbFunctions _, (IPAddress Address, int Subnet) cidr, (IPAddress Address, int Subnet) other) => throw new ClientEvaluationNotSupportedException();

/// <summary>
/// Sets the last 3 bytes of the MAC address to zero. For macaddr8, the last 5 bytes are set to zero.
/// </summary>
/// <param name="_">The <see cref="DbFunctions"/> instance.</param>
/// <param name="macAddress">The MAC address to truncate.</param>
/// <returns>
/// The MAC address with the last 3 bytes set to zero. For macaddr8, the last 5 bytes are set to zero.
/// </returns>
/// <exception cref="ClientEvaluationNotSupportedException">
/// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
/// </exception>
public static PhysicalAddress Truncate([CanBeNull] this DbFunctions _, PhysicalAddress macAddress) => throw new ClientEvaluationNotSupportedException();

/// <summary>
/// Sets the 7th bit to one, also known as modified EUI-64, for inclusion in an IPv6 address.
/// </summary>
/// <param name="_">The <see cref="DbFunctions"/> instance.</param>
/// <param name="macAddress">The MAC address to modify.</param>
/// <returns>
/// The MAC address with the 7th bit set to one.
/// </returns>
/// <exception cref="ClientEvaluationNotSupportedException">
/// This method is only intended for use via SQL translation as part of an EF Core LINQ query.
/// </exception>
public static PhysicalAddress Set7BitMac8([CanBeNull] this DbFunctions _, PhysicalAddress macAddress) => throw new ClientEvaluationNotSupportedException();
}
}
Expand Up @@ -25,6 +25,7 @@

using System.Linq.Expressions;
using System.Net;
using System.Net.NetworkInformation;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.ExpressionTranslators;
Expand Down Expand Up @@ -130,6 +131,12 @@ public Expression Translate(MethodCallExpression expression)
case nameof(NpgsqlNetworkAddressExtensions.Merge):
return new PgFunctionExpression("inet_merge", typeof((IPAddress Address, int Subnet)), new[] { expression.Arguments[1], expression.Arguments[2] });

case nameof(NpgsqlNetworkAddressExtensions.Truncate):
return new PgFunctionExpression("trunc", typeof(PhysicalAddress), new[] { expression.Arguments[1] });

case nameof(NpgsqlNetworkAddressExtensions.Set7BitMac8):
return new PgFunctionExpression("macaddr8_set7bit", typeof(PhysicalAddress), new[] { expression.Arguments[1] });

default:
return null;
}
Expand Down
Expand Up @@ -50,7 +50,7 @@ protected override string GenerateNonNullSqlLiteral(object value)

public class NpgsqlMacaddr8TypeMapping : NpgsqlTypeMapping
{
public NpgsqlMacaddr8TypeMapping() : base("macaddr8", typeof(PhysicalAddress), NpgsqlDbType.MacAddr) { }
public NpgsqlMacaddr8TypeMapping() : base("macaddr8", typeof(PhysicalAddress), NpgsqlDbType.MacAddr8) { }

protected NpgsqlMacaddr8TypeMapping(RelationalTypeMappingParameters parameters, NpgsqlDbType npgsqlDbType)
: base(parameters, npgsqlDbType) { }
Expand Down
@@ -1,7 +1,9 @@
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;
Expand Down Expand Up @@ -630,6 +632,45 @@ public void ValueTuple_cidr_Merge()
}
}

/// <summary>
/// Tests translation for <see cref="NpgsqlNetworkAddressExtensions.Truncate(DbFunctions,PhysicalAddress)"/>.
/// </summary>
[Fact]
public void PhysicalAddress_macaddr_Truncate()
{
using (NetContext context = Fixture.CreateContext())
{
var _ =
context.NetTestEntities
.Select(
x => new
{
macaddr = EF.Functions.Truncate(x.Macaddr),
macaddr8 = EF.Functions.Truncate(x.Macaddr8)
})
.ToArray();

AssertContainsSql("SELECT trunc(x.\"Macaddr\") AS macaddr, trunc(x.\"Macaddr8\") AS macaddr8");
}
}

/// <summary>
/// Tests translation for <see cref="NpgsqlNetworkAddressExtensions.Set7BitMac8(DbFunctions,PhysicalAddress)"/>.
/// </summary>
[Fact]
public void PhysicalAddress_macaddr_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
Expand Down Expand Up @@ -733,6 +774,17 @@ public class NetTestEntity
/// The network address.
/// </summary>
public (IPAddress Address, int Subnet) Cidr { get; set; }

/// <summary>
/// The MAC address.
/// </summary>
public PhysicalAddress Macaddr { get; set; }

/// <summary>
/// The MAC address.
/// </summary>
[Column(TypeName = "macaddr8")]
public PhysicalAddress Macaddr8 { get; set; }
}

/// <summary>
Expand Down

0 comments on commit 8b5f37a

Please sign in to comment.