Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Book of Babar

Typed Postgres for Rust, built directly on Tokio and the PostgreSQL wire protocol.

The Babar brand sheet — wordmark, palette, and the herd at work

babar gives you a small set of Postgres-shaped building blocks:

  • Config describes how to connect.
  • Session owns one connection and a background driver task.
  • query! and command! define typed SQL from authored schema facts.
  • Query::raw, Query::raw_with, Command::raw, and Command::raw_with stay available when you need an explicit fallback.
cargo add babar

One typed-SQL path

The primary application story is:

  1. author schema facts with schema!
  2. build statements with schema-scoped query! / command!
  3. pass Rust values that already match the SQL shape
use babar::query::{Command, Query};
use babar::{Config, Session};

#[derive(Debug, Clone, PartialEq, babar::Codec)]
struct DemoUser {
    id: i32,
    name: String,
}

babar::schema! {
    mod app_schema {
        table demo_users {
            id: primary_key(int4),
            name: text,
        }
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> babar::Result<()> {
    let session: Session = Session::connect(
        Config::new("localhost", 5432, "postgres", "postgres")
            .password("secret")
            .application_name("hello-babar"),
    )
    .await?;

    let create: Command<()> =
        Command::raw("CREATE TEMP TABLE demo_users (id int4 PRIMARY KEY, name text NOT NULL)");
    session.execute(&create, ()).await?;

    let insert: Command<DemoUser> =
        app_schema::command!(INSERT INTO demo_users (id, name) VALUES ($id, $name));
    session
        .execute(
            &insert,
            DemoUser {
                id: 1,
                name: "Ada".to_string(),
            },
        )
        .await?;

    let select: Query<(), DemoUser> = app_schema::query!(
        SELECT demo_users.id, demo_users.name
        FROM demo_users
        ORDER BY demo_users.id
    );

    let rows: Vec<DemoUser> = session.query(&select, ()).await?;
    for row in &rows {
        println!("{}	{}", row.id, row.name);
    }

    session.close().await?;
    Ok(())
}

That example shows the intended split:

  • schema-aware macros for application SQL
  • explicit raw fallbacks for bootstrap or unsupported statements
  • structs as the normal shape for application-facing rows and parameters, with one shared struct when the input and row field sets are the same

Choose your path

  • Product docs path — the direct route for readers who want to connect, query, and ship with babar.
  • Rust learning track — an optional guided path for readers who want to learn Rust concepts through babar examples.

Rust learning track (optional)

The Rust learning track is a separate top-level section in the book navigation. Use it if you want a guided Rust-first tour through babar. Skip it if you already know Rust or just want the fastest route into the product docs. Start at Learn Rust with babar when you want that companion path.

How the docs are organized

  • Get Started teaches the first successful round-trip.
  • The Book walks feature-by-feature through everyday usage.
  • Explanation covers architecture, design, and trade-offs.
  • Reference is the catalog for codecs, errors, features, and configuration.

Where to go next