Skip to content

Commit 8a33029

Browse files
committed
Make FromSql and FromSqlRow more generic over the backend
This allows each backend to provide a "value" type that is used by `FromSql`. This is required for Sqlite support. While I can do some semi-hacky nonsense to make Sqlite work with our current `ToSql` structure, there's just no way I can make it work with our `FromSql` structure. Sqlite only returns c ints from its values, and there's no way I can know at the row level the number of bytes that are needed for `FromSql` for that specific sized integer. This unfortunately means that we can no longer assume that all backends provide `String: FromSql<VarChar, Self>`. We can bring this requirement back by changing `String: FromSql<VarChar, Pg>` to something like `Pg: CanDeserialize<VarChar, String>`. I'm unsure how this will interact with coherence, and feels significanly less natural than the `NativeSqlType` change that we made for this. I will likely make a similar change for `ToSql` in the future to make Sqlite work in a less hacky manner.
1 parent c784e47 commit 8a33029

12 files changed

Lines changed: 46 additions & 29 deletions

File tree

diesel/src/backend.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub trait Backend where
1919
Self: HasSqlType<types::Timestamp>,
2020
{
2121
type QueryBuilder: QueryBuilder<Self>;
22+
type RawValue: ?Sized;
2223
}
2324

2425
pub trait TypeMetadata {
@@ -29,6 +30,7 @@ pub struct Debug;
2930

3031
impl Backend for Debug {
3132
type QueryBuilder = DebugQueryBuilder;
33+
type RawValue = ();
3234
}
3335

3436
impl TypeMetadata for Debug {
@@ -45,6 +47,7 @@ pub struct PgTypeMetadata {
4547

4648
impl Backend for Pg {
4749
type QueryBuilder = PgQueryBuilder;
50+
type RawValue = [u8];
4851
}
4952

5053
impl TypeMetadata for Pg {

diesel/src/migrations/mod.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use self::migration::*;
6767
use self::migration_error::MigrationError::*;
6868
use self::schema::NewMigration;
6969
use self::schema::__diesel_schema_migrations::dsl::*;
70+
use types::{FromSql, VarChar};
7071
use {Connection, QueryResult};
7172

7273
use std::collections::HashSet;
@@ -86,7 +87,10 @@ use std::path::{PathBuf, Path};
8687
///
8788
/// See the [module level documentation](index.html) for information on how migrations should be
8889
/// structured, and where Diesel will look for them by default.
89-
pub fn run_pending_migrations<Conn: Connection>(conn: &Conn) -> Result<(), RunMigrationsError> {
90+
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError> where
91+
Conn: Connection,
92+
String: FromSql<VarChar, Conn::Backend>,
93+
{
9094
try!(create_schema_migrations_table_if_needed(conn));
9195
let already_run = try!(previously_run_migration_versions(conn));
9296
let migrations_dir = try!(find_migrations_directory());
@@ -102,7 +106,10 @@ pub fn run_pending_migrations<Conn: Connection>(conn: &Conn) -> Result<(), RunMi
102106
///
103107
/// See the [module level documentation](index.html) for information on how migrations should be
104108
/// structured, and where Diesel will look for them by default.
105-
pub fn revert_latest_migration<Conn: Connection>(conn: &Conn) -> Result<String, RunMigrationsError> {
109+
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError> where
110+
Conn: Connection,
111+
String: FromSql<VarChar, Conn::Backend>,
112+
{
106113
try!(create_schema_migrations_table_if_needed(conn));
107114
let latest_migration_version = try!(latest_run_migration_version(conn));
108115
revert_migration_with_version(conn, &latest_migration_version)
@@ -145,13 +152,19 @@ pub fn create_schema_migrations_table_if_needed<Conn: Connection>(conn: &Conn) -
145152
})
146153
}
147154

148-
fn previously_run_migration_versions<Conn: Connection>(conn: &Conn) -> QueryResult<HashSet<String>> {
155+
fn previously_run_migration_versions<Conn>(conn: &Conn) -> QueryResult<HashSet<String>> where
156+
Conn: Connection,
157+
String: FromSql<VarChar, Conn::Backend>,
158+
{
149159
__diesel_schema_migrations.select(version)
150160
.load(conn)
151161
.map(|r| r.collect())
152162
}
153163

154-
fn latest_run_migration_version<Conn: Connection>(conn: &Conn) -> QueryResult<String> {
164+
fn latest_run_migration_version<Conn>(conn: &Conn) -> QueryResult<String> where
165+
Conn: Connection,
166+
String: FromSql<VarChar, Conn::Backend>,
167+
{
155168
use ::expression::dsl::max;
156169
__diesel_schema_migrations.select(max(version))
157170
.first(conn)

diesel/src/row.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use backend::{Backend, Pg};
12
use db_result::PgResult;
23

3-
pub trait Row {
4-
fn take(&mut self) -> Option<&[u8]>;
4+
pub trait Row<DB: Backend> {
5+
fn take(&mut self) -> Option<&DB::RawValue>;
56
fn next_is_null(&self, count: usize) -> bool;
67
}
78

@@ -21,7 +22,7 @@ impl<'a> PgRow<'a> {
2122
}
2223
}
2324

24-
impl<'a> Row for PgRow<'a> {
25+
impl<'a> Row<Pg> for PgRow<'a> {
2526
fn take(&mut self) -> Option<&[u8]> {
2627
let current_idx = self.col_idx;
2728
self.col_idx += 1;

diesel/src/types/impls/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<T, ST> FromSqlRow<Array<ST>, Pg> for Vec<T> where
6767
Pg: HasSqlType<ST>,
6868
Vec<T>: FromSql<Array<ST>, Pg>,
6969
{
70-
fn build_from_row<R: Row>(row: &mut R) -> Result<Self, Box<Error>> {
70+
fn build_from_row<R: Row<Pg>>(row: &mut R) -> Result<Self, Box<Error>> {
7171
FromSql::<Array<ST>, Pg>::from_sql(row.take())
7272
}
7373
}

diesel/src/types/impls/floats/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extern crate byteorder;
22

33
use std::error::Error;
4-
use std::io::Write;
4+
use std::io::prelude::*;
55

66
use backend::Backend;
77
use self::byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
@@ -11,7 +11,7 @@ use types::{self, FromSql, ToSql, IsNull};
1111
#[cfg(feature = "quickcheck")]
1212
mod quickcheck_impls;
1313

14-
impl<DB: Backend> FromSql<types::Float, DB> for f32 {
14+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::Float, DB> for f32 {
1515
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
1616
let mut bytes = not_none!(bytes);
1717
bytes.read_f32::<BigEndian>().map_err(|e| Box::new(e) as Box<Error>)
@@ -26,7 +26,7 @@ impl<DB: Backend> ToSql<types::Float, DB> for f32 {
2626
}
2727
}
2828

29-
impl<DB: Backend> FromSql<types::Double, DB> for f64 {
29+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::Double, DB> for f64 {
3030
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
3131
let mut bytes = not_none!(bytes);
3232
bytes.read_f64::<BigEndian>().map_err(|e| Box::new(e) as Box<Error>)

diesel/src/types/impls/integers.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
extern crate byteorder;
22

33
use std::error::Error;
4-
use std::io::Write;
4+
use std::io::prelude::*;
55

66
use backend::{Backend, Pg};
77
use self::byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
88
use super::option::UnexpectedNullError;
99
use types::{self, FromSql, ToSql, IsNull};
1010

11-
impl<DB: Backend> FromSql<types::SmallInt, DB> for i16 {
11+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::SmallInt, DB> for i16 {
1212
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
1313
let mut bytes = not_none!(bytes);
1414
bytes.read_i16::<BigEndian>().map_err(|e| Box::new(e) as Box<Error>)
@@ -23,7 +23,7 @@ impl<DB: Backend> ToSql<types::SmallInt, DB> for i16 {
2323
}
2424
}
2525

26-
impl<DB: Backend> FromSql<types::Integer, DB> for i32 {
26+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::Integer, DB> for i32 {
2727
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
2828
let mut bytes = not_none!(bytes);
2929
bytes.read_i32::<BigEndian>().map_err(|e| Box::new(e) as Box<Error>)
@@ -38,7 +38,7 @@ impl<DB: Backend> ToSql<types::Integer, DB> for i32 {
3838
}
3939
}
4040

41-
impl<DB: Backend> FromSql<types::BigInt, DB> for i64 {
41+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::BigInt, DB> for i64 {
4242
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
4343
let mut bytes = not_none!(bytes);
4444
bytes.read_i64::<BigEndian>().map_err(|e| Box::new(e) as Box<Error>)

diesel/src/types/impls/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ macro_rules! queryable_impls {
6363
DB: $crate::backend::Backend + $crate::types::HasSqlType<types::$Source>,
6464
$Target: $crate::types::FromSql<types::$Source, DB>,
6565
{
66-
fn build_from_row<R: $crate::row::Row>(row: &mut R) -> Result<Self, Box<Error>> {
66+
fn build_from_row<R: $crate::row::Row<DB>>(row: &mut R) -> Result<Self, Box<Error>> {
6767
$crate::types::FromSql::<types::$Source, DB>::from_sql(row.take())
6868
}
6969
}
@@ -73,7 +73,7 @@ macro_rules! queryable_impls {
7373
DB: $crate::backend::Backend + $crate::types::HasSqlType<types::$Source>,
7474
Option<$Target>: $crate::types::FromSql<types::Nullable<types::$Source>, DB>,
7575
{
76-
fn build_from_row<R: $crate::row::Row>(row: &mut R) -> Result<Self, Box<Error>> {
76+
fn build_from_row<R: $crate::row::Row<DB>>(row: &mut R) -> Result<Self, Box<Error>> {
7777
$crate::types::FromSql::<types::Nullable<types::$Source>, DB>::from_sql(row.take())
7878
}
7979
}

diesel/src/types/impls/option.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl<T, ST, DB> FromSql<Nullable<ST>, DB> for Option<T> where
2020
T: FromSql<ST, DB>,
2121
DB: Backend + HasSqlType<ST>, ST: NotNull,
2222
{
23-
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
23+
fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self, Box<Error>> {
2424
match bytes {
2525
Some(_) => T::from_sql(bytes).map(Some),
2626
None => Ok(None)

diesel/src/types/impls/primitives.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl ToSql<types::Bool, Pg> for bool {
5959
}
6060
}
6161

62-
impl<DB: Backend> FromSql<types::VarChar, DB> for String {
62+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::VarChar, DB> for String {
6363
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
6464
let bytes = not_none!(bytes);
6565
String::from_utf8(bytes.into()).map_err(|e| Box::new(e) as Box<Error>)
@@ -87,7 +87,7 @@ impl<DB> FromSql<types::Text, DB> for String where
8787
DB: Backend,
8888
String: FromSql<types::VarChar, DB>,
8989
{
90-
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
90+
fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self, Box<Error>> {
9191
<Self as FromSql<types::VarChar, DB>>::from_sql(bytes)
9292
}
9393
}
@@ -110,8 +110,8 @@ impl<'a, DB> ToSql<types::Text, DB> for &'a str where
110110
}
111111
}
112112

113-
impl<DB: Backend> FromSql<types::Binary, DB> for Vec<u8> {
114-
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
113+
impl<DB: Backend<RawValue=[u8]>> FromSql<types::Binary, DB> for Vec<u8> {
114+
fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self, Box<Error>> {
115115
Ok(not_none!(bytes).into())
116116
}
117117
}
@@ -152,7 +152,7 @@ impl<'a, T: ?Sized, ST, DB> FromSql<ST, DB> for Cow<'a, T> where
152152
DB: Backend + HasSqlType<ST>,
153153
T::Owned: FromSql<ST, DB>,
154154
{
155-
fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error>> {
155+
fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self, Box<Error>> {
156156
T::Owned::from_sql(bytes).map(Cow::Owned)
157157
}
158158
}
@@ -162,7 +162,7 @@ impl <'a, T: ?Sized, ST, DB> ::types::FromSqlRow<ST, DB> for Cow<'a, T> where
162162
DB: Backend + HasSqlType<ST>,
163163
Cow<'a, T>: FromSql<ST, DB>,
164164
{
165-
fn build_from_row<R: ::row::Row>(row: &mut R) -> Result<Self, Box<Error>> {
165+
fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> Result<Self, Box<Error>> {
166166
FromSql::<ST, DB>::from_sql(row.take())
167167
}
168168
}

diesel/src/types/impls/tuples.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ macro_rules! tuple_impls {
3838
$(DB: HasSqlType<$ST>),+,
3939
DB: HasSqlType<($($ST,)+)>,
4040
{
41-
fn build_from_row<RowT: Row>(row: &mut RowT) -> Result<Self, Box<Error>> {
41+
fn build_from_row<RowT: Row<DB>>(row: &mut RowT) -> Result<Self, Box<Error>> {
4242
Ok(($(try!($T::build_from_row(row)),)+))
4343
}
4444
}
@@ -49,7 +49,7 @@ macro_rules! tuple_impls {
4949
$(DB: HasSqlType<$ST>),+,
5050
DB: HasSqlType<($($ST,)+)>,
5151
{
52-
fn build_from_row<RowT: Row>(row: &mut RowT) -> Result<Self, Box<Error>> {
52+
fn build_from_row<RowT: Row<DB>>(row: &mut RowT) -> Result<Self, Box<Error>> {
5353
if e!(row.next_is_null($Tuple)) {
5454
Ok(None)
5555
} else {

0 commit comments

Comments
 (0)