kurtbuilds / ormlite

An ORM in Rust for developers that love SQL.
https://crates.io/crates/ormlite
MIT License
234 stars 13 forks source link

Using insert on a separate insertion struct returns the insertion struct instead of the original #54

Closed SpartanPlume closed 2 months ago

SpartanPlume commented 2 months ago

When using the insert function on a separate insertion struct, it returns the insertion struct instead of the original struct.

Dependencies:

[dependencies]
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
ormlite = { version = "0.18", features = ["sqlite"] }

Working case without separate insertion struct:

use ormlite::model::*;
use ormlite::sqlite::SqliteConnection;
use ormlite::Connection;

#[derive(Model, Debug)]
#[ormlite(insertable = InsertPerson)]
pub struct Person {
    pub id: i32,
    pub name: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut conn = SqliteConnection::connect(":memory:").await.unwrap();
    let insert_person = InsertPerson {
        name: "abc".to_string(),
    };
    let inserted_person: Person = insert_person.insert(&mut conn).await?;
    Ok(())
}

Non-working case with separate insertion struct:

use ormlite::model::*;
use ormlite::sqlite::SqliteConnection;
use ormlite::Connection;

#[derive(Model, Debug)]
pub struct Person {
    pub id: i32,
    pub name: String,
}

#[derive(Model, Debug)]
#[ormlite(table = "person")]
pub struct InsertPerson {
    pub id: i32, // Needed because of issue #53
    pub name: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut conn = SqliteConnection::connect(":memory:").await.unwrap();
    let insert_person = InsertPerson {
        id: 1,
        name: "abc".to_string(),
    };
    let inserted_person: Person = insert_person.insert(&mut conn).await?; // Compilation fails
    // Compiler says the return type is InsertPerson and not Person
    Ok(())
}

Error:

error[E0308]: `?` operator has incompatible types
  --> src/main.rs:25:35
   |
25 |     let inserted_person: Person = insert_person.insert(&mut conn).await?;
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Person`, found `InsertPerson`
   |
   = note: `?` operator cannot convert from `InsertPerson` to `Person`
note: return type inferred to be `Person` here
  --> src/main.rs:25:35
   |
25 |     let inserted_person: Person = insert_person.insert(&mut conn).await?;
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It doesn't seem expected that the behaviour is different between the 2 ways of having insertion struct.

kurtbuilds commented 2 months ago

This is fixed in a newly cut version, 0.19.

See the test 06-insert.rs for usage, copied here:

#[derive(Model)]
#[ormlite(insert = "InsertUser")]
// Note the previous syntax, #[ormlite(insertable = InsertUser)] still works, but the new syntax is preferred.
pub struct User {
    id: i32,
    name: String,
    #[ormlite(default)]
    secret: Option<String>,
    #[ormlite(default_value = "5")]
    number: i32,
    #[ormlite(column = "type")]
    ty: i32,
    #[ormlite(join_column = "org_id")]
    organization: Join<Organization>,
}

#[derive(Insert)]
#[ormlite(returns = "User")]
pub struct InsertUser2 {
    name: String,
    number: i32,
    #[ormlite(column = "type")]
    ty: i32,
    org_id: i32,
}

Released as 0.19 because I batched some other updates, upgrading to sqlx 0.8, among other updates.

I'll mark as resolved, but feel free to respond and/or open a new issue if you still run into issues.

SpartanPlume commented 2 months ago

Thanks for the new version, it works perfectly.