ormx
                                
                                 ormx copied to clipboard
                                
                                    ormx copied to clipboard
                            
                            
                            
                        Postgres: get_by_any getters
Description
This PR adds get_by_any getters. These getters will return all records that match any of the provided values/ids.
Usage
My current use case is a graphql api that utilizes data loaders to avoid N+1 queries:
#[derive(Debug, Clone, SimpleObject, ormx::Table)]
#[ormx(table = "addresses", id = id, insertable)]
pub struct Address {
    #[ormx(get_optional = get_by_id(&Uuid), get_by_any)]
    pub id: Uuid,
    pub address_line1: Option<String>,
    pub address_line2: Option<String>,
    pub city: Option<String>,
    pub province_code: Option<String>,
    pub country_code: Option<String>,
    pub postal_code: Option<String>
}
#[async_trait]
impl<'a> Loader<Uuid> for AddressDataLoader {
    type Value = Address;
    type Error = Arc<sqlx::Error>;
    async fn load(
        &self,
        keys: &[Uuid],
    ) -> Result<std::collections::HashMap<Uuid, Self::Value>, Self::Error> {
        let mut conn = self.0.acquire().await?;
        let addresses = Address::get_by_any_id(&mut conn, keys).await?; // <- generated getter
        Ok(addresses.into_iter().map(|a| (a.id, a)).collect())
    }
}
Implementation
It generates the following SQL, to be type checked by sqlx: SELECT {} FROM {} WHERE {} = ANY($1).
It is only available for postgres since mysql does not support arrays.
closes #7
great work! could you add a small example and note it in the documentation?
yes no problem, will add an example + documentation this weekend : )
On another (related) note, I was thinking...
ormx offloads the heavy lifting to sqlx, so the different backends of ormx in essence just have to come up with the correct SQL statements at compile time.
Would it make sense to refactor the backend trait towards something like:
pub trait Backend: Sized + Clone {
    // ...
    fn insert_statement(table: &Table<Self>) -> String {
        common::insert_statement(table)
    }
    fn get_statement(table: &Table<Self>) -> String {
        common::get_statement(table)
    }
    // ...
    fn get_any_statement(table: &Table<Self>) -> String
}
impl Backend for MySqlBackend {
    
    // ...
    fn get_any_statement(table: &Table<Self>) -> String {
        compile_error!("'get_many' getters are not supported with the MySql driver")
    }
}
This way we would not end up with feature flags throughout the code base
tldr: sqlx's fetch_one, fetch_many, fetch_optional, execute work on all drivers, the only thing that distinguishes them at the API surface is the database-specific SQL statements. Are there any differences in the actual code generation between different ormx drivers except the SQL itself?
@NyxCode added small example and note in docs
Anything happening with this PR?
Anything happening with this PR?
Just waiting for @bram209 to rename it to get_to_any 🙂
@bram209 are you still working on this? If not, I'd happily rename the attribute myself and merge it.
@bram209 are you still working on this? If not, I'd happily rename the attribute myself and merge it.
Sorry, this one slipped through : /
You can do it if you want, I am a bit busy rest of the week
Sry have been extremely busy lately :/ @NyxCode did the renaming, should be good to go now
cleaning up my PR list