## Name pending (currently DB sets) [![Crates.io](https://img.shields.io/crates/v/db-set-macros)](https://crates.io/crates/db-set-macros) [![CI](https://github.com/jayy-lmao/sql-db-set-macros/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jayy-lmao/sql-db-set-macros/actions?query=branch%3Amain) https://github.com/jayy-lmao/sql-db-set-macros Inpsired a little bit by Toasty rs and my work on sql-gen. Idea is to implement the most common SQLX queries, but allow you to still ultimately use SQLX for anything more complex than a basic query. Currently it's only for PostgresQL, so that I can dogfood. But PRs welcome. ### Why not X **_Why not SQLX_?** I _love_ sqlx. It's a delight to work with. I like writing SQL. That's why _this is sqlx_. This macro allows me to continue writing SQLX, but just shaves off some `sqlx prepare` cycles, and some boring same queries you write over and over again. Ultimately I still just want to write SQLX, but just save myself all the `by id` style queries. *Why not SeaORM?* I've used SeaORM before at a job. I find it verbose. *Why not Diesel?* I like the look of diesel. I don't like dedicated single-use config filetypes. Might end up having to write one though for my codegen tool, so maybe I'll eat those words. *Why not Toasy?* Same as diesel. And it's not out yet. But I must like the look of it a little, as I took inspiration from its model definitions. ### Current features Can currently: - [x] Query one - [x] Query many - [x] Insert (ignoring auto fields) - [x] Update - [x] Delete ### Roadmap TODO: - [x] Allow for multiple-field primary keys for query-one - [x] Allow query many by one key field when there are two key fields - [x] Update - [x] Delete - [~] Release early version! - [ ] Limit / Offset - [ ] Create a version of https://github.com/jayy-lmao/sql-gen for generating these - [ ] Do more than just `eq` to match fields (map of ops for each type) ### Examples ```rs #[derive(DbSet, Debug)] // DbSet also implements sqlx::FromRow by default #[dbset(table_name = "users")] // Used for queries, will be used for codegen pub struct User { #[key] // For `::one` queries, can add `auto` to have it ignored as required for inserts. id: String, name: String, // Will be required for insert details: Option, // wont be required for insert #[unique] email: String, // Will generate `::one` queries as it's unique } // Fetch one user let user: User = UserDbSet::one() .id_eq("user-1".to_string()) // type-state pattern, you must provide a key or unique field to be able to call fetch_one .fetch_one(pool) .await?; let user_maybe: Option = UserDbSet::one() .id_eq("user-1".to_string()) // type-state pattern, you must provide a key or unique field to be able to call fetch_one .fetch_optional(pool) .await?; // We can also just write regular SQLX queries. // DbSet implements FromRow for your struct also. let same_user_again = sqlx::query_as!( User, "SELECT id, name, email, details FROM users WHERE id = 'user-1';" ) .fetch_one(pool) .await?; // Fetch all users let users = UserDbSet::many() .fetch_all(pool) // Can call without setting fields to match to get all results .await?; // Fetch many users with one field let users = UserDbSet::many() .name_eq("bob".to_string()) // Can set fields to match on .fetch_all(pool) .await?; // Fetch many users with multiple fields let users = UserDbSet::many() .name_eq("bob".to_string()) .details_eq("the best bob".to_string()) // Can set multiple fields to match on .fetch_all(pool) .await?; // Insert a user let inserted_user = UserDbSet::insert() .id("id-3".to_string()) .email("steven@stevenson.com".to_string()) .name("steven".to_string()) .insert(pool) // Due to type-state insert can't be called until all non-nullable (besides auto) fields have been set .await?; // Update a user user.details = Some("Updated details!".to_string()); user.email = String::from("mynewemail@bigpond.com.au"); UserDbSet::update() .data(user.clone()) .update(pool) .await?; // Delete a user UserDbSet::one() .id_eq("user-1".to_string()) // type-state pattern, you must provide a key or unique field to be able to call fetch_one .delete(pool) .await?; ```