TORM - Tokio ORM
TORM is a Rust ORM (Object-Relational Mapping) library built on the Tokio async runtime, providing GORM-like functionality with a layered module design (Database / ORM / Utils / Monitoring).
🎯 Key Features
- ✅ Standard SQLite Support - Built on rusqlite, generates standard SQLite file format (readable by sqlite3 and other SQLite tools)
- ✅ Pure Rust Storage Engine - Built-in zero-dependency in-memory storage engine (StorageEngine)
- ✅ PostgreSQL Support - Native wire protocol implementation (cleartext / MD5 / SCRAM-SHA-256 auth, parameterized queries)
- ✅ MySQL Support - Native wire protocol implementation (mysql_native_password / caching_sha2_password / sha256_password auth, text/binary protocol parameterized queries)
- ✅ Async/await Support - Fully based on the Tokio async runtime
- ✅ Multi-Database Support - MySQL, PostgreSQL, SQLite
- ✅ Fluent Query Builder - Clean and intuitive query API
- ✅ Query Direct Execution -
insert/update/deleteexecute SQL directly, inspect withreturn_sql() - ✅ Advanced Queries - JOIN, GROUP BY, HAVING, aggregate functions
- ✅ Model Trait - Automatic management of created_at, updated_at timestamps
- ✅
#[derive(Model)]Macro - Generate theModelimpl from a plain struct, eliminating boilerplate - ✅ GORM-style Model CRUD -
create/first_model/find_models/update/deleteonDatabase - ✅ Transaction Support - Create, commit, and rollback transactions
- ✅ Connection Pooling - Pools for SQLite/MySQL/PostgreSQL
- ✅ SQL Injection Protection - Identifier validation/quotation, string escaping, and dangerous-pattern detection (
utils::sql_safety) - ✅ Logging & Performance Monitoring - Built-in logging system and performance stats
📦 Dependencies
[]
= "1.53" # Async runtime
= { = "0.30", = ["bundled"] } # SQLite (standard file format)
= "1.0" # UUID generation
= "1.0" # Serialization
= "1.0" # JSON support
= "0.4" # Time handling
= "0.1" # Async traits
= "1.0" # Error derivation
# PostgreSQL / MySQL wire protocol authentication
= "0.10" # PostgreSQL SCRAM-SHA-256 / MySQL caching_sha2_password
= "0.10" # MySQL mysql_native_password authentication
= "0.10" # PostgreSQL MD5 authentication
= "0.4" # Byte/hex encoding
= "0.22" # SCRAM base64 encoding
# RSA encryption for MySQL caching_sha2_password full auth (MySQL 8.0+)
= "0.9"
= "0.4"
= "0.8"
Database Layer Implementation
| Feature | Implementation | Status |
|---|---|---|
| SQLite | rusqlite (standard file format) | ✅ Complete |
| In-memory engine | Pure Rust StorageEngine | ✅ Complete |
| MySQL | Custom wire protocol (native) | ✅ Complete |
| PostgreSQL | Custom wire protocol (native) | ✅ Complete |
| Type safety | Custom SqlValue | ✅ Complete |
| Transactions | Custom implementation | ✅ Complete |
🏗 Module Structure
src/
├── lib.rs # Module declarations and exports
├── db/ # Database layer
│ ├── db_types.rs # SQL type system (SqlValue, Row, QueryResult)
│ ├── database.rs # Connection abstraction, transactions, factory, Database
│ ├── driver.rs # DBDriver, Dsn
│ ├── error.rs # TormError
│ ├── storage.rs # Pure Rust in-memory storage engine
│ ├── sqlite.rs # SQLite implementation (rusqlite backend)
│ ├── mysql.rs # MySQL wire protocol implementation
│ ├── postgresql.rs # PostgreSQL wire protocol implementation
│ └── pool.rs # Connection pools
├── orm/ # ORM layer
│ ├── model.rs # Model trait
│ ├── query.rs # Query/QueryBuilder
│ ├── advanced_query.rs # Advanced queries (JOIN/GROUP BY/aggregates)
│ ├── relations.rs # Relationships
│ └── migration.rs # Migrations
├── utils/ # Utils layer (zero-dependency implementations)
│ ├── simple_pool.rs # Simple connection pool
│ ├── simple_lru.rs # LRU cache
│ ├── simple_error.rs # Simplified errors
│ ├── simple_uuid.rs # UUID/ID generation
│ └── sql_safety.rs # SQL injection protection (identifiers, escaping, detection)
└── monitoring/ # Monitoring layer
├── logger.rs # Logging system
└── performance.rs # Performance monitoring
🚀 Quick Start
Basic Usage
use ;
async
The generated mydb.db is a standard SQLite file, directly inspectable with sqlite3 mydb.db:
||
||
Type-Safe SQL Values
let value: SqlValue = 42.into; // I32(42)
let value: SqlValue = "hello".into; // String("hello")
let value: SqlValue = true.into; // Bool(true)
let value = DateTime; // DateTime(...)
// SQL string conversion
let sql = value.to_sql_string; // "42", "'hello'", "TRUE"
SQL Injection Protection
The utils::sql_safety module (re-exported at the crate root) provides defense-in-depth against SQL injection. While parameterized queries (? / $1 placeholders) are the first line of defense for values, identifiers (table/column names) are still interpolated directly into SQL. The library automatically validates identifiers in Query / AdvancedQuery / model CRUD; for custom SQL you can use these utilities directly:
use ;
// 1. Validate / quote identifiers before splicing them into SQL
assert_eq!;
assert!;
assert_eq!;
// SqlSanitizer::identifier returns a safe, splicable string
// (falls back to "" and warns when the identifier is unsafe)
let col = identifier;
let query = format!; // safe
// 2. Escape string literals if you must inline values
let value = escape_string; // "O''Reilly"
// 3. Heuristically audit raw SQL for dangerous patterns
// (skips string literals & comments to reduce false positives)
assert!;
assert!;
Note:
contains_injection_patternis a heuristic audit tool for assisting review — it does not replace parameterized queries.
Query Builder
Query provides a fluent builder that can execute directly against a &Database, or inspect the generated SQL with return_sql().
use ;
async
Query::query(db) returns a QueryExecutor for chaining read operations:
QueryExecutor::count()- executesSELECT COUNT(*), returning a result set with aCOUNT(*)columnQueryExecutor::select()- executesSELECT *
Query also returns a SqlStatement from build() / count() / build_update() / etc., which offers both execution and inspection:
SqlStatement::execute(&db)/SqlStatement::query(&db)- run the statement directlySqlStatement::return_sql()- get the(sql, params)pairQuery::return_sql()- get the(sql, params)of the most recently built / executed operation
Note: SQLite and MySQL use
?placeholders; PostgreSQL uses$1/$2/.... The conversion happens automatically during execution.
Deriving a Model
Instead of hand-writing the Model impl, annotate your struct with #[derive(Model)] and a #[model(table_name = "...")] attribute. The macro generates columns(), from_row(), primary-key accessors, and timestamp accessors for you.
use ;
use ;
Supported field types: String, bool, i8/i16/i32/i64, f32/f64, chrono::DateTime<Utc>, Uuid, Vec<u8> and their Option<...> wrappers. Other types are skipped automatically; use #[model(skip)] to exclude a field explicitly, and #[model(column = "...")] to rename a DB column.
Connection Pool
use Pool;
let config = sqlite
.with_max_connections;
let pool = sqlite.await?;
let conn = pool.get_connection.await?;
MySQL Connection
use ;
async
📊 Database Support Status
✅ SQLite (Production-ready, standard file format)
- Built on rusqlite, generates standard SQLite files (sqlite3 compatible)
- Full CRUD operations
- Parameterized queries
- Transaction support
- Foreign key constraints
- Status: Ready for production
✅ Pure Rust In-Memory Engine (StorageEngine)
- Zero-dependency in-memory database
- Custom binary persistence format (TORMDB01)
- Full CRUD + WHERE conditions (AND/OR/comparison/LIKE)
- Status: Usable as a lightweight in-memory database
✅ MySQL (Native wire protocol, production-ready)
- Real TCP connection via
tokio::net::TcpStream - Full initial handshake (Protocol 10) and handshake response
- Authentication:
mysql_native_password,caching_sha2_password(fast/full auth with RSA encryption),sha256_password - AuthSwitchRequest / AuthMoreData auth exchange flow
- Text protocol (
COM_QUERY) for parameterless queries - Binary protocol (
COM_STMT_PREPARE/COM_STMT_EXECUTE) for parameterized queries - Column definition, text-row / binary-row decoding, OK/EOF/Error packets
- Supports
CLIENT_DEPRECATE_EOF(MySQL 5.7+) and classic EOF protocol - Transactions (BEGIN / COMMIT / ROLLBACK)
- Status: Ready for production use with MySQL 5.7+
✅ PostgreSQL (Native wire protocol, production-ready)
- Real TCP connection via
tokio::net::TcpStream - Full startup handshake (StartupMessage, protocol 3.0)
- Authentication: cleartext, MD5, SCRAM-SHA-256 (with server signature verification)
- Simple query protocol (
Q) for multi-statement SQL - Extended query protocol (Parse/Bind/Describe/Execute/Sync) for parameterized statements
- Row decoding: bool, int2/4/8, float4/8, text/varchar, bytea, json/jsonb, date/timestamp/timestamptz, numeric
- Transactions (BEGIN / COMMIT / ROLLBACK)
- Status: Ready for production use with PostgreSQL 10+
🏃 Run Examples
# Basic usage example
# Complete feature demo
# Advanced features demo (relations, migrations, performance)
# Database integration example
# Run tests
🛠 Tech Stack
External Dependencies
- Async Runtime: Tokio 1.53+
- SQLite Implementation: rusqlite 0.30 (bundled)
- UUID Generation: uuid 1.0
- Serialization: Serde 1.0
- Time Handling: Chrono 0.4
Custom Implementations
- Pure Rust Storage Engine: StorageEngine (zero-dependency in-memory database)
- MySQL Protocol: MySqlConnection (native wire protocol)
- PostgreSQL Protocol: PostgresConnection (native wire protocol)
- Type System: SqlValue, Row, QueryResult
- Connection Abstraction: DatabaseConnection trait
- Transaction System: Transaction
- Connection Pools: Pool / SimplePool
- Utilities: SimpleUuid, SimpleLruCache, SimpleError, SqlSanitizer (SQL injection protection)
📚 Documentation
- README.md - English README
- README.zh.md - Chinese README
- DATABASE_REPLACEMENT.md - Database layer replacement details
- DEPENDENCY_OPTIMIZATION.md - Dependency optimization details
- PROJECT_SUMMARY.md - Project summary
🎓 Learning Value
TORM demonstrates:
- How to implement database protocols in Rust
- Type-safe database abstraction design
- Async I/O and network programming
- MySQL and PostgreSQL protocol fundamentals
- Production-grade SQLite implementation
- Zero-dependency utility libraries (UUID, LRU cache, connection pool)
🎯 Use Cases
Production
- ✅ SQLite applications (mobile, desktop, lightweight web)
- ✅ Projects requiring standard SQLite file format (interoperable with other SQLite tools)
- ✅ MySQL applications (web services, enterprise apps, supports MySQL 5.7+)
- ✅ PostgreSQL applications (web services, enterprise apps, supports PostgreSQL 10+)
- ✅ Projects with strict dependency control
Learning & Development
- ✅ Database protocol learning
- ✅ Rust async programming
- ✅ ORM design patterns
📝 License
MIT
🤝 Contributing
Issues and Pull Requests are welcome!