Skip to content

Commit 35cb1ad

Browse files
authored
Merge pull request #182 from weiznich/fix/cast_truncations
Enable a few more lints regarding truncations in numerical casts
2 parents a123c80 + 6c981bf commit 35cb1ad

11 files changed

+66
-37
lines changed

CHANGELOG.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/
66

77
## [Unreleased]
88

9+
## [0.5.1] - 2024-11-01
10+
911
* Add crate feature `pool` for extending connection pool implements through external crate
12+
* Implement `Deref` and `DerefMut` for `AsyncConnectionWrapper` to allow using it in an async context as well
1013

1114
## [0.5.0] - 2024-07-19
1215

@@ -79,4 +82,5 @@ in the pool should be checked if they are still valid
7982
[0.4.0]: https://github.com/weiznich/diesel_async/compare/v0.3.2...v0.4.0
8083
[0.4.1]: https://github.com/weiznich/diesel_async/compare/v0.4.0...v0.4.1
8184
[0.5.0]: https://github.com/weiznich/diesel_async/compare/v0.4.0...v0.5.0
82-
[Unreleased]: https://github.com/weiznich/diesel_async/compare/v0.5.0...main
85+
[0.5.1]: https://github.com/weiznich/diesel_async/compare/v0.5.0...v0.5.1
86+
[Unreleased]: https://github.com/weiznich/diesel_async/compare/v0.5.1...main

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "diesel-async"
3-
version = "0.5.0"
3+
version = "0.5.1"
44
authors = ["Georg Semmler <[email protected]>"]
55
edition = "2021"
66
autotests = false

src/lib.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,12 @@
6666
//! # }
6767
//! ```
6868
69-
#![warn(missing_docs)]
69+
#![warn(
70+
missing_docs,
71+
clippy::cast_possible_wrap,
72+
clippy::cast_possible_truncation,
73+
clippy::cast_sign_loss
74+
)]
7075

7176
use diesel::backend::Backend;
7277
use diesel::connection::Instrumentation;

src/mysql/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ impl AsyncConnection for AsyncMysqlConnection {
150150
+ 'query,
151151
{
152152
self.with_prepared_statement(source, |conn, stmt, binds| async move {
153-
conn.exec_drop(&*stmt, binds).await.map_err(ErrorHelper)?;
153+
let params = mysql_async::Params::try_from(binds)?;
154+
conn.exec_drop(&*stmt, params).await.map_err(ErrorHelper)?;
154155
// We need to close any non-cached statement explicitly here as otherwise
155156
// we might error out on too many open statements. See https://github.com/weiznich/diesel_async/issues/26
156157
// for details
@@ -165,7 +166,9 @@ impl AsyncConnection for AsyncMysqlConnection {
165166
if let MaybeCached::CannotCache(stmt) = stmt {
166167
conn.close(stmt).await.map_err(ErrorHelper)?;
167168
}
168-
Ok(conn.affected_rows() as usize)
169+
conn.affected_rows()
170+
.try_into()
171+
.map_err(|e| diesel::result::Error::DeserializationError(Box::new(e)))
169172
})
170173
}
171174

@@ -325,8 +328,10 @@ impl AsyncMysqlConnection {
325328
mut tx: futures_channel::mpsc::Sender<QueryResult<MysqlRow>>,
326329
) -> QueryResult<()> {
327330
use futures_util::sink::SinkExt;
331+
let params = mysql_async::Params::try_from(binds)?;
332+
328333
let res = conn
329-
.exec_iter(stmt_for_exec, binds)
334+
.exec_iter(stmt_for_exec, params)
330335
.await
331336
.map_err(ErrorHelper)?;
332337

src/mysql/row.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,12 @@ impl<'a> diesel::row::Row<'a, Mysql> for MysqlRow {
9999
Some(Cow::Owned(buffer))
100100
}
101101
_t => {
102-
let mut buffer = Vec::with_capacity(value.bin_len() as usize);
102+
let mut buffer = Vec::with_capacity(
103+
value
104+
.bin_len()
105+
.try_into()
106+
.expect("Failed to cast byte size to usize"),
107+
);
103108
mysql_common::proto::MySerialize::serialize(value, &mut buffer);
104109
Some(Cow::Owned(buffer))
105110
}

src/mysql/serialize.rs

+29-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use diesel::mysql::data_types::MysqlTime;
22
use diesel::mysql::MysqlType;
33
use diesel::mysql::MysqlValue;
4+
use diesel::QueryResult;
45
use mysql_async::{Params, Value};
56
use std::convert::TryInto;
67

@@ -9,10 +10,11 @@ pub(super) struct ToSqlHelper {
910
pub(super) binds: Vec<Option<Vec<u8>>>,
1011
}
1112

12-
fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> Value {
13-
match bind {
13+
fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> QueryResult<Value> {
14+
let cast_helper = |e| diesel::result::Error::SerializationError(Box::new(e));
15+
let v = match bind {
1416
Some(bind) => match metadata {
15-
MysqlType::Tiny => Value::Int((bind[0] as i8) as i64),
17+
MysqlType::Tiny => Value::Int(i8::from_be_bytes([bind[0]]) as i64),
1618
MysqlType::Short => Value::Int(i16::from_ne_bytes(bind.try_into().unwrap()) as _),
1719
MysqlType::Long => Value::Int(i32::from_ne_bytes(bind.try_into().unwrap()) as _),
1820
MysqlType::LongLong => Value::Int(i64::from_ne_bytes(bind.try_into().unwrap())),
@@ -38,11 +40,11 @@ fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> Value {
3840
.expect("This does not fail");
3941
Value::Time(
4042
time.neg,
41-
time.day as _,
42-
time.hour as _,
43-
time.minute as _,
44-
time.second as _,
45-
time.second_part as _,
43+
time.day,
44+
time.hour.try_into().map_err(cast_helper)?,
45+
time.minute.try_into().map_err(cast_helper)?,
46+
time.second.try_into().map_err(cast_helper)?,
47+
time.second_part.try_into().expect("Cast does not fail"),
4648
)
4749
}
4850
MysqlType::Date | MysqlType::DateTime | MysqlType::Timestamp => {
@@ -52,13 +54,13 @@ fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> Value {
5254
>::from_sql(MysqlValue::new(&bind, metadata))
5355
.expect("This does not fail");
5456
Value::Date(
55-
time.year as _,
56-
time.month as _,
57-
time.day as _,
58-
time.hour as _,
59-
time.minute as _,
60-
time.second as _,
61-
time.second_part as _,
57+
time.year.try_into().map_err(cast_helper)?,
58+
time.month.try_into().map_err(cast_helper)?,
59+
time.day.try_into().map_err(cast_helper)?,
60+
time.hour.try_into().map_err(cast_helper)?,
61+
time.minute.try_into().map_err(cast_helper)?,
62+
time.second.try_into().map_err(cast_helper)?,
63+
time.second_part.try_into().expect("Cast does not fail"),
6264
)
6365
}
6466
MysqlType::Numeric
@@ -70,12 +72,19 @@ fn to_value((metadata, bind): (MysqlType, Option<Vec<u8>>)) -> Value {
7072
_ => unreachable!(),
7173
},
7274
None => Value::NULL,
73-
}
75+
};
76+
Ok(v)
7477
}
7578

76-
impl From<ToSqlHelper> for Params {
77-
fn from(ToSqlHelper { metadata, binds }: ToSqlHelper) -> Self {
78-
let values = metadata.into_iter().zip(binds).map(to_value).collect();
79-
Params::Positional(values)
79+
impl TryFrom<ToSqlHelper> for Params {
80+
type Error = diesel::result::Error;
81+
82+
fn try_from(ToSqlHelper { metadata, binds }: ToSqlHelper) -> Result<Self, Self::Error> {
83+
let values = metadata
84+
.into_iter()
85+
.zip(binds)
86+
.map(to_value)
87+
.collect::<Result<Vec<_>, Self::Error>>()?;
88+
Ok(Params::Positional(values))
8089
}
8190
}

src/pg/error_helper.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ impl diesel::result::DatabaseErrorInformation for PostgresDbErrorWrapper {
8181

8282
fn statement_position(&self) -> Option<i32> {
8383
use tokio_postgres::error::ErrorPosition;
84-
self.0.position().map(|e| match e {
84+
self.0.position().and_then(|e| match *e {
8585
ErrorPosition::Original(position) | ErrorPosition::Internal { position, .. } => {
86-
*position as i32
86+
position.try_into().ok()
8787
}
8888
})
8989
}

src/pg/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ async fn execute_prepared(
274274
let res = tokio_postgres::Client::execute(&conn, &stmt, &binds as &[_])
275275
.await
276276
.map_err(ErrorHelper)?;
277-
Ok(res as usize)
277+
res.try_into()
278+
.map_err(|e| diesel::result::Error::DeserializationError(Box::new(e)))
278279
}
279280

280281
#[inline(always)]

tests/instrumentation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ async fn check_events_are_emitted_for_load() {
116116
async fn check_events_are_emitted_for_execute_returning_count_does_not_contain_cache_for_uncached_queries(
117117
) {
118118
let (events_to_check, mut conn) = setup_test_case().await;
119-
conn.execute_returning_count(&diesel::sql_query("select 1"))
119+
conn.execute_returning_count(diesel::sql_query("select 1"))
120120
.await
121121
.unwrap();
122122
let events = events_to_check.lock().unwrap();
@@ -141,7 +141,7 @@ async fn check_events_are_emitted_for_load_does_not_contain_cache_for_uncached_q
141141
async fn check_events_are_emitted_for_execute_returning_count_does_contain_error_for_failures() {
142142
let (events_to_check, mut conn) = setup_test_case().await;
143143
let _ = conn
144-
.execute_returning_count(&diesel::sql_query("invalid"))
144+
.execute_returning_count(diesel::sql_query("invalid"))
145145
.await;
146146
let events = events_to_check.lock().unwrap();
147147
assert_eq!(events.len(), 2, "{:?}", events);

tests/pooling.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async fn save_changes_bb8() {
1717

1818
let mut conn = pool.get().await.unwrap();
1919

20-
super::setup(&mut *conn).await;
20+
super::setup(&mut conn).await;
2121

2222
diesel::insert_into(users::table)
2323
.values(users::name.eq("John"))
@@ -51,7 +51,7 @@ async fn save_changes_deadpool() {
5151

5252
let mut conn = pool.get().await.unwrap();
5353

54-
super::setup(&mut *conn).await;
54+
super::setup(&mut conn).await;
5555

5656
diesel::insert_into(users::table)
5757
.values(users::name.eq("John"))
@@ -85,7 +85,7 @@ async fn save_changes_mobc() {
8585

8686
let mut conn = pool.get().await.unwrap();
8787

88-
super::setup(&mut *conn).await;
88+
super::setup(&mut conn).await;
8989

9090
diesel::insert_into(users::table)
9191
.values(users::name.eq("John"))

tests/type_check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ async fn test_datetime() {
200200
type_check::<_, sql_types::Datetime>(
201201
conn,
202202
chrono::NaiveDateTime::new(
203-
chrono::NaiveDate::from_ymd_opt(2021, 09, 30).unwrap(),
204-
chrono::NaiveTime::from_hms_milli_opt(12, 06, 42, 0).unwrap(),
203+
chrono::NaiveDate::from_ymd_opt(2021, 9, 30).unwrap(),
204+
chrono::NaiveTime::from_hms_milli_opt(12, 6, 42, 0).unwrap(),
205205
),
206206
)
207207
.await;

0 commit comments

Comments
 (0)