use convert_case::{Case, Casing};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use super::context::Context;
use crate::entity::parse::ProjectionDef;
impl Context<'_> {
pub fn projection_methods(&self) -> TokenStream {
let methods: Vec<TokenStream> = self
.entity
.projections
.iter()
.map(|proj| self.projection_method(proj))
.collect();
quote! { #(#methods)* }
}
fn projection_method(&self, proj: &ProjectionDef) -> TokenStream {
let entity_name = self.entity_name;
let proj_snake = proj.name.to_string().to_case(Case::Snake);
let method_name = format_ident!("find_by_id_{}", proj_snake);
let proj_type = format_ident!("{}{}", entity_name, proj.name);
let id_name = self.id_name;
let id_type = self.id_type;
let table = &self.table;
let placeholder = self.dialect.placeholder(1);
let columns_str: String = proj
.fields
.iter()
.map(|f| f.to_string())
.collect::<Vec<_>>()
.join(", ");
quote! {
async fn #method_name(&self, id: #id_type) -> Result<Option<#proj_type>, Self::Error> {
let row = sqlx::query_as::<_, #proj_type>(
&format!("SELECT {} FROM {} WHERE {} = {}", #columns_str, #table, stringify!(#id_name), #placeholder)
).bind(&id).fetch_optional(self).await?;
Ok(row)
}
}
}
}