Skip to content

Commit 5f67882

Browse files
committed
Move errors to error package
1 parent a115c45 commit 5f67882

4 files changed

Lines changed: 164 additions & 151 deletions

File tree

error.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
//! Postgres errors
22
3+
use std::hashmap::HashMap;
4+
5+
use super::ssl::error::SslError;
6+
use self::hack::PostgresSqlState;
7+
38
macro_rules! make_errors(
49
($($code:pat => $error:ident),+) => (
510
// TODO: Get rid of this module when mozilla/rust#4375 is fixed
@@ -345,3 +350,145 @@ make_errors!(
345350
"XX002" => IndexCorrupted
346351
)
347352

353+
/// Reasons a new Postgres connection could fail
354+
#[deriving(ToStr)]
355+
pub enum PostgresConnectError {
356+
/// The provided URL could not be parsed
357+
InvalidUrl,
358+
/// The URL was missing a user
359+
MissingUser,
360+
/// DNS lookup failed
361+
DnsError,
362+
/// There was an error opening a socket to the server
363+
SocketError,
364+
/// An error from the Postgres server itself
365+
DbError(PostgresDbError),
366+
/// A password was required but not provided in the URL
367+
MissingPassword,
368+
/// The Postgres server requested an authentication method not supported
369+
/// by the driver
370+
UnsupportedAuthentication,
371+
/// The Postgres server does not support SSL encryption
372+
NoSslSupport,
373+
/// There was an error initializing the SSL session
374+
SslError(SslError)
375+
}
376+
377+
/// Represents the position of an error in a query
378+
#[deriving(ToStr)]
379+
pub enum PostgresErrorPosition {
380+
/// A position in the original query
381+
Position(uint),
382+
/// A position in an internally generated query
383+
InternalPosition {
384+
/// The byte position
385+
position: uint,
386+
/// A query generated by the Postgres server
387+
query: ~str
388+
}
389+
}
390+
391+
/// Encapsulates a Postgres error or notice.
392+
#[deriving(ToStr)]
393+
pub struct PostgresDbError {
394+
/// The field contents are ERROR, FATAL, or PANIC (in an error message),
395+
/// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a
396+
/// localized translation of one of these.
397+
severity: ~str,
398+
/// The SQLSTATE code for the error.
399+
code: PostgresSqlState,
400+
/// The primary human-readable error message. This should be accurate but
401+
/// terse (typically one line).
402+
message: ~str,
403+
/// An optional secondary error message carrying more detail about the
404+
/// problem. Might run to multiple lines.
405+
detail: Option<~str>,
406+
/// An optional suggestion what to do about the problem. This is intended
407+
/// to differ from Detail in that it offers advice (potentially
408+
/// inappropriate) rather than hard facts. Might run to multiple lines.
409+
hint: Option<~str>,
410+
/// An optional error cursor position into either the original query string
411+
/// or an internally generated query.
412+
position: Option<PostgresErrorPosition>,
413+
/// An indication of the context in which the error occurred. Presently
414+
/// this includes a call stack traceback of active procedural language
415+
/// functions and internally-generated queries. The trace is one entry per
416+
/// line, most recent first.
417+
where: Option<~str>,
418+
/// If the error was associated with a specific database object, the name
419+
/// of the schema containing that object, if any. (PostgreSQL 9.3+)
420+
schema: Option<~str>,
421+
/// If the error was associated with a specific table, the name of the
422+
/// table. (Refer to the schema name field for the name of the table's
423+
/// schema.) (PostgreSQL 9.3+)
424+
table: Option<~str>,
425+
/// If the error was associated with a specific table column, the name of
426+
/// the column. (Refer to the schema and table name fields to identify the
427+
/// table.) (PostgreSQL 9.3+)
428+
column: Option<~str>,
429+
/// If the error was associated with a specific data type, the name of the
430+
/// data type. (Refer to the schema name field for the name of the data
431+
/// type's schema.) (PostgreSQL 9.3+)
432+
datatype: Option<~str>,
433+
/// If the error was associated with a specific constraint, the name of the
434+
/// constraint. Refer to fields listed above for the associated table or
435+
/// domain. (For this purpose, indexes are treated as constraints, even if
436+
/// they weren't created with constraint syntax.) (PostgreSQL 9.3+)
437+
constraint: Option<~str>,
438+
/// The file name of the source-code location where the error was reported.
439+
file: ~str,
440+
/// The line number of the source-code location where the error was
441+
/// reported.
442+
line: uint,
443+
/// The name of the source-code routine reporting the error.
444+
routine: ~str
445+
}
446+
447+
impl PostgresDbError {
448+
#[doc(hidden)]
449+
pub fn new(fields: ~[(u8, ~str)]) -> PostgresDbError {
450+
// move_rev_iter is more efficient than move_iter
451+
let mut map: HashMap<u8, ~str> = fields.move_rev_iter().collect();
452+
PostgresDbError {
453+
severity: map.pop(&('S' as u8)).unwrap(),
454+
code: FromStr::from_str(map.pop(&('C' as u8)).unwrap()).unwrap(),
455+
message: map.pop(&('M' as u8)).unwrap(),
456+
detail: map.pop(&('D' as u8)),
457+
hint: map.pop(&('H' as u8)),
458+
position: match map.pop(&('P' as u8)) {
459+
Some(pos) => Some(Position(FromStr::from_str(pos).unwrap())),
460+
None => match map.pop(&('p' as u8)) {
461+
Some(pos) => Some(InternalPosition {
462+
position: FromStr::from_str(pos).unwrap(),
463+
query: map.pop(&('q' as u8)).unwrap()
464+
}),
465+
None => None
466+
}
467+
},
468+
where: map.pop(&('W' as u8)),
469+
schema: map.pop(&('s' as u8)),
470+
table: map.pop(&('t' as u8)),
471+
column: map.pop(&('c' as u8)),
472+
datatype: map.pop(&('d' as u8)),
473+
constraint: map.pop(&('n' as u8)),
474+
file: map.pop(&('F' as u8)).unwrap(),
475+
line: FromStr::from_str(map.pop(&('L' as u8)).unwrap()).unwrap(),
476+
routine: map.pop(&('R' as u8)).unwrap()
477+
}
478+
}
479+
480+
#[doc(hidden)]
481+
pub fn pretty_error(&self, query: &str) -> ~str {
482+
match self.position {
483+
Some(Position(pos)) =>
484+
format!("{}: {} at position {} in\n{}", self.severity,
485+
self.message, pos, query),
486+
Some(InternalPosition { position, query: ref inner_query }) =>
487+
format!("{}: {} at position {} in\n{} called from\n{}",
488+
self.severity, self.message, position, *inner_query,
489+
query),
490+
None => format!("{}: {} in\n{}", self.severity, self.message,
491+
query)
492+
}
493+
}
494+
}

lib.rs

Lines changed: 11 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,25 @@ use extra::container::Deque;
7474
use extra::ringbuf::RingBuf;
7575
use extra::url::{UserInfo, Url};
7676
use ssl::{SslStream, SslContext};
77-
use ssl::error::SslError;
7877
use std::cell::Cell;
79-
use std::hashmap::HashMap;
8078
use std::rt::io::{Writer, io_error, Decorator};
8179
use std::rt::io::buffered::BufferedStream;
8280
use std::rt::io::net;
8381
use std::rt::io::net::ip::{Port, SocketAddr};
8482
use std::rt::io::net::tcp::TcpStream;
8583
use std::task;
8684

87-
use self::error::hack::PostgresSqlState;
85+
use self::error::{PostgresConnectError,
86+
PostgresDbError,
87+
InvalidUrl,
88+
DnsError,
89+
SocketError,
90+
NoSslSupport,
91+
SslError,
92+
MissingUser,
93+
DbError,
94+
UnsupportedAuthentication,
95+
MissingPassword};
8896
use self::message::{BackendMessage,
8997
AuthenticationOk,
9098
AuthenticationKerberosV5,
@@ -181,147 +189,6 @@ impl<'self> Iterator<PostgresNotification> for
181189
}
182190
}
183191

184-
/// Reasons a new Postgres connection could fail
185-
#[deriving(ToStr)]
186-
pub enum PostgresConnectError {
187-
/// The provided URL could not be parsed
188-
InvalidUrl,
189-
/// The URL was missing a user
190-
MissingUser,
191-
/// DNS lookup failed
192-
DnsError,
193-
/// There was an error opening a socket to the server
194-
SocketError,
195-
/// An error from the Postgres server itself
196-
DbError(PostgresDbError),
197-
/// A password was required but not provided in the URL
198-
MissingPassword,
199-
/// The Postgres server requested an authentication method not supported
200-
/// by the driver
201-
UnsupportedAuthentication,
202-
/// The Postgres server does not support SSL encryption
203-
NoSslSupport,
204-
/// There was an error initializing the SSL session
205-
SslError(SslError)
206-
}
207-
208-
/// Represents the position of an error in a query
209-
#[deriving(ToStr)]
210-
pub enum PostgresErrorPosition {
211-
/// A position in the original query
212-
Position(uint),
213-
/// A position in an internally generated query
214-
InternalPosition {
215-
/// The byte position
216-
position: uint,
217-
/// A query generated by the Postgres server
218-
query: ~str
219-
}
220-
}
221-
222-
/// Encapsulates a Postgres error or notice.
223-
#[deriving(ToStr)]
224-
pub struct PostgresDbError {
225-
/// The field contents are ERROR, FATAL, or PANIC (in an error message),
226-
/// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a
227-
/// localized translation of one of these.
228-
severity: ~str,
229-
/// The SQLSTATE code for the error.
230-
code: PostgresSqlState,
231-
/// The primary human-readable error message. This should be accurate but
232-
/// terse (typically one line).
233-
message: ~str,
234-
/// An optional secondary error message carrying more detail about the
235-
/// problem. Might run to multiple lines.
236-
detail: Option<~str>,
237-
/// An optional suggestion what to do about the problem. This is intended
238-
/// to differ from Detail in that it offers advice (potentially
239-
/// inappropriate) rather than hard facts. Might run to multiple lines.
240-
hint: Option<~str>,
241-
/// An optional error cursor position into either the original query string
242-
/// or an internally generated query.
243-
position: Option<PostgresErrorPosition>,
244-
/// An indication of the context in which the error occurred. Presently
245-
/// this includes a call stack traceback of active procedural language
246-
/// functions and internally-generated queries. The trace is one entry per
247-
/// line, most recent first.
248-
where: Option<~str>,
249-
/// If the error was associated with a specific database object, the name
250-
/// of the schema containing that object, if any. (PostgreSQL 9.3+)
251-
schema: Option<~str>,
252-
/// If the error was associated with a specific table, the name of the
253-
/// table. (Refer to the schema name field for the name of the table's
254-
/// schema.) (PostgreSQL 9.3+)
255-
table: Option<~str>,
256-
/// If the error was associated with a specific table column, the name of
257-
/// the column. (Refer to the schema and table name fields to identify the
258-
/// table.) (PostgreSQL 9.3+)
259-
column: Option<~str>,
260-
/// If the error was associated with a specific data type, the name of the
261-
/// data type. (Refer to the schema name field for the name of the data
262-
/// type's schema.) (PostgreSQL 9.3+)
263-
datatype: Option<~str>,
264-
/// If the error was associated with a specific constraint, the name of the
265-
/// constraint. Refer to fields listed above for the associated table or
266-
/// domain. (For this purpose, indexes are treated as constraints, even if
267-
/// they weren't created with constraint syntax.) (PostgreSQL 9.3+)
268-
constraint: Option<~str>,
269-
/// The file name of the source-code location where the error was reported.
270-
file: ~str,
271-
/// The line number of the source-code location where the error was
272-
/// reported.
273-
line: uint,
274-
/// The name of the source-code routine reporting the error.
275-
routine: ~str
276-
}
277-
278-
impl PostgresDbError {
279-
fn new(fields: ~[(u8, ~str)]) -> PostgresDbError {
280-
// move_rev_iter is more efficient than move_iter
281-
let mut map: HashMap<u8, ~str> = fields.move_rev_iter().collect();
282-
PostgresDbError {
283-
severity: map.pop(&('S' as u8)).unwrap(),
284-
code: FromStr::from_str(map.pop(&('C' as u8)).unwrap()).unwrap(),
285-
message: map.pop(&('M' as u8)).unwrap(),
286-
detail: map.pop(&('D' as u8)),
287-
hint: map.pop(&('H' as u8)),
288-
position: match map.pop(&('P' as u8)) {
289-
Some(pos) => Some(Position(FromStr::from_str(pos).unwrap())),
290-
None => match map.pop(&('p' as u8)) {
291-
Some(pos) => Some(InternalPosition {
292-
position: FromStr::from_str(pos).unwrap(),
293-
query: map.pop(&('q' as u8)).unwrap()
294-
}),
295-
None => None
296-
}
297-
},
298-
where: map.pop(&('W' as u8)),
299-
schema: map.pop(&('s' as u8)),
300-
table: map.pop(&('t' as u8)),
301-
column: map.pop(&('c' as u8)),
302-
datatype: map.pop(&('d' as u8)),
303-
constraint: map.pop(&('n' as u8)),
304-
file: map.pop(&('F' as u8)).unwrap(),
305-
line: FromStr::from_str(map.pop(&('L' as u8)).unwrap()).unwrap(),
306-
routine: map.pop(&('R' as u8)).unwrap()
307-
}
308-
}
309-
310-
fn pretty_error(&self, query: &str) -> ~str {
311-
match self.position {
312-
Some(Position(pos)) =>
313-
format!("{}: {} at position {} in\n{}", self.severity,
314-
self.message, pos, query),
315-
Some(InternalPosition { position, query: ref inner_query }) =>
316-
format!("{}: {} at position {} in\n{} called from\n{}",
317-
self.severity, self.message, position, *inner_query,
318-
query),
319-
None => format!("{}: {} in\n{}", self.severity, self.message,
320-
query)
321-
}
322-
}
323-
}
324-
325192
/// Contains information necessary to cancel queries for a session
326193
pub struct PostgresCancelData {
327194
/// The process ID of the session

pool.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ use super::{PostgresNotificationIterator,
88
PostgresCancelData,
99
PostgresConnection,
1010
NormalPostgresStatement,
11-
PostgresDbError,
12-
PostgresConnectError,
1311
PostgresTransaction,
1412
NoSsl};
13+
use super::error::{PostgresConnectError, PostgresDbError};
1514
use super::types::ToSql;
1615

1716
struct InnerConnectionPool {

test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ use std::rt::io::timer;
1616

1717
use lib::{PostgresNoticeHandler,
1818
PostgresNotification,
19-
DbError,
20-
DnsError,
21-
MissingPassword,
22-
Position,
2319
PostgresConnection,
24-
PostgresDbError,
2520
PostgresStatement,
2621
ResultDescription,
2722
RequireSsl,
2823
PreferSsl,
2924
NoSsl};
25+
use lib::error::{DbError,
26+
DnsError,
27+
MissingPassword,
28+
Position,
29+
PostgresDbError};
3030
use lib::error::hack::{SyntaxError,
3131
InvalidPassword,
3232
QueryCanceled,

0 commit comments

Comments
 (0)