# xql
> An SQL query builder for [sqlx][sqlx]. **Work in progress**
# example usages
Suppose you have a table like this:
```sql
CREATE TABLE book(
id INTEGER NOT NULL PRIMARY KEY,
title TEXT NOT NULL,
year SMALLINT NOT NULL,
author TEXT
);
```
The CRUD (or ISUD with sql acronym) will be look like this:
1. `INSERT` statement.
```rust
let book1 = "The Fellowship of the Rings".to_string();
let auth1 = "J. R. R. Tolkien".to_string();
let book2 = "Dune".to_string();
let auth2 = "Frank Herbret".to_string();
let insert = xql::insert("book", ["id", "title", "year", "author"])
.values([
(1_i32, &book1, 1954_i16, &auth1),
(2_i32, &book2, 1965_i16, &auth2),
])
.returning(["id"]);
assert_eq!(
insert.to_string(),
"INSERT INTO book(id, title, year, author) VALUES \
(1, 'The Fellowship of the Rings', 1954, 'J. R. R. Tolkien'), \
(2, 'Dune', 1965, 'Frank Herbret') \
RETURNING id",
);
```
2. `SELECT` statement.
```rust
use xql::blanket::ExprExt;
use xql::ops::or;
let select = xql::select(["id", "title"])
.from("book")
.filter(or(
"id".equal(1),
"id".equal(2),
))
.order_by(xql::desc("year"));
assert_eq!(
select.to_string(),
"SELECT id, title \
FROM book \
WHERE id = 1 OR id = 2 \
ORDER BY year DESC"
);
```
3. `UPDATE` statement.
```rust
let author = &"Frank Herbert".to_string();
let update = xql::update("book")
.set("author", author)
.filter(xql::eq("id", 2))
.returning(["id"]);
assert_eq!(
update.to_string(),
"UPDATE book \
SET author = 'Frank Herbert' \
WHERE id = 2 \
RETURNING id",
);
```
4. `DELETE` statement.
```rust
let delete = xql::delete("book")
.filter(xql::eq("id", 1))
.returning(["id", "title"]);
assert_eq!(
delete.to_string(),
"DELETE FROM book \
WHERE id = 1 \
RETURNING id, title",
);
```
To execute those queries, add [sqlx][sqlx] to dependencies and enable the backend.
```rust
#[cfg(all(feature = "postgres", not(feature = "mysql"), not(feature = "sqlite")))]
async fn execute<'a>(
pool: sqlx::Pool<sqlx::Postgres>,
insert: xql::stmt::insert::Insert<'a>,
select: xql::stmt::select::Select<'a>,
update: xql::stmt::update::Update<'a>,
delete: xql::stmt::delete::Delete<'a>,
) -> Result<(), sqlx::Error> {
xql::exec::fetch_all(insert, &pool).await?;
xql::exec::fetch_all(select, &pool).await?;
xql::exec::fetch_all(update, &pool).await?;
xql::exec::fetch_all(delete, &pool).await?;
Ok(())
}
#[cfg(all(not(feature = "postgres"), feature = "mysql", not(feature = "sqlite")))]
async fn execute<'a>(
pool: sqlx::Pool<sqlx::MySql>,
insert: xql::stmt::insert::Insert<'a>,
select: xql::stmt::select::Select<'a>,
update: xql::stmt::update::Update<'a>,
delete: xql::stmt::delete::Delete<'a>,
) -> Result<(), sqlx::Error> {
xql::exec::fetch_all(insert, &pool).await?;
xql::exec::fetch_all(select, &pool).await?;
xql::exec::fetch_all(update, &pool).await?;
xql::exec::fetch_all(delete, &pool).await?;
Ok(())
}
#[cfg(all(not(feature = "postgres"), not(feature = "mysql"), feature = "sqlite"))]
async fn execute<'a>(
pool: sqlx::Pool<sqlx::Sqlite>,
insert: xql::stmt::insert::Insert<'a>,
select: xql::stmt::select::Select<'a>,
update: xql::stmt::update::Update<'a>,
delete: xql::stmt::delete::Delete<'a>,
) -> Result<(), sqlx::Error> {
xql::exec::fetch_all(insert, &pool).await?;
xql::exec::fetch_all(select, &pool).await?;
xql::exec::fetch_all(update, &pool).await?;
xql::exec::fetch_all(delete, &pool).await?;
Ok(())
}
```
[sqlx]: https://crates.io/crates/sqlx