| Crates.io | bottle-orm |
| lib.rs | bottle-orm |
| version | 0.4.3 |
| created_at | 2026-01-18 20:21:12.180446+00 |
| updated_at | 2026-01-24 00:10:13.7961+00 |
| description | A lightweight and simple ORM for Rust built on top of sqlx |
| homepage | |
| repository | https://github.com/Murilinho145SG/bottle-orm |
| max_upload_size | |
| id | 2053020 |
| size | 254,253 |
Bottle ORM is a lightweight, async ORM for Rust built on top of sqlx. It is designed to be simple, efficient, and easy to use, providing a fluent Query Builder and automatic schema migrations.
tokio and sqlx.sqlx::Any).#[derive(Model)].Add bottle-orm to your Cargo.toml. You will also need sqlx, tokio, and serde.
[dependencies]
bottle-orm = "0.1.0"
sqlx = { version = "0.8", features = ["runtime-tokio", "tls-native-tls", "any", "postgres", "sqlite", "mysql", "chrono"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
chrono = { version = "0.4", features = ["serde"] }
Use the #[derive(Model)] macro to define your database tables. You can use the #[orm(...)] attribute to configure columns.
use bottle_orm::Model;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
#[derive(Model, Debug, Clone, Serialize, Deserialize, FromRow)]
struct User {
#[orm(primary_key)]
id: i32,
#[orm(size = 50, unique)]
username: String,
age: i32,
#[orm(create_time)]
created_at: DateTime<Utc>,
}
#[derive(Model, Debug, Clone, Serialize, Deserialize, FromRow)]
struct Post {
#[orm(primary_key)]
id: i32,
#[orm(foreign_key = "User::id")]
user_id: i32,
title: String,
content: String,
}
Initialize the database connection and run migrations to create tables automatically.
use bottle_orm::Database;
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load environment variables (DATABASE_URL)
// dotenvy::dotenv().ok();
// let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let database_url = "sqlite::memory:"; // Example for SQLite
// 1. Connect to the database
let db = Database::connect(&database_url).await?;
// 2. Run Migrations (Create tables and FKs)
db.migrator()
.register::<User>()
.register::<Post>()
.run()
.await?;
println!("Database migration completed!");
Ok(())
}
let new_user = User {
id: 1,
username: "alice".to_string(),
age: 30,
created_at: chrono::Utc::now(),
};
db.model::<User>().insert(&new_user).await?;
Use the fluent query builder to filter and retrieve data.
// Fetch a single user by ID
let user: User = db.model::<User>()
.filter("id", "=", 1)
.first()
.await?;
println!("Found user: {:?}", user);
// Fetch multiple records with conditions, order, and pagination
let adults: Vec<User> = db.model::<User>()
.filter("age", ">=", 18)
.order("age DESC")
.limit(10)
.scan()
.await?;
for u in adults {
println!("Adult user: {}", u.username);
}
#[orm(...)])primary_key: Marks the column as the Primary Key.unique: Adds a UNIQUE constraint.create_time: Sets default value to current timestamp on creation.foreign_key = "Table::Column": Creates a Foreign Key relationship.size = N: (Optional) Hints the size for text columns (mostly for docs/optimization).index: Creates an index for this column.Bottle ORM uses sqlx::Any to support multiple databases. The driver is detected automatically from the connection string scheme:
postgres://... -> PostgreSQLmysql://... -> MySQLsqlite://... -> SQLiteThis project is licensed under the MIT License - see the LICENSE file for details.