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

Error mapping one column type to an entire struct. #3761

Closed
3 tasks done
axos88 opened this issue Aug 23, 2023 · 3 comments
Closed
3 tasks done

Error mapping one column type to an entire struct. #3761

axos88 opened this issue Aug 23, 2023 · 3 comments
Labels

Comments

@axos88
Copy link

axos88 commented Aug 23, 2023

Setup

Versions

  • Rust: 1.73.0-nightly
  • Diesel: 2.1.0 with diesel-async 0.3.2
  • Database: pg 14
  • Operating System ubuntu 22.04

Feature Flags

  • diesel: postgres, chrono

Problem Description

Can't correctly map one database column to an entire struct and back

Steps to reproduce

diesel::table! {
    users (local, domain) {
        local -> Text,
        domain -> Text,
        password -> Text,
        level -> Nullable<Int4>,
        created -> Nullable<Timestamptz>,
    }
}
#[derive(Queryable, Identifiable, Selectable)]
#[diesel(primary_key(local, domain))]
pub struct User {
    pub local: String,
    pub domain: String,
    pub password: Password,
    pub level: Option<i32>,
    pub created: Option<DateTime<Utc>>,
}
use diesel::{AsExpression, FromSqlRow, Queryable, QueryableByName};
use diesel::backend::Backend;
use diesel::deserialize::FromSql;
use diesel::serialize::{Output, ToSql};
use diesel::sql_types::Text;
use regex::Regex;

#[derive(Clone, Debug, PartialEq, Eq, FromSqlRow, AsExpression, QueryableByName)]
#[sql_type = "Text"]
pub struct Password {
  pub alg: Option<String>,
  pub hash: String
}

impl<DB: Backend> FromSql<String, DB> for Password where String: FromSql<Text, DB> {
  fn from_sql(bytes: DB::RawValue<'_>) -> diesel::deserialize::Result<Self> {
    let re = Regex::new(r"(\{\w+\})?(.*)").expect("Could not compile Password regex");

    let string_values = <String as FromSql<Text, DB>>::from_sql(bytes)?;

    let captures = re.captures(&string_values).expect("Could not capture error");

    let alg = captures.get(0).map(|m| m.as_str().to_string());
    let hash = captures.get(1).map(|m| m.as_str().to_string()).expect("No hash part?");

    Ok(Self { alg, hash })
  }
}

impl<DB: Backend> ToSql<String, DB> for Password where String: ToSql<Text, DB> {
  fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
    let s = format!("{}{}", self.alg.unwrap_or(String::new()), self.hash);
    s.to_sql(out)
  }
}

Expect this to take a db row, and deserialize the password text column into a Password struct correctly, however:

error[E0277]: the trait bound `diesel::expression::select_by::SelectBy<db::model::User, Pg>: CompatibleType<db::model::User, Pg>` is not satisfied
  --> backend/src/routes/api/login.rs:69:8
   |
69 |       .first::<db::User>(&mut conn)
   |        ^^^^^ the trait `CompatibleType<db::model::User, Pg>` is not implemented for `diesel::expression::select_by::SelectBy<db::model::User, Pg>`
   |
   = help: the trait `CompatibleType<U, DB>` is implemented for `diesel::expression::select_by::SelectBy<U, DB>`
   = note: required for `SelectStatement<FromClause<table>, SelectClause<SelectBy<User, Pg>>, NoDistinctClause, ..., ..., ...>` to implement `diesel_async::methods::LoadQuery<'_, _, db::model::User>`
   = note: the full type name has been written to '/home/akos/projects/rust/emailadmin/target/debug/deps/emailadmin-694eaea5ca79c3f9.long-type-3122529722960146015.txt'

Checklist

  • This issue can be reproduced on Rust's stable channel. (Your issue will be
    closed if this is not the case)
  • This issue can be reproduced without requiring a third party crate
@axos88 axos88 added the bug label Aug 23, 2023
@axos88
Copy link
Author

axos88 commented Aug 23, 2023

Probably not a real bug, but the error message is too cryptic to be of any use, and I could not find any examples in the docs on how to achieve this.

@axos88
Copy link
Author

axos88 commented Aug 23, 2023

Turns out the issue is in the FromSql implementation which should be FromSql<Text, DB>.

I'll keep this open in case there is a possibility to add a more helpful error message.

@weiznich
Copy link
Member

This seems to be more a support question, which would belong to the discussion forum.

For the error messages: There is already #151 to track that, so even for that it's a duplicated issue. In addition there are flags for this specific case to improve the generated error messages. They are documented here and here

Closed as duplicate/misplaced support question in our issue tracker.

@weiznich weiznich closed this as not planned Won't fix, can't repro, duplicate, stale Aug 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants