Merge branch 'release-v0.11.1' into release

This commit is contained in:
Steven Fackler 2016-02-01 22:49:45 +00:00
commit fed121d921
8 changed files with 76 additions and 19 deletions

View File

@ -3,7 +3,7 @@ sudo: required
rust: rust:
- nightly - nightly
- beta - beta
- 1.4.0 - 1.5.0
addons: addons:
postgresql: 9.4 postgresql: 9.4
before_script: before_script:

View File

@ -1,13 +1,13 @@
[package] [package]
name = "postgres" name = "postgres"
version = "0.11.0" version = "0.11.1"
authors = ["Steven Fackler <sfackler@gmail.com>"] authors = ["Steven Fackler <sfackler@gmail.com>"]
license = "MIT" license = "MIT"
description = "A native PostgreSQL driver" description = "A native PostgreSQL driver"
repository = "https://github.com/sfackler/rust-postgres" repository = "https://github.com/sfackler/rust-postgres"
documentation = "https://sfackler.github.io/rust-postgres/doc/v0.11.0/postgres" documentation = "https://sfackler.github.io/rust-postgres/doc/v0.11.1/postgres"
readme = "README.md" readme = "README.md"
keywords = ["database", "sql"] keywords = ["database", "postgres", "postgresql", "sql"]
build = "build.rs" build = "build.rs"
include = ["src/*", "build.rs", "Cargo.toml", "LICENSE", "README.md", "THIRD_PARTY"] include = ["src/*", "build.rs", "Cargo.toml", "LICENSE", "README.md", "THIRD_PARTY"]
@ -42,4 +42,4 @@ security-framework = { version = "0.1.2", optional = true }
bit-vec = { version = "0.4", optional = true } bit-vec = { version = "0.4", optional = true }
[dev-dependencies] [dev-dependencies]
url = "0.2" url = "0.5"

View File

@ -1,7 +1,7 @@
# Rust-Postgres # Rust-Postgres
A native PostgreSQL driver for Rust. A native PostgreSQL driver for Rust.
[Documentation](https://sfackler.github.io/rust-postgres/doc/v0.11.0/postgres) [Documentation](https://sfackler.github.io/rust-postgres/doc/v0.11.1/postgres)
[![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) [![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)
@ -54,7 +54,7 @@ fn main() {
``` ```
## Requirements ## Requirements
* **Rust** - Rust-Postgres is developed against the 1.4 release of Rust * **Rust** - Rust-Postgres is developed against the 1.5 release of Rust
available on http://www.rust-lang.org. It should also compile against more available on http://www.rust-lang.org. It should also compile against more
recent releases. recent releases.

View File

@ -38,7 +38,7 @@
//! } //! }
//! } //! }
//! ``` //! ```
#![doc(html_root_url="https://sfackler.github.io/rust-postgres/doc/v0.11.0")] #![doc(html_root_url="https://sfackler.github.io/rust-postgres/doc/v0.11.1")]
#![warn(missing_docs)] #![warn(missing_docs)]
extern crate bufstream; extern crate bufstream;
@ -462,7 +462,7 @@ impl InnerConnection {
#[cfg_attr(rustfmt, rustfmt_skip)] #[cfg_attr(rustfmt, rustfmt_skip)]
fn setup_typeinfo_query(&mut self) -> result::Result<(), ConnectError> { fn setup_typeinfo_query(&mut self) -> result::Result<(), ConnectError> {
match self.raw_prepare(TYPEINFO_QUERY, match self.raw_prepare(TYPEINFO_QUERY,
"SELECT t.typname, t.typelem, r.rngsubtype, n.nspname \ "SELECT t.typname, t.typelem, r.rngsubtype, t.typbasetype, n.nspname \
FROM pg_catalog.pg_type t \ FROM pg_catalog.pg_type t \
LEFT OUTER JOIN pg_catalog.pg_range r ON \ LEFT OUTER JOIN pg_catalog.pg_range r ON \
r.rngtypid = t.oid \ r.rngtypid = t.oid \
@ -478,7 +478,7 @@ impl InnerConnection {
} }
match self.raw_prepare(TYPEINFO_QUERY, match self.raw_prepare(TYPEINFO_QUERY,
"SELECT t.typname, t.typelem, NULL::OID, n.nspname \ "SELECT t.typname, t.typelem, NULL::OID, t.typbasetype, n.nspname \
FROM pg_catalog.pg_type t \ FROM pg_catalog.pg_type t \
INNER JOIN pg_catalog.pg_namespace n \ INNER JOIN pg_catalog.pg_namespace n \
ON t.typnamespace = n.oid \ ON t.typnamespace = n.oid \
@ -749,7 +749,7 @@ impl InnerConnection {
} }
_ => bad_response!(self), _ => bad_response!(self),
} }
let (name, elem_oid, rngsubtype, schema) = match try!(self.read_message()) { let (name, elem_oid, rngsubtype, basetype, schema) = match try!(self.read_message()) {
DataRow { row } => { DataRow { row } => {
let ctx = SessionInfo::new(self); let ctx = SessionInfo::new(self);
let name = try!(String::from_sql(&Type::Name, let name = try!(String::from_sql(&Type::Name,
@ -762,10 +762,13 @@ impl InnerConnection {
Some(ref data) => try!(Option::<Oid>::from_sql(&Type::Oid, &mut &**data, &ctx)), Some(ref data) => try!(Option::<Oid>::from_sql(&Type::Oid, &mut &**data, &ctx)),
None => try!(Option::<Oid>::from_sql_null(&Type::Oid, &ctx)), None => try!(Option::<Oid>::from_sql_null(&Type::Oid, &ctx)),
}; };
let schema = try!(String::from_sql(&Type::Name, let basetype = try!(Oid::from_sql(&Type::Oid,
&mut &**row[3].as_ref().unwrap(), &mut &**row[3].as_ref().unwrap(),
&ctx)); &ctx));
(name, elem_oid, rngsubtype, schema) let schema = try!(String::from_sql(&Type::Name,
&mut &**row[4].as_ref().unwrap(),
&ctx));
(name, elem_oid, rngsubtype, basetype, schema)
} }
ErrorResponse { fields } => { ErrorResponse { fields } => {
try!(self.wait_for_ready()); try!(self.wait_for_ready());
@ -783,7 +786,9 @@ impl InnerConnection {
} }
try!(self.wait_for_ready()); try!(self.wait_for_ready());
let kind = if elem_oid != 0 { let kind = if basetype != 0 {
Kind::Domain(try!(self.get_type(basetype)))
} else if elem_oid != 0 {
Kind::Array(try!(self.get_type(elem_oid))) Kind::Array(try!(self.get_type(elem_oid)))
} else { } else {
match rngsubtype { match rngsubtype {

View File

@ -21,7 +21,8 @@ struct StepUp<T> {
ammount: T, ammount: T,
} }
impl<T> Iterator for StepUp<T> where T: Add<T, Output = T> + PartialOrd + Copy impl<T> Iterator for StepUp<T>
where T: Add<T, Output = T> + PartialOrd + Copy
{ {
type Item = T; type Item = T;
@ -41,7 +42,8 @@ trait RangeExt<T> {
fn step_up(self, ammount: T) -> StepUp<T>; fn step_up(self, ammount: T) -> StepUp<T>;
} }
impl<T> RangeExt<T> for Range<T> where T: Add<T, Output = T> + PartialOrd + Copy impl<T> RangeExt<T> for Range<T>
where T: Add<T, Output = T> + PartialOrd + Copy
{ {
fn step_up(self, ammount: T) -> StepUp<T> { fn step_up(self, ammount: T) -> StepUp<T> {
StepUp { StepUp {

View File

@ -107,6 +107,8 @@ pub enum Kind {
Array(Type), Array(Type),
/// A range type along with the type of its elements. /// A range type along with the type of its elements.
Range(Type), Range(Type),
/// Domain type along with its underlying type.
Domain(Type),
#[doc(hidden)] #[doc(hidden)]
__PseudoPrivateForExtensibility, __PseudoPrivateForExtensibility,
} }
@ -889,7 +891,8 @@ pub trait ToSql: fmt::Debug {
fn to_sql_checked(&self, ty: &Type, out: &mut Write, ctx: &SessionInfo) -> Result<IsNull>; fn to_sql_checked(&self, ty: &Type, out: &mut Write, ctx: &SessionInfo) -> Result<IsNull>;
} }
impl<'a, T> ToSql for &'a T where T: ToSql impl<'a, T> ToSql for &'a T
where T: ToSql
{ {
to_sql_checked!(); to_sql_checked!();

View File

@ -1,3 +1,4 @@
#[macro_use]
extern crate postgres; extern crate postgres;
extern crate url; extern crate url;
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]

View File

@ -2,10 +2,11 @@ use std::collections::HashMap;
use std::f32; use std::f32;
use std::f64; use std::f64;
use std::fmt; use std::fmt;
use std::io::{Read, Write};
use postgres::{Connection, SslMode}; use postgres::{Connection, SslMode, Result};
use postgres::error::Error; use postgres::error::Error;
use postgres::types::{ToSql, FromSql, Slice, WrongType}; use postgres::types::{ToSql, FromSql, Slice, WrongType, Type, IsNull, Kind, SessionInfo};
#[cfg(feature = "bit-vec")] #[cfg(feature = "bit-vec")]
mod bit_vec; mod bit_vec;
@ -233,3 +234,48 @@ fn test_slice_range() {
Err(e) => panic!("Unexpected error {:?}", e), Err(e) => panic!("Unexpected error {:?}", e),
}; };
} }
#[test]
fn domain() {
#[derive(Debug, PartialEq)]
struct SessionId(Vec<u8>);
impl ToSql for SessionId {
fn to_sql<W: ?Sized>(&self, ty: &Type, out: &mut W, ctx: &SessionInfo) -> Result<IsNull>
where W: Write
{
let inner = match *ty.kind() {
Kind::Domain(ref inner) => inner,
_ => unreachable!(),
};
self.0.to_sql(inner, out, ctx)
}
fn accepts(ty: &Type) -> bool {
ty.name() == "session_id" && match *ty.kind() { Kind::Domain(_) => true, _ => false }
}
to_sql_checked!();
}
impl FromSql for SessionId {
fn from_sql<R: Read>(ty: &Type, raw: &mut R, ctx: &SessionInfo) -> Result<Self> {
Vec::<u8>::from_sql(ty, raw, ctx).map(SessionId)
}
fn accepts(ty: &Type) -> bool {
// This is super weird!
<Vec<u8> as FromSql>::accepts(ty)
}
}
let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
conn.batch_execute("CREATE DOMAIN pg_temp.session_id AS bytea CHECK(octet_length(VALUE) = 16);
CREATE TABLE pg_temp.foo (id pg_temp.session_id);")
.unwrap();
let id = SessionId(b"0123456789abcdef".to_vec());
conn.execute("INSERT INTO pg_temp.foo (id) VALUES ($1)", &[&id]).unwrap();
let rows = conn.query("SELECT id FROM pg_temp.foo", &[]).unwrap();
assert_eq!(id, rows.get(0).get(0));
}