Type-safe SQL query wrappers

Related tags

Database fnsql
Overview

fnsql   Build Status Latest Version Docs badge License badge

The fnsql crate provides simple type-safe optional wrappers around SQL queries. Instead of calling type-less .query() and .execute(), you call to auto-generated unique wrappers that are strongly typed, .query_<name>() and .execute_<name>(). However, you manually specify the input and output types, but only once, with the query, and in separation with the code that uses the query.

It's a very simple implementation that doesn't force any schema or ORM down your throat, so if you are already using the rusqlite or postgres crates, you can gradually replace your type-less queries with the type-ful wrappers, or migrate from an opinionated ORM.

The way to generate these wrappers is to specify input and output types for each one of the queries. For example, consider the following definitions specified with fnsql, based on the rusqlite example:

fnsql::fnsql! {
    #[rusqlite, test]
    create_table_pet() {
        "CREATE TABLE pet (
              id      INTEGER PRIMARY KEY,
              name    TEXT NOT NULL,
              data    BLOB
        )"
    }

    #[rusqlite, test(with=[create_table_pet])]
    insert_new_pet(name: String, data: Option<Vec<u8>>) {
        "INSERT INTO pet (name, data) VALUES (:name, :data)"
    }

    #[rusqlite, test(with=[create_table_pet])]
    get_pet_id_data(name: Option<String>) -> [(i32, Option<Vec<u8>>, String)] {
        "SELECT id, data, name FROM pet WHERE pet.name = :name"
    }
}

The definitions can be used as such (commented out is how the previous type-less interfaces were used):

let mut conn = rusqlite::Connection::open_in_memory()?;

conn.execute_create_table_pet()?;
// conn.execute(
//    "CREATE TABLE pet (
//               id              INTEGER PRIMARY KEY,
//               name            TEXT NOT NULL,
//               data            BLOB
//               )",
//     [],
// )?;

conn.execute_insert_new_pet(&me.name, &me.data)?;
// conn.execute(
//     "INSERT INTO pet (name, data) VALUES (?1, ?2)",
//     params![me.name, me.data],
// )?;

let mut stmt = conn.prepare_get_pet_id_data()?;
// let mut stmt = conn.prepare("SELECT id, data, name FROM pet WHERE pet.name = :name")?;

let pet_iter = stmt.query_map(&Some("Max".to_string()), |id, data, name| {
    Ok::<_, rusqlite::Error>(Pet {
        id,
        data,
        name,
    })
})?;
// let pet_iter = stmt.query_map([(":name", "Max".to_string())], |row| {
//     Ok(Pet {
//         id: row.get(0)?,
//         name: row.get(1)?,
//         data: row.get(2)?,
//     })
// })?;

Technical discussion

The idea with this crate is to allow direct SQL usage but never use inline queries or have type inference at the call-site. Instead, we declare each query on top-level, giving each a name and designated accessor methods that derive from the name.

  • The types of named variables are give in a Rust-like syntax.
  • The type of the returned row is also provided.
  • fnsql does not make an assurances to make sure the types match the query, you will discover it with cargo test and no additional code.
  • fnsql writes the tests for each of the queries. - Arbitrary is used to generate parameter values.
  • If testing one query depend on another, you can specify that with test(with=[..]).
running 3 tests
test auto_create_table_pet ... ok
test auto_insert_new_pet ... ok
test auto_get_pet_id_data ... ok

The following is for allowing generated query tests to compile:

[dev-dependencies]
arbitrary = { version = "1", features = ["derive"] }

Limitations

  • Though it does provide auto-generated tests for validating queries in cargo test, it does not do any compile-time validation based on the SQL query string.
  • It only supports rusqlite and postgres for now.

License

fnsql is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in fnsql by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
A safe, extensible ORM and Query Builder for Rust

A safe, extensible ORM and Query Builder for Rust API Documentation: latest release – master branch Homepage Diesel gets rid of the boilerplate for da

Diesel - A safe, extensible ORM and Query Builder for Rust

A safe, extensible ORM and Query Builder for Rust API Documentation: latest release – master branch Homepage Diesel gets rid of the boilerplate for da

TDS 7.2+ (mssql / Microsoft SQL Server) async driver for rust

Tiberius A native Microsoft SQL Server (TDS) client for Rust. Supported SQL Server versions Version Support level Notes 2019 Tested on CI 2017 Tested

FeOphant - A SQL database server written in Rust and inspired by PostreSQL.

A PostgreSQL inspired SQL database written in Rust.

GlueSQL is a SQL database library written in Rust

GlueSQL is a SQL database library written in Rust. It provides a parser (sqlparser-rs), execution layer, and optional storage (sled) packaged into a single library.

Run SQL queries on CSV files

zsql run SQL queries on csv files A terminal utility to easily run SQL queries on CSV files. zsql is shipped as a small single binary powered by rust

Running SQL-like queries on files.

filesql Running SQL-like queries on files. Features Supported: REPL Basic SQL expressions. INSERT clause. (which inserts data into another file) WHERE

Tool to automate the visualisation of UML dependencies from a SQL file
Tool to automate the visualisation of UML dependencies from a SQL file

Doteur A simple tool to draw your mysql relations from exports. Help us If you use the tool, and like it, don't forget to add a star to the project on

Ormlite - An ORM in Rust for developers that love SQL.

ormlite ormlite is an ORM in Rust for developers that love SQL. It provides the following, while staying close to SQL, both in syntax and performance:

Owner
Dan Aloni
C/C++, Linux kernel, Rust, Haskell. Fixing the world, one Git commit at a time.
Dan Aloni
Gh-sql - Query GitHub Projects (beta) with SQL

gh-sql: Query GitHub Projects (beta) with SQL Installation gh extension install KOBA789/gh-sql Features SELECT items DELETE items UPDATE item fields

Hidekazu Kobayashi 108 Dec 7, 2022
🧰 The Rust SQL Toolkit. An async, pure Rust SQL crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, SQLite, and MSSQL.

SQLx ?? The Rust SQL Toolkit Install | Usage | Docs Built with ❤️ by The LaunchBadge team SQLx is an async, pure Rust† SQL crate featuring compile-tim

launchbadge 7.6k Dec 31, 2022
SQL validator tool for BigQuery standard SQL.

bqvalid What bqvalid does bqvalid is the SQL validator tool for BigQuery standard SQL. bqvalid fails with error message if there's the expression that

null 10 Dec 25, 2022
Query LDAP and AD with SQL

SQLDAP Ever wanted to query AD or LDAP with SQL like queries ? I'm going to answer this question myself: yes ! Why ? Because I never could remember al

null 9 Nov 15, 2022
An object-relational in-memory cache, supports queries with an SQL-like query language.

qlcache An object-relational in-memory cache, supports queries with an SQL-like query language. Warning This is a rather low-level library, and only p

null 3 Nov 14, 2021
Fully typed SQL query builder for Rust [deprecated]

What is Deuterium? Deuterium is a fancy SQL builder for Rust. It's designed to provide a DSL to easily build SQL queries in safe and typed way. Like R

Stanislav Panferov 169 Nov 20, 2022
Rust library to parse, deparse and normalize SQL queries using the PostgreSQL query parser

This Rust library uses the actual PostgreSQL server source to parse SQL queries and return the internal PostgreSQL parse tree.

pganalyze 37 Dec 18, 2022
A Toy Query Engine & SQL interface

Naive Query Engine (Toy for Learning) ?? This is a Query Engine which support SQL interface. And it is only a Toy for learn query engine only. You can

谭巍 45 Dec 21, 2022
Query system statistics with SQL.

pg_stat_sysinfo Collects system statistics. ---- CREATE EXTENSION pg_stat_sysinfo; CREATE EXTENSION ---- SELECT * FROM pg_stat_sysinfo_collect();

PostgresML 12 Jun 14, 2023
ReefDB is a minimalistic, in-memory and on-disk database management system written in Rust, implementing basic SQL query capabilities and full-text search.

ReefDB ReefDB is a minimalistic, in-memory and on-disk database management system written in Rust, implementing basic SQL query capabilities and full-

Sacha Arbonel 75 Jun 12, 2023