Skip to content

Commit 5c16d43

Browse files
committed
HACK: allow custom types in the records
1 parent 23c8966 commit 5c16d43

File tree

3 files changed

+76
-7
lines changed

3 files changed

+76
-7
lines changed

postgres-derive-test/src/records.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,73 @@ fn nested_structs() {
117117
assert_eq!(result, expected);
118118
}
119119

120+
#[test]
121+
fn domains() {
122+
#[derive(FromSql, Debug, PartialEq)]
123+
struct SpecialId(i32);
124+
125+
#[derive(FromSql, Debug, PartialEq)]
126+
struct Person {
127+
name: String,
128+
age: Option<i32>,
129+
id: SpecialId,
130+
}
131+
132+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
133+
conn.execute("CREATE DOMAIN pg_temp.\"special_id\" AS integer;", &[])
134+
.unwrap();
135+
136+
let result: Person = conn
137+
.query_one("SELECT ('John', 30, 42::special_id)", &[])
138+
.unwrap()
139+
.get(0);
140+
141+
let expected = Person {
142+
name: "John".to_owned(),
143+
age: Some(30),
144+
id: SpecialId(42),
145+
};
146+
147+
assert_eq!(result, expected);
148+
}
149+
150+
#[test]
151+
fn enums() {
152+
#[derive(FromSql, Debug, PartialEq)]
153+
enum Employment {
154+
Salaried,
155+
Hourly,
156+
Unemployed,
157+
}
158+
159+
#[derive(FromSql, Debug, PartialEq)]
160+
struct Person {
161+
name: String,
162+
age: Option<i32>,
163+
employment: Employment,
164+
}
165+
166+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
167+
conn.execute(
168+
"CREATE TYPE pg_temp.employment AS ENUM ('Salaried', 'Hourly', 'Unemployed')",
169+
&[],
170+
)
171+
.unwrap();
172+
173+
let result: Person = conn
174+
.query_one("SELECT ('John', 30, 'Hourly'::employment)", &[])
175+
.unwrap()
176+
.get(0);
177+
178+
let expected = Person {
179+
name: "John".to_owned(),
180+
age: Some(30),
181+
employment: Employment::Hourly,
182+
};
183+
184+
assert_eq!(result, expected);
185+
}
186+
120187
#[test]
121188
fn generics() {
122189
#[derive(FromSql, ToSql, Debug, PartialEq)]

postgres-derive/src/accepts.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub fn enum_body(name: &str, variants: &[Variant], allow_mismatch: bool) -> Toke
4141
}
4242
} else {
4343
quote! {
44+
if *type_ == postgres_types::Type::UNKNOWN {
45+
return true;
46+
}
4447
if type_.name() != #name {
4548
return false;
4649
}

postgres-derive/src/fromsql.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ fn domain_accepts_body(name: &str, field: &syn::Field) -> TokenStream {
171171
if <#ty as postgres_types::FromSql>::accepts(type_) {
172172
return true;
173173
}
174+
if *type_ == postgres_types::Type::UNKNOWN {
175+
return true;
176+
}
174177

175178
#normal_body
176179
}
@@ -250,13 +253,9 @@ fn composite_body(ident: &Ident, fields: &[Field]) -> TokenStream {
250253

251254
for i in 0..num_fields {
252255
let oid = postgres_types::private::read_be_i32(&mut buf)? as u32;
253-
let ty = match postgres_types::Type::from_oid(oid) {
254-
std::option::Option::None => {
255-
return std::result::Result::Err(std::convert::Into::into(
256-
format!("cannot decode OID {} inside of anonymous record", oid)));
257-
}
258-
std::option::Option::Some(ty) => ty,
259-
};
256+
// FIXME: I see no other way to make this work with non-builtin types
257+
// besides expanding the FromSql trait to also require passing the client
258+
let ty = postgres_types::Type::from_oid(oid).unwrap_or(postgres_types::Type::UNKNOWN);
260259

261260
match i as usize {
262261
#(

0 commit comments

Comments
 (0)