|
1 | 1 | //! Error types. |
2 | 2 |
|
| 3 | +use fallible_iterator::FallibleIterator; |
| 4 | +use postgres_protocol::message::backend::ErrorFields; |
3 | 5 | use std::error; |
4 | 6 | use std::convert::From; |
5 | 7 | use std::fmt; |
6 | 8 | use std::io; |
7 | 9 | use std::result; |
8 | | -use std::collections::HashMap; |
9 | 10 |
|
10 | 11 | pub use self::sqlstate::SqlState; |
11 | 12 | use {Result, DbErrorNew}; |
@@ -85,52 +86,92 @@ pub struct DbError { |
85 | 86 | } |
86 | 87 |
|
87 | 88 | impl DbErrorNew for DbError { |
88 | | - fn new_raw(fields: Vec<(u8, String)>) -> result::Result<DbError, ()> { |
89 | | - let mut map: HashMap<_, _> = fields.into_iter().collect(); |
| 89 | + fn new_raw(fields: &mut ErrorFields) -> io::Result<DbError> { |
| 90 | + let mut severity = None; |
| 91 | + let mut code = None; |
| 92 | + let mut message = None; |
| 93 | + let mut detail = None; |
| 94 | + let mut hint = None; |
| 95 | + let mut normal_position = None; |
| 96 | + let mut internal_position = None; |
| 97 | + let mut internal_query = None; |
| 98 | + let mut where_ = None; |
| 99 | + let mut schema = None; |
| 100 | + let mut table = None; |
| 101 | + let mut column = None; |
| 102 | + let mut datatype = None; |
| 103 | + let mut constraint = None; |
| 104 | + let mut file = None; |
| 105 | + let mut line = None; |
| 106 | + let mut routine = None; |
| 107 | + |
| 108 | + while let Some(field) = try!(fields.next()) { |
| 109 | + match field.type_() { |
| 110 | + b'S' => severity = Some(field.value().to_owned()), |
| 111 | + b'C' => code = Some(SqlState::from_code(field.value())), |
| 112 | + b'M' => message = Some(field.value().to_owned()), |
| 113 | + b'D' => detail = Some(field.value().to_owned()), |
| 114 | + b'H' => hint = Some(field.value().to_owned()), |
| 115 | + b'P' => normal_position = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))), |
| 116 | + b'p' => internal_position = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))), |
| 117 | + b'q' => internal_query = Some(field.value().to_owned()), |
| 118 | + b'W' => where_ = Some(field.value().to_owned()), |
| 119 | + b's' => schema = Some(field.value().to_owned()), |
| 120 | + b't' => table = Some(field.value().to_owned()), |
| 121 | + b'c' => column = Some(field.value().to_owned()), |
| 122 | + b'd' => datatype = Some(field.value().to_owned()), |
| 123 | + b'n' => constraint = Some(field.value().to_owned()), |
| 124 | + b'F' => file = Some(field.value().to_owned()), |
| 125 | + b'L' => line = Some(try!(field.value().parse::<u32>().map_err(|_| ::bad_response()))), |
| 126 | + b'R' => routine = Some(field.value().to_owned()), |
| 127 | + _ => {}, |
| 128 | + } |
| 129 | + } |
| 130 | + |
90 | 131 | Ok(DbError { |
91 | | - severity: try!(map.remove(&b'S').ok_or(())), |
92 | | - code: SqlState::from_code(try!(map.remove(&b'C').ok_or(()))), |
93 | | - message: try!(map.remove(&b'M').ok_or(())), |
94 | | - detail: map.remove(&b'D'), |
95 | | - hint: map.remove(&b'H'), |
96 | | - position: match map.remove(&b'P') { |
97 | | - Some(pos) => Some(ErrorPosition::Normal(try!(pos.parse().map_err(|_| ())))), |
| 132 | + severity: try!(severity.ok_or_else(|| ::bad_response())), |
| 133 | + code: try!(code.ok_or_else(|| ::bad_response())), |
| 134 | + message: try!(message.ok_or_else(|| ::bad_response())), |
| 135 | + detail: detail, |
| 136 | + hint: hint, |
| 137 | + position: match normal_position { |
| 138 | + Some(position) => Some(ErrorPosition::Normal(position)), |
98 | 139 | None => { |
99 | | - match map.remove(&b'p') { |
100 | | - Some(pos) => { |
| 140 | + match internal_position { |
| 141 | + Some(position) => { |
101 | 142 | Some(ErrorPosition::Internal { |
102 | | - position: try!(pos.parse().map_err(|_| ())), |
103 | | - query: try!(map.remove(&b'q').ok_or(())), |
| 143 | + position: position, |
| 144 | + query: try!(internal_query.ok_or_else(|| ::bad_response())), |
104 | 145 | }) |
105 | 146 | } |
106 | 147 | None => None, |
107 | 148 | } |
108 | 149 | } |
109 | 150 | }, |
110 | | - where_: map.remove(&b'W'), |
111 | | - schema: map.remove(&b's'), |
112 | | - table: map.remove(&b't'), |
113 | | - column: map.remove(&b'c'), |
114 | | - datatype: map.remove(&b'd'), |
115 | | - constraint: map.remove(&b'n'), |
116 | | - file: map.remove(&b'F'), |
117 | | - line: map.remove(&b'L').and_then(|l| l.parse().ok()), |
118 | | - routine: map.remove(&b'R'), |
| 151 | + where_: where_, |
| 152 | + schema: schema, |
| 153 | + table: table, |
| 154 | + column: column, |
| 155 | + datatype: datatype, |
| 156 | + constraint: constraint, |
| 157 | + file: file, |
| 158 | + line: line, |
| 159 | + routine: routine, |
119 | 160 | _p: (), |
120 | 161 | }) |
121 | 162 | } |
122 | 163 |
|
123 | | - fn new_connect<T>(fields: Vec<(u8, String)>) -> result::Result<T, ConnectError> { |
| 164 | + fn new_connect<T>(fields: &mut ErrorFields) -> result::Result<T, ConnectError> { |
124 | 165 | match DbError::new_raw(fields) { |
125 | 166 | Ok(err) => Err(ConnectError::Db(Box::new(err))), |
126 | | - Err(()) => Err(ConnectError::Io(::bad_response())), |
| 167 | + Err(e) => Err(ConnectError::Io(e)), |
127 | 168 | } |
128 | 169 | } |
129 | 170 |
|
130 | | - fn new<T>(fields: Vec<(u8, String)>) -> Result<T> { |
| 171 | + fn new<T>(fields: &mut ErrorFields) -> Result<T> { |
131 | 172 | match DbError::new_raw(fields) { |
132 | 173 | Ok(err) => Err(Error::Db(Box::new(err))), |
133 | | - Err(()) => Err(Error::Io(::bad_response())), |
| 174 | + Err(e) => Err(Error::Io(e)), |
134 | 175 | } |
135 | 176 | } |
136 | 177 | } |
|
0 commit comments