Skip to content

Instantly share code, notes, and snippets.

@sgrif
Last active January 8, 2018 08:32
Show Gist options
  • Save sgrif/57728bf080ea05dfdf3f12fffabeb40d to your computer and use it in GitHub Desktop.
Save sgrif/57728bf080ea05dfdf3f12fffabeb40d to your computer and use it in GitHub Desktop.
// This is what it looks like in Diesel 1.0.
// This is a "bare minimum" set of impls, which do not result in a type that can be used everywhere
// a built in one can. There are 7 variants of `AsExpression` and an additional `ToSql` impl
// that a type needs to be used absolutely everywhere.
pub struct MyType;
#[derive(Debug, PartialEq)]
pub enum MyEnum {
Foo,
Bar,
}
mod impls_for_insert_and_query {
use diesel::Queryable;
use diesel::expression::AsExpression;
use diesel::expression::bound::Bound;
use diesel::pg::Pg;
use diesel::row::Row;
use diesel::types::*;
use std::error::Error;
use std::io::Write;
use super::{MyEnum, MyType};
impl HasSqlType<MyType> for Pg {
fn metadata(lookup: &Self::MetadataLookup) -> Self::TypeMetadata {
lookup.lookup_type("my_type")
}
}
impl NotNull for MyType {}
impl SingleValue for MyType {}
impl<'a> AsExpression<MyType> for &'a MyEnum {
type Expression = Bound<MyType, &'a MyEnum>;
fn as_expression(self) -> Self::Expression {
Bound::new(self)
}
}
impl ToSql<MyType, Pg> for MyEnum {
fn to_sql<W: Write>(
&self,
out: &mut ToSqlOutput<W, Pg>,
) -> Result<IsNull, Box<Error + Send + Sync>> {
match *self {
MyEnum::Foo => out.write_all(b"foo")?,
MyEnum::Bar => out.write_all(b"bar")?,
}
Ok(IsNull::No)
}
}
impl FromSqlRow<MyType, Pg> for MyEnum {
fn build_from_row<T: Row<Pg>>(row: &mut T) -> Result<Self, Box<Error + Send + Sync>> {
match row.take() {
Some(b"foo") => Ok(MyEnum::Foo),
Some(b"bar") => Ok(MyEnum::Bar),
Some(_) => Err("Unrecognized enum variant".into()),
None => Err("Unexpected null for non-null column".into()),
}
}
}
impl Queryable<MyType, Pg> for MyEnum {
type Row = Self;
fn build(row: Self::Row) -> Self {
row
}
}
}
// This is what it looks like in Diesel 1.1
#[derive(SqlType)]
#[postgres(type_name = "my_type")]
pub struct MyType;
#[derive(Debug, PartialEq, FromSqlRow, AsExpression)]
#[sql_type = "MyType"]
pub enum MyEnum {
Foo,
Bar,
}
use diesel::serialize::{self, ToSql, Output, IsNull};
use diesel::deserialize::{self, FromSql};
use std::io::Write;
impl ToSql<MyType, Pg> for MyEnum {
fn to_sql<W: Write>(&self, out: &mut Output<W, Pg>) -> serialize::Result {
match *self {
MyEnum::Foo => out.write_all(b"foo")?,
MyEnum::Bar => out.write_all(b"bar")?,
}
Ok(IsNull::No)
}
}
impl FromSql<MyType, Pg> for MyEnum {
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
match not_none!(bytes) {
b"foo" => Ok(MyEnum::Foo),
b"bar" => Ok(MyEnum::Bar),
_ => Err("Unrecognized enum variant".into()),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment