Skip to content

Commit

Permalink
Merge pull request #4313 from SolutionTech-SRL/feat-pg_macaddr8_type_…
Browse files Browse the repository at this point in the history
…support

Add postgres macaddr8 type support
  • Loading branch information
weiznich authored Oct 29, 2024
2 parents e33cdeb + 257bf00 commit cd4300b
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 1 deletion.
49 changes: 49 additions & 0 deletions diesel/src/pg/types/mac_addr_8.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::io::prelude::*;

use super::sql_types::MacAddr8;
use crate::deserialize::{self, FromSql};
use crate::pg::{Pg, PgValue};
use crate::serialize::{self, IsNull, Output, ToSql};

#[allow(dead_code)]
mod foreign_derives {
use super::*;
use crate::deserialize::FromSqlRow;
use crate::expression::AsExpression;

#[derive(AsExpression, FromSqlRow)]
#[diesel(foreign_derive)]
#[diesel(sql_type = MacAddr8)]
struct ByteArrayProxy([u8; 8]);
}

#[cfg(feature = "postgres_backend")]
impl FromSql<MacAddr8, Pg> for [u8; 8] {
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
value
.as_bytes()
.try_into()
.map_err(|_| "invalid network address format: input isn't 8 bytes.".into())
}
}

#[cfg(feature = "postgres_backend")]
impl ToSql<MacAddr8, Pg> for [u8; 8] {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
out.write_all(&self[..])
.map(|_| IsNull::No)
.map_err(Into::into)
}
}

#[test]
fn macaddr8_roundtrip() {
use crate::query_builder::bind_collector::ByteWrapper;

let mut buffer = Vec::new();
let mut bytes = Output::test(ByteWrapper(&mut buffer));
let input_address = [0x52, 0x54, 0x00, 0xfb, 0xc6, 0x16, 0x17, 0xFF];
ToSql::<MacAddr8, Pg>::to_sql(&input_address, &mut bytes).unwrap();
let output_address: [u8; 8] = FromSql::from_sql(PgValue::for_test(&buffer)).unwrap();
assert_eq!(input_address, output_address);
}
49 changes: 49 additions & 0 deletions diesel/src/pg/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod ipnet_address;
#[cfg(feature = "serde_json")]
mod json;
mod mac_addr;
mod mac_addr_8;
#[doc(hidden)]
pub(in crate::pg) mod money;
mod multirange;
Expand Down Expand Up @@ -407,6 +408,54 @@ pub mod sql_types {
/// Alias for `MacAddr` to be able to use it with `diesel print-schema`.
pub type Macaddr = MacAddr;

/// The [`MACADDR8`](https://www.postgresql.org/docs/current/static/datatype-net-types.html) SQL type.
///
/// ### [`ToSql`] impls
///
/// - `[u8; 8]`
///
/// ### [`FromSql`] impls
///
/// - `[u8; 8]`
///
/// [`ToSql`]: crate::serialize::ToSql
/// [`FromSql`]: crate::deserialize::FromSql
///
/// # Examples
///
/// ```rust
/// # include!("../../doctest_setup.rs");
/// table! {
/// devices {
/// id -> Integer,
/// macaddr -> MacAddr8,
/// }
/// }
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # use diesel::insert_into;
/// # use self::devices::dsl::*;
/// # let connection = &mut connection_no_data();
/// # diesel::sql_query("CREATE TABLE devices (
/// # id SERIAL PRIMARY KEY,
/// # macaddr MACADDR8 NOT NULL
/// # )").execute(connection)?;
/// let inserted_macaddr = insert_into(devices)
/// .values(macaddr.eq([0x08, 0x00, 0x2b, 0x01, 0x02, 0x03, 0x04, 0x05]))
/// .returning(macaddr)
/// .get_result::<[u8; 8]>(connection)?;
/// assert_eq!([0x08, 0x00, 0x2b, 0x01, 0x02, 0x03, 0x04, 0x05], inserted_macaddr);
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "postgres_backend")]
#[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
#[diesel(postgres_type(oid = 774, array_oid = 775))]
pub struct MacAddr8;

/// Alias for `MacAddr` to be able to use it with `diesel print-schema`.
pub type Macaddr8 = MacAddr8;

/// The [`INET`](https://www.postgresql.org/docs/current/static/datatype-net-types.html) SQL type. This type can only be used with `feature = "network-address"` or `feature = "ipnet-address"`.
///
/// ### [`ToSql`] impls
Expand Down
2 changes: 2 additions & 0 deletions diesel_cli/src/print_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ fn pg_diesel_types() -> HashSet<&'static str> {
types.insert("Inet");
types.insert("Jsonb");
types.insert("MacAddr");
types.insert("MacAddr8");
types.insert("Money");
types.insert("Oid");
types.insert("Range");
Expand Down Expand Up @@ -127,6 +128,7 @@ fn pg_diesel_types() -> HashSet<&'static str> {
types.insert("Bytea");
types.insert("Bpchar");
types.insert("Macaddr");
types.insert("Macaddr8");

common_diesel_types(&mut types);
types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ table! {
inet_col -> Inet,
jsonb_col -> Jsonb,
macaddr_col -> MacAddr,
macaddr8_col -> MacAddr8,
money_col -> Money,
oid_col -> Oid,
timestamptz_col -> Timestamptz,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ diesel::table! {
inet_col -> Inet,
jsonb_col -> Jsonb,
macaddr_col -> Macaddr,
macaddr8_col -> Macaddr8,
money_col -> Money,
oid_col -> Oid,
timestamptz_col -> Timestamptz,
Expand All @@ -57,4 +58,3 @@ diesel::table! {
macaddr2_col -> Macaddr,
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ CREATE TABLE "all_the_types"(
"inet_col" INET NOT NULL,
"jsonb_col" JSONB NOT NULL,
"macaddr_col" MACADDR NOT NULL,
"macaddr8_col" MACADDR8 NOT NULL,
"money_col" MONEY NOT NULL,
"oid_col" OID NOT NULL,
"timestamptz_col" TIMESTAMPTZ NOT NULL,
Expand Down
22 changes: 22 additions & 0 deletions diesel_tests/tests/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,28 @@ fn pg_macaddress_to_sql_macaddress() {
));
}

#[test]
#[cfg(feature = "postgres")]
fn pg_macaddress8_from_sql() {
let query = "'08:00:2b:01:02:03:04:05'::macaddr8";
let expected_value = [0x08, 0x00, 0x2b, 0x01, 0x02, 0x03, 0x04, 0x05];
assert_eq!(
expected_value,
query_single_value::<MacAddr8, [u8; 8]>(query)
);
}

#[test]
#[cfg(feature = "postgres")]
fn pg_macaddress8_to_sql_macaddress() {
let expected_value = "'08:00:2b:01:02:03:04:05'::macaddr8";
let value = [0x08, 0x00, 0x2b, 0x01, 0x02, 0x03, 0x04, 0x05];
assert!(query_to_sql_equality::<MacAddr8, [u8; 8]>(
expected_value,
value
));
}

#[test]
#[cfg(feature = "postgres")]
fn pg_v4address_from_sql() {
Expand Down
12 changes: 12 additions & 0 deletions diesel_tests/tests/types_roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ mod pg_types {
(u8, u8, u8, u8, u8, u8),
mk_macaddr
);
test_round_trip!(
macaddr8_roundtrips,
MacAddr8,
(u8, u8, u8, u8, u8, u8, u8, u8),
mk_macaddr8
);
test_round_trip!(cidr_v4_roundtrips, Cidr, (u8, u8, u8, u8), mk_ipv4);
test_round_trip!(
cidr_v4_roundtrips_ipnet,
Expand Down Expand Up @@ -304,6 +310,12 @@ mod pg_types {
[data.0, data.1, data.2, data.3, data.4, data.5]
}

fn mk_macaddr8(data: (u8, u8, u8, u8, u8, u8, u8, u8)) -> [u8; 8] {
[
data.0, data.1, data.2, data.3, data.4, data.5, data.6, data.7,
]
}

fn mk_ipv4(data: (u8, u8, u8, u8)) -> ipnetwork::IpNetwork {
use std::net::Ipv4Addr;
let ip = Ipv4Addr::new(data.0, data.1, data.2, data.3);
Expand Down

0 comments on commit cd4300b

Please sign in to comment.