keelson-gen 0.1.0

keelson's code generator: introspect a live schema, emit readable model .rs files against keelson-models.
Documentation
// @generated by keelson-gen. DO NOT EDIT.
// Regenerate from the schema instead; hand-written code (hooks included)
// belongs outside this directory.

/// The model marker `posts::table()` hangs off.
#[derive(Debug, Clone, Copy)]
pub struct Posts;
/// One row of `posts`.
#[derive(Debug, Clone, PartialEq)]
pub struct Post {
    pub id: i64,
    pub user_id: i64,
    pub title: String,
    pub status: Option<String>,
    pub views: i64,
    pub published_at: Option<chrono::NaiveDateTime>,
    /// Relations, filled by `preload`/`then_load` mods; empty otherwise.
    pub rel: Rel,
}
/// `posts`' relations.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Rel {
    /// Belongs-to `users`, via `posts.user_id`.
    pub user: Option<Box<super::users::User>>,
    /// Belongs-to `post_authors`, via `posts.id`.
    pub authorship: Option<Box<super::post_authors::PostAuthor>>,
    /// Has-many `comments`, via `comments.post_id`.
    pub comments: Vec<super::comments::Comment>,
    /// Has-many `post_tags`, via `post_tags.post_id`.
    pub post_tags: Vec<super::post_tags::PostTag>,
}
impl keelson_exec::FromRow for Post {
    fn from_row(row: &mut keelson_exec::Row) -> Result<Self, keelson_exec::ExecError> {
        Ok(Post {
            id: row.take("id")?,
            user_id: row.take("user_id")?,
            title: row.take("title")?,
            status: row.take("status")?,
            views: row.take("views")?,
            published_at: row.take("published_at")?,
            rel: Rel::default(),
        })
    }
}
/// `published_at` (db type `TEXT`) is overridden by configuration to `chrono::NaiveDateTime`; the replacement must bind.
const _: () = keelson_exec::assert_bind::<chrono::NaiveDateTime>();
/// The three-state setter: unset fields stay out of the statement.
#[derive(Debug, Clone, Default)]
pub struct Setter {
    pub id: keelson_models::Set<i64>,
    pub user_id: keelson_models::Set<i64>,
    pub title: keelson_models::Set<String>,
    pub status: keelson_models::Set<String>,
    pub views: keelson_models::Set<i64>,
    pub published_at: keelson_models::Set<chrono::NaiveDateTime>,
}
/// The entry point: `posts::table().query(…)` / `.insert(…)` / ….
pub fn table() -> keelson_models::ModelTable<Posts> {
    keelson_models::ModelTable::new()
}
pub fn id() -> keelson_models::Column<i64> {
    keelson_models::Column::new("posts", "id")
}
pub fn user_id() -> keelson_models::Column<i64> {
    keelson_models::Column::new("posts", "user_id")
}
pub fn title() -> keelson_models::Column<String> {
    keelson_models::Column::new("posts", "title")
}
pub fn status() -> keelson_models::Column<String> {
    keelson_models::Column::new("posts", "status")
}
pub fn views() -> keelson_models::Column<i64> {
    keelson_models::Column::new("posts", "views")
}
pub fn published_at() -> keelson_models::Column<chrono::NaiveDateTime> {
    keelson_models::Column::new("posts", "published_at")
}
#[allow(clippy::type_complexity)]
fn all_columns() -> (
    keelson_models::Column<i64>,
    keelson_models::Column<i64>,
    keelson_models::Column<String>,
    keelson_models::Column<String>,
    keelson_models::Column<i64>,
    keelson_models::Column<chrono::NaiveDateTime>,
) {
    (id(), user_id(), title(), status(), views(), published_at())
}
impl keelson_models::View for Posts {
    type Row = Post;
    type Select = keelson_sqlite::SelectQuery;
    fn base_select() -> Self::Select {
        keelson_sqlite::select((
            keelson_sqlite::select::columns(all_columns()),
            keelson_sqlite::select::from(keelson_sqlite::quote("posts")),
        ))
    }
}
impl keelson_models::Table for Posts {
    type Pk = i64;
    type Setter = Setter;
    type Insert = keelson_sqlite::InsertQuery;
    type Update = keelson_sqlite::UpdateQuery;
    type Delete = keelson_sqlite::DeleteQuery;
    fn insert_query(s: Setter) -> Self::Insert {
        let mut cols: Vec<&'static str> = Vec::new();
        let mut vals: Vec<keelson_core::expr::Expr> = Vec::new();
        s.id.push_into("id", &mut cols, &mut vals);
        s.user_id.push_into("user_id", &mut cols, &mut vals);
        s.title.push_into("title", &mut cols, &mut vals);
        s.status.push_into("status", &mut cols, &mut vals);
        s.views.push_into("views", &mut cols, &mut vals);
        s.published_at.push_into("published_at", &mut cols, &mut vals);
        let mut q = keelson_sqlite::insert((
            keelson_sqlite::insert::into(keelson_sqlite::quote("posts")).columns(cols),
            keelson_sqlite::insert::returning(all_columns()),
        ));
        if !vals.is_empty() {
            q.apply(keelson_sqlite::insert::values(vals));
        }
        q
    }
    fn update_query() -> Self::Update {
        keelson_sqlite::update(
            keelson_sqlite::update::table(keelson_sqlite::quote("posts")),
        )
    }
    fn apply_setter(s: Setter, q: &mut Self::Update) {
        if let Some(v) = s.id.into_expr() {
            q.apply(keelson_sqlite::update::set_col("id").to(v));
        }
        if let Some(v) = s.user_id.into_expr() {
            q.apply(keelson_sqlite::update::set_col("user_id").to(v));
        }
        if let Some(v) = s.title.into_expr() {
            q.apply(keelson_sqlite::update::set_col("title").to(v));
        }
        if let Some(v) = s.status.into_expr() {
            q.apply(keelson_sqlite::update::set_col("status").to(v));
        }
        if let Some(v) = s.views.into_expr() {
            q.apply(keelson_sqlite::update::set_col("views").to(v));
        }
        if let Some(v) = s.published_at.into_expr() {
            q.apply(keelson_sqlite::update::set_col("published_at").to(v));
        }
    }
    fn delete_query() -> Self::Delete {
        keelson_sqlite::delete(
            keelson_sqlite::delete::from(keelson_sqlite::quote("posts")),
        )
    }
    fn pk(row: &Post) -> Self::Pk {
        row.id
    }
}
/// Preload mods: the relation joins into the *same* query — no second statement, and deliberately no `.then(…)`. A level below a join has no distinct child set to key on, so a nested path is spelled with `then_load` (see `keelson_models::ThenLoad`).
pub mod preload {
    /// Same-query `LEFT JOIN` preload of the to-one `user`.
    pub fn user() -> impl keelson_core::Mod<keelson_models::ModelSelect<super::Posts>> {
        keelson_core::mod_fn(|q: &mut keelson_models::ModelSelect<super::Posts>| {
            use keelson_sqlite::Chain as _;
            use keelson_sqlite::Mod as _;
            (
                keelson_sqlite::select::left_join(keelson_sqlite::quote("users"))
                    .on(
                        keelson_sqlite::quote(("users", "id"))
                            .eq(keelson_sqlite::quote(("posts", "user_id"))),
                    ),
                keelson_sqlite::select::preload_columns((
                    keelson_sqlite::quote(("users", "id")).as_("user.id"),
                    keelson_sqlite::quote(("users", "name")).as_("user.name"),
                    keelson_sqlite::quote(("users", "email")).as_("user.email"),
                    keelson_sqlite::quote(("users", "age")).as_("user.age"),
                    keelson_sqlite::quote(("users", "is_active")).as_("user.is_active"),
                    keelson_sqlite::quote(("users", "created_at")).as_("user.created_at"),
                )),
            )
                .apply(q);
            q.add_mapper_mod(
                keelson_models::mapper_mod(|row, parent: &mut super::Post| {
                    parent.rel.user = user_from_preload(row)?.map(Box::new);
                    Ok(())
                }),
            );
        })
    }
    /// Decode the prefixed columns; the joined key column decides a `LEFT JOIN` miss.
    pub fn user_from_preload(
        row: &mut keelson_exec::Row,
    ) -> Result<Option<super::super::users::User>, keelson_exec::ExecError> {
        if matches!(row.value("user.id"), None | Some(keelson_sqlite::Value::Null)) {
            return Ok(None);
        }
        Ok(
            Some(super::super::users::User {
                id: row.take("user.id")?,
                name: row.take("user.name")?,
                email: row.take("user.email")?,
                age: row.take("user.age")?,
                is_active: row.take("user.is_active")?,
                created_at: row.take("user.created_at")?,
                rel: super::super::users::Rel::default(),
            }),
        )
    }
    /// Same-query `LEFT JOIN` preload of the to-one `authorship`.
    pub fn authorship() -> impl keelson_core::Mod<
        keelson_models::ModelSelect<super::Posts>,
    > {
        keelson_core::mod_fn(|q: &mut keelson_models::ModelSelect<super::Posts>| {
            use keelson_sqlite::Chain as _;
            use keelson_sqlite::Mod as _;
            (
                keelson_sqlite::select::left_join(keelson_sqlite::quote("post_authors"))
                    .on(
                        keelson_sqlite::quote(("post_authors", "post_id"))
                            .eq(keelson_sqlite::quote(("posts", "id"))),
                    ),
                keelson_sqlite::select::preload_columns((
                    keelson_sqlite::quote(("post_authors", "post_id"))
                        .as_("authorship.post_id"),
                    keelson_sqlite::quote(("post_authors", "title"))
                        .as_("authorship.title"),
                    keelson_sqlite::quote(("post_authors", "user_id"))
                        .as_("authorship.user_id"),
                    keelson_sqlite::quote(("post_authors", "user_name"))
                        .as_("authorship.user_name"),
                )),
            )
                .apply(q);
            q.add_mapper_mod(
                keelson_models::mapper_mod(|row, parent: &mut super::Post| {
                    parent.rel.authorship = authorship_from_preload(row)?.map(Box::new);
                    Ok(())
                }),
            );
        })
    }
    /// Decode the prefixed columns; the joined key column decides a `LEFT JOIN` miss.
    pub fn authorship_from_preload(
        row: &mut keelson_exec::Row,
    ) -> Result<
        Option<super::super::post_authors::PostAuthor>,
        keelson_exec::ExecError,
    > {
        if matches!(
            row.value("authorship.post_id"), None | Some(keelson_sqlite::Value::Null)
        ) {
            return Ok(None);
        }
        Ok(
            Some(super::super::post_authors::PostAuthor {
                post_id: row.take("authorship.post_id")?,
                title: row.take("authorship.title")?,
                user_id: row.take("authorship.user_id")?,
                user_name: row.take("authorship.user_name")?,
                rel: super::super::post_authors::Rel::default(),
            }),
        )
    }
}
/// Then-load mods: one keyed, batched query per level of a load path — `then_load::a().then(b::then_load::c())` is two levels, two queries, checked by the compiler.
pub mod then_load {
    /// Load each row's `user` (to-one), one keyed query per batch of keys — `.then(…)` hangs the next level of the path off this one.
    pub fn user() -> keelson_models::ThenLoad<
        super::Posts,
        super::super::users::Users,
        i64,
    > {
        keelson_models::ThenLoad::new(
            |rows: &[super::Post]| rows.iter().map(|r| r.user_id).collect(),
            |keys, q| keelson_core::Mod::apply(super::super::users::id().in_(keys), q),
            |rows: &mut [super::Post], related| {
                keelson_models::attach_to_one(
                    rows,
                    related,
                    |r| r.user_id,
                    |c| c.id,
                    |r, c| {
                        r.rel.user = c.map(Box::new);
                    },
                );
            },
        )
    }
    /// Load each row's `authorship` (to-one), one keyed query per batch of keys — `.then(…)` hangs the next level of the path off this one.
    pub fn authorship() -> keelson_models::ThenLoad<
        super::Posts,
        super::super::post_authors::PostAuthors,
        i64,
    > {
        keelson_models::ThenLoad::new(
            |rows: &[super::Post]| rows.iter().map(|r| r.id).collect(),
            |keys, q| keelson_core::Mod::apply(
                super::super::post_authors::post_id().in_(keys),
                q,
            ),
            |rows: &mut [super::Post], related| {
                keelson_models::attach_to_one(
                    rows,
                    related,
                    |r| Some(r.id),
                    |c| c.post_id,
                    |r, c| {
                        r.rel.authorship = c.map(Box::new);
                    },
                );
            },
        )
    }
    /// Load each row's `comments` (to-many), one keyed query per batch of keys — `.then(…)` hangs the next level of the path off this one.
    pub fn comments() -> keelson_models::ThenLoad<
        super::Posts,
        super::super::comments::Comments,
        i64,
    > {
        keelson_models::ThenLoad::new(
            |rows: &[super::Post]| rows.iter().map(|r| r.id).collect(),
            |keys, q| keelson_core::Mod::apply(
                super::super::comments::post_id().in_(keys),
                q,
            ),
            |rows: &mut [super::Post], related| {
                keelson_models::attach_to_many(
                    rows,
                    related,
                    |r| r.id,
                    |c| c.post_id,
                    |r, cs| {
                        r.rel.comments = cs;
                    },
                );
            },
        )
    }
    /// Load each row's `post_tags` (to-many), one keyed query per batch of keys — `.then(…)` hangs the next level of the path off this one.
    pub fn post_tags() -> keelson_models::ThenLoad<
        super::Posts,
        super::super::post_tags::PostTags,
        i64,
    > {
        keelson_models::ThenLoad::new(
            |rows: &[super::Post]| rows.iter().map(|r| r.id).collect(),
            |keys, q| keelson_core::Mod::apply(
                super::super::post_tags::post_id().in_(keys),
                q,
            ),
            |rows: &mut [super::Post], related| {
                keelson_models::attach_to_many(
                    rows,
                    related,
                    |r| r.id,
                    |c| c.post_id,
                    |r, cs| {
                        r.rel.post_tags = cs;
                    },
                );
            },
        )
    }
}