blackbeam / rust-mysql-simple

Mysql client library implemented in rust.
Apache License 2.0
661 stars 144 forks source link

In mysql database query, the JOIN query involves multiple tables. How to merge the existing structure to meet the result of the join query #384

Open tgy3300 opened 3 months ago

tgy3300 commented 3 months ago

There is a requirement: in mysql database query, single table query uses a structure, JOIN table query (JOIN) involves multiple tables, need to combine multiple single table structures together, because the single table structure has been written, so at this time only want to combine multiple structures to meet, golang, my approach is:

type A struct {...}
type B struct {...}
type C struct {
  A
  B
}

Pass the C structure to the associative table query on the line, but in rust, how to achieve, look at the following code: How can the CompanyAccount struct be written to fit your needs, not foolishly rewriting the Company and Account struct fields in CompanyAccount

use mysql::{
    prelude::{FromRow, Queryable},
    PooledConn,
};

#[derive(Debug, FromRow)]
struct Company {
    id: i64,
    name: String,
    status: i16,
    err_info: Option<String>,
    account_id: i64,
    create_at: i64,
    update_at: i64,
}

#[derive(Debug, FromRow)]
struct Account {
    id: i64,
    username: i64,
    password: String,
    salt: String,
    phone: String,
    email: String,
    client: i16,
    status: i16,
    system_id: i64,
    create_at: i64,
    last_login_at: i64,
    err_info: Option<String>,
}

#[derive(Debug, FromRow)]
struct CompanyAccount {...}

fn get_info<T: FromRow + Debug>(
    conn: &mut PooledConn,
    sql: String,
) -> Result<Option<T>, Box<dyn std::error::Error + Send + Sync + 'static>> {
    let s = conn.query_first(sql)?;
    Ok(s)
}

fn main() {
    let mut cli = get_client();
    let s: Company = get_info(&mut cli, "select * from company").unwrap().unwrap();
    println!("----------{:#?}", s);

    let s1: CompanyAccount = get_info(&mut cli, "select company.*, account.*  from company left join account on company.account_id = account.id").unwrap().unwrap();
    println!("----------{:#?}", s1);
}
blackbeam commented 3 months ago

Hi. In the current version from_row consumes Row (non-consuming API is partially implemented and planned for the next release). This means that for now your only option is to manually disassemble the row into Company and Account (using Row::take) or to use CompanyAccount intermediate structure.

Please be aware of the fact that FromRow may fail or even give unexpected result if column names collide - this is the case in your example (id, status, create_at, ...)