The current implementation uses an
r2d2 connection pool in src/utils/database.rs and runs embedded migrations on startup. Use those helpers as the source of truth when the examples on this page are too generic.Overview
Diesel provides:- Type-safe queries - Compile-time guarantees for SQL correctness
- Migration management - Version-controlled schema changes
- Auto-generated schema - Rust types from database tables
Configuration
Diesel is configured viadiesel.toml at the project root:
- Where to write the generated schema (
src/schema.rs) - Where to find migration files (
migrations/directory)
Creating Migrations
Migrations are SQL files that modify the database schema. Each migration has two parts:up.sql- Apply changes (e.g., create table)down.sql- Revert changes (e.g., drop table)
Generate Migration Files
Use the Diesel CLI to create migration scaffolding:This creates a new directory:The timestamp prefix ensures migrations run in chronological order.
Write the Up Migration
Edit
up.sql to define schema changes:migrations/YYYY-MM-DD-HHMMSS_create_songs/up.sql
Write the Down Migration
Edit
down.sql to undo the changes:migrations/YYYY-MM-DD-HHMMSS_create_songs/down.sql
The down migration should completely revert the up migration, allowing you to roll back if needed.
Run the Migration
Apply the migration to your database:This:
- Executes the SQL in
up.sql - Updates
src/schema.rswith the new table - Records the migration in the
__diesel_schema_migrationstable
Migration Examples
Creating a Table
Frommigrations/2023-01-22-200806_create_users/up.sql:
down.sql:
Adding an Index
Frommigrations/2023-02-02-080943_users_add_index_discord_id_anilist_id/up.sql:
down.sql:
Removing a Constraint
Frommigrations/2023-02-02-075156_remove_unique_constraint_from_user/up.sql:
down.sql:
Rolling Back Migrations
Revert the most recent migration:- Executes the SQL in
down.sql - Updates
src/schema.rsto remove the table/changes - Removes the migration record from the database
Creating Database Models
After running migrations, create Rust models insrc/models/db/:
src/models/db/user.rs
Queryable- For selecting data from the databaseSelectable- Explicitly map struct fields to columnsInsertable- For inserting new rowsAsChangeset- For updating existing rows
Querying the Database
Diesel queries are type-safe and compile-time checked:Select Query
Insert Query
Update Query
Delete Query
Database Connection
Create the pool and fetch a connection insrc/utils/database.rs:
src/main.rs:199-202:
Running Migrations Programmatically
Annie Mei runs migrations automatically at startup usingdiesel_migrations:
src/utils/database.rs
Migration Best Practices
Always Write Down Migrations
Every
up.sql must have a corresponding down.sql that fully reverts the changes.Test Migrations
Test both up and down migrations:
Use Transactions
Wrap complex migrations in transactions:
Avoid Data Loss
Be cautious with:
- Dropping tables
- Removing columns
- Changing data types
Troubleshooting
Migration fails with 'relation already exists'
Migration fails with 'relation already exists'
The table may already exist. Check current schema:Either:
- Drop the table manually and re-run
- Update the migration to check for existence:
Schema.rs not updating
Schema.rs not updating
Manually regenerate the schema:Or delete
src/schema.rs and re-run migrations.Migration order is wrong
Migration order is wrong
Diesel runs migrations in timestamp order. If you need to reorder:
- Revert all migrations:
diesel migration revert --all - Rename migration directories to change timestamps
- Re-run migrations:
diesel migration run
Can't connect to database
Can't connect to database
Verify environment variables:Test connection:
Next Steps
Architecture
Understand how database fits in the architecture
Adding Commands
Use database models in commands
Diesel Documentation
Official Diesel ORM documentation
