8000 GitHub - rksm/rusqlite-mapper: Traits and derive macros to map Rust structs to and from sqlite tables. Not a full ORM.
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Traits and derive macros to map Rust structs to and from sqlite tables. Not a full ORM.

License

Notifications You must be signed in to change notification settings

rksm/rusqlite-mapper

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rusqlite-mapper

Derive Sqlite to generate a mapping between a struct and rusqlite rows.

[dependencies]
rusqlite-mapper = "0.1.0"

Usage

Derive Sqlite and execute a query that selects columns with the same names and types.

use rusqlite_mapper::Sqlite;

#[derive(Sqlite)]
struct Todo {
    todo_id: i32,
    text: String,
    author_id: i32,
}

let row = connection.query_row("SELECT todo_id, text, author_id FROM todos", [], Todo::try_from_row).unwrap();

Nesting, Joins and Flattening

You might want to represent a join between two tables as nested structs. This is possible using the #[from_row(flatten)] on the nested field. This will delegate the creation of that field to FromRow::from_row with the same row, instead of to FromSql.

Because tables might have naming collisions when joining them, you can specify a prefix = ".." to retrieve the columns uniquely. This prefix should match the prefix you specify when renaming the column in a select, like select <column> as <prefix><column>. Nested prefixing is supported.

Outer joins can be supported by wrapping the flattened type in an Option. The FromRow implementation of Option will still require all columns to present, but will produce a None if all the columns are an SQL null value.

use rusqlite_mapper::Sqlite;

#[derive(Sqlite)]
struct Todo {
    id: i32,
    name: String,
    text: String,
    #[sqlite(flatten, prefix = "user_")]
    author: User
}

#[derive(Sqlite)]
struct User {
    id: i32,
    name: String
}

// Rename all `User` fields to have `user_` prefix.
let row = client.query_one("SELECT t.id, t.name, t.text, u.name as user_name, u.id as user_id FROM todos t JOIN user u ON t.author_id = u.user_id", [], Todo::try_from_row).unwrap();

Renaming and Converting

If a struct contains a field with a name that differs from the name of the sql column, you can use the #[from_row(rename = "..")] attribute.

Normally if you have a custom wrapper type like struct DbId(i32), you'd need to implement FromSql in order to use it in a query. A simple alternative is to implement From<i32> or TryFrom<i32> for DbId and annotating a field with #[from_row(from = "i32")] or #[from_row(try_from = "i32")].

This will delegate the sql conversion to <i32 as FromSql> and subsequently convert it to DbId.

struct DbId(i32);

impl From<i32> for DbId {
    fn from(value: i32) -> Self {
        Self(value)
    }
}

struct Todo {
    // If the sqlite column is named `todo_id`.
    #[from_row(rename = "todo_id", from = "i32")]
    id: i32,
    // If the sqlite column is `TEXT`, it will be decoded to `String`,
    // using `FromSql` and then converted to `Vec<u8>` using `std::convert::From`.
    #[from_row(from = "String")]
    todo: Vec<u8>
}

About

Traits and derive macros to map Rust structs to and from sqlite tables. Not a full ORM.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 99.6%
  • Just 0.4%
0