Skip to content

Commit b6864b9

Browse files
committed
Merge branch 'release-v0.9.0' into release
2 parents aae925a + 8e7144e commit b6864b9

23 files changed

+1302
-1282
lines changed

.travis.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,11 @@ language: rust
22
rust:
33
- nightly
44
- beta
5+
- stable
56
addons:
67
postgresql: 9.4
78
before_script:
89
- "./.travis/setup.sh"
910
script:
1011
- cargo test
11-
- cargo test --features "uuid rustc-serialize time unix_socket serde chrono"
12-
- cargo doc --no-deps --features "unix_socket"
13-
after_success:
14-
- test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && test $TRAVIS_RUST_VERSION == "nightly" && ./.travis/update_docs.sh
15-
env:
16-
global:
17-
secure: cZEcWfKI7Pml5og9o1zBMYhbj20Pa22kYVDTDEHqvOoe0kq1cnB5sTH7P0FUgiPq2Ax4B8eQIaC30yvFJ02R7kmTys4aQD98NyCyzdO+dqYi93C9PFYGhl/DKsb4iZ2VP+8LffYSwRGsNSzE9Fj9SFRMIOjHN+UfaVHXaUVjE7Y=
12+
- cargo test --features "uuid rustc-serialize time unix_socket serde chrono openssl"

.travis/update_docs.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ cd deploy_docs
88
git config user.name "Steven Fackler"
99
git config user.email "sfackler@gmail.com"
1010

11-
rm -rf doc
12-
mv ../target/doc .
11+
rm -rf doc/master
12+
mv ../target/doc doc/master
1313

1414
git add -A .
1515
git commit -m "rebuild pages at ${TRAVIS_COMMIT}"

Cargo.toml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
22
name = "postgres"
3-
version = "0.8.9"
3+
version = "0.9.0"
44
authors = ["Steven Fackler <sfackler@gmail.com>"]
55
license = "MIT"
66
description = "A native PostgreSQL driver"
77
repository = "https://github.com/sfackler/rust-postgres"
8-
documentation = "https://sfackler.github.io/rust-postgres/doc/v0.8.9/postgres"
8+
documentation = "https://sfackler.github.io/rust-postgres/doc/v0.9.0/postgres"
99
readme = "README.md"
1010
keywords = ["database", "sql"]
1111
build = "build.rs"
@@ -24,18 +24,19 @@ path = "tests/test.rs"
2424
phf_codegen = "0.7"
2525

2626
[dependencies]
27-
phf = "0.7"
28-
openssl = "0.6"
29-
log = "0.3"
30-
rustc-serialize = "0.3"
27+
bufstream = "0.1"
3128
byteorder = "0.3"
3229
debug-builders = "0.1"
33-
bufstream = "0.1"
34-
uuid = { version = "0.1", optional = true }
35-
unix_socket = { version = "0.3", optional = true }
36-
time = { version = "0.1.14", optional = true }
37-
serde = { version = "0.3", optional = true }
30+
log = "0.3"
31+
phf = "0.7"
32+
rust-crypto = "0.2"
33+
rustc-serialize = "0.3"
3834
chrono = { version = "0.2.14", optional = true }
35+
openssl = { version = "0.6", optional = true }
36+
serde = { version = "0.3", optional = true }
37+
time = { version = "0.1.14", optional = true }
38+
unix_socket = { version = ">= 0.3, < 0.5", optional = true }
39+
uuid = { version = "0.1", optional = true }
3940

4041
[dev-dependencies]
4142
url = "0.2"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Rust-Postgres
22
A native PostgreSQL driver for Rust.
33

4-
Documentation is available at https://sfackler.github.io/rust-postgres/doc/postgres
4+
Documentation is available at https://sfackler.github.io/rust-postgres/doc/v0.8.9/postgres
55

66
[![Build Status](https://travis-ci.org/sfackler/rust-postgres.png?branch=master)](https://travis-ci.org/sfackler/rust-postgres) [![Latest Version](https://img.shields.io/crates/v/postgres.svg)](https://crates.io/crates/postgres)
77

@@ -57,7 +57,7 @@ fn main() {
5757
```
5858

5959
## Requirements
60-
* **Rust** - Rust-Postgres is developed against the 1.0.0 beta release of Rust
60+
* **Rust** - Rust-Postgres is developed against the 1.0.0 release of Rust
6161
available on http://www.rust-lang.org. It should also compile against more
6262
recent unstable releases.
6363

src/error.rs

Lines changed: 186 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,195 @@
1-
pub use ugh_privacy::DbError;
1+
//! Error types.
22
33
use byteorder;
4-
use openssl::ssl::error::SslError;
54
use phf;
65
use std::error;
76
use std::convert::From;
87
use std::fmt;
98
use std::io;
9+
use std::result;
10+
use std::collections::HashMap;
1011

11-
use Result;
12+
use {Result, DbErrorNew};
1213
use types::Type;
1314

1415
include!(concat!(env!("OUT_DIR"), "/sqlstate.rs"));
1516

17+
/// A Postgres error or notice.
18+
#[derive(Clone, PartialEq, Eq, Debug)]
19+
pub struct DbError {
20+
severity: String,
21+
code: SqlState,
22+
message: String,
23+
detail: Option<String>,
24+
hint: Option<String>,
25+
position: Option<ErrorPosition>,
26+
where_: Option<String>,
27+
schema: Option<String>,
28+
table: Option<String>,
29+
column: Option<String>,
30+
datatype: Option<String>,
31+
constraint: Option<String>,
32+
file: String,
33+
line: u32,
34+
routine: String,
35+
}
36+
37+
impl DbErrorNew for DbError {
38+
fn new_raw(fields: Vec<(u8, String)>) -> result::Result<DbError, ()> {
39+
let mut map: HashMap<_, _> = fields.into_iter().collect();
40+
Ok(DbError {
41+
severity: try!(map.remove(&b'S').ok_or(())),
42+
code: SqlState::from_code(try!(map.remove(&b'C').ok_or(()))),
43+
message: try!(map.remove(&b'M').ok_or(())),
44+
detail: map.remove(&b'D'),
45+
hint: map.remove(&b'H'),
46+
position: match map.remove(&b'P') {
47+
Some(pos) => Some(ErrorPosition::Normal(try!(pos.parse().map_err(|_| ())))),
48+
None => match map.remove(&b'p') {
49+
Some(pos) => Some(ErrorPosition::Internal {
50+
position: try!(pos.parse().map_err(|_| ())),
51+
query: try!(map.remove(&b'q').ok_or(()))
52+
}),
53+
None => None
54+
}
55+
},
56+
where_: map.remove(&b'W'),
57+
schema: map.remove(&b's'),
58+
table: map.remove(&b't'),
59+
column: map.remove(&b'c'),
60+
datatype: map.remove(&b'd'),
61+
constraint: map.remove(&b'n'),
62+
file: try!(map.remove(&b'F').ok_or(())),
63+
line: try!(map.remove(&b'L').and_then(|l| l.parse().ok()).ok_or(())),
64+
routine: try!(map.remove(&b'R').ok_or(())),
65+
})
66+
}
67+
68+
fn new_connect<T>(fields: Vec<(u8, String)>) -> result::Result<T, ConnectError> {
69+
match DbError::new_raw(fields) {
70+
Ok(err) => Err(ConnectError::DbError(err)),
71+
Err(()) => Err(ConnectError::IoError(::bad_response())),
72+
}
73+
}
74+
75+
fn new<T>(fields: Vec<(u8, String)>) -> Result<T> {
76+
match DbError::new_raw(fields) {
77+
Ok(err) => Err(Error::DbError(err)),
78+
Err(()) => Err(Error::IoError(::bad_response())),
79+
}
80+
}
81+
}
82+
83+
impl DbError {
84+
/// The field contents are ERROR, FATAL, or PANIC (in an error message),
85+
/// or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a
86+
/// localized translation of one of these.
87+
pub fn severity(&self) -> &str {
88+
&self.severity
89+
}
90+
91+
/// The SQLSTATE code for the error.
92+
pub fn code(&self) -> &SqlState {
93+
&self.code
94+
}
95+
96+
/// The primary human-readable error message. This should be accurate but
97+
/// terse (typically one line).
98+
pub fn message(&self) -> &str {
99+
&self.message
100+
}
101+
102+
/// An optional secondary error message carrying more detail about the
103+
/// problem. Might run to multiple lines.
104+
pub fn detail(&self) -> Option<&str> {
105+
self.detail.as_ref().map(|s| &**s)
106+
}
107+
108+
/// An optional suggestion what to do about the problem. This is intended
109+
/// to differ from Detail in that it offers advice (potentially
110+
/// inappropriate) rather than hard facts. Might run to multiple lines.
111+
pub fn hint(&self) -> Option<&str> {
112+
self.hint.as_ref().map(|s| &**s)
113+
}
114+
115+
/// An optional error cursor position into either the original query string
116+
/// or an internally generated query.
117+
pub fn position(&self) -> Option<&ErrorPosition> {
118+
self.position.as_ref()
119+
}
120+
121+
/// An indication of the context in which the error occurred. Presently
122+
/// this includes a call stack traceback of active procedural language
123+
/// functions and internally-generated queries. The trace is one entry per
124+
/// line, most recent first.
125+
pub fn where_(&self) -> Option<&str> {
126+
self.where_.as_ref().map(|s| &**s)
127+
}
128+
129+
/// If the error was associated with a specific database object, the name
130+
/// of the schema containing that object, if any. (PostgreSQL 9.3+)
131+
pub fn schema(&self) -> Option<&str> {
132+
self.schema.as_ref().map(|s| &**s)
133+
}
134+
135+
/// If the error was associated with a specific table, the name of the
136+
/// table. (Refer to the schema name field for the name of the table's
137+
/// schema.) (PostgreSQL 9.3+)
138+
pub fn table(&self) -> Option<&str> {
139+
self.table.as_ref().map(|s| &**s)
140+
}
141+
142+
/// If the error was associated with a specific table column, the name of
143+
/// the column. (Refer to the schema and table name fields to identify the
144+
/// table.) (PostgreSQL 9.3+)
145+
pub fn column(&self) -> Option<&str> {
146+
self.column.as_ref().map(|s| &**s)
147+
}
148+
149+
/// If the error was associated with a specific data type, the name of the
150+
/// data type. (Refer to the schema name field for the name of the data
151+
/// type's schema.) (PostgreSQL 9.3+)
152+
pub fn datatype(&self) -> Option<&str> {
153+
self.datatype.as_ref().map(|s| &**s)
154+
}
155+
156+
/// If the error was associated with a specific constraint, the name of the
157+
/// constraint. Refer to fields listed above for the associated table or
158+
/// domain. (For this purpose, indexes are treated as constraints, even if
159+
/// they weren't created with constraint syntax.) (PostgreSQL 9.3+)
160+
pub fn constraint(&self) -> Option<&str> {
161+
self.constraint.as_ref().map(|s| &**s)
162+
}
163+
164+
/// The file name of the source-code location where the error was reported.
165+
pub fn file(&self) -> &str {
166+
&self.file
167+
}
168+
169+
/// The line number of the source-code location where the error was
170+
/// reported.
171+
pub fn line(&self) -> u32 {
172+
self.line
173+
}
174+
175+
/// The name of the source-code routine reporting the error.
176+
pub fn routine(&self) -> &str {
177+
&self.routine
178+
}
179+
}
180+
181+
impl fmt::Display for DbError {
182+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
183+
write!(fmt, "{}: {}", self.severity, self.message)
184+
}
185+
}
186+
187+
impl error::Error for DbError {
188+
fn description(&self) -> &str {
189+
&self.message
190+
}
191+
}
192+
16193
/// Reasons a new Postgres connection could fail.
17194
#[derive(Debug)]
18195
pub enum ConnectError {
@@ -30,11 +207,9 @@ pub enum ConnectError {
30207
/// The Postgres server does not support SSL encryption.
31208
NoSslSupport,
32209
/// There was an error initializing the SSL session.
33-
SslError(SslError),
210+
SslError(Box<error::Error+Sync+Send>),
34211
/// There was an error communicating with the server.
35212
IoError(io::Error),
36-
/// The server sent an unexpected response.
37-
BadResponse,
38213
}
39214

40215
impl fmt::Display for ConnectError {
@@ -60,14 +235,13 @@ impl error::Error for ConnectError {
60235
ConnectError::NoSslSupport => "The server does not support SSL",
61236
ConnectError::SslError(_) => "Error initiating SSL session",
62237
ConnectError::IoError(_) => "Error communicating with server",
63-
ConnectError::BadResponse => "The server returned an unexpected response",
64238
}
65239
}
66240

67241
fn cause(&self) -> Option<&error::Error> {
68242
match *self {
69243
ConnectError::DbError(ref err) => Some(err),
70-
ConnectError::SslError(ref err) => Some(err),
244+
ConnectError::SslError(ref err) => Some(&**err),
71245
ConnectError::IoError(ref err) => Some(err),
72246
_ => None
73247
}
@@ -86,12 +260,6 @@ impl From<DbError> for ConnectError {
86260
}
87261
}
88262

89-
impl From<SslError> for ConnectError {
90-
fn from(err: SslError) -> ConnectError {
91-
ConnectError::SslError(err)
92-
}
93-
}
94-
95263
impl From<byteorder::Error> for ConnectError {
96264
fn from(err: byteorder::Error) -> ConnectError {
97265
ConnectError::IoError(From::from(err))
@@ -119,18 +287,13 @@ pub enum Error {
119287
DbError(DbError),
120288
/// An error communicating with the Postgres server.
121289
IoError(io::Error),
122-
/// The communication channel with the Postgres server has desynchronized
123-
/// due to an earlier communications error.
124-
StreamDesynchronized,
125290
/// An attempt was made to convert between incompatible Rust and Postgres
126291
/// types.
127292
WrongType(Type),
128293
/// An attempt was made to read from a column that does not exist.
129294
InvalidColumn,
130-
/// A value was NULL but converted to a non-nullable Rust type.
131-
WasNull,
132-
/// The server returned an unexpected response.
133-
BadResponse,
295+
/// An error converting between Postgres and Rust types.
296+
Conversion(Box<error::Error+Sync+Send>),
134297
}
135298

136299
impl fmt::Display for Error {
@@ -148,20 +311,17 @@ impl error::Error for Error {
148311
match *self {
149312
Error::DbError(_) => "An error reported by the Postgres server",
150313
Error::IoError(_) => "An error communicating with the Postgres server",
151-
Error::StreamDesynchronized => {
152-
"Communication with the server has desynchronized due to an earlier IO error"
153-
}
154314
Error::WrongType(_) => "Unexpected type",
155315
Error::InvalidColumn => "Invalid column",
156-
Error::WasNull => "The value was NULL",
157-
Error::BadResponse => "The server returned an unexpected response",
316+
Error::Conversion(_) => "An error converting between Postgres and Rust types",
158317
}
159318
}
160319

161320
fn cause(&self) -> Option<&error::Error> {
162321
match *self {
163322
Error::DbError(ref err) => Some(err),
164323
Error::IoError(ref err) => Some(err),
324+
Error::Conversion(ref err) => Some(&**err),
165325
_ => None
166326
}
167327
}

0 commit comments

Comments
 (0)