Top Related Projects
🐚 An async & dynamic ORM for Rust
🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.
🚂 Engine components of Prisma ORM
Rust Compile Time ORM robustness,async, pure Rust Dynamic SQL
Native PostgreSQL driver for the Rust programming language
Quick Overview
Diesel is a safe, extensible ORM and Query Builder for Rust. It provides a high-level, type-safe API for interacting with SQL databases, allowing developers to write efficient database queries without compromising on Rust's safety guarantees.
Pros
- Strong type safety and compile-time query checking
- Support for multiple database backends (PostgreSQL, MySQL, SQLite)
- Excellent performance due to zero-cost abstractions
- Seamless integration with Rust's ecosystem and tooling
Cons
- Steeper learning curve compared to some other ORMs
- Limited support for NoSQL databases
- May require more boilerplate code for complex queries
- Documentation can be challenging for beginners
Code Examples
- Defining a table structure:
table! {
users (id) {
id -> Integer,
name -> Text,
email -> Text,
}
}
- Inserting a new record:
let new_user = NewUser { name: "John Doe", email: "john@example.com" };
diesel::insert_into(users::table)
.values(&new_user)
.execute(conn)?;
- Querying records:
let results = users::table
.filter(users::name.eq("John Doe"))
.limit(5)
.load::<User>(conn)?;
- Updating a record:
diesel::update(users::table)
.filter(users::id.eq(1))
.set(users::name.eq("Jane Doe"))
.execute(conn)?;
Getting Started
-
Add Diesel to your
Cargo.toml
:[dependencies] diesel = { version = "2.0.0", features = ["postgres"] }
-
Set up the database connection:
use diesel::prelude::*; use diesel::pg::PgConnection; let database_url = "postgres://username:password@localhost/diesel_demo"; let conn = PgConnection::establish(&database_url) .expect("Error connecting to database");
-
Generate schema and models:
diesel setup diesel migration generate create_users diesel migration run
-
Use Diesel in your Rust code:
use diesel::prelude::*; use crate::schema::users; #[derive(Queryable)] struct User { id: i32, name: String, email: String, } let users = users::table.load::<User>(&mut conn)?;
Competitor Comparisons
🐚 An async & dynamic ORM for Rust
Pros of Sea-ORM
- Async support out of the box, making it suitable for modern asynchronous Rust applications
- More flexible and adaptable to different database schemas without requiring code regeneration
- Supports multiple databases (MySQL, PostgreSQL, SQLite) with a unified API
Cons of Sea-ORM
- Generally slower performance compared to Diesel due to its runtime abstraction
- Less mature ecosystem and community support
- Steeper learning curve for developers new to ORM concepts
Code Comparison
Diesel query:
let results = users
.filter(published.eq(true))
.limit(5)
.load::<Post>(&mut conn)?;
Sea-ORM query:
let results = Post::find()
.filter(post::Column::Published.eq(true))
.limit(5)
.all(&db).await?;
Both ORMs provide a similar query-building experience, but Sea-ORM's async nature is evident in its use of .await
. Diesel's syntax is slightly more concise, while Sea-ORM's is more explicit about column references.
Sea-ORM offers more flexibility in working with different database schemas without regenerating code, which can be advantageous in certain development scenarios. However, Diesel's static approach often results in better performance and compile-time checks.
The choice between these ORMs depends on specific project requirements, such as the need for async support, performance considerations, and the desired level of abstraction.
🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.
Pros of SQLx
- Async-first design, supporting modern asynchronous Rust programming
- Compile-time checked queries, ensuring SQL correctness at compile-time
- Support for multiple databases (PostgreSQL, MySQL, SQLite) without changing code
Cons of SQLx
- Steeper learning curve due to its more low-level nature
- Less abstraction over database operations compared to Diesel's ORM approach
- Potentially more verbose for complex queries or relationships
Code Comparison
SQLx:
let users = sqlx::query!("SELECT * FROM users WHERE active = ?", true)
.fetch_all(&pool)
.await?;
Diesel:
let users = users::table
.filter(users::active.eq(true))
.load::<User>(&connection)?;
Summary
SQLx offers a more low-level, async-first approach with compile-time query checking, while Diesel provides a higher-level ORM experience. SQLx supports multiple databases seamlessly, but may require more code for complex operations. Diesel offers a more traditional ORM interface, potentially simplifying certain tasks at the cost of less flexibility in some scenarios.
🚂 Engine components of Prisma ORM
Pros of Prisma Engines
- More extensive database support, including MongoDB and CockroachDB
- Automatic database migrations and schema generation
- Powerful query API with type-safe queries and results
Cons of Prisma Engines
- Steeper learning curve due to its unique query API
- Less flexibility in raw SQL queries compared to Diesel
- Potentially higher overhead for simple applications
Code Comparison
Prisma query:
const users = await prisma.user.findMany({
where: { age: { gte: 18 } },
select: { name: true, email: true }
})
Diesel query:
let users = users::table
.filter(users::age.ge(18))
.select((users::name, users::email))
.load::<(String, String)>(&mut conn)?;
Both Prisma and Diesel are powerful ORM tools for Rust, but they cater to different needs. Prisma offers a more comprehensive solution with automatic migrations and support for various databases, while Diesel provides a more Rust-native approach with better raw SQL integration. The choice between them depends on project requirements, database complexity, and developer preferences.
Rust Compile Time ORM robustness,async, pure Rust Dynamic SQL
Pros of rbatis
- Supports multiple databases (MySQL, PostgreSQL, SQLite, etc.) out of the box
- Provides dynamic SQL generation with a macro-based approach
- Offers both synchronous and asynchronous APIs
Cons of rbatis
- Less mature and less widely adopted compared to Diesel
- Documentation may be less comprehensive or up-to-date
- Steeper learning curve due to its macro-heavy approach
Code Comparison
rbatis:
#[crud_table]
#[derive(Clone, Debug)]
pub struct User {
pub id: Option<u64>,
pub name: Option<String>,
}
let user = User { id: None, name: Some("John".to_string()) };
rb.save(&user, &[]).await?;
Diesel:
#[derive(Queryable, Insertable)]
#[table_name = "users"]
struct User {
id: Option<i32>,
name: String,
}
let user = User { id: None, name: "John".to_string() };
diesel::insert_into(users::table).values(&user).execute(conn)?;
Both rbatis and Diesel provide ORM functionality for Rust, but they differ in their approach and feature set. rbatis offers more flexibility with database support and dynamic SQL generation, while Diesel is more established and has a simpler learning curve. The choice between them depends on specific project requirements and developer preferences.
Native PostgreSQL driver for the Rust programming language
Pros of rust-postgres
- More lightweight and focused solely on PostgreSQL
- Provides lower-level control over database operations
- Supports asynchronous operations with tokio
Cons of rust-postgres
- Requires more manual SQL writing compared to Diesel's ORM approach
- Less abstraction for database-agnostic operations
- Steeper learning curve for developers unfamiliar with raw SQL
Code Comparison
Diesel (ORM-style query):
let results = users
.filter(published.eq(true))
.limit(5)
.load::<Post>(&mut conn)?;
rust-postgres (raw SQL query):
let rows = client.query(
"SELECT * FROM posts WHERE published = $1 LIMIT $2",
&[&true, &5],
)?;
Diesel focuses on type-safe, ORM-style queries using Rust's type system, while rust-postgres requires writing raw SQL strings. Diesel provides more compile-time safety and abstraction, whereas rust-postgres offers more direct control over the SQL being executed.
Both libraries are well-maintained and popular choices for working with PostgreSQL in Rust. Diesel is better suited for projects requiring an ORM with database-agnostic features, while rust-postgres is ideal for developers who prefer working directly with SQL and need PostgreSQL-specific functionality.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
A safe, extensible ORM and Query Builder for Rust
API Documentation: latest release â master branch
Diesel gets rid of the boilerplate for database interaction and eliminates runtime errors without sacrificing performance. It takes full advantage of Rust's type system to create a low overhead query builder that "feels like Rust."
Supported databases:
You can configure the database backend in Cargo.toml
:
[dependencies]
diesel = { version = "<version>", features = ["<postgres|mysql|sqlite>"] }
Getting Started
Find our extensive Getting Started tutorial at https://diesel.rs/guides/getting-started. Guides on more specific features are coming soon.
Getting help
If you run into problems, Diesel has a very active Gitter room. You can come ask for help at gitter.im/diesel-rs/diesel. For help with longer questions and discussion about the future of Diesel, open a discussion on GitHub Discussions.
Usage
Simple queries
Simple queries are a complete breeze. Loading all users from a database:
users::table.load(&mut connection)
Executed SQL:
SELECT * FROM users;
Loading all the posts for a user:
Post::belonging_to(user).load(&mut connection)
Executed SQL:
SELECT * FROM posts WHERE user_id = 1;
Complex queries
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)?;
Executed SQL:
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
Less boilerplate
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, Selectable)]
#[diesel(table_name = downloads)]
pub struct Download {
id: i32,
version_id: i32,
downloads: i32,
counted: i32,
date: SystemTime,
}
Instead of this without Diesel:
pub struct Download {
id: i32,
version_id: i32,
downloads: i32,
counted: i32,
date: SystemTime,
}
impl Download {
fn from_row(row: &Row) -> Download {
Download {
id: row.get("id"),
version_id: row.get("version_id"),
downloads: row.get("downloads"),
counted: row.get("counted"),
date: row.get("date"),
}
}
}
Inserting data
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> {
name: &'a str,
hair_color: Option<&'a str>,
}
let new_users = vec![
NewUser { name: "Sean", hair_color: Some("Black") },
NewUser { name: "Gordon", hair_color: None },
];
insert_into(users)
.values(&new_users)
.execute(&mut connection);
Executed SQL:
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![
NewUser { name: "Sean", hair_color: Some("Black") },
NewUser { name: "Gordon", hair_color: None },
];
let inserted_users = insert_into(users)
.values(&new_users)
.get_results::<User>(&mut connection);
Executed SQL:
INSERT INTO users (name, hair_color) VALUES
('Sean', 'Black'),
('Gordon', DEFAULT)
RETURNING *
Updating data
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.
Modifying a struct:
post.published = true;
post.save_changes(&mut connection);
One-off batch changes:
update(users.filter(email.like("%@spammer.com")))
.set(banned.eq(true))
.execute(&mut connection)
Using a struct for encapsulation:
update(Settings::belonging_to(current_user))
.set(&settings_form)
.execute(&mut connection)
Raw SQL
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 {
id: i32,
name: String,
organization_id: i32,
}
// Using `include_str!` allows us to keep the SQL in a
// separate file, where our editor can give us SQL specific
// syntax highlighting.
sql_query(include_str!("complex_users_by_organization.sql"))
.bind::<Integer, _>(organization_id)
.bind::<BigInt, _>(offset)
.bind::<BigInt, _>(limit)
.load::<User>(&mut conn)?;
Code of conduct
Anyone who interacts with Diesel in any space, including but not limited to this GitHub repository, must follow our code of conduct.
License
Licensed under either of these:
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
Contributing
Before contributing, please read the contributors guide for useful information about setting up Diesel locally, coding style and common abbreviations.
Unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in the work, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.
Top Related Projects
🐚 An async & dynamic ORM for Rust
🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and SQLite.
🚂 Engine components of Prisma ORM
Rust Compile Time ORM robustness,async, pure Rust Dynamic SQL
Native PostgreSQL driver for the Rust programming language
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot