Skip to content

Commit a229973

Browse files
committed
Update to new postgres
1 parent e9381be commit a229973

File tree

4 files changed

+61
-108
lines changed

4 files changed

+61
-108
lines changed

Cargo.toml

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ repository = "https://github.com/sfackler/rust-postgres-array"
88
documentation = "https://sfackler.github.io/rust-postgres-array/doc/v0.6.2/postgres_array"
99

1010
[dependencies]
11-
postgres = "0.11"
12-
byteorder = "0.5"
13-
14-
[dev-dependencies]
15-
rustc-serialize = "0.3"
16-
time = "0.1"
17-
uuid = "0.1"
18-
postgres = { version = "0.11", features = ["rustc-serialize", "time", "uuid"] }
11+
fallible-iterator = "0.1"
12+
postgres = { git = "https://github.com/sfackler/rust-postgres" }
13+
postgres-protocol = "0.1"

src/array.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl<T: fmt::Display> fmt::Display for Array<T> {
1919
try!(write!(fmt,
2020
"[{}:{}]",
2121
dim.lower_bound,
22-
dim.lower_bound + dim.len as isize - 1));
22+
dim.lower_bound as isize + dim.len as isize - 1));
2323
}
2424
try!(write!(fmt, "="));
2525
}
@@ -61,7 +61,7 @@ impl<T> Array<T> {
6161
/// elements specified by the dimensions.
6262
pub fn from_parts(data: Vec<T>, dimensions: Vec<Dimension>) -> Array<T> {
6363
assert!((data.is_empty() && dimensions.is_empty()) ||
64-
data.len() == dimensions.iter().fold(1, |acc, i| acc * i.len),
64+
data.len() == dimensions.iter().fold(1, |acc, i| acc * i.len as usize),
6565
"size mismatch");
6666
Array {
6767
dims: dimensions,
@@ -70,10 +70,10 @@ impl<T> Array<T> {
7070
}
7171

7272
/// Creates a new one-dimensional array.
73-
pub fn from_vec(data: Vec<T>, lower_bound: isize) -> Array<T> {
73+
pub fn from_vec(data: Vec<T>, lower_bound: i32) -> Array<T> {
7474
Array {
7575
dims: vec![Dimension {
76-
len: data.len(),
76+
len: data.len() as i32,
7777
lower_bound: lower_bound,
7878
}],
7979
data: data,
@@ -84,7 +84,7 @@ impl<T> Array<T> {
8484
///
8585
/// For example, the one dimensional array `[1, 2]` would turn into the
8686
/// two-dimensional array `[[1, 2]]`.
87-
pub fn wrap(&mut self, lower_bound: isize) {
87+
pub fn wrap(&mut self, lower_bound: i32) {
8888
self.dims.insert(0,
8989
Dimension {
9090
len: 1,
@@ -128,7 +128,7 @@ impl<T> Array<T> {
128128
.rev()
129129
.fold((0, 1), |(acc, stride), (dim, idx)| {
130130
let shifted = dim.shift(idx);
131-
(acc + shifted * stride, dim.len * stride)
131+
(acc + shifted * stride, dim.len as usize * stride)
132132
})
133133
.0
134134
}

src/impls.rs

Lines changed: 45 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,33 @@
1-
use std::io::prelude::*;
2-
use std::error;
3-
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
4-
5-
use postgres::{self, Result};
6-
use postgres::error::Error;
7-
use postgres::types::{Type, Kind, ToSql, FromSql, Oid, IsNull, SessionInfo};
1+
use fallible_iterator::FallibleIterator;
2+
use postgres::types::{Type, Kind, ToSql, FromSql, IsNull, SessionInfo};
3+
use postgres_protocol::types;
4+
use postgres_protocol;
5+
use std::error::Error;
86

97
use {Array, Dimension};
108

119
impl<T> FromSql for Array<T>
1210
where T: FromSql
1311
{
14-
fn from_sql<R: Read>(ty: &Type, raw: &mut R, info: &SessionInfo) -> postgres::Result<Array<T>> {
15-
let element_type = match ty.kind() {
16-
&Kind::Array(ref ty) => ty,
17-
_ => panic!("unexpected type {:?}", ty),
12+
fn from_sql(ty: &Type, raw: &[u8], info: &SessionInfo) -> Result<Array<T>, Box<Error + Sync + Send>> {
13+
let element_type = match *ty.kind() {
14+
Kind::Array(ref ty) => ty,
15+
_ => unreachable!(),
1816
};
1917

20-
let ndim = try!(raw.read_u32::<BigEndian>()) as usize;
21-
let _has_null = try!(raw.read_i32::<BigEndian>()) == 1;
22-
let _element_type: Oid = try!(raw.read_u32::<BigEndian>());
18+
let array = try!(types::array_from_sql(raw));
2319

24-
let mut dim_info = Vec::with_capacity(ndim);
25-
for _ in 0..ndim {
26-
dim_info.push(Dimension {
27-
len: try!(raw.read_u32::<BigEndian>()) as usize,
28-
lower_bound: try!(raw.read_i32::<BigEndian>()) as isize,
29-
});
30-
}
31-
let nele = if dim_info.len() == 0 {
32-
0
33-
} else {
34-
dim_info.iter().fold(1, |product, info| product * info.len)
35-
};
20+
let dimensions = try!(array.dimensions()
21+
.map(|d| {
22+
Dimension { len: d.len, lower_bound: d.lower_bound }
23+
})
24+
.collect());
3625

37-
let mut elements = Vec::with_capacity(nele);
38-
for _ in 0..nele {
39-
let len = try!(raw.read_i32::<BigEndian>());
40-
if len < 0 {
41-
elements.push(try!(FromSql::from_sql_null(&element_type, info)));
42-
} else {
43-
let mut limit = raw.take(len as u64);
44-
elements.push(try!(FromSql::from_sql(&element_type, &mut limit, info)));
45-
if limit.limit() != 0 {
46-
let err: Box<error::Error + Sync + Send> = "from_sql call did not consume all \
47-
data"
48-
.into();
49-
return Err(Error::Conversion(err));
50-
}
51-
}
52-
}
26+
let elements = try!(array.values()
27+
.and_then(|v| FromSql::from_sql_nullable(element_type, v, info))
28+
.collect());
5329

54-
Ok(Array::from_parts(elements, dim_info))
30+
Ok(Array::from_parts(elements, dimensions))
5531
}
5632

5733
fn accepts(ty: &Type) -> bool {
@@ -65,44 +41,34 @@ impl<T> FromSql for Array<T>
6541
impl<T> ToSql for Array<T>
6642
where T: ToSql
6743
{
68-
fn to_sql<W: ?Sized + Write>(&self,
69-
ty: &Type,
70-
mut w: &mut W,
71-
info: &SessionInfo)
72-
-> postgres::Result<IsNull> {
44+
fn to_sql(&self, ty: &Type, w: &mut Vec<u8>, info: &SessionInfo) -> Result<IsNull, Box<Error + Sync + Send>> {
7345
let element_type = match ty.kind() {
7446
&Kind::Array(ref ty) => ty,
75-
_ => panic!("unexpected type {:?}", ty),
47+
_ => unreachable!(),
7648
};
7749

78-
try!(w.write_i32::<BigEndian>(try!(downcast(self.dimensions().len()))));
79-
try!(w.write_i32::<BigEndian>(1));
80-
try!(w.write_u32::<BigEndian>(element_type.oid()));
81-
82-
for info in self.dimensions() {
83-
try!(w.write_i32::<BigEndian>(try!(downcast(info.len))));
84-
85-
let bound = if info.lower_bound > i32::max_value() as isize ||
86-
info.lower_bound < i32::min_value() as isize {
87-
let err: Box<error::Error + Sync + Send> = "value too large to transmit".into();
88-
return Err(Error::Conversion(err));
89-
} else {
90-
info.lower_bound as i32
91-
};
92-
try!(w.write_i32::<BigEndian>(bound));
93-
}
94-
95-
let mut inner_buf = vec![];
96-
for v in self {
97-
match try!(v.to_sql(element_type, &mut inner_buf, info)) {
98-
IsNull::Yes => try!(w.write_i32::<BigEndian>(-1)),
99-
IsNull::No => {
100-
try!(w.write_i32::<BigEndian>(try!(downcast(inner_buf.len()))));
101-
try!(w.write_all(&inner_buf));
50+
let dimensions = self.dimensions()
51+
.iter()
52+
.map(|d| {
53+
types::ArrayDimension {
54+
len: d.len,
55+
lower_bound: d.lower_bound,
10256
}
103-
}
104-
inner_buf.clear();
105-
}
57+
});
58+
let elements = self.iter();
59+
60+
try!(types::array_to_sql(dimensions,
61+
true,
62+
element_type.oid(),
63+
elements,
64+
|v, w| {
65+
match v.to_sql(element_type, w, info) {
66+
Ok(IsNull::Yes) => Ok(postgres_protocol::IsNull::Yes),
67+
Ok(IsNull::No) => Ok(postgres_protocol::IsNull::No),
68+
Err(e) => Err(e),
69+
}
70+
},
71+
w));
10672

10773
Ok(IsNull::No)
10874
}
@@ -117,26 +83,17 @@ impl<T> ToSql for Array<T>
11783
to_sql_checked!();
11884
}
11985

120-
fn downcast(len: usize) -> Result<i32> {
121-
if len > i32::max_value() as usize {
122-
let err: Box<error::Error + Sync + Send> = "value too large to transmit".into();
123-
Err(Error::Conversion(err))
124-
} else {
125-
Ok(len as i32)
126-
}
127-
}
128-
12986
#[cfg(test)]
13087
mod test {
13188
use std::fmt;
13289

133-
use postgres::{Connection, SslMode};
90+
use postgres::{Connection, TlsMode};
13491
use postgres::types::{FromSql, ToSql};
13592
use Array;
13693

13794
fn test_type<T: PartialEq + FromSql + ToSql, S: fmt::Display>(sql_type: &str,
13895
checks: &[(T, S)]) {
139-
let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
96+
let conn = Connection::connect("postgres://postgres@localhost", TlsMode::None).unwrap();
14097
for &(ref val, ref repr) in checks.iter() {
14198
let stmt = conn.prepare(&format!("SELECT {}::{}", *repr, sql_type)).unwrap();
14299
let result = stmt.query(&[]).unwrap().iter().next().unwrap().get(0);
@@ -256,7 +213,7 @@ mod test {
256213

257214
#[test]
258215
fn test_empty_array() {
259-
let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
216+
let conn = Connection::connect("postgres://postgres@localhost", TlsMode::None).unwrap();
260217
let stmt = conn.prepare("SELECT '{}'::INT4[]").unwrap();
261218
stmt.query(&[]).unwrap().iter().next().unwrap().get::<_, Array<i32>>(0);
262219
}

src/lib.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! Multi-dimensional arrays with per-dimension specifiable lower bounds
22
#![doc(html_root_url="https://sfackler.github.io/rust-postgres-array/doc/v0.6.2")]
33

4-
#[macro_use(to_sql_checked)]
4+
extern crate fallible_iterator;
5+
#[macro_use]
56
extern crate postgres;
6-
extern crate byteorder;
7+
extern crate postgres_protocol;
78

89
#[doc(inline)]
910
pub use array::Array;
@@ -15,19 +16,19 @@ mod impls;
1516
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1617
pub struct Dimension {
1718
/// The length of the dimension.
18-
pub len: usize,
19+
pub len: i32,
1920
/// The index of the first element of the dimension.
20-
pub lower_bound: isize,
21+
pub lower_bound: i32,
2122
}
2223

2324
impl Dimension {
2425
fn shift(&self, idx: isize) -> usize {
25-
let offset = self.lower_bound;
26+
let offset = self.lower_bound as isize;
2627
assert!(idx >= offset, "out of bounds array access");
2728
assert!(offset >= 0 || idx <= 0 || usize::max_value() - (-offset) as usize >= idx as usize,
2829
"out of bounds array access");
2930
let shifted = idx.wrapping_sub(offset) as usize;
30-
assert!(shifted < self.len, "out of bounds array access");
31+
assert!(shifted < self.len as usize, "out of bounds array access");
3132
shifted
3233
}
3334
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy