The Book of Babar
Typed Postgres for Rust, built directly on Tokio and the PostgreSQL wire protocol.

babar gives you a small set of Postgres-shaped building blocks:
Configdescribes how to connect.Sessionowns one connection and a background driver task.query!andcommand!define typed SQL from authored schema facts.Query::raw,Query::raw_with,Command::raw, andCommand::raw_withstay available when you need an explicit fallback.
cargo add babar
One typed-SQL path
The primary application story is:
- author schema facts with
schema! - build statements with schema-scoped
query!/command! - 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
babarexamples.
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
- Prerequisites → — start a local Postgres and make the examples observable.
- Your first query → — connect, create a table, insert a row, and read it back.
- Rust learning track → — take the optional guided route
if you want to learn Rust through
babar. - Selecting rows → — learn the standard query shape with schema-scoped wrappers and row structs.
- What makes babar babar → — see how the driver task, typed boundaries, and Postgres-specific design fit together.
- The typed-SQL macro pipeline → — follow
schema!,query!, andcommand!from authored schema facts to runtime values.