Lume
A type-safe, ergonomic schema builder and ORM for SQL databases, inspired by Drizzle ORM.

Features
- 🚀 Type-safe: Compile-time type checking for all database operations
- 🎯 Ergonomic: Clean, intuitive API inspired by modern ORMs
- ⚡ Performance: Zero-cost abstractions with minimal runtime overhead
- 🔧 Flexible: Support for various column constraints and SQL types
- 🛡️ Safe: Prevents SQL injection and runtime type errors
- 📦 Lightweight: Minimal dependencies, maximum functionality
Quick Start
Add Lume to your Cargo.toml:
[dependencies]
lume = "0.1"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
Basic Usage
use lume::{
database::Database,
define_schema,
filter::eq_value,
schema::{ColumnInfo, Schema},
};
define_schema! {
Users {
id: i32 [primary_key().not_null()],
username: String [not_null()],
email: String,
age: i32,
is_active: bool [default_value(true)],
created_at: i64 [not_null()],
}
Posts {
id: i32 [primary_key().not_null()],
title: String [not_null()],
content: String,
created_at: i64 [not_null()],
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let db = Database::connect("mysql://user:password@localhost/database").await?;
db.register_table::<Users>().await?;
db.register_table::<Posts>().await?;
let users = db
.query::<Users, QueryUsers>()
.select(QueryUsers {
username: true,
age: true,
..Default::default()
})
.filter(eq_value(Users::username(), "john_doe"))
.execute()
.await?;
for user in users {
let username: Option<String> = user.get(Users::username());
let age: Option<i32> = user.get(Users::age());
println!(
"User: {} (age: {})",
username.unwrap_or_default(),
age.unwrap_or(0)
);
}
db.insert(Users {
id: 0,
age: 25,
username: "john_doe".to_string(),
email: "john.doe@example.com".to_string(),
is_active: true,
created_at: 1677721600,
})
.execute()
.await
.unwrap();
let posts = db
.sql::<Posts>("SELECT * FROM Users WHERE age > 18")
.await
.unwrap();
for post in posts {
let title: Option<String> = post.get(Posts::title());
println!("Post: {}", title.unwrap_or_default());
}
Ok(())
}
Schema Definition
Lume provides a powerful macro system for defining database schemas:
define_schema! {
Product {
id: i32 [primary_key().not_null()],
name: String [not_null().unique()],
description: String,
price: f64 [not_null()],
stock: i32 [default_value(0)],
category_id: i32 [not_null().indexed()],
created_at: i64 [not_null()],
updated_at: i64 [not_null()],
}
}
Supported Types
String → VARCHAR(255)
i32 → INTEGER
i64 → BIGINT
f32 → FLOAT
f64 → DOUBLE
bool → BOOLEAN
Column Constraints
primary_key() - Sets the column as primary key
not_null() - Makes the column NOT NULL
unique() - Adds a UNIQUE constraint
indexed() - Creates an index on the column
default_value(value) - Sets a default value
Type-Safe Queries
let active_users = db
.query::<Users, QueryUsers>()
.filter(Filter::eq_value("is_active", true))
.execute()
.await?;
let young_active_users = db
.query::<Users, QueryUsers>()
.filter(Filter::eq_value("is_active", true))
.filter(Filter::lt("age", 25))
.execute()
.await?;
for user in young_active_users {
let id: Option<i32> = user.get(Users::id());
let username: Option<String> = user.get(Users::username());
let email: Option<String> = user.get(Users::email());
println!("User {}: {} ({})", id.unwrap_or(0), username.unwrap_or_default(), email.unwrap_or_default());
}
Advanced Features
Custom Default Values
define_schema! {
Settings {
id: i32 [primary_key().not_null()],
theme: String [default_value("dark".to_string())],
notifications: bool [default_value(true)],
max_connections: i32 [default_value(10)],
}
}
Table Relationships
define_schema! {
Author {
id: i32 [primary_key().not_null()],
name: String [not_null()],
email: String [not_null().unique()],
}
Book {
id: i32 [primary_key().not_null()],
title: String [not_null()],
author_id: i32 [not_null()], published_year: i32,
isbn: String [unique()],
}
}
Error Handling
Lume provides comprehensive error handling:
use lume::database::DatabaseError;
match db.query::<Users, QueryUsers>().execute().await {
Ok(users) => {
println!("Found {} users", users.len());
}
Err(DatabaseError::ConnectionFailed) => {
eprintln!("Failed to connect to database");
}
Err(DatabaseError::QueryFailed) => {
eprintln!("Query execution failed");
}
Err(e) => {
eprintln!("Unexpected error: {:?}", e);
}
}
Testing
Lume includes comprehensive unit tests:
cargo test
Run specific test categories:
cargo test schema cargo test row cargo test value cargo test registry
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests for any improvements.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog
See CHANGELOG.md for a detailed list of changes and improvements.