weldsorm / welds

BSD 3-Clause "New" or "Revised" License
119 stars 6 forks source link

from_raw_sql without static strings #22

Closed waywardcoder closed 6 months ago

waywardcoder commented 6 months ago

I would like to use from_raw_sql to populate a struct, the query needs to take in two parameters. I can't seem to find the combination that works. I can pass in the string "select substring(code,1,3) as agency, substring(subcode,4,8) as agent from table where field=@p1" but cannot figure out what i need to put in the args to get the query to work. I am using Mssql. Thanks for the help!

lex148 commented 6 months ago

Here is an example from one of the tests. however it uses a static str

use welds::WeldsModel;
#[derive(Debug, WeldsModel)]
#[welds(schema = "welds", table = "Products")]
pub struct Product {
    #[welds(primary_key)]
    pub id: i32,
    pub active: Option<bool>,
    pub description: Option<String>,
    pub name: String,
    pub price_1: Option<f32>,
    pub price_2: Option<f32>,
}
#[tokio::test]
async fn should_be_able_to_run_raw_sql() {
    //setup
    let conn = get_conn().await;

    // Go run a query from the database.
    let sql = "SELECT * FROM welds.products where id < @p1".to_owned();

    use welds::connections::Param;
    let args: Vec<&(dyn Param + Sync)> = vec![&9000];
    let all = Product::from_raw_sql(&sql, &args, &conn).await.unwrap();

    assert_eq!(all.len(), 6);
}

I wasn't aware but from_raw_sql want a &Vec not a slice. I am going to fix this to make it simpler to use.

If you REALLY want a not static str this is possible you are looking for something like this.

    //setup
    let client = get_conn().await;

    // Go run a query from the database.
    let sql = "SELECT * FROM welds.products where id < @p1".to_owned();
    let args: Vec<&(dyn Param + Sync)> = vec![&9000];

    use welds::connections::Param;
    use welds::state::DbState;
    use welds::Row;

    let mut rows: Vec<Row> = client.fetch_rows(&sql, &args).await?;
    let data: Result<Vec<Product>, _> = rows.drain(..).map(Product::try_from).collect();
    let mut data = data?;
    let products: Vec<DbState<Product>> = data.drain(..).map(DbState::db_loaded).collect();

If this isn't what you are looking for, let me know I want to get you what you need

waywardcoder commented 6 months ago

This is perfect and works! thank you for the quick response and complete example!