A mini ORM to quickly find / insert / retrieve records with tokio-postgres.
If #[mini_query(primary_key)] is set:
get(id:&T) -> Result<Option<T>>For all fields marked with #[mini_query(find_by)]:
find_by_{x}(client:&impl GenericClient, val:&T) -> Result<Option<T>>For all fields marked with #[mini_query(get_by)]:
get_by_{x}(client:&impl GenericClient, val:&T) -> Result<Vec<T>>And of course, support for inserting and updating.
quick_insert(&self, client:&impl GenericClient) -> Result<Self>quick_insert_no_return(&self, client:&impl GenericClient) -> Result<()>quick_update(&self, client:&impl GenericClient) -> Result<Self>This macro also implements the From<Row> trait for your struct. Making this possible:
let user:User = client.query_one("SELECT * FROM users WHERE id = $1",&[&1]).await?.into();use chrono::prelude::*;use mini_query::MiniQuery;use tokio_postgres::GenericClient;#[derive(MiniQuery,Default)]#[mini_query(table_name = "users")]structUser{#[mini_query(primary_key)]pubid:i32,#[mini_query(find_by)]pubemail:String,#[mini_query(skip)]pubraw_password:Option<String>,#[mini_query(rename = "password")]// renames field to "password" when savingpubenc_password:String,#[mini_query(cast = i16, get_by)]// field is represented by a smallint in postgrespubrole:UserRole,pubcreated_at:DateTime<Utc>,pubupdated_at:DateTime<Utc>,}implUser{fnencrypt_password(&mutself){letSome(raw_password) = &self.raw_passwordelse{return;}self.enc_password = format!("{raw_password} - tada, I am encrypted");}}#[derive(Default,Clone,Copy)]#[repr(i16)]enumUserRole{#[default]User = 0,Admin = 1}implFrom<i16>forUserRole{fnfrom(val:i16) -> Self{match val {0 => UserRole::User,1 => UserRole::Admin,
_ => unimplemented!(),}}}#[derive(MiniQuery,Default)]#[mini_query(table_name = "posts")]structPost{#[mini_query(primary_key)]pubuser_id:i32,pubcontent:String}implPost{belongs_to!(User, user, user_id);}#[tokio::main]asyncfnmain() -> Result<()>{let(client, connection) =
tokio_postgres::connect("postgresql://postgres@localhost/mydb-dev",NoTls).await?;
tokio::spawn(asyncmove{ connection.await});letmut user = User{email:"foo@dog.com".to_owned(),raw_password:Some("I am bad password".to_owned()),role:UserRole::Admin,
..Default::default()};
user.encrypt_password();// fn is prefixed with "quick_" to avoid naming collisions',// in case you wish to write your own validation wrapper.
user.quick_insert(&client).await?;// find user by emaillet same_user = User::find_by_email(&client,"foo@dog.com").await?.unwrap();assert_eq!(user.email, same_user.email);// get all the adminslet admin = User::get_by_role(&client,&UserRole::Admin).await?
.pop().unwrap();assert_eq!(same_user.email, admin.email);// get user by id and updateletmut user = User::get(&client,&same_user.id).await?.unwrap();
user.email = "bar@dog.com".to_owned();
user.quick_update(&client).await?;// assert it savedassert_eq!(&User::get(&client,&user.id).await?.unwrap().email,"bar@dog.com");Ok(())}Only supports tokio-postgres right now.