Skip to content

Commit 958826d

Browse files
committed
Merge remote-tracking branch 'upstream/master' into mz-master
2 parents 6e68c10 + d2634a4 commit 958826d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2010
-459
lines changed

.github/workflows/ci.yml

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- uses: actions/checkout@v3
2121
- uses: sfackler/actions/rustup@master
2222
- uses: sfackler/actions/rustfmt@master
23-
23+
2424
clippy:
2525
name: clippy
2626
runs-on: ubuntu-latest
@@ -47,6 +47,33 @@ jobs:
4747
key: clippy-target-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }}y
4848
- run: cargo clippy --all --all-targets
4949

50+
check-wasm32:
51+
name: check-wasm32
52+
runs-on: ubuntu-latest
53+
steps:
54+
- uses: actions/checkout@v3
55+
- uses: sfackler/actions/rustup@master
56+
- run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT
57+
id: rust-version
58+
- run: rustup target add wasm32-unknown-unknown
59+
- uses: actions/cache@v3
60+
with:
61+
path: ~/.cargo/registry/index
62+
key: index-${{ runner.os }}-${{ github.run_number }}
63+
restore-keys: |
64+
index-${{ runner.os }}-
65+
- run: cargo generate-lockfile
66+
- uses: actions/cache@v3
67+
with:
68+
path: ~/.cargo/registry/cache
69+
key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }}
70+
- run: cargo fetch
71+
- uses: actions/cache@v3
72+
with:
73+
path: target
74+
key: check-wasm32-target-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }}
75+
- run: cargo check --target wasm32-unknown-unknown --manifest-path tokio-postgres/Cargo.toml --no-default-features --features js
76+
5077
test:
5178
name: test
5279
runs-on: ubuntu-latest
@@ -55,7 +82,7 @@ jobs:
5582
- run: docker compose up -d
5683
- uses: sfackler/actions/rustup@master
5784
with:
58-
version: 1.64.0
85+
version: 1.74.0
5986
- run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT
6087
id: rust-version
6188
- uses: actions/cache@v3

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ members = [
1010
"postgres-types",
1111
"tokio-postgres",
1212
]
13+
resolver = "2"
1314

1415
[profile.release]
1516
debug = 2
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use postgres_types::{FromSql, ToSql};
2+
3+
#[derive(ToSql, Debug)]
4+
#[postgres(allow_mismatch)]
5+
struct ToSqlAllowMismatchStruct {
6+
a: i32,
7+
}
8+
9+
#[derive(FromSql, Debug)]
10+
#[postgres(allow_mismatch)]
11+
struct FromSqlAllowMismatchStruct {
12+
a: i32,
13+
}
14+
15+
#[derive(ToSql, Debug)]
16+
#[postgres(allow_mismatch)]
17+
struct ToSqlAllowMismatchTupleStruct(i32, i32);
18+
19+
#[derive(FromSql, Debug)]
20+
#[postgres(allow_mismatch)]
21+
struct FromSqlAllowMismatchTupleStruct(i32, i32);
22+
23+
#[derive(FromSql, Debug)]
24+
#[postgres(transparent, allow_mismatch)]
25+
struct TransparentFromSqlAllowMismatchStruct(i32);
26+
27+
#[derive(FromSql, Debug)]
28+
#[postgres(allow_mismatch, transparent)]
29+
struct AllowMismatchFromSqlTransparentStruct(i32);
30+
31+
fn main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: #[postgres(allow_mismatch)] may only be applied to enums
2+
--> src/compile-fail/invalid-allow-mismatch.rs:4:1
3+
|
4+
4 | / #[postgres(allow_mismatch)]
5+
5 | | struct ToSqlAllowMismatchStruct {
6+
6 | | a: i32,
7+
7 | | }
8+
| |_^
9+
10+
error: #[postgres(allow_mismatch)] may only be applied to enums
11+
--> src/compile-fail/invalid-allow-mismatch.rs:10:1
12+
|
13+
10 | / #[postgres(allow_mismatch)]
14+
11 | | struct FromSqlAllowMismatchStruct {
15+
12 | | a: i32,
16+
13 | | }
17+
| |_^
18+
19+
error: #[postgres(allow_mismatch)] may only be applied to enums
20+
--> src/compile-fail/invalid-allow-mismatch.rs:16:1
21+
|
22+
16 | / #[postgres(allow_mismatch)]
23+
17 | | struct ToSqlAllowMismatchTupleStruct(i32, i32);
24+
| |_______________________________________________^
25+
26+
error: #[postgres(allow_mismatch)] may only be applied to enums
27+
--> src/compile-fail/invalid-allow-mismatch.rs:20:1
28+
|
29+
20 | / #[postgres(allow_mismatch)]
30+
21 | | struct FromSqlAllowMismatchTupleStruct(i32, i32);
31+
| |_________________________________________________^
32+
33+
error: #[postgres(transparent)] is not allowed with #[postgres(allow_mismatch)]
34+
--> src/compile-fail/invalid-allow-mismatch.rs:24:25
35+
|
36+
24 | #[postgres(transparent, allow_mismatch)]
37+
| ^^^^^^^^^^^^^^
38+
39+
error: #[postgres(allow_mismatch)] is not allowed with #[postgres(transparent)]
40+
--> src/compile-fail/invalid-allow-mismatch.rs:28:28
41+
|
42+
28 | #[postgres(allow_mismatch, transparent)]
43+
| ^^^^^^^^^^^

postgres-derive-test/src/composites.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,49 @@ fn name_overrides() {
8989
);
9090
}
9191

92+
#[test]
93+
fn rename_all_overrides() {
94+
#[derive(FromSql, ToSql, Debug, PartialEq)]
95+
#[postgres(name = "inventory_item", rename_all = "SCREAMING_SNAKE_CASE")]
96+
struct InventoryItem {
97+
name: String,
98+
supplier_id: i32,
99+
#[postgres(name = "Price")]
100+
price: Option<f64>,
101+
}
102+
103+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
104+
conn.batch_execute(
105+
"CREATE TYPE pg_temp.inventory_item AS (
106+
\"NAME\" TEXT,
107+
\"SUPPLIER_ID\" INT,
108+
\"Price\" DOUBLE PRECISION
109+
);",
110+
)
111+
.unwrap();
112+
113+
let item = InventoryItem {
114+
name: "foobar".to_owned(),
115+
supplier_id: 100,
116+
price: Some(15.50),
117+
};
118+
119+
let item_null = InventoryItem {
120+
name: "foobar".to_owned(),
121+
supplier_id: 100,
122+
price: None,
123+
};
124+
125+
test_type(
126+
&mut conn,
127+
"inventory_item",
128+
&[
129+
(item, "ROW('foobar', 100, 15.50)"),
130+
(item_null, "ROW('foobar', 100, NULL)"),
131+
],
132+
);
133+
}
134+
92135
#[test]
93136
fn wrong_name() {
94137
#[derive(FromSql, ToSql, Debug, PartialEq)]

postgres-derive-test/src/enums.rs

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::test_type;
2-
use postgres::{Client, NoTls};
2+
use postgres::{error::DbError, Client, NoTls};
33
use postgres_types::{FromSql, ToSql, WrongType};
44
use std::error::Error;
55

@@ -53,6 +53,35 @@ fn name_overrides() {
5353
);
5454
}
5555

56+
#[test]
57+
fn rename_all_overrides() {
58+
#[derive(Debug, ToSql, FromSql, PartialEq)]
59+
#[postgres(name = "mood", rename_all = "snake_case")]
60+
enum Mood {
61+
VerySad,
62+
#[postgres(name = "okay")]
63+
Ok,
64+
VeryHappy,
65+
}
66+
67+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
68+
conn.execute(
69+
"CREATE TYPE pg_temp.mood AS ENUM ('very_sad', 'okay', 'very_happy')",
70+
&[],
71+
)
72+
.unwrap();
73+
74+
test_type(
75+
&mut conn,
76+
"mood",
77+
&[
78+
(Mood::VerySad, "'very_sad'"),
79+
(Mood::Ok, "'okay'"),
80+
(Mood::VeryHappy, "'very_happy'"),
81+
],
82+
);
83+
}
84+
5685
#[test]
5786
fn wrong_name() {
5887
#[derive(Debug, ToSql, FromSql, PartialEq)]
@@ -102,3 +131,73 @@ fn missing_variant() {
102131
let err = conn.execute("SELECT $1::foo", &[&Foo::Bar]).unwrap_err();
103132
assert!(err.source().unwrap().is::<WrongType>());
104133
}
134+
135+
#[test]
136+
fn allow_mismatch_enums() {
137+
#[derive(Debug, ToSql, FromSql, PartialEq)]
138+
#[postgres(allow_mismatch)]
139+
enum Foo {
140+
Bar,
141+
}
142+
143+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
144+
conn.execute("CREATE TYPE pg_temp.\"Foo\" AS ENUM ('Bar', 'Baz')", &[])
145+
.unwrap();
146+
147+
let row = conn.query_one("SELECT $1::\"Foo\"", &[&Foo::Bar]).unwrap();
148+
assert_eq!(row.get::<_, Foo>(0), Foo::Bar);
149+
}
150+
151+
#[test]
152+
fn missing_enum_variant() {
153+
#[derive(Debug, ToSql, FromSql, PartialEq)]
154+
#[postgres(allow_mismatch)]
155+
enum Foo {
156+
Bar,
157+
Buz,
158+
}
159+
160+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
161+
conn.execute("CREATE TYPE pg_temp.\"Foo\" AS ENUM ('Bar', 'Baz')", &[])
162+
.unwrap();
163+
164+
let err = conn
165+
.query_one("SELECT $1::\"Foo\"", &[&Foo::Buz])
166+
.unwrap_err();
167+
assert!(err.source().unwrap().is::<DbError>());
168+
}
169+
170+
#[test]
171+
fn allow_mismatch_and_renaming() {
172+
#[derive(Debug, ToSql, FromSql, PartialEq)]
173+
#[postgres(name = "foo", allow_mismatch)]
174+
enum Foo {
175+
#[postgres(name = "bar")]
176+
Bar,
177+
#[postgres(name = "buz")]
178+
Buz,
179+
}
180+
181+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
182+
conn.execute("CREATE TYPE pg_temp.foo AS ENUM ('bar', 'baz', 'buz')", &[])
183+
.unwrap();
184+
185+
let row = conn.query_one("SELECT $1::foo", &[&Foo::Buz]).unwrap();
186+
assert_eq!(row.get::<_, Foo>(0), Foo::Buz);
187+
}
188+
189+
#[test]
190+
fn wrong_name_and_allow_mismatch() {
191+
#[derive(Debug, ToSql, FromSql, PartialEq)]
192+
#[postgres(allow_mismatch)]
193+
enum Foo {
194+
Bar,
195+
}
196+
197+
let mut conn = Client::connect("user=postgres host=localhost port=5433", NoTls).unwrap();
198+
conn.execute("CREATE TYPE pg_temp.foo AS ENUM ('Bar', 'Baz')", &[])
199+
.unwrap();
200+
201+
let err = conn.query_one("SELECT $1::foo", &[&Foo::Bar]).unwrap_err();
202+
assert!(err.source().unwrap().is::<WrongType>());
203+
}

postgres-derive/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Change Log
22

3+
## v0.4.5 - 2023-08-19
4+
5+
### Added
6+
7+
* Added a `rename_all` option for enum and struct derives.
8+
* Added an `allow_mismatch` option to disable strict enum variant checks against the Postgres type.
9+
310
## v0.4.4 - 2023-03-27
411

512
### Changed

postgres-derive/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[package]
22
name = "postgres-derive"
3-
version = "0.4.4"
3+
version = "0.4.5"
44
authors = ["Steven Fackler <sfackler@palantir.com>"]
5-
license = "MIT/Apache-2.0"
5+
license = "MIT OR Apache-2.0"
66
edition = "2018"
77
description = "An internal crate used by postgres-types"
88
repository = "https://github.com/sfackler/rust-postgres"
@@ -15,3 +15,4 @@ test = false
1515
syn = "2.0"
1616
proc-macro2 = "1.0"
1717
quote = "1.0"
18+
heck = "0.5"

postgres-derive/src/accepts.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,37 @@ pub fn domain_body(name: &str, field: &syn::Field) -> TokenStream {
3131
}
3232
}
3333

34-
pub fn enum_body(name: &str, variants: &[Variant]) -> TokenStream {
34+
pub fn enum_body(name: &str, variants: &[Variant], allow_mismatch: bool) -> TokenStream {
3535
let num_variants = variants.len();
3636
let variant_names = variants.iter().map(|v| &v.name);
3737

38-
quote! {
39-
if type_.name() != #name {
40-
return false;
38+
if allow_mismatch {
39+
quote! {
40+
type_.name() == #name
4141
}
42+
} else {
43+
quote! {
44+
if type_.name() != #name {
45+
return false;
46+
}
4247

43-
match *type_.kind() {
44-
::postgres_types::Kind::Enum(ref variants) => {
45-
if variants.len() != #num_variants {
46-
return false;
47-
}
48-
49-
variants.iter().all(|v| {
50-
match &**v {
51-
#(
52-
#variant_names => true,
53-
)*
54-
_ => false,
48+
match *type_.kind() {
49+
::postgres_types::Kind::Enum(ref variants) => {
50+
if variants.len() != #num_variants {
51+
return false;
5552
}
56-
})
53+
54+
variants.iter().all(|v| {
55+
match &**v {
56+
#(
57+
#variant_names => true,
58+
)*
59+
_ => false,
60+
}
61+
})
62+
}
63+
_ => false,
5764
}
58-
_ => false,
5965
}
6066
}
6167
}

0 commit comments

Comments
 (0)