Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 77cf4f3

Browse files
committed
Allow FromSql to borrow from the buffer
This allows for in-place deserialization of text and bytea values in particular. Row::get_bytes is removed since it previously existed for this use case. Closes #281
1 parent 520aaca commit 77cf4f3

File tree

13 files changed

+172
-163
lines changed

13 files changed

+172
-163
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
build:
2424
working_directory: ~/build
2525
docker:
26-
- image: rust:1.21.0
26+
- image: rust:1.25.0-slim
2727
environment:
2828
RUSTFLAGS: -D warnings
2929
- image: sfackler/rust-postgres-test:3

codegen/src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ extern crate marksman_escape;
33
extern crate phf_codegen;
44
extern crate regex;
55

6-
#[allow(unused_imports)]
7-
use std::ascii::AsciiExt;
86
use std::path::Path;
97

108
mod sqlstate;

codegen/src/type_gen.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1+
use marksman_escape::Escape;
12
use regex::Regex;
2-
#[allow(unused_imports)]
3-
use std::ascii::AsciiExt;
43
use std::collections::BTreeMap;
54
use std::fs::File;
65
use std::io::{BufWriter, Write};
76
use std::path::Path;
8-
use marksman_escape::Escape;
97

108
use snake_to_camel;
119

@@ -178,8 +176,7 @@ fn make_impl(w: &mut BufWriter<File>, types: &BTreeMap<u32, Type>) {
178176
w,
179177
" {} => Some(Inner::{}),
180178
",
181-
oid,
182-
type_.variant
179+
oid, type_.variant
183180
).unwrap();
184181
}
185182

@@ -194,14 +191,12 @@ fn make_impl(w: &mut BufWriter<File>, types: &BTreeMap<u32, Type>) {
194191
",
195192
).unwrap();
196193

197-
198194
for (oid, type_) in types {
199195
write!(
200196
w,
201197
" Inner::{} => {},
202198
",
203-
type_.variant,
204-
oid
199+
type_.variant, oid
205200
).unwrap();
206201
}
207202

@@ -231,8 +226,7 @@ fn make_impl(w: &mut BufWriter<File>, types: &BTreeMap<u32, Type>) {
231226
V
232227
}}
233228
",
234-
type_.variant,
235-
kind
229+
type_.variant, kind
236230
).unwrap();
237231
}
238232

@@ -252,8 +246,7 @@ fn make_impl(w: &mut BufWriter<File>, types: &BTreeMap<u32, Type>) {
252246
w,
253247
r#" Inner::{} => "{}",
254248
"#,
255-
type_.variant,
256-
type_.name
249+
type_.variant, type_.name
257250
).unwrap();
258251
}
259252

postgres-shared/src/rows.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
use fallible_iterator::FallibleIterator;
22
use postgres_protocol::message::backend::DataRowBody;
3-
#[allow(unused_imports)]
4-
use std::ascii::AsciiExt;
53
use std::io;
64
use std::ops::Range;
75

8-
use stmt::Column;
96
use rows::sealed::Sealed;
7+
use stmt::Column;
108

119
mod sealed {
1210
use stmt::Column;

postgres-shared/src/types/mod.rs

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use types::type_gen::{Inner, Other};
1414
#[doc(inline)]
1515
pub use postgres_protocol::Oid;
1616

17-
pub use types::type_gen::consts::*;
1817
pub use types::special::{Date, Timestamp};
18+
pub use types::type_gen::consts::*;
1919

2020
/// Generates a simple implementation of `ToSql::accepts` which accepts the
2121
/// types passed to it.
@@ -68,20 +68,20 @@ where
6868

6969
#[cfg(feature = "with-bit-vec")]
7070
mod bit_vec;
71-
#[cfg(feature = "with-uuid")]
72-
mod uuid;
73-
#[cfg(feature = "with-time")]
74-
mod time;
75-
#[cfg(feature = "with-rustc-serialize")]
76-
mod rustc_serialize;
77-
#[cfg(feature = "with-serde_json")]
78-
mod serde_json;
7971
#[cfg(feature = "with-chrono")]
8072
mod chrono;
8173
#[cfg(feature = "with-eui48")]
8274
mod eui48;
8375
#[cfg(feature = "with-geo")]
8476
mod geo;
77+
#[cfg(feature = "with-rustc-serialize")]
78+
mod rustc_serialize;
79+
#[cfg(feature = "with-serde_json")]
80+
mod serde_json;
81+
#[cfg(feature = "with-time")]
82+
mod time;
83+
#[cfg(feature = "with-uuid")]
84+
mod uuid;
8585

8686
mod special;
8787
mod type_gen;
@@ -254,8 +254,8 @@ impl WrongType {
254254
/// | `i64` | BIGINT, BIGSERIAL |
255255
/// | `f32` | REAL |
256256
/// | `f64` | DOUBLE PRECISION |
257-
/// | `String` | VARCHAR, CHAR(n), TEXT, CITEXT, NAME, UNKNOWN |
258-
/// | `Vec<u8>` | BYTEA |
257+
/// | `&str`/`String` | VARCHAR, CHAR(n), TEXT, CITEXT, NAME, UNKNOWN |
258+
/// | `&[u8]`/`Vec<u8>` | BYTEA |
259259
/// | `HashMap<String, Option<String>>` | HSTORE |
260260
///
261261
/// In addition, some implementations are provided for types in third party
@@ -290,13 +290,13 @@ impl WrongType {
290290
///
291291
/// `FromSql` is implemented for `Vec<T>` where `T` implements `FromSql`, and
292292
/// corresponds to one-dimensional Postgres arrays.
293-
pub trait FromSql: Sized {
293+
pub trait FromSql<'a>: Sized {
294294
/// Creates a new value of this type from a buffer of data of the specified
295295
/// Postgres `Type` in its binary format.
296296
///
297297
/// The caller of this method is responsible for ensuring that this type
298298
/// is compatible with the Postgres `Type`.
299-
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Self, Box<Error + Sync + Send>>;
299+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<Error + Sync + Send>>;
300300

301301
/// Creates a new value of this type from a `NULL` SQL value.
302302
///
@@ -312,7 +312,10 @@ pub trait FromSql: Sized {
312312

313313
/// A convenience function that delegates to `from_sql` and `from_sql_null` depending on the
314314
/// value of `raw`.
315-
fn from_sql_nullable(ty: &Type, raw: Option<&[u8]>) -> Result<Self, Box<Error + Sync + Send>> {
315+
fn from_sql_nullable(
316+
ty: &Type,
317+
raw: Option<&'a [u8]>,
318+
) -> Result<Self, Box<Error + Sync + Send>> {
316319
match raw {
317320
Some(raw) => Self::from_sql(ty, raw),
318321
None => Self::from_sql_null(ty),
@@ -324,8 +327,19 @@ pub trait FromSql: Sized {
324327
fn accepts(ty: &Type) -> bool;
325328
}
326329

327-
impl<T: FromSql> FromSql for Option<T> {
328-
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Option<T>, Box<Error + Sync + Send>> {
330+
/// A trait for types which can be created from a Postgres value without borrowing any data.
331+
///
332+
/// This is primarily useful for trait bounds on functions.
333+
pub trait FromSqlOwned: for<'a> FromSql<'a> {}
334+
335+
impl<T> FromSqlOwned for T
336+
where
337+
T: for<'a> FromSql<'a>,
338+
{
339+
}
340+
341+
impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
342+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<Error + Sync + Send>> {
329343
<T as FromSql>::from_sql(ty, raw).map(Some)
330344
}
331345

@@ -338,8 +352,8 @@ impl<T: FromSql> FromSql for Option<T> {
338352
}
339353
}
340354

341-
impl<T: FromSql> FromSql for Vec<T> {
342-
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Vec<T>, Box<Error + Sync + Send>> {
355+
impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
356+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<Error + Sync + Send>> {
343357
let member_type = match *ty.kind() {
344358
Kind::Array(ref member) => member,
345359
_ => panic!("expected array type"),
@@ -364,19 +378,37 @@ impl<T: FromSql> FromSql for Vec<T> {
364378
}
365379
}
366380

367-
impl FromSql for Vec<u8> {
368-
fn from_sql(_: &Type, raw: &[u8]) -> Result<Vec<u8>, Box<Error + Sync + Send>> {
381+
impl<'a> FromSql<'a> for Vec<u8> {
382+
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<Error + Sync + Send>> {
369383
Ok(types::bytea_from_sql(raw).to_owned())
370384
}
371385

372386
accepts!(BYTEA);
373387
}
374388

375-
impl FromSql for String {
376-
fn from_sql(_: &Type, raw: &[u8]) -> Result<String, Box<Error + Sync + Send>> {
389+
impl<'a> FromSql<'a> for &'a [u8] {
390+
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<Error + Sync + Send>> {
391+
Ok(types::bytea_from_sql(raw))
392+
}
393+
394+
accepts!(BYTEA);
395+
}
396+
397+
impl<'a> FromSql<'a> for String {
398+
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<String, Box<Error + Sync + Send>> {
377399
types::text_from_sql(raw).map(|b| b.to_owned())
378400
}
379401

402+
fn accepts(ty: &Type) -> bool {
403+
<&str as FromSql>::accepts(ty)
404+
}
405+
}
406+
407+
impl<'a> FromSql<'a> for &'a str {
408+
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a str, Box<Error + Sync + Send>> {
409+
types::text_from_sql(raw)
410+
}
411+
380412
fn accepts(ty: &Type) -> bool {
381413
match *ty {
382414
VARCHAR | TEXT | BPCHAR | NAME | UNKNOWN => true,
@@ -388,10 +420,8 @@ impl FromSql for String {
388420

389421
macro_rules! simple_from {
390422
($t:ty, $f:ident, $($expected:pat),+) => {
391-
impl FromSql for $t {
392-
fn from_sql(_: &Type,
393-
raw: &[u8])
394-
-> Result<$t, Box<Error + Sync + Send>> {
423+
impl<'a> FromSql<'a> for $t {
424+
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<Error + Sync + Send>> {
395425
types::$f(raw)
396426
}
397427

@@ -409,10 +439,10 @@ simple_from!(i64, int8_from_sql, INT8);
409439
simple_from!(f32, float4_from_sql, FLOAT4);
410440
simple_from!(f64, float8_from_sql, FLOAT8);
411441

412-
impl FromSql for HashMap<String, Option<String>> {
442+
impl<'a> FromSql<'a> for HashMap<String, Option<String>> {
413443
fn from_sql(
414444
_: &Type,
415-
raw: &[u8],
445+
raw: &'a [u8],
416446
) -> Result<HashMap<String, Option<String>>, Box<Error + Sync + Send>> {
417447
types::hstore_from_sql(raw)?
418448
.map(|(k, v)| (k.to_owned(), v.map(str::to_owned)))

postgres-shared/src/types/special.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use postgres_protocol::types;
2-
use std::{i32, i64};
32
use std::error::Error;
3+
use std::{i32, i64};
44

5-
use types::{Type, FromSql, ToSql, IsNull, DATE, TIMESTAMP, TIMESTAMPTZ};
5+
use types::{FromSql, IsNull, ToSql, Type, DATE, TIMESTAMP, TIMESTAMPTZ};
66

77
/// A wrapper that can be used to represent infinity with `Type::Date` types.
88
#[derive(Debug, Clone, Copy, PartialEq)]
@@ -15,8 +15,8 @@ pub enum Date<T> {
1515
Value(T),
1616
}
1717

18-
impl<T: FromSql> FromSql for Date<T> {
19-
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Self, Box<Error + Sync + Send>> {
18+
impl<'a, T: FromSql<'a>> FromSql<'a> for Date<T> {
19+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<Error + Sync + Send>> {
2020
match types::date_from_sql(raw)? {
2121
i32::MAX => Ok(Date::PosInfinity),
2222
i32::MIN => Ok(Date::NegInfinity),
@@ -28,6 +28,7 @@ impl<T: FromSql> FromSql for Date<T> {
2828
*ty == DATE && T::accepts(ty)
2929
}
3030
}
31+
3132
impl<T: ToSql> ToSql for Date<T> {
3233
fn to_sql(&self, ty: &Type, out: &mut Vec<u8>) -> Result<IsNull, Box<Error + Sync + Send>> {
3334
let value = match *self {
@@ -59,8 +60,8 @@ pub enum Timestamp<T> {
5960
Value(T),
6061
}
6162

62-
impl<T: FromSql> FromSql for Timestamp<T> {
63-
fn from_sql(ty: &Type, raw: &[u8]) -> Result<Self, Box<Error + Sync + Send>> {
63+
impl<'a, T: FromSql<'a>> FromSql<'a> for Timestamp<T> {
64+
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<Error + Sync + Send>> {
6465
match types::timestamp_from_sql(raw)? {
6566
i64::MAX => Ok(Timestamp::PosInfinity),
6667
i64::MIN => Ok(Timestamp::NegInfinity),
@@ -71,7 +72,7 @@ impl<T: FromSql> FromSql for Timestamp<T> {
7172
fn accepts(ty: &Type) -> bool {
7273
match *ty {
7374
TIMESTAMP | TIMESTAMPTZ if T::accepts(ty) => true,
74-
_ => false
75+
_ => false,
7576
}
7677
}
7778
}
@@ -91,7 +92,7 @@ impl<T: ToSql> ToSql for Timestamp<T> {
9192
fn accepts(ty: &Type) -> bool {
9293
match *ty {
9394
TIMESTAMP | TIMESTAMPTZ if T::accepts(ty) => true,
94-
_ => false
95+
_ => false,
9596
}
9697
}
9798

postgres/src/lib.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ extern crate postgres_shared;
8080
extern crate socket2;
8181

8282
use fallible_iterator::FallibleIterator;
83+
use postgres_protocol::authentication;
84+
use postgres_protocol::authentication::sasl::{self, ScramSha256};
85+
use postgres_protocol::message::backend::{self, ErrorFields};
86+
use postgres_protocol::message::frontend;
87+
use postgres_shared::rows::RowData;
8388
use std::cell::{Cell, RefCell};
8489
use std::collections::{HashMap, VecDeque};
8590
use std::fmt;
@@ -88,38 +93,33 @@ use std::mem;
8893
use std::result;
8994
use std::sync::Arc;
9095
use std::time::Duration;
91-
use postgres_protocol::authentication;
92-
use postgres_protocol::authentication::sasl::{self, ScramSha256};
93-
use postgres_protocol::message::backend::{self, ErrorFields};
94-
use postgres_protocol::message::frontend;
95-
use postgres_shared::rows::RowData;
9696

9797
use error::{DbError, UNDEFINED_COLUMN, UNDEFINED_TABLE};
98-
use tls::TlsHandshake;
9998
use notification::{Notification, Notifications};
10099
use params::{IntoConnectParams, User};
101100
use priv_io::MessageStream;
102101
use rows::Rows;
103102
use stmt::{Column, Statement};
103+
use tls::TlsHandshake;
104104
use transaction::{IsolationLevel, Transaction};
105105
use types::{Field, FromSql, IsNull, Kind, Oid, ToSql, Type, CHAR, NAME, OID};
106106

107+
#[doc(inline)]
108+
pub use error::Error;
107109
#[doc(inline)]
108110
pub use postgres_shared::CancelData;
109111
#[doc(inline)]
110112
pub use postgres_shared::{error, types};
111-
#[doc(inline)]
112-
pub use error::Error;
113113

114114
#[macro_use]
115115
mod macros;
116116

117-
mod priv_io;
118-
pub mod tls;
119117
pub mod notification;
120118
pub mod params;
119+
mod priv_io;
121120
pub mod rows;
122121
pub mod stmt;
122+
pub mod tls;
123123
pub mod transaction;
124124

125125
const TYPEINFO_QUERY: &'static str = "__typeinfo";

0 commit comments

Comments
 (0)