Skip to content

Commit ad07c56

Browse files
committed
wip
1 parent dcf13d8 commit ad07c56

File tree

1 file changed

+63
-3
lines changed

1 file changed

+63
-3
lines changed

benzina/src/array.rs

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::fmt::Debug;
22

33
use diesel::{
4-
deserialize::{FromSql, FromSqlRow},
4+
deserialize::FromSql,
55
expression::{AppearsOnTable, Expression, SelectableExpression},
66
pg::{Pg, PgValue},
77
query_builder::{AstPass, QueryFragment, QueryId},
@@ -12,7 +12,67 @@ use diesel::{
1212

1313
use crate::{U15, U31, U63, error::InvalidArray};
1414

15-
#[derive(Debug, FromSqlRow)]
15+
/// Since postgres ignores the array dimension (if specified) diesel implements [`FromSql`] for `Vec<T>` and [`ToSql`] for `Vec<T>`/`&[T]`.
16+
/// In addition postgres also consider array items as always nullable.
17+
/// This makes hard to deal with real arrays, that have a predetermined length, and an omogeneous nullability.
18+
/// This type checks at runtime the array length and the NON nullability of its items, to be completely safe you should also add some `CHECK` constraints to your array fields.
19+
///
20+
/// This type is not intended to be used directly in the model but rather to be
21+
/// used with diesel [`serialize_as`] and [`deserialize_as`].
22+
///
23+
/// ```
24+
/// use benzina::{Array, U31};
25+
/// use diesel::{Insertable, Queryable};
26+
/// use serde::{Deserialize, Serialize};
27+
///
28+
/// #[derive(Debug, Queryable)]
29+
/// #[diesel(table_name = users, check_for_backend(diesel::pg::Pg))]
30+
/// struct User {
31+
/// id: U31,
32+
/// first_name: String,
33+
/// last_name: String,
34+
/// #[diesel(deserialize_as = Array<bool, 5>)]
35+
/// flags: UserFlags,
36+
/// }
37+
///
38+
/// #[derive(Debug, Insertable)]
39+
/// #[diesel(table_name = users)]
40+
/// struct NewUser {
41+
/// first_name: String,
42+
/// last_name: String,
43+
/// #[diesel(serialize_as = Array<bool, 5>)]
44+
/// flags: UserFlags,
45+
/// }
46+
///
47+
/// #[derive(Debug, Serialize, Deserialize)]
48+
/// struct UserFlags([5; bool]);
49+
///
50+
/// // needed by deserialize_as
51+
/// impl From<benzina::Array<bool, 5>> for UserFlags {
52+
/// fn from(value: benzina::Array<bool, 5>) -> Self {
53+
/// Self::new(value.get())
54+
/// }
55+
/// }
56+
///
57+
/// // needed by serialize_as
58+
/// impl From<UserFlags> for benzina::Array<bool, 5> {
59+
/// fn from(value: UserFlags) -> Self {
60+
/// Self::new(value.0)
61+
/// }
62+
/// }
63+
///
64+
/// diesel::table! {
65+
/// users (id) {
66+
/// id -> Int4,
67+
/// first_name -> Text,
68+
/// last_name -> Text,
69+
/// flags -> Array<Nullable<Bool>>,
70+
/// }
71+
/// }
72+
///
73+
/// [`serialize_as`]: diesel::prelude::Insertable#optional-field-attributes
74+
/// [`deserialize_as`]: diesel::prelude::Queryable#deserialize_as-attribute
75+
#[derive(Debug)]
1676
pub struct Array<T, const N: usize>([T; N]);
1777
impl<T, const N: usize> Array<T, N> {
1878
pub fn new(values: [T; N]) -> Self {
@@ -24,7 +84,7 @@ impl<T, const N: usize> Array<T, N> {
2484
}
2585
}
2686

27-
#[derive(Debug, FromSqlRow)]
87+
#[derive(Debug)]
2888
pub struct ArrayWithNullableItems<T, const N: usize>([Option<T>; N]);
2989
impl<T, const N: usize> ArrayWithNullableItems<T, N> {
3090
pub fn new(values: [Option<T>; N]) -> Self {

0 commit comments

Comments
 (0)