sqlb is a simple and expressive SQLBuilder for Rust for sqlx focused on PostgreSQL (for now).
sqlb
goal is to have a highly ergonomic API at a minimum performance cost. However, using sqlx directly for high bach commands or more advanced usecases is an encouraged approach. WARNING: During the
0.y.z
period API changes will result in.y
increments.
NOTE: SQL Builders are typically not used directly by application business logic, but rather to be wrapped in some Application Model Access Layer (e.g., DAOs or MCs - Model Controller - patterns). Even when using ORMs, it is often a good code design to wrap those access via some model access layers.
NOTE: sqlb has the feature
runtime-tokio-rustls
enabled by the sqlx crate. Do not enable a conflicting runtime feature when adding sqlx to your project.
Goals for first 0.x.x releases:
sqlb
they must implementsqlb::SqlxBindable
trait. The aim is to implement SqlxBindable
for all sqlx
types and allowing app code to implement SqlxBindable
for their specific types. If there are any external types that should be supported but are not currently, please feel free to log a ticket.``rust
//
sqlx::FromRowallows to do sqlx_exec::fetch_as...
//
sqlb::Fieldsallows to have:
// -
toto.fields()(name, value)[] (only direct or NOT Not values)
// -
Todo::field_names()here would return
["id", "title"]`
pub struct Todo { id: i64,
title: String,
#[field(name="description")]
desc: Option<String>,
#[field(skip)]
someting_else: String,
}
pub struct TodoForCreate {
title: String,
desc: Option
#[field(skip)]
someting_else: String,
}
pub struct TodoForUpdate {
title: Option
// -- Get the field names let fieldnames = Todo::fieldnames(); // ["id", "title", "description"]
// -- Create new row let todoc = TodoForCreate { title: "title 01".tostring(), desc: "desc 01".tostring() }; // will update all fields specified in TodoForCreate let sb = sqlb::insert().table("todo").data(todoc.allfields()); let sb = sb.returning(&["id", "title"]); let (id, title) = sb.fetchone::<_, (i64, String)>(&dbpool).await?;
// -- Select
let sb = sqlb::select().table("todo").columns(Todo::fieldnames()).orderby("!id");
let todos: Vec
// -- Update
let todou - TodoForUpdate { desc: "Updated desc 01".tostring()};
let sb = sqlb::update().table("todo").data(todou.notnonefields()).andwhereeq("id", 123);
let rowaffected = sb.exec(&db_pool).await?;
// will not update .title because of the use of .not_none_fields()
.
```
!
breaking change, +
addition, -
fix.
0.3.1
!
BREAKING CHANGE - HasFields.fields
has been rename to HasFields.not_none_fields()
.!
BREAKING CHANGE - HasFields.not_none_fields()
and HasFields.all_fields()
consume the self
(to avoid uncessary clone).+
- HasFields.all_fields()
- returns all fields (even the one where value are None).+
- HasFields::field_names(): &'static [&'static]
- list of field names (i.e., column names).+
- Added SqlxBindable
for the Option<T>
(not a blanket impl at this point).0.3.0
been deprecated since did not have the ...fields(self)
behavior. 0.2.0
sqlx
. From .fetch_one::<(i64, String), _>
to .fetch_one::<_, (i64, String)>
0.0.7
sqlb::insert().table("todo")
(in 0.0.7) rather than sqlb::insert("toto")
(<=0.0.6) (for all SqlBuilders)Start a PostgreSQL
```sh
docker run --rm --name pg -p 5432:5432 -e POSTGRES_PASSWORD=welcome postgres:15
docker exec -it -u postgres pg psql
cargo test
cargo watch -q -c -x 'test --test testsbinsert ```