#postgresql #database-access #sql-database #sql #macro

include-postgres-sql

A Yesql inspired macro for using PostgreSQL SQL in Rust

13 releases

0.2.2 Mar 7, 2023
0.2.1 Feb 13, 2023
0.1.10 Feb 7, 2023
0.1.9 Nov 15, 2022
0.1.3 Feb 22, 2022

#880 in Database interfaces

MIT license

2MB
17K SLoC

SQL 16K SLoC // 0.0% comments Rust 793 SLoC // 0.1% comments

crates.io Documentation MIT

include-postgres-sql is an extension of include-sql for using Postgres SQL in Rust. It completes include-sql by providing impl_sql macro to generate database access methods from the included SQL. include-postgres-sql uses Rust-Postgres for database access.

Example

Write your SQL and save it in a file. For example, let's say the following is saved as library.sql in the project's sql folder:

-- name: get_loaned_books?
--
-- Returns the list of books loaned to a patron
--
-- # Parameters
--
-- param: user_id: &str - user ID
--
SELECT book_title
  FROM library
 WHERE loaned_to = :user_id
 ORDER BY 1

-- name: loan_books!
--
-- Updates the book records to reflect loan to a patron
--
-- # Parameters
--
-- param: book_titles: &str - book titles
-- param: user_id: &str - user ID
--
UPDATE library
   SET loaned_to = :user_id
     , loaned_on = current_timestamp
 WHERE book_title IN (:book_titles)

And then use it in Rust as:

use include_postgres_sql::{include_sql, impl_sql};
use postgres::{Config, NoTls, Error};

include_sql!("sql/library.sql");

fn main() -> Result<(),Error> {
    let mut db = Config::new().host("localhost").connect(NoTls)?;

    db.loan_books(&["War and Peace", "Gone With the Wind"], "Sheldon Cooper")?;

    db.get_loaned_books("Sheldon Cooper", |row| {
        let book_title : &str = row.try_get(0)?;
        println!("{book_title}");
        Ok(())
    })?;

    Ok(())
}

Or, when include-postgres-sql tokio feature is selected:

use include_postgres_sql::{include_sql, impl_sql};
use tokio_postgres::{Config, NoTls, Error};

include_sql!("sql/library.sql");

#[tokio::main]
async fn main() -> Result<(),Error> {
    let (db, conn) = Config::new().host("localhost").connect(NoTls).await?;
    tokio::spawn(async move {
        if let Err(e) = conn.await {
            eprintln!("connection error: {}", e);
        }
    });

    db.loan_books(&["War and Peace", "Gone With the Wind"], "Sheldon Cooper").await?;

    db.get_loaned_books("Sheldon Cooper", |row| {
        let book_title : &str = row.try_get(0)?;
        println!("{book_title}");
        Ok(())
    }).await?;

    Ok(())
}

Documentation

The included documentation describes the supported SQL file format and provides additional details on the generated code.

💥 Breaking Changes in 0.2

  • include-sql changed optional statement terminator from ; to /. SQL files that used ; terminator would need to change it to / or remove it completely.

Dependencies

~3.5–5MB
~95K SLoC