diff --git a/pg-worm/src/lib.rs b/pg-worm/src/lib.rs index 7586c1c..8a37489 100644 --- a/pg-worm/src/lib.rs +++ b/pg-worm/src/lib.rs @@ -15,57 +15,78 @@ //! Here's a quick example: //! //! ``` -//! use pg_worm::{force_register, connect, NoTls, Model, Filter}; -//! +//! +//! use pg_worm::{connect, force_register, Filter, JoinType, Model, NoTls, Query, QueryBuilder}; +//! use tokio::try_join; +//! +//! // First easily define your models. //! #[derive(Model)] -//! // Postgres doesn't allow tables named `user` -//! #[table(table_name = "users")] -//! struct User { -//! // A primary key which automatically increments +//! struct Book { +//! // `id` will be the primary key column and +//! // automatically generated/incremented //! #[column(primary_key, auto)] //! id: i64, -//! // A column which requires unique values //! #[column(unique)] +//! title: String, +//! author_id: i64, +//! } +//! +//! #[derive(Model)] +//! struct Author { +//! #[column(primary_key, auto)] +//! id: i64, //! name: String, -//! // You can rename columns too -//! #[column(column_name = "pwd_hash")] -//! password: String //! } -//! +//! //! #[tokio::main] //! async fn main() -> Result<(), pg_worm::Error> { -//! // Simply connect to your server... +//! // First connect to your server. This can be only done once. //! connect!("postgres://me:me@localhost:5432", NoTls).await?; -//! -//! // ...and then register your `Model`. -//! // This creates a new table. Be aware -//! // that any old table with the same name -//! // will be dropped and you _will_ lose your data. -//! force_register!(User)?; -//! -//! // Now start doing what you actually care about. -//! -//! // First, we will create some new users. -//! User::insert("Bob", "very_hashed_password").await?; -//! User::insert("Kate", "another_hashed_password").await?; -//! -//! // Querying data is just as easy: -//! -//! // Retrieve all users there are... -//! let all_users: Vec = User::select(Filter::all()).await; -//! assert_eq!(all_users.len(), 2); -//! -//! // Or look for Bob... -//! let bob: Option = User::select_one(User::name.eq("Bob")).await; -//! assert!(bob.is_some()); -//! assert_eq!(bob.unwrap().name, "Bob"); -//! -//! // Or delete Bob, since he does not actually exists -//! User::delete(User::name.eq("Bob")).await; -//! -//! // Graceful shutdown +//! +//! // Then, create tables for your models. +//! // Use `register!` if you want to fail if a +//! // table with the same name already exists. +//! // +//! // `force_register` drops the old table, +//! // which is useful for development. +//! // +//! // If your tables already exist, skip this part. +//! force_register!(Author, Book)?; +//! +//! // Next, insert some data. +//! // This works by passing values for all +//! // fields which aren't autogenerated. +//! try_join!( +//! Author::insert("Stephen King"), +//! Author::insert("Martin Luther King"), +//! Author::insert("Karl Marx"), +//! Book::insert("Foo - Part I", 1), +//! Book::insert("Foo - Part II", 2), +//! Book::insert("Foo - Part III", 3) +//! )?; +//! +//! // Do a simple query for all books +//! let books: Vec = Book::select(Filter::all()).await; +//! assert_eq!(books.len(), 3); +//! +//! // Or search for a specific book +//! let book = Book::select_one(Book::title.eq("Foo - Part II")).await; +//! assert!(book.is_some()); +//! +//! // Or make more complex queries using the query builder +//! let king_books: Vec = Query::select(Book::COLUMNS) +//! .filter(Author::name.like("%King%")) +//! .join(&Book::author_id, &Author::id, JoinType::Inner) +//! .build() +//! .exec() +//! .await?; +//! assert_eq!(king_books.len(), 2); +//! +//! // Or delete a book, you don't like +//! Book::delete(Book::title.eq("Foo - Part II")).await; +//! +//! // Graceful shutdown //! Ok(()) -//! } //! ``` //! //! ## Filters @@ -92,6 +113,27 @@ //! Please notice that, at this point, custom priorization via parantheses //! is **not possible**. //! +//! +//! ## Query Builder +//! Simply attaching a [`Filter`] to your query often does not suffice. +//! For this reason, `pg-worm` provides a `QueryBuilder` interface for +//! constructing more complex queries. +//! +//! Start building your query by calling `Query::select()` and passing +//! the columns you want to select. +//! Normally you want to query all columns of a `Model` which you can do by passing +//! `YourModel::columns()`. +//! +//! You can modify your query using the following methods: +//! +//! * `.filter()` - add a `WHERE` clause +//! * `.join()` - add a `JOIN` for querying accross tables/models +//! * `.limit()` - add a `LIMIT` to how many rows are returned +//! +//! After you have configured your query, build it using the `.build()` method. +//! Then, execute it by calling `.exec::()`, where `M` is the `Model` which +//! should be parsed from the query result. It may be inferred. +//! //! ## Opiniatedness //! As mentioned before, `pg_worm` is opiniated in a number of ways. //! These include: