|
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