This commit is contained in:
Steven Fackler 2016-09-12 21:48:49 -07:00
parent bcb104793b
commit fbcdd6b547
12 changed files with 119 additions and 196 deletions

View File

@ -139,22 +139,22 @@ impl DbErrorNew for DbError {
impl fmt::Debug for DbError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("DbError")
.field("severity", &self.severity)
.field("code", &self.code)
.field("message", &self.message)
.field("detail", &self.detail)
.field("hint", &self.hint)
.field("position", &self.position)
.field("where_", &self.where_)
.field("schema", &self.schema)
.field("table", &self.table)
.field("column", &self.column)
.field("datatype", &self.datatype)
.field("constraint", &self.constraint)
.field("file", &self.file)
.field("line", &self.line)
.field("routine", &self.routine)
.finish()
.field("severity", &self.severity)
.field("code", &self.code)
.field("message", &self.message)
.field("detail", &self.detail)
.field("hint", &self.hint)
.field("position", &self.position)
.field("where_", &self.where_)
.field("schema", &self.schema)
.field("table", &self.table)
.field("column", &self.column)
.field("datatype", &self.datatype)
.field("constraint", &self.constraint)
.field("file", &self.file)
.field("line", &self.line)
.field("routine", &self.routine)
.finish()
}
}
@ -207,7 +207,8 @@ impl error::Error for ConnectError {
fn cause(&self) -> Option<&error::Error> {
match *self {
ConnectError::ConnectParams(ref err) | ConnectError::Ssl(ref err) => Some(&**err),
ConnectError::ConnectParams(ref err) |
ConnectError::Ssl(ref err) => Some(&**err),
ConnectError::Db(ref err) => Some(&**err),
ConnectError::Io(ref err) => Some(err),
}

View File

@ -245,7 +245,8 @@ impl InnerConnection {
let user = match user {
Some(user) => user,
None => {
return Err(ConnectError::ConnectParams("User missing from connection parameters".into()));
return Err(ConnectError::ConnectParams("User missing from connection parameters"
.into()));
}
};
@ -337,8 +338,7 @@ impl InnerConnection {
}
}
fn read_message_with_notification_nonblocking(&mut self)
-> std::io::Result<Option<Backend>> {
fn read_message_with_notification_nonblocking(&mut self) -> std::io::Result<Option<Backend>> {
debug_assert!(!self.desynchronized);
loop {
match try_desync!(self, self.stream.read_message_nonblocking()) {
@ -471,7 +471,8 @@ impl InnerConnection {
let more_rows;
loop {
match try!(self.read_message()) {
Backend::EmptyQueryResponse | Backend::CommandComplete { .. } => {
Backend::EmptyQueryResponse |
Backend::CommandComplete { .. } => {
more_rows = false;
break;
}
@ -813,10 +814,8 @@ impl InnerConnection {
Backend::ReadyForQuery { .. } => break,
Backend::DataRow { row } => {
result.push(row.into_iter()
.map(|opt| {
opt.map(|b| String::from_utf8_lossy(&b).into_owned())
})
.collect());
.map(|opt| opt.map(|b| String::from_utf8_lossy(&b).into_owned()))
.collect());
}
Backend::CopyInResponse { .. } => {
try!(self.stream.write_message(&frontend::CopyFail {
@ -857,13 +856,13 @@ impl fmt::Debug for Connection {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let conn = self.conn.borrow();
fmt.debug_struct("Connection")
.field("stream", &conn.stream.get_ref())
.field("cancel_data", &conn.cancel_data)
.field("notifications", &conn.notifications.len())
.field("transaction_depth", &conn.trans_depth)
.field("desynchronized", &conn.desynchronized)
.field("cached_statements", &conn.cached_statements.len())
.finish()
.field("stream", &conn.stream.get_ref())
.field("cancel_data", &conn.cancel_data)
.field("notifications", &conn.notifications.len())
.field("transaction_depth", &conn.trans_depth)
.field("desynchronized", &conn.desynchronized)
.field("cached_statements", &conn.cached_statements.len())
.finish()
}
}

View File

@ -166,11 +166,11 @@ macro_rules! impl_fixed_buffer( ($name:ident, $size:expr) => (
fn input<F: FnMut(&[u8])>(&mut self, input: &[u8], mut func: F) {
let mut i = 0;
// FIXME: #6304 - This local variable shouldn't be necessary.
// FIXME: #6304 - This local variable shouldn't be necessary.
let size = $size;
// If there is already data in the buffer, copy as much as we can into it and process
// the data if the buffer becomes full.
// If there is already data in the buffer, copy as much as we can into it and process
// the data if the buffer becomes full.
if self.buffer_idx != 0 {
let buffer_remaining = size - self.buffer_idx;
if input.len() >= buffer_remaining {
@ -189,16 +189,16 @@ macro_rules! impl_fixed_buffer( ($name:ident, $size:expr) => (
}
}
// While we have at least a full buffer size chunks's worth of data, process that data
// without copying it into the buffer
// While we have at least a full buffer size chunks's worth of data, process that data
// without copying it into the buffer
while input.len() - i >= size {
func(&input[i..i + size]);
i += size;
}
// Copy any input data into the buffer. At this point in the method, the ammount of
// data left in the input vector will be less than the buffer size and the buffer will
// be empty.
// Copy any input data into the buffer. At this point in the method, the ammount of
// data left in the input vector will be less than the buffer size and the buffer will
// be empty.
let input_remaining = input.len() - i;
copy_memory(
&input[i..],

View File

@ -8,24 +8,15 @@ pub enum Backend {
AuthenticationCleartextPassword,
AuthenticationGSS,
AuthenticationKerberosV5,
AuthenticationMD5Password {
salt: [u8; 4],
},
AuthenticationMD5Password { salt: [u8; 4] },
AuthenticationOk,
AuthenticationSCMCredential,
AuthenticationSSPI,
BackendKeyData {
process_id: i32,
secret_key: i32,
},
BackendKeyData { process_id: i32, secret_key: i32 },
BindComplete,
CloseComplete,
CommandComplete {
tag: String,
},
CopyData {
data: Vec<u8>,
},
CommandComplete { tag: String },
CopyData { data: Vec<u8> },
CopyDone,
CopyInResponse {
format: u8,
@ -35,37 +26,22 @@ pub enum Backend {
format: u8,
column_formats: Vec<u16>,
},
DataRow {
row: Vec<Option<Vec<u8>>>,
},
DataRow { row: Vec<Option<Vec<u8>>> },
EmptyQueryResponse,
ErrorResponse {
fields: Vec<(u8, String)>,
},
ErrorResponse { fields: Vec<(u8, String)> },
NoData,
NoticeResponse {
fields: Vec<(u8, String)>,
},
NoticeResponse { fields: Vec<(u8, String)> },
NotificationResponse {
process_id: i32,
channel: String,
payload: String,
},
ParameterDescription {
types: Vec<Oid>,
},
ParameterStatus {
parameter: String,
value: String,
},
ParameterDescription { types: Vec<Oid> },
ParameterStatus { parameter: String, value: String },
ParseComplete,
PortalSuspended,
ReadyForQuery {
_state: u8,
},
RowDescription {
descriptions: Vec<RowDescriptionEntry>,
},
ReadyForQuery { _state: u8 },
RowDescription { descriptions: Vec<RowDescriptionEntry>, },
}
impl Backend {
@ -89,9 +65,7 @@ impl Backend {
Message::BindComplete => Backend::BindComplete,
Message::CloseComplete => Backend::CloseComplete,
Message::CommandComplete(body) => {
Backend::CommandComplete {
tag: body.tag().to_owned()
}
Backend::CommandComplete { tag: body.tag().to_owned() }
}
Message::CopyData(body) => Backend::CopyData { data: body.data().to_owned() },
Message::CopyDone => Backend::CopyDone,
@ -115,13 +89,17 @@ impl Backend {
Message::EmptyQueryResponse => Backend::EmptyQueryResponse,
Message::ErrorResponse(body) => {
Backend::ErrorResponse {
fields: try!(body.fields().map(|f| (f.type_(), f.value().to_owned())).collect()),
fields: try!(body.fields()
.map(|f| (f.type_(), f.value().to_owned()))
.collect()),
}
}
Message::NoData => Backend::NoData,
Message::NoticeResponse(body) => {
Backend::NoticeResponse {
fields: try!(body.fields().map(|f| (f.type_(), f.value().to_owned())).collect()),
fields: try!(body.fields()
.map(|f| (f.type_(), f.value().to_owned()))
.collect()),
}
}
Message::NotificationResponse(body) => {
@ -132,9 +110,7 @@ impl Backend {
}
}
Message::ParameterDescription(body) => {
Backend::ParameterDescription {
types: try!(body.parameters().collect()),
}
Backend::ParameterDescription { types: try!(body.parameters().collect()) }
}
Message::ParameterStatus(body) => {
Backend::ParameterStatus {
@ -158,9 +134,7 @@ impl Backend {
format: f.format(),
}
});
Backend::RowDescription {
descriptions: try!(fields.collect()),
}
Backend::RowDescription { descriptions: try!(fields.collect()) }
}
_ => return Err(io::Error::new(io::ErrorKind::InvalidInput, "unknown message type")),
};

View File

@ -27,8 +27,8 @@ pub struct Notifications<'conn> {
impl<'a> fmt::Debug for Notifications<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Notifications")
.field("pending", &self.len())
.finish()
.field("pending", &self.len())
.finish()
}
}

View File

@ -85,9 +85,8 @@ impl MessageStream {
match b {
Ok(b) => self.inner_read_message(b).map(Some),
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock || e.kind() == io::ErrorKind::TimedOut => {
Ok(None)
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock ||
e.kind() == io::ErrorKind::TimedOut => Ok(None),
Err(e) => Err(e),
}
}

View File

@ -397,11 +397,7 @@ impl<'trans, 'stmt> FallibleIterator for LazyRows<'trans, 'stmt> {
fn size_hint(&self) -> (usize, Option<usize>) {
let lower = self.data.len();
let upper = if self.more_rows {
None
} else {
Some(lower)
};
let upper = if self.more_rows { None } else { Some(lower) };
(lower, upper)
}
}

View File

@ -12,8 +12,8 @@ use types::{SessionInfo, Type, ToSql};
use message::Backend;
use rows::{Rows, LazyRows};
use transaction::Transaction;
use {bad_response, Connection, StatementInternals, Result, RowsNew, InnerConnection, SessionInfoNew,
LazyRowsNew, DbErrorNew, ColumnNew, StatementInfo, TransactionInternals};
use {bad_response, Connection, StatementInternals, Result, RowsNew, InnerConnection,
SessionInfoNew, LazyRowsNew, DbErrorNew, ColumnNew, StatementInfo, TransactionInternals};
/// A prepared statement.
pub struct Statement<'conn> {
@ -26,10 +26,10 @@ pub struct Statement<'conn> {
impl<'a> fmt::Debug for Statement<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Statement")
.field("name", &self.info.name)
.field("parameter_types", &self.info.param_types)
.field("columns", &self.info.columns)
.finish()
.field("name", &self.info.name)
.field("parameter_types", &self.info.param_types)
.field("columns", &self.info.columns)
.finish()
}
}
@ -417,7 +417,8 @@ impl<'conn> Statement<'conn> {
Ok(n) => data = &data[n..],
Err(e) => {
loop {
if let Backend::ReadyForQuery { .. } = try!(info.conn.read_message()) {
if let Backend::ReadyForQuery { .. } =
try!(info.conn.read_message()) {
return Err(Error::Io(e));
}
}

View File

@ -4,8 +4,7 @@ use std::cell::Cell;
use std::fmt;
use std::ascii::AsciiExt;
use {bad_response, Result, Connection, TransactionInternals, ConfigInternals,
IsolationLevelNew};
use {bad_response, Result, Connection, TransactionInternals, ConfigInternals, IsolationLevelNew};
use error::Error;
use rows::Rows;
use stmt::Statement;
@ -159,9 +158,9 @@ pub struct Transaction<'conn> {
impl<'a> fmt::Debug for Transaction<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Transaction")
.field("commit", &self.commit.get())
.field("depth", &self.depth)
.finish()
.field("commit", &self.commit.get())
.field("depth", &self.depth)
.finish()
}
}
@ -199,15 +198,13 @@ impl<'conn> Transaction<'conn> {
debug_assert!(self.depth == conn.trans_depth);
conn.trans_depth -= 1;
match (self.commit.get(), &self.savepoint_name) {
(false, &Some(ref savepoint_name)) => {
conn.quick_query(&format!("ROLLBACK TO {}", savepoint_name))
}
(false, &None) => conn.quick_query("ROLLBACK"),
(true, &Some(ref savepoint_name)) => {
conn.quick_query(&format!("RELEASE {}", savepoint_name))
}
(true, &None) => conn.quick_query("COMMIT"),
}.map(|_| ())
(false, &Some(ref sp)) => try!(conn.quick_query(&format!("ROLLBACK TO {}", sp))),
(false, &None) => try!(conn.quick_query("ROLLBACK")),
(true, &Some(ref sp)) => try!(conn.quick_query(&format!("RELEASE {}", sp))),
(true, &None) => try!(conn.quick_query("COMMIT")),
};
Ok(())
}
/// Like `Connection::prepare`.

View File

@ -97,8 +97,8 @@ impl<'a> SessionInfo<'a> {
impl<'a> fmt::Debug for SessionInfo<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("SessionInfo")
.field("parameters", &self.conn.parameters)
.finish()
.field("parameters", &self.conn.parameters)
.finish()
}
}
@ -158,11 +158,11 @@ pub struct Other(Arc<OtherInner>);
impl fmt::Debug for Other {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("Other")
.field("name", &self.0.name)
.field("oid", &self.0.oid)
.field("kind", &self.0.kind)
.field("schema", &self.0.schema)
.finish()
.field("name", &self.0.name)
.field("oid", &self.0.oid)
.field("kind", &self.0.kind)
.field("schema", &self.0.schema)
.finish()
}
}
@ -634,7 +634,8 @@ impl ToSql for bool {
impl<'a, T: ToSql> ToSql for &'a [T] {
to_sql_checked!();
fn to_sql<W: Write + ?Sized>(&self, ty: &Type,
fn to_sql<W: Write + ?Sized>(&self,
ty: &Type,
mut w: &mut W,
ctx: &SessionInfo)
-> Result<IsNull> {

View File

@ -39,7 +39,11 @@ impl<T: FromSql> FromSql for Date<T> {
}
}
impl<T: ToSql> ToSql for Date<T> {
fn to_sql<W: Write+?Sized>(&self, ty: &Type, out: &mut W, ctx: &SessionInfo) -> Result<IsNull> {
fn to_sql<W: Write + ?Sized>(&self,
ty: &Type,
out: &mut W,
ctx: &SessionInfo)
-> Result<IsNull> {
if *ty != Type::Date {
return Err(Error::Conversion("expected date type".into()));
}
@ -95,7 +99,11 @@ impl<T: FromSql> FromSql for Timestamp<T> {
}
impl<T: ToSql> ToSql for Timestamp<T> {
fn to_sql<W: Write+?Sized>(&self, ty: &Type, out: &mut W, ctx: &SessionInfo) -> Result<IsNull> {
fn to_sql<W: Write + ?Sized>(&self,
ty: &Type,
out: &mut W,
ctx: &SessionInfo)
-> Result<IsNull> {
if *ty != Type::Timestamp && *ty != Type::Timestamptz {
return Err(Error::Conversion("expected timestamp or timestamptz type".into()));
}

View File

@ -126,7 +126,8 @@ fn decode_inner(c: &str, full_url: bool) -> DecodeResult<String> {
(Some(one), Some(two)) => [one, two],
_ => {
return Err("Malformed input: found '%' without two \
trailing bytes".to_owned())
trailing bytes"
.to_owned())
}
};
@ -135,31 +136,16 @@ fn decode_inner(c: &str, full_url: bool) -> DecodeResult<String> {
_ => {
return Err("Malformed input: found '%' followed by \
invalid hex values. Character '%' must \
escaped.".to_owned())
escaped."
.to_owned())
}
};
// Only decode some characters if full_url:
match bytes_from_hex[0] as char {
// gen-delims:
':' |
'/' |
'?' |
'#' |
'[' |
']' |
'@' |
'!' |
'$' |
'&' |
'"' |
'(' |
')' |
'*' |
'+' |
',' |
';' |
'=' if full_url => {
':' | '/' | '?' | '#' | '[' | ']' | '@' | '!' | '$' | '&' | '"' |
'(' | ')' | '*' | '+' | ',' | ';' | '=' if full_url => {
out.push('%');
out.push(bytes[0] as char);
out.push(bytes[1] as char);
@ -201,8 +187,7 @@ fn query_from_str(rawquery: &str) -> DecodeResult<Query> {
pub fn get_scheme(rawurl: &str) -> DecodeResult<(&str, &str)> {
for (i, c) in rawurl.chars().enumerate() {
let result = match c {
'A'...'Z' |
'a'...'z' => continue,
'A'...'Z' | 'a'...'z' => continue,
'0'...'9' | '+' | '-' | '.' => {
if i != 0 {
continue;
@ -263,34 +248,18 @@ fn get_authority(rawurl: &str) -> DecodeResult<(Option<UserInfo>, &str, Option<u
let mut end = len;
for (i, c) in rawurl.chars()
.enumerate()
.skip(2) {
.enumerate()
.skip(2) {
// deal with input class first
match c {
'0'...'9' => (),
'A'...'F' |
'a'...'f' => {
'A'...'F' | 'a'...'f' => {
if input == Input::Digit {
input = Input::Hex;
}
}
'G'...'Z' |
'g'...'z' |
'-' |
'.' |
'_' |
'~' |
'%' |
'&' |
'\'' |
'(' |
')' |
'+' |
'!' |
'*' |
',' |
';' |
'=' => input = Input::Unreserved,
'G'...'Z' | 'g'...'z' | '-' | '.' | '_' | '~' | '%' | '&' | '\'' | '(' | ')' |
'+' | '!' | '*' | ',' | ';' | '=' => input = Input::Unreserved,
':' | '@' | '?' | '#' | '/' => {
// separators, don't change anything
}
@ -372,17 +341,14 @@ fn get_authority(rawurl: &str) -> DecodeResult<(Option<UserInfo>, &str, Option<u
// finish up
match st {
State::PassHostPort |
State::Ip6Port => {
State::PassHostPort | State::Ip6Port => {
if input != Input::Digit {
return Err("Non-digit characters in port.".to_owned());
}
host = &rawurl[begin..pos];
port = Some(&rawurl[pos + 1..end]);
}
State::Ip6Host |
State::InHost |
State::Start => host = &rawurl[begin..end],
State::Ip6Host | State::InHost | State::Start => host = &rawurl[begin..end],
State::InPort => {
if input != Input::Digit {
return Err("Non-digit characters in port.".to_owned());
@ -413,27 +379,8 @@ fn get_path(rawurl: &str, is_authority: bool) -> DecodeResult<(String, &str)> {
let mut end = len;
for (i, c) in rawurl.chars().enumerate() {
match c {
'A'...'Z' |
'a'...'z' |
'0'...'9' |
'&' |
'\'' |
'(' |
')' |
'.' |
'@' |
':' |
'%' |
'/' |
'+' |
'!' |
'*' |
',' |
';' |
'=' |
'_' |
'-' |
'~' => continue,
'A'...'Z' | 'a'...'z' | '0'...'9' | '&' | '\'' | '(' | ')' | '.' | '@' | ':' |
'%' | '/' | '+' | '!' | '*' | ',' | ';' | '=' | '_' | '-' | '~' => continue,
'?' | '#' => {
end = i;
break;