Add Debug impls.

This commit makes the following changes

 - Add an opaque `Debug` impl for `Client`.
 - Add a rich `Debug` impl for `Row`.
 - Make the `Debug` impl for `Type` clearer.
 - Change the `Debug` for `Column` to be slightly neater.
This commit is contained in:
Richard Dodd 2019-12-30 12:36:16 +00:00
parent 4c0ee2c715
commit 51dac3c862
4 changed files with 90 additions and 5 deletions

View File

@ -207,9 +207,15 @@ mod special;
mod type_gen;
/// A Postgres type.
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
#[derive(PartialEq, Eq, Clone, Hash)]
pub struct Type(Inner);
impl fmt::Debug for Type {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, fmt)
}
}
impl fmt::Display for Type {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.schema() {

View File

@ -21,6 +21,7 @@ use futures::{future, pin_mut, ready, StreamExt, TryStreamExt};
use parking_lot::Mutex;
use postgres_protocol::message::backend::Message;
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::time::Duration;
@ -529,3 +530,9 @@ impl Client {
self.inner.sender.is_closed()
}
}
impl fmt::Debug for Client {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Client").finish()
}
}

View File

@ -100,6 +100,62 @@ pub struct Row {
ranges: Vec<Option<Range<usize>>>,
}
/// A macro to map pg types to rust types, for debug display.
macro_rules! debug_row_type {
($this:expr; $map:expr; $idx:expr; $name:expr; $type:expr; $($pg_ty:tt => $ty:ty),*) => {
match $type {
$(
&Type::$pg_ty => match <$ty as FromSql>::from_sql_nullable(
&Type::$pg_ty,
$this.0.col_buffer($idx),
) {
Ok(val) => $map.entry(&$name, &val),
Err(_) => $map.entry(&$name, &"<error>"),
},
)*
_ => $map.entry(&$name, &"<opaque type>"),
}
}
}
impl fmt::Debug for Row {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// Provides debug impl for row contents.
struct RowData<'a>(&'a Row);
impl fmt::Debug for RowData<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut map = f.debug_map();
for (idx, col) in self.0.columns().iter().enumerate() {
debug_row_type!(self; map; idx; col.name(); col.type_();
BOOL => bool,
INT2 => i16,
INT4 => i32,
INT8 => i64,
FLOAT4 => f32,
FLOAT8 => f64,
VARCHAR => String,
BPCHAR => String,
TEXT => String,
JSON => String,
XML => String,
TIMESTAMPTZ => std::time::SystemTime,
TIMESTAMP => std::time::SystemTime,
BYTEA => Vec<u8>
// More types could be added here.
);
}
map.finish()
}
}
f.debug_struct("Row")
.field("columns", &self.columns())
.field("data", &RowData(self))
.finish()
}
}
impl Row {
pub(crate) fn new(statement: Statement, body: DataRowBody) -> Result<Row, Error> {
let ranges = body.ranges().collect().map_err(Error::parse)?;
@ -170,8 +226,13 @@ impl Row {
));
}
let buf = self.ranges[idx].clone().map(|r| &self.body.buffer()[r]);
FromSql::from_sql_nullable(ty, buf).map_err(|e| Error::from_sql(e, idx))
FromSql::from_sql_nullable(ty, self.col_buffer(idx)).map_err(|e| Error::from_sql(e, idx))
}
/// Get the raw bytes for the column at the given index.
fn col_buffer(&self, idx: usize) -> Option<&[u8]> {
let range = self.ranges[idx].to_owned()?;
Some(&self.body.buffer()[range])
}
}

View File

@ -3,7 +3,10 @@ use crate::codec::FrontendMessage;
use crate::connection::RequestMessages;
use crate::types::Type;
use postgres_protocol::message::frontend;
use std::sync::{Arc, Weak};
use std::{
fmt,
sync::{Arc, Weak},
};
struct StatementInner {
client: Weak<InnerClient>,
@ -62,7 +65,6 @@ impl Statement {
}
/// Information about a column of a query.
#[derive(Debug)]
pub struct Column {
name: String,
type_: Type,
@ -83,3 +85,12 @@ impl Column {
&self.type_
}
}
impl fmt::Debug for Column {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Column")
.field("name", &self.name)
.field("type", &self.type_)
.finish()
}
}