#sql #sql-database #orm #postgresql #async #compile-time

nightly gorm

An orm that is simple to use and prevents all mistakes at compile time

5 releases

0.1.4 Aug 11, 2022
0.1.3 Aug 11, 2022
0.1.2 Aug 10, 2022
0.1.1 Aug 10, 2022
0.1.0 Aug 9, 2022

#1369 in Database interfaces

GPL-3.0-only

155KB
3.5K SLoC

gorm

An orm that is simple to use and prevents all mistakes at compile time.

This is done by encoding sql logic into rust's rich type system.

For an example of using this orm, check out the examples directory.

For more information about how to use this crate, check out the documentation.


lib.rs:

An orm that is simple to use and prevents runtime errors by using rust's rich type system to enforce sql logic at compile time.

Usage

The core of this crate is the Table derive macro, which you can derive on your rust structs to tell the orm that they represent tables in your database.

Example

#[derive(Debug, Table)]
pub struct Person {
    id: i32,
    name: String,
    age: i32,

    #[table(foreign_key(School))]
    school_id: i32,
}

#[derive(Debug, Table)]
pub struct School {
    id: i32,
    name: String,
}

struct MyMigration;
migration! { MyMigration => school, person }

let pool =
    DatabaseConnectionPool::connect("postgres://postgres:postgres@localhost/some_database")
        .await?;

MyMigration::down(&pool).await?;
MyMigration::up(&pool).await?;

let school_id = school::new { name: "Stanford" }
    .insert_returning_value(returning!(school::id), &pool)
    .await?;

person::new {
    name: "James",
    age: &35,
    school_id,
}
.insert(&pool)
.await?;

#[derive(FromQueryResult)]
struct PersonNameAndSchoolName {
    person_name: String,
    school_name: String,
}
let person_and_school_names = person::table
    .inner_join(school::table)
    .find()
    .select(select_values!(
        person::name as person_name,
        school::name as school_name
    ))
    .load_all::<PersonNameAndSchoolName>(&pool)
    .await?;

struct AgeSumOfSchool {
    school_name: String,
    age_sum: i64,
}
let age_sum_of_each_school_from_highest_to_lowest = person::table
    .inner_join(school::table)
    .find()
    .select(select_values!(
        school::name as school_name,
        person::age.sum() as age_sum
    ))
    .group_by(school::id)
    .order_by_selected_value_descending(selected_value_to_order_by!(age_sum))
    .load_all::<AgeSumOfSchool>(&pool)
    .await?;

let old_enough_people_ids = person::table
    .find()
    .filter(person::age.greater_equals(20))
    .select(select_values!(person::id))
    .load_all_values(&pool)
    .await?;

For more examples, check out the examples directory.

Migration Cli

If you want to create a cli to manage your migration, you can use the migration_cli feature flag. This feature flag will provide you the migration_cli_main function which you can call in your main function and it will take care of the rest.

For an example of this, check out the migration_cli example in the examples directory.

Dependencies

~9–18MB
~264K SLoC