SkillAgentSearch skills...

Sqlar

SQL to type-safe rust code

Install / Use

/learn @guissalustiano/Sqlar
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

SQLc: SQL to type-safe rust code

[!CAUTION] This repo is a work in progress and is not ready to be used yet

Plan

Before publish I with improve the type analysis, infering the righ types to output. It's also planned to support domains and references with new types patters. And explore dimensional analysis with constraints to avoid return Vec to everthing

How to use?

Write prepare statments in sql file aside your rust code

PREPARE find_user AS SELECT id, name FROM users WHERE id = $1;
PREPARE list_users AS SELECT id, name FROM users;
PREPARE create_user AS INSERT INTO users(name) VALUES ($1);
PREPARE update_user AS UPDATE users SET name = $2 WHERE id = $1;
PREPARE delete_user AS DELETE FROM users WHERE id = $1;

When done, run the cli to generate the rust code

  $ sqlc .

Which generates:

pub struct FindUserParams {
    pub eq_id: i32,
}
pub struct FindUserRows {
    pub id: i32,
    pub name: Option<String>,
}
pub async fn find_user(
    c: &impl tokio_postgres::GenericClient,
    p: FindUserParams,
) -> Result<Vec<FindUserRows>, tokio_postgres::Error> {
    c.query("SELECT id, name FROM users WHERE id = $1", &[&p.eq_id])
        .await
        .map(|rs| {
            rs.into_iter()
                .map(|r| FindUserRows {
                    id: r.get(0),
                    name: r.get(1),
                })
                .collect()
        })
}

pub struct ListUsersRows {
    pub id: i32,
    pub name: Option<String>,
}
pub async fn list_users(
    c: &impl tokio_postgres::GenericClient,
) -> Result<Vec<ListUsersRows>, tokio_postgres::Error> {
    c.query("SELECT id, name FROM users", &[])
        .await
        .map(|rs| {
            rs.into_iter()
                .map(|r| ListUsersRows {
                    id: r.get(0),
                    name: r.get(1),
                })
                .collect()
        })
}

pub struct CreateUserParams {
    pub name: String,
}
pub async fn create_user(
    c: &impl tokio_postgres::GenericClient,
    p: CreateUserParams,
) -> Result<u64, tokio_postgres::Error> {
    c.execute("INSERT INTO users (name) VALUES ($1)", &[&p.name]).await
}

pub struct UpdateUserParams {
    pub eq_id: i32,
    pub set_name: String,
}
pub async fn update_user(
    c: &impl tokio_postgres::GenericClient,
    p: UpdateUserParams,
) -> Result<u64, tokio_postgres::Error> {
    c.execute("UPDATE users SET name = $2 WHERE id = $1", &[&p.eq_id, &p.set_name]).await
}

pub struct DeleteUserParams {
    pub eq_id: i32,
}
pub async fn delete_user(
    c: &impl tokio_postgres::GenericClient,
    p: DeleteUserParams,
) -> Result<u64, tokio_postgres::Error> {
    c.execute("DELETE FROM users WHERE id = $1", &[&p.eq_id]).await
}

Inspirations

  • cornucopia - The first sql code gen for rust, but uses a slice different sql grammar with don't allows "copy-paste" to postgres
  • diesel - Diesel had create a sql syntact anaylize using rust type system. This is awensome but the error generates are hard and slow to compile.
  • sqlx - Proves that people want to write sql, but a inpure proc-macro makes cache compile harder.

Licences

SQLc is licenced under AGPL-3.0. You're free to use it to generate code for the Rust projects of your choice, even commercial.

The generated code is not licenced by AGPL-3.0.

View on GitHub
GitHub Stars7
CategoryData
Updated6mo ago
Forks0

Languages

Rust

Security Score

77/100

Audited on Oct 1, 2025

No findings