Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Unsigned Types in Mysql #1561

Closed
wants to merge 4 commits into from
Closed

Add Support for Unsigned Types in Mysql #1561

wants to merge 4 commits into from

Conversation

joshleeb
Copy link
Contributor

Ref. Handling unsigned integer types from MySQL #1181

This functionality was originally added in #782 and then reverted in #912.

@joshleeb joshleeb changed the title Add support for unsigned types in mysql [WIP] Add Support for Unsigned Types in Mysql Feb 17, 2018
@sgrif
Copy link
Member

sgrif commented Feb 17, 2018

Tests are failing

@@ -12,6 +12,12 @@ use mysql::Mysql;
use serialize::{self, IsNull, Output, ToSql};
use sql_types;

impl sql_types::HasSqlType<sql_types::Unsigned<sql_types::Integer>> for Mysql {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to support more than just Integer doesn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, is it just SmallInt, Integer, and BigInt?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This impl can probably just be generic over everything.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsigned strings let's go ! :trollface:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There wouldn't be a corresponding AsExpression impl, so... :P

There's nothing to prevent you from putting Unsigned<Text> in your table declaration already

type QueryId = ();
}

// impl<ST: NotNull + SingleValue> QueryId for ST {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

@sgrif
Copy link
Member

sgrif commented Feb 17, 2018

You're missing AsExpression and FromSqlRow derives

@joshleeb
Copy link
Contributor Author

@sgrif it seems as though, for the u32_to_sql_integer tests that the newly defined ToSql<Unsigned<Integer>>... implementation isn't being called and I'm not really sure why.

@sgrif
Copy link
Member

sgrif commented Feb 25, 2018

@@ -70,7 +72,7 @@ pub struct Tinyint;
/// - [`i16`][i16]
///
/// [i16]: https://doc.rust-lang.org/nightly/std/primitive.i16.html
#[derive(Debug, Clone, Copy, Default, QueryId, SqlType)]
#[derive(Debug, Clone, Copy, Default, QueryId, SqlType, FromSqlRow)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type should not be deriving FromSqlRow, nor should any other SQL types.

/// The unsigned SQL type.
/// TODO: Add proper documentation.
#[derive(Debug, Clone, Copy, Default, SqlType, FromSqlRow, AsExpression)]
pub struct Unsigned<ST: NotNull + SingleValue + QueryId + Expression + AsExpression<ST>>(ST);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the mysql module, it's backend specific.

type SqlType = BigInt;
}

impl QueryId for u16 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these should have QueryId implemented.

const HAS_STATIC_QUERY_ID: bool = ST::HAS_STATIC_QUERY_ID;
}

impl Expression for SmallInt {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these should have Expression implemented.

@@ -467,3 +481,37 @@ impl<T: NotNull> IntoNullable for Nullable<T> {
pub trait SingleValue {}

impl<T: NotNull + SingleValue> SingleValue for Nullable<T> {}

impl<ST: NotNull + SingleValue + QueryId + Expression + AsExpression<ST>> QueryId for Unsigned<ST> {
type QueryId = ST::QueryId;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be Unsigned<ST::QueryId>.

@@ -88,3 +88,85 @@ impl<DB: Backend> ToSql<sql_types::BigInt, DB> for i64 {
.map_err(|e| Box::new(e) as Box<Error + Send + Sync>)
}
}

impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::SmallInt, DB> for u16 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be implemented for Unsigned<SmallInt>.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also all of these implementations are backend specific, they should not be generic like this.

}
}

impl<DB: Backend> ToSql<sql_types::SmallInt, DB> for u16 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be implemented for Unsigned<SmallInt>.

}
}

impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::Integer, DB> for u32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be implemented for Unsigned<Integer>.

}
}

impl<DB: Backend> ToSql<sql_types::Integer, DB> for u32 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be implemented for Unsigned<Integer>.

}
}

impl<DB: Backend<RawValue = [u8]>> FromSql<sql_types::BigInt, DB> for u64 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be implemented for Unsigned<BigInt>.

}
}

impl<DB: Backend> ToSql<sql_types::BigInt, DB> for u64 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only be implemented for Unsigned<BigInt>.

use query_builder::QueryId;
use sql_types::*;

impl<T, DB> HasSqlType<Unsigned<T>> for DB
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be MySQL specific.

pub struct Unsigned<ST: NotNull + SingleValue + QueryId>(ST);

#[doc(hidden)]
pub type UInt2 = Unsigned<SmallInt>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these types?

@sgrif
Copy link
Member

sgrif commented Mar 4, 2018

@joshleeb Since CI is still red, and there's still a bunch of debug code in there I'm assuming this is still WIP. I'm hoping to release 1.2 this week, so let me know what I can do to help get this done.

@joshleeb
Copy link
Contributor Author

joshleeb commented Mar 5, 2018

So far the added tests for unsigned types are passing but some documentation still needs to be added.

@joshleeb joshleeb changed the title [WIP] Add Support for Unsigned Types in Mysql Add Support for Unsigned Types in Mysql Mar 6, 2018
@joshleeb
Copy link
Contributor Author

joshleeb commented Mar 6, 2018

@sgrif I'm not sure what's causing the compile-fail tests to fail here.

@sgrif
Copy link
Member

sgrif commented Mar 7, 2018

Your code has changed the errors that occur. You should look at the differences, if they seem reasonable, update the tests.

@sclarson
Copy link

Thanks for doing this. Just started trying diesel out on our existing database today and ran into this almost immediately.

Also it looks like the tests are all passing now 👍

#[derive(Debug, Clone, Copy, Default, SqlType)]
pub struct Unsigned<ST: NotNull + SingleValue + QueryId>(ST);

impl ToSql<Unsigned<Integer>, Mysql> for u16 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be impl ToSql<Unsigned<SmallInt>, Mysql> for u16?

}
}

impl ToSql<Unsigned<Integer>, Mysql> for u64 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be impl ToSql<Unsigned<BigInt>, Mysql> for u64 ?

fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
Ok(not_none!(bytes).iter().any(|x| *x != 0))
}
}

impl<ST> HasSqlType<Unsigned<ST>> for Mysql
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is a good idea, because this will allow also things like Unsigned<Bool> to be valid in some contexts. (Note for @diesel-rs/reviewers)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weiznich would it be better to have a HasSqlType for SmallInt, Integer, and BigInt, instead of this more generic version?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the HasSqlType impl being generic is a problem. It doesn't enable anything on its own.

fn build(row: Self::Row) -> Self {
row
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it seems like the impl for u32 is missing?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went to add this and doing so causes a compilation error. It looks like this implementation is already done by https://github.com/diesel-rs/diesel/blob/master/diesel/src/type_impls/primitives.rs#L38

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add similar structs to /diesel/src/type_impls/primitives.rs for u16 and u64. I imagine that's better than implementing the traits manually here.

fn build_from_row<T: Row<Mysql>>(row: &mut T) -> deserialize::Result<Self> {
Self::from_sql(row.take())
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also: Is the impl for u32 missing?

@@ -101,14 +103,22 @@ fn determine_type_name(sql_type_name: &str) -> Result<&str, Box<Error>> {
};

if result.to_lowercase().contains("unsigned") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this condition should be replaced with a call to determine_unsigned

@sclarson
Copy link

The travis build appears to be breaking on compiling cargo metadata. That seems like it should be unrelated to the change here.

@sgrif sgrif mentioned this pull request Apr 5, 2018
@sgrif sgrif closed this in #1618 Apr 6, 2018
sgrif added a commit that referenced this pull request Apr 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants