Why did we make Diesel?
Preventing Runtime Errors
We don’t want to waste time tracking down runtime errors. We achieve this by having Diesel eliminate the possibility of incorrect database interactions at compile time.
Built for Performance
Diesel offers a high level query builder and lets you think about your problems in Rust, not SQL. Our focus on zero-cost abstractions allows Diesel to run your query and load your data even faster than C.
Productive and Extensible
Unlike Active Record and other ORMs, Diesel is designed to be abstracted over. Diesel enables you to write reusable code and think in terms of your problem domain and not SQL.
Still not sold? Have a look at an in-depth comparison with other rust database crates.
See some examples
Simple Queries Complex Queries Less Boilerplate Inserting Data Updating Data Ergonomic Raw SQL Popular Projects using Diesel Community Extensions
Simple queries are a complete breeze. Loading all users from a database:
users::table.load(&mut connection)
SELECT * FROM users;
Loading all the posts for a user:
Post::belonging_to(user).load(&mut connection)
SELECT * FROM posts WHERE user_id = 1;
Diesel’s powerful query builder helps you construct queries as simple or complex as you need, at zero cost.
let versions = Version::belonging_to(krate)
.select(id)
.order(num.desc())
.limit(5);
let downloads = version_downloads
.filter(date.gt(now - 90.days()))
.filter(version_id.eq(any(versions)))
.order(date)
.load::<Download>(&mut conn)?;
SELECT version_downloads.*
WHERE date > (NOW() - '90 days')
AND version_id = ANY(
SELECT id FROM versions
WHERE crate_id = 1
ORDER BY num DESC
LIMIT 5
)ORDER BY date
Diesel codegen generates boilerplate for you. It lets you focus on your business logic, not mapping to and from SQL rows.
That means you can write this:
#[derive(Queryable)]
pub struct Download {
: i32,
id: i32,
version_id: i32,
downloads: i32,
counted: SystemTime,
date}
Instead of this:
pub struct Download {
: i32,
id: i32,
version_id: i32,
downloads: i32,
counted: SystemTime,
date}
impl Download {
fn from_row(row: &Row) -> Download {
{
Download : row.get("id"),
id: row.get("version_id"),
version_id: row.get("downloads"),
downloads: row.get("counted"),
counted: row.get("date"),
date}
}
}
It’s not just about reading data. Diesel makes it easy to use structs for new records.
#[derive(Insertable)]
#[diesel(table_name = users)]
struct NewUser<'a> {
: &'a str,
name: Option<&'a str>,
hair_color}
let new_users = vec![
{ name: "Sean", hair_color: Some("Black") },
NewUser { name: "Gordon", hair_color: None },
NewUser ;
]
insert_into(users).values(&new_users)
.execute(&mut connection);
INSERT INTO users (name, hair_color) VALUES
'Sean', 'Black'),
('Gordon', DEFAULT) (
If you need data from the rows you inserted, just change execute
to get_result
or get_results
. Diesel will take care of the rest.
let new_users = vec![
{ name: "Sean", hair_color: Some("Black") },
NewUser { name: "Gordon", hair_color: None },
NewUser ;
]
let inserted_users = insert_into(users)
.values(&new_users)
.get_results::<User>(&mut connection);
INSERT INTO users (name, hair_color) VALUES
'Sean', 'Black'),
('Gordon', DEFAULT)
(RETURNING *
Diesel’s codegen can generate several ways to update a row, letting you encapsulate your logic in the way that makes sense for your app.
.published = true;
post.save_changes(&mut connection); post
.filter(email.like("%@spammer.com")))
update(users.set(banned.eq(true))
.execute(&mut connection)
Settings::belonging_to(current_user))
update(.set(&settings_form)
.execute(&mut connection)
There will always be certain queries that are just easier to write as raw SQL, or can’t be expressed with the query builder. Even in these cases, Diesel provides an easy to use API for writing raw SQL.
#[derive(QueryableByName)]
#[diesel(table_name = users)]
struct User {
: i32,
id: String,
name: i32,
organization_id}
// Using `include_str!` allows us to keep the SQL in a
// separate file, where our editor can give us SQL specific
// syntax highlighting.
include_str!("complex_users_by_organization.sql"))
sql_query(.bind::<Integer, _>(organization_id)
.bind::<BigInt, _>(offset)
.bind::<BigInt, _>(limit)
.load::<User>(&mut conn)?;
crates.io
crates.io serves as a central registry for sharing “crates”, which are packages or libraries written in Rust that you can use to enhance your projects. This repository contains the source code and infrastructure for the crates.io website, including both frontend and backend components. It uses Diesel as central component to store crate metadata in a database.
vaultwarden
Vaultwarden is a alternative server implementation of the Bitwarden Client API, written in Rust and compatible with official Bitwarden clients [disclaimer], perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. Diesel is used to store sensitive data in their backend application.
lemmy
Lemmy is a link aggregator and forum for the fediverse. It’s similar to sites like Reddit, Lobste.rs, or Hacker News: you subscribe to forums you’re interested in, post links and discussions, then vote, and comment on them. It’s a well established software for the fediverse using Diesel in the backend.
Do you have found some cool project that should be linked here? Submit an issue here
The community has made some utilities to help make diesel even easier to work with!
dsync
Generate rust structs & query functions from diesel schema files.
diesel-logger
A generic diesel connection implementations that allows to log any executed query.
diesel-derive-enum
Use Rust enums directly with diesel.
diesel-oci
A diesel backend and connection implementation for oracles database system.
rsfbclient-diesel
A diesel backend and connection implementation for the Firebird database system.
diesel-async
An experimental async diesel connection implementation for PostgreSQL and MySQL.
Something missing? Submit an issue here.