A boilerplate eliminator for rusqlite.

Overview

Exemplar

A boilerplate eliminator for rusqlite.

Getting Started

A taste of what you can do:

#[derive(Debug, PartialEq, Model)]
#[table("users")]
#[check("../tests/schema.sql")]
struct User {
   username: String,
   #[bind(bind_path)]
   #[extr(extr_path)]
   home_dir: PathBuf,
   #[column("pwd")]
   password: Vec<u8>,
}
 
fn main() -> Result<()> {
    let conn = Connection::open_in_memory()?;
 
    conn.execute_batch(
        include_str!("../tests/schema.sql")
    )?;
 
    let alice = User {
        username: "Alice".to_owned(),
        home_dir: "/var/home/alice".into(),
        password: b"hunter2".to_vec()
    };
 
    let bob = User {
        username: "Bob".to_owned(),
        home_dir: "/var/home/robert".into(),
        password: b"password".to_vec()
    };
 
    alice.insert(&conn)?;
    bob.insert(&conn)?;
 
    let mut stmt = conn.prepare("
        SELECT * FROM users ORDER BY username ASC
    ")?;
    
    let mut iter = stmt.query_and_then([], User::from_row)?;
 
    assert_eq!(alice, iter.next().unwrap()?);
    assert_eq!(bob, iter.next().unwrap()?);
 
    Ok(())
}

Exemplar is based around the Model trait, which has its own derive macro.

  • See the aformentioned macro's documentation to get started.
  • For handling enums in models, check out the sql_enum macro.
  • For working with "anonymous" record types, look at the record macro.

Features

  • Works with raw SQL, not against it.
  • Thin, zero-cost API.
    • Most of Exemplar revolves around the Model trait, which gets inlined and monomorphized away before runtime. The resulting code is roughly what you'd write by hand when using pure rusqlite.
    • Designed to be drop-in; reuses rusqlite's existing types where possible, including its Result type alias.
    • Supports any type that Deref's to rusqlite::Connection, such as transactions or pooled connections.
  • Optional test derivation for guarding against drift between your database schema and Rust model types.
  • Macros for working with SQL-compatible enums and "anonymous" record types that map to ad-hoc queries.
  • Some ability to reflect on/work with dyn Models at runtime.

If you just need to CRUD some Rust data with sqlite and don't want a whole ORM or enterprise-grade DBMS, then Exemplar is for you!

FAQ

"What does Exemplar not do?"

A few key things:

  • Schema generation and management. Exemplar is explicitly not an ORM, and it's difficult to represent concepts like foreign keys and migrations without falling into ORM territory.
    • If this is a "must" for you, check out diesel or sqlx/seaorm, which both support SQLite.
  • Query generation (excluding INSERT.)
  • Interface portability. Only rusqlite is supported.

"Is it blazing fast?"

Yes. On my machine (according to these benchmarks) Exemplar can:

  • Insert a non-trivial model type in ~600 nanoseconds (1.6 million rows/sec)
  • Query and reconstruct the same type in ~9 microseconds (111,000 rows/sec, using SELECT * LIMIT 1)

Obviously the credit for this speed goes to the SQLite and rusqlite developers, but I can confidently say that I didn't slow things down!

"How does this compare to serde-rusqlite?"

serde_rusqlite is a clever hack, but it still involved too much contorting and boilerplate for my taste - that's why I created Exemplar.

The pain points I tried to fix were:

  • Needing to allocate and juggle a slice of String column names to efficiently deserialize rows - probably due to serde limitations?
    • Exemplar statically knows what columns to expect, so from_row requires no extra inputs and makes no superfluous allocations.
  • Odd design choices for field-less enums - they are inefficiently serialized as TEXT instead of INTEGER. This was nice for debugging, but I figured the faster option should be Exemplar's default.
  • to_params_named(&row1).unwrap().to_slice().as_slice()
    • Equivalent to row1.insert(&conn) or row1.insert_with(&stmt) in Exemplar.
  • General serde overhead popping up, both at compile and runtime.
    • Benchmarking shows that serde_rusqlite is ~25% slower on insert operations compared to Exemplar.
    • Retrieval operations are equally fast, likely because the final conversion step is nothing compared to query calculation and I/O.

Acknowledgements

  • rusqlite, for providing the foundation on which this library is built.
  • David Tolnay, for his various proc macro incantations crates.
You might also like...
Uclicious is a flexible reduced boilerplate configuration framework.

Uclicious What is Uclicious Usage Raw API Derive-driven Validators Type Mapping Supported attributes (#[ucl(..)]) Structure level Field level Addition

One-Stop Solution for all boilerplate needs!
One-Stop Solution for all boilerplate needs!

One Stop Solution for all boilerplate needs! Consider leaving a ⭐ if you found the project helpful. Templa-rs Templa-rs is a one-of-a-kind TUI tool wr

A fast & simple boilerplate generator, built with Rust. 🦀
A fast & simple boilerplate generator, built with Rust. 🦀

Boom 💥 A fast & simple boilerplate generator, built with Rust. Installing boom This package is not yet downloadable on Brew or other package managers

A simple code boilerplate generator written in Rust.

💻 Cgen What is Cgen? A modern, cross-platform, multi-language boilerplate generator aimed to make your code generation less hectic! If you wish to su

An interactive, low-boilerplate creative coding platform
An interactive, low-boilerplate creative coding platform

nightgraph A creative coding platform in Rust. Provides drawing APIs, a CLI, Native and WASM GUIs, and low-boilerplate artwork creation. Designed init

A place to start when building webgl apps in Bevy. Use this to avoid writing the boilerplate.

Template Bevy project with WebGL enabled Prerequisites cargo install cargo-make Build and serve WASM version Set your local ip address in Makefile.to

A Rust Boilerplate server with GraphQL API, Diesel, PostgreSQL, session authentication and JWT
A Rust Boilerplate server with GraphQL API, Diesel, PostgreSQL, session authentication and JWT

Canduma rust Graphql A Rust authentication server with GraphQL API, Diesel, PostgreSQL session authentication and JWT This repository contains a Graph

Solana NFT marketplace boilerplate with anchor & react & candy-machine-cli

The Heros NFT Marketplace Boilerplate project is designed to let users fork, customize, and deploy their own nft marketplace app to a custom domain, ultra fast.

Solana NFT marketplace boilerplate with anchor & react & candy-machine-cli

Solana_Marketplace_HerosNFT The Heros NFT Marketplace Boilerplate project is designed to let users fork, customize, and deploy their own nft marketpla

The Heros NFT Marketplace Boilerplate project is designed to let users fork, customize, and deploy their own nft marketplace app to a custom domain, ultra fast.

Heros NFT on Solana The Heros NFT Marketplace Boilerplate project is designed to let users fork, customize, and deploy their own nft marketplace app t

Rust Rocket MongoDB token-authorization REST API boilerplate

Rust Rocket MongoDB token-auth REST API boilerplate In this repository, you can find backend Rust rocket mongodb rest-api boilerplate with token autho

BoilerFiles is a CLI for downloading your boilerplate files from a public GitHub template repo.

BoilerFiles Available on crates.io. BoilerFiles is a CLI for downloading your boilerplate files from a public GitHub template repo. Features Are you t

Bootstrap your MEV bot strategies with a simple boilerplate to build on top of.

MEV Template Designed by DeGatchi. Bootstrap your MEV bot strategies with a simple boilerplate to build on top of. How To Use This Template I wrote an

A boilerplate++ for a minimal rust web backend

Boiler room A boilerplate++ for a minimal rust web backend Just fork/clone/download this repo and build your backend on it. Why? Both routing and erro

A minimal boilerplate for Astro / Vite with the Nannou creative framework (Rust → WASM). Supports multiple sketches + hot-reload.
A minimal boilerplate for Astro / Vite with the Nannou creative framework (Rust → WASM). Supports multiple sketches + hot-reload.

Astro x Nannou Starter astro-nannou-demo-1c.mov 🕹 Try it online! # 0a. Rust language tools open https://www.rust-lang.org/tools/install # 0b. wasm-p

A dead simple boilerplate for Rust projects.
A dead simple boilerplate for Rust projects.

boilerplate-rs • A dead simple boilerplate for Rust projects. Project Structure ├── assets │ └── logo.png ├── bin │ ├── Cargo.toml │ └── src │

Rust crate: Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation.

overloaded_literals   Overloaded Literals to construct your datatypes without boilerplate and with compile-time validation. Features Compile-time vali

ethers-rs scripting boilerplate

ethers-rs script boilerplate ethers-rs is a great blockchain scripting framework! This repo contains the essentials I find are useful when reading/wri

zink! is a library for developing ink! smart contracts with useful Rust macros that extend functionality and reduce boilerplate code.
zink! is a library for developing ink! smart contracts with useful Rust macros that extend functionality and reduce boilerplate code.

zink! Smart Contract Macros This is a helper library for developing ink! smart contracts. It contains useful Rust macros that extend functionality and

Asynchronous handle for rusqlite library.

tokio-rusqlite Asynchronous handle for rusqlite library. Usage use rusqlite::{params, Result}; use tokio_rusqlite::Connection; #[derive(Debug)] struc

Eray Karatay 22 Dec 22, 2022
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
Rusqlite is an ergonomic wrapper for using SQLite from Rust

Rusqlite Rusqlite is an ergonomic wrapper for using SQLite from Rust. It attempts to expose an interface similar to rust-postgres. use rusqlite::{para

Rusqlite 1.9k Jan 7, 2023
Asynchronous handle for rusqlite library.

tokio-rusqlite Asynchronous handle for rusqlite library. Usage use rusqlite::{params, Result}; use tokio_rusqlite::Connection; #[derive(Debug)] struc

Eray Karatay 22 Dec 22, 2022
App Engine Rust boilerplate

Rust App Engine This projects is a minimal boilerplate ro run Rust web application inside Google App Engine. To deploy it use Google Cloud Shell: ```s

Denis Kolodin 48 Apr 26, 2022
A fast, boilerplate free, web framework for Rust

Tower Web A web framework for Rust with a focus on removing boilerplate. API Documentation Tower Web is: Fast: Fully asynchronous, built on Tokio and

Carl Lerche 969 Dec 22, 2022
A rust layered configuration loader with zero-boilerplate configuration management.

salak A layered configuration loader with zero-boilerplate configuration management. About Features Placeholder Key Convension Cargo Features Default

Daniel YU 28 Sep 20, 2022
Improve and strengthen your strings by making them strongly-typed with less boilerplate

aliri_braid Improve and strengthen your strings Strongly-typed APIs reduce errors and confusion over passing around un-typed strings.

Marcus Griep 27 Dec 29, 2022
Quickly create boilerplate projects and templates.

boyl boyl is a command-line tool written in Rust to manage template folders. boyl can copy existing folders (with support for glob-like ignore pattern

Miguel M. 13 Feb 16, 2022
Build a config structure from environment variables in Rust without boilerplate

Yasec Yet another stupid environment config (YASEC) creates settings from environment variables. (Envconig-rs fork) Features Nested configuration stru

null 4 Dec 28, 2021