Georm
What is Georm?
Georm is a quite simple ORM built around SQLx that gives access to a few useful functions when interacting with a database, implementing automatically the most basic SQL interactions you’re tired of writing.
Why is Georm?
I wanted an ORM that’s easy and straightforward to use. I am aware some other projects exist, such as SeaORM, but they generally don’t fit my needs and/or my wants of a simple interface. I ended up writing the ORM I wanted to use.
How is Georm?
I use it in a few projects, and I’m quite happy with it right now. But of course, I’m open to constructive criticism and suggestions!
How can I use it?
Georm works with SQLx, but does not re-export it itself. To get started, install both Georm and SQLx in your Rust project:
cargo add sqlx --features postgres,macros # and any other feature you might want
cargo add georm
As Georm relies heavily on the macro
query_as!
,
the macros
feature is not optional. Declare your tables in your
Postgres database (you may want to use SQLx’s migrate
feature for
this), and then declare their equivalent in Rust.
CREATE TABLE biographies (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL
);
CREATE TABLE authors (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
biography_id INT,
FOREIGN KEY (biography_id) REFERENCES biographies(id)
);
pub struct Author {
pub id: i32,
pub name: String,
}
To link a struct to a table in your database, derive the
sqlx::FromRow
and the georm::Georm
traits.
#[derive(sqlx::FromRow, Georm)]
pub struct Author {
pub id: i32,
pub name: String,
}
Now, indicate with the georm
proc-macro which table they refer to.
#[derive(sqlx::FromRow, Georm)]
#[georm(table = "authors")]
pub struct Author {
pub id: i32,
pub name: String,
}
Finally, indicate with the same proc-macro which field of your struct is the primary key in your database.
#[derive(sqlx::FromRow, Georm)]
#[georm(table = "authors")]
pub struct Author {
#[georm(id)]
pub id: i32,
pub name: String,
}
Congratulations, your struct Author
now has access to all the
functions described in the Georm
trait!
Entity relationship
It is possible to implement one-to-one, one-to-many, and many-to-many relationships with Georm. This is a quick example of how a struct with several relationships of different types may be declared:
#[derive(sqlx::FromRow, Georm)]
#[georm(
table = "books",
one_to_one = [
{ name = "draft", remote_id = "book_id", table = "drafts", entity = Draft }
],
one_to_many = [
{ name = "reviews", remote_id = "book_id", table = "reviews", entity = Review },
{ name = "reprints", remote_id = "book_id", table = "reprints", entity = Reprint }
],
many_to_many = [{
name = "genres",
table = "genres",
entity = Genre,
link = { table = "book_genres", from = "book_id", to = "genre_id" }
}]
)]
pub struct Book {
#[georm(id)]
ident: i32,
title: String,
#[georm(relation = {entity = Author, table = "authors", name = "author"})]
author_id: i32,
}
To read more about these features, you can refer to the online documentation.
Roadmap / TODO
The following features are being considered for future development:
High Priority
- Transaction Support: Add comprehensive transaction support with transaction-aware CRUD methods and relationship handling for atomic operations across multiple entities
- Race Condition Fix: Replace the current
create_or_update
implementation with database-specific UPSERT operations (PostgreSQLON CONFLICT
, MySQLON DUPLICATE KEY UPDATE
, SQLiteON CONFLICT
) to prevent race conditions
Medium Priority
- Multi-Database Support: Extend Georm to support MySQL and SQLite in addition to PostgreSQL, with database-specific optimizations and dialect handling
- Relationship Optimization: Implement eager loading and N+1 query prevention with circular dependency protection to dramatically improve performance when working with related entities
- Composite Primary Keys: Add support for entities with multiple primary key fields using auto-generated ID structs and type-safe composite key handling
- Soft Delete: Implement optional soft delete functionality with
deleted_at
timestamps, allowing entities to be marked as deleted without physical removal
Lower Priority
- Migration Support: Add optional migration utilities that leverage SQLx's existing infrastructure for schema generation, verification, and evolution
- Enhanced Error Handling: Consider implementing custom error types with better categorization and operation context while maintaining compatibility with SQLx errors
- Many-to-Many Relationship Improvements: Add direct methods to add or remove items from many-to-many relationships without manually handling the join table
Recently Completed
- ✅ Defaultable Fields: Support for fields with database defaults or auto-generated values, creating companion structs with optional fields for easier entity creation