| Crates.io | tursorm |
| lib.rs | tursorm |
| version | 0.0.2 |
| created_at | 2025-12-18 03:11:46.698147+00 |
| updated_at | 2025-12-18 13:01:14.40013+00 |
| description | A simple ORM for Turso inspired by SeaORM |
| homepage | |
| repository | https://github.com/blprnt-ai/tursoorm |
| max_upload_size | |
| id | 1991629 |
| size | 321,524 |
A simple ORM for Turso inspired by SeaORM.
[dependencies]
tursorm = "0.0.1"
Features:
with-arrays (default) - Vec<T> support for String, i32, i64, f32, f64, boolwith-json - JSON serialization with Json<T> wrapperwith-chrono - Date/time typeswith-uuid - UUID supportuse tursorm::prelude::*;
#[derive(Clone, Debug, Entity)]
#[tursorm(table_name = "users")]
pub struct User {
#[tursorm(primary_key, auto_increment)]
pub id: i64,
pub name: String,
pub email: String,
}
#[tokio::main]
async fn main() -> Result<()> {
let db = Builder::new_local(":memory:").build().await?;
let conn = db.connect()?;
Schema::create_table::<UserEntity>(&conn, true).await?;
// Insert
let user = User::insert(UserActiveModel {
name: set("Alice".to_string()),
email: set("alice@example.com".to_string()),
..Default::default()
}).exec_with_returning(&conn).await?;
// Query
let users = User::find()
.filter(Condition::eq(UserColumn::Name, "Alice"))
.all(&conn).await?;
// Update
let mut update: UserActiveModel = user.clone().into();
update.name = set("Alice Smith".to_string());
User::update(update).exec(&conn).await?;
// Delete
User::delete_by_id(user.id).exec(&conn).await?;
Ok(())
}
#[derive(Clone, Debug, Entity)]
#[tursorm(table_name = "products")]
pub struct Product {
#[tursorm(primary_key, auto_increment)]
pub id: i64,
pub name: String,
#[tursorm(unique)]
pub sku: String,
#[tursorm(column_name = "unit_price")]
pub price: f64,
pub description: Option<String>, // nullable
}
Attributes:
table_name (struct) - Custom table nameprimary_key (field) - Mark as primary keyauto_increment (field) - Auto-incrementing keycolumn_name (field) - Custom column nameunique (field) - Unique constraintThe macro generates ProductEntity, ProductColumn, and ProductActiveModel.
let users = User::find().all(&conn).await?;
let user = User::find_by_id(1).one(&conn).await?;
let users = User::find()
.filter(Condition::eq(UserColumn::Name, "Alice"))
.filter(Condition::gt(UserColumn::Age, 18))
.order_by_desc(UserColumn::CreatedAt)
.limit(10)
.offset(0)
.all(&conn).await?;
let count = User::find().count(&conn).await?;
let exists = User::find().filter(...).exists(&conn).await?;
let affected = User::insert(model).exec(&conn).await?;
let user = User::insert(model).exec_with_returning(&conn).await?;
let id = User::insert(model).exec_with_last_insert_id(&conn).await?;
InsertMany::<UserEntity>::new(vec![model1, model2]).exec(&conn).await?;
let mut update: UserActiveModel = user.into();
update.name = set("New Name".to_string());
User::update(update).exec(&conn).await?;
Update::<UserEntity>::many()
.set(UserColumn::Status, "inactive")
.filter(Condition::lt(UserColumn::LastLogin, cutoff))
.exec(&conn).await?;
User::delete_by_id(1).exec(&conn).await?;
Delete::<UserEntity>::new()
.filter(Condition::eq(UserColumn::Status, "deleted"))
.exec(&conn).await?;
Condition::eq(col, value) // =
Condition::ne(col, value) // !=
Condition::gt(col, value) // >
Condition::gte(col, value) // >=
Condition::lt(col, value) // <
Condition::lte(col, value) // <=
Condition::like(col, pattern) // LIKE
Condition::contains(col, value) // LIKE %value%
Condition::starts_with(col, value) // LIKE value%
Condition::ends_with(col, value) // LIKE %value
Condition::is_null(col) // IS NULL
Condition::is_not_null(col) // IS NOT NULL
Condition::is_in(col, vec) // IN (...)
Condition::between(col, low, high) // BETWEEN
// Combine
cond1.and(cond2)
cond1.or(cond2)
cond.not()
Schema::create_table::<UserEntity>(&conn, true).await?;
Schema::drop_table::<UserEntity>(&conn, true).await?;
Schema::table_exists::<UserEntity>(&conn).await?;
// Auto-migration
use tursorm::migration::{Migrator, MigrationOptions};
Migrator::migrate::<UserEntity>(&conn).await?;
Migrator::migrate_with_options::<UserEntity>(&conn, MigrationOptions {
allow_drop_columns: false,
dry_run: true,
verbose: true,
..Default::default()
}).await?;
// Local file
let db = Builder::new_local("./data.db").build().await?;
// In-memory
let db = Builder::new_local(":memory:").build().await?;
// Remote Turso
let db = Builder::new_remote(url, token).build().await?;
let conn = db.connect()?;
| Rust | SQLite |
|---|---|
i8-i64, u8-u32 |
INTEGER |
f32, f64 |
REAL |
String, &str |
TEXT |
Vec<u8> |
BLOB |
Vec<T>* |
TEXT (JSON array) |
bool |
INTEGER (0/1) |
Option<T> |
NULL when None |
*Vec<T> supported for String, i32, i64, f32, f64, bool (requires with-arrays feature, enabled by default)
MIT