Skip to content

Commit d884298

Browse files
committed
Include the parameter/column index in type conversion errors
Closes sfackler#442
1 parent 1270524 commit d884298

File tree

3 files changed

+33
-30
lines changed

3 files changed

+33
-30
lines changed

tokio-postgres/src/error/mod.rs

+22-23
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ enum Kind {
334334
Io,
335335
UnexpectedMessage,
336336
Tls,
337-
ToSql,
338-
FromSql,
337+
ToSql(usize),
338+
FromSql(usize),
339339
Column,
340340
CopyInStream,
341341
Closed,
@@ -368,25 +368,24 @@ impl fmt::Debug for Error {
368368

369369
impl fmt::Display for Error {
370370
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
371-
let s = match self.0.kind {
372-
Kind::Io => "error communicating with the server",
373-
Kind::UnexpectedMessage => "unexpected message from server",
374-
Kind::Tls => "error performing TLS handshake",
375-
Kind::ToSql => "error serializing a value",
376-
Kind::FromSql => "error deserializing a value",
377-
Kind::Column => "invalid column",
378-
Kind::CopyInStream => "error from a copy_in stream",
379-
Kind::Closed => "connection closed",
380-
Kind::Db => "db error",
381-
Kind::Parse => "error parsing response from server",
382-
Kind::Encode => "error encoding message to server",
383-
Kind::Authentication => "authentication error",
384-
Kind::ConfigParse => "invalid connection string",
385-
Kind::Config => "invalid configuration",
371+
match self.0.kind {
372+
Kind::Io => fmt.write_str("error communicating with the server")?,
373+
Kind::UnexpectedMessage => fmt.write_str("unexpected message from server")?,
374+
Kind::Tls => fmt.write_str("error performing TLS handshake")?,
375+
Kind::ToSql(idx) => write!(fmt, "error serializing parameter {}", idx)?,
376+
Kind::FromSql(idx) => write!(fmt, "error deserializing column {}", idx)?,
377+
Kind::Column => fmt.write_str("invalid column")?,
378+
Kind::CopyInStream => fmt.write_str("error from a copy_in stream")?,
379+
Kind::Closed => fmt.write_str("connection closed")?,
380+
Kind::Db => fmt.write_str("db error")?,
381+
Kind::Parse => fmt.write_str("error parsing response from server")?,
382+
Kind::Encode => fmt.write_str("error encoding message to server")?,
383+
Kind::Authentication => fmt.write_str("authentication error")?,
384+
Kind::ConfigParse => fmt.write_str("invalid connection string")?,
385+
Kind::Config => fmt.write_str("invalid configuration")?,
386386
#[cfg(feature = "runtime")]
387-
Kind::Connect => "error connecting to server",
387+
Kind::Connect => fmt.write_str("error connecting to server")?,
388388
};
389-
fmt.write_str(s)?;
390389
if let Some(ref cause) = self.0.cause {
391390
write!(fmt, ": {}", cause)?;
392391
}
@@ -445,12 +444,12 @@ impl Error {
445444
}
446445

447446
#[allow(clippy::wrong_self_convention)]
448-
pub(crate) fn to_sql(e: Box<dyn error::Error + Sync + Send>) -> Error {
449-
Error::new(Kind::ToSql, Some(e))
447+
pub(crate) fn to_sql(e: Box<dyn error::Error + Sync + Send>, idx: usize) -> Error {
448+
Error::new(Kind::ToSql(idx), Some(e))
450449
}
451450

452-
pub(crate) fn from_sql(e: Box<dyn error::Error + Sync + Send>) -> Error {
453-
Error::new(Kind::FromSql, Some(e))
451+
pub(crate) fn from_sql(e: Box<dyn error::Error + Sync + Send>, idx: usize) -> Error {
452+
Error::new(Kind::FromSql(idx), Some(e))
454453
}
455454

456455
pub(crate) fn column() -> Error {

tokio-postgres/src/proto/client.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -298,22 +298,26 @@ impl Client {
298298
);
299299

300300
let mut buf = vec![];
301+
let mut error_idx = 0;
301302
let r = frontend::bind(
302303
name,
303304
statement.name(),
304305
Some(1),
305-
params.iter().zip(statement.params()),
306-
|(param, ty), buf| match param.to_sql_checked(ty, buf) {
306+
params.iter().zip(statement.params()).enumerate(),
307+
|(idx, (param, ty)), buf| match param.to_sql_checked(ty, buf) {
307308
Ok(IsNull::No) => Ok(postgres_protocol::IsNull::No),
308309
Ok(IsNull::Yes) => Ok(postgres_protocol::IsNull::Yes),
309-
Err(e) => Err(e),
310+
Err(e) => {
311+
error_idx = idx;
312+
Err(e)
313+
}
310314
},
311315
Some(1),
312316
&mut buf,
313317
);
314318
match r {
315319
Ok(()) => Ok(buf),
316-
Err(frontend::BindError::Conversion(e)) => Err(Error::to_sql(e)),
320+
Err(frontend::BindError::Conversion(e)) => Err(Error::to_sql(e, error_idx)),
317321
Err(frontend::BindError::Serialization(e)) => Err(Error::encode(e)),
318322
}
319323
}

tokio-postgres/src/row.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,11 @@ impl Row {
167167

168168
let ty = self.columns()[idx].type_();
169169
if !T::accepts(ty) {
170-
return Err(Error::from_sql(Box::new(WrongType::new(ty.clone()))));
170+
return Err(Error::from_sql(Box::new(WrongType::new(ty.clone())), idx));
171171
}
172172

173173
let buf = self.ranges[idx].clone().map(|r| &self.body.buffer()[r]);
174-
FromSql::from_sql_nullable(ty, buf).map_err(Error::from_sql)
174+
FromSql::from_sql_nullable(ty, buf).map_err(|e| Error::from_sql(e, idx))
175175
}
176176
}
177177

@@ -238,6 +238,6 @@ impl SimpleQueryRow {
238238
};
239239

240240
let buf = self.ranges[idx].clone().map(|r| &self.body.buffer()[r]);
241-
FromSql::from_sql_nullable(&Type::TEXT, buf).map_err(Error::from_sql)
241+
FromSql::from_sql_nullable(&Type::TEXT, buf).map_err(|e| Error::from_sql(e, idx))
242242
}
243243
}

0 commit comments

Comments
 (0)