Hello.
I'am trying to use Enums with Diesel(postgres), but I'am stuck with serializing(Diesel ORM -> Postgres Types and via verse). Found this example in master and 2.2.x branches, but it didn't help me. Could you please help with next errors in code and answer on question how correct use(for what situation I need impl this examples and by what logic (except for the DBMS type) should I choose one or another interface for implementation in (ToSql in diesel::serialize - Rust) and FromSql Implementations on Foreign Types section?
I have:
[dependencies]
serde_json = "1.0.128"
diesel = { version = "2.2.0", features = ["postgres"] }
models.rs
use diesel::{Queryable, Insertable, Selectable};
use diesel::deserialize::{FromSqlRow, QueryableByName, FromSql};
use diesel::pg::{Pg, PgValue};
use diesel::serialize::{IsNull, Output, ToSql};
use diesel::sql_types::{Integer, SqlType};
use diesel::{serialize, deserialize};
use crate::schema;
#[derive(Debug, PartialEq, FromSqlRow, Eq)]
#[diesel(sql_type = schema::sql_types::RoleType)]
pub enum Role {
Mr,
Batrak,
R,
}
#[derive(Debug, Clone, Copy, PartialEq, FromSqlRow, Eq)]
#[diesel(sql_type = schema::sql_types::SexType)]
pub enum Sex {
M = 0,
F = 1,
}
impl ToSql<schema::sql_types::RoleType, Pg> for Role {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
match *self {
Role::Mr => out.write_all(b"mr")?,
Role::Batrak => out.write_all(b"batrak")?,
Role::R => out.write_all(b"r")?,
}
Ok(IsNull::No)
}
}
impl ToSql<Integer, Pg> for Sex {
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
match self {
Sex::M => 0.to_sql(out)?,
Sex::F => 1.to_sql(out)?,
}
Ok(IsNull::No)
}
}
impl FromSql<schema::sql_types::RoleType, Pg> for Role {
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
match bytes.as_bytes() {
b"mr" => Ok(Role::Mr),
b"batrak" => Ok(Role::Batrak),
b"r" => Ok(Role::R),
_ => Err("Unrecognized role variant".into()),
}
}
}
impl FromSql<Integer, Pg> for Sex {
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
match i32::from_sql(value)? {
0 => Ok(Sex::M),
1 => Ok(Sex::F),
x => Err(format!("Unrecognized variant {}", x).into()),
}
}
}
#[derive(QueryableByName, Debug)]
#[diesel(table_name = gql_entity)]
pub struct SelectEntity {
pub id: i32,
pub name: String,
pub project: String,
pub role: Role,
pub sex: Sex,
}
#[derive(Insertable)]
#[diesel(table_name = gql_entity)]
pub struct NewEntity<'a> {
pub name: &'a str,
pub project: &'a str,
pub role: &'a Role,
pub sex: &'a Sex
}
schema.rs
// @generated automatically by Diesel CLI.
pub mod sql_types {
#[derive(
diesel::query_builder::QueryId,
Clone,
diesel::sql_types::SqlType
)]
#[diesel(postgres_type(name = "role_type"))]
pub struct RoleType;
#[derive(
diesel::query_builder::QueryId,
Clone,
diesel::sql_types::SqlType
)]
#[diesel(postgres_type(name = "sex_type"))]
pub struct SexType;
}
diesel::table! {
use diesel::sql_types::*;
use super::sql_types::RoleType;
use super::sql_types::SexType;
gql_entity (id) {
id -> Int4,
name -> Varchar,
project -> Varchar,
role -> RoleType,
sex -> SexType,
}
}
up migration
-- Your SQL goes here
CREATE TYPE role_type AS ENUM ('mr', 'batrak', 'r');
CREATE TYPE sex_type AS ENUM (0, 1);
CREATE TABLE gql_entity (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL UNIQUE,
project VARCHAR NOT NULL,
role role_type NOT NULL,
sex sex_type NOT NULL
)
and few methods that raises errors
pub fn create_gql_entity(&mut self, new_entity: NewEntity) {
diesel::insert_into(schema::gql_entity::table)
.values(&new_entity)
.execute(&mut self.connection)
.expect("Fail to add new entity");
}
pub fn get_all(&mut self) -> Vec<SelectEntity> {
schema::gql_entity::table
.load::<SelectEntity>(&mut self.connection)
.expect("Fail to get all entities")
}
in
schema::gql_entity::table
.load::<SelectEntity>(&mut self.connection)
have error:
error[E0277]: the trait bound (Integer, diesel::sql_types::Text, diesel::sql_types::Text, RoleType, SexType): load_dsl::private::CompatibleType<SelectEntity, _>
is not satisfied
--> src\db\db_connection.rs:35:35
|
35 | .load::(&mut self.connection)
| ---- ^^^^^^^^^^^^^^^^^^^^ the trait load_dsl::private::CompatibleType<SelectEntity, _>
is not implemented for (Integer, diesel::sql_types::Text, diesel::sql_types::Text, RoleType, SexType)
, which is required by table: LoadQuery<'_, _, SelectEntity>
in
diesel::insert_into(schema::gql_entity::table)
.values(&new_entity)
.execute(&mut self.connection)
have error:
error[E0277]: the trait bound &NewEntity<'_>: diesel::Insertable<table>
is not satisfied
--> src\db\db_connection.rs:28:21
|
28 | .values(&new_entity)
| ------ ^^^^^^^^^^^ the trait diesel::Insertable<table>
is not implemented for &NewEntity<'_>