njord-rs / njord

A versatile, feature-rich Rust ORM ⛵
https://njord.rs
BSD 3-Clause "New" or "Revised" License
409 stars 21 forks source link

experimenting with sql! #202

Closed chaseWillden closed 3 days ago

chaseWillden commented 3 days ago

This is an experimental PR, if you don't like it not worries at all. In my personal project, I have a semi complex query, which if I were to translate this into the Njord function style, it would be actually quite a bit of code. This potentially solves that issue:

This introduces the beginning of the sql!() function:

let user_id = 1;

let query = sql! {
    SELECT *
    FROM user
    WHERE id = {user_id}
};

Eventually, the user_id would be completely sanitized to prevent sql injection attacks, but would allow for complex queries easily. For example:

let complex_query = sql! {
    SELECT a.company, COUNT(i.id) AS total_impressions, COUNT(DISTINCT i.ip_address) AS unique_impressions
    FROM impressions i
    INNER JOIN cached_content c ON c.content_hash = i.content_hash
    INNER JOIN ads a ON a.id = c.ad_id
    GROUP BY a.company;
};

Usage in sqlite would look like this:

let username = "mjovanc";

let query = sql! {
    SELECT *
    FROM users
    WHERE username = {username}
};

match conn {
    Ok(ref c) => {
        let result = sqlite::select::raw_execute::<User>(&query, c);
        match result {
            Ok(r) => assert_eq!(r.len(), 2),
            Err(e) => panic!("Failed to SELECT: {:?}", e),
        };
    }
    Err(e) => panic!("Failed to SELECT: {:?}", e),
};
mjovanc commented 3 days ago

This is fantastic and exactly how I imagined it. Awesome stuff! We will do this. And btw, we need to create a big table in the README so we can track all the features we have implemented and what we need to implement for the different adapters.

I will merge this.