Macro impl_sql

Source
macro_rules! impl_sql {
    ( $sql_name:ident = $( { $kind:tt $name:ident ($($variant:tt $param:ident $ptype:tt)*) $doc:literal $s:tt $( $text:tt )+ } ),+ ) => { ... };
}
Expand description

Generates Rust code to use included SQL.

This macro defines a trait with methods to access data and implements it for rusqlite::Connection.

This macro recognizes and generates 3 variants of database access methods using the following selectors:

  • ? - methods that process rows retrieved by SELECT,
  • ! - methods that execute all other non-SELECT methods, and
  • & - methods that execute multiple SQL statements (as a batch), and
  • -> - methods that execute RETURNING statements and provide access to returned data.

For SELECT statements (?) like:

-- name: get_loaned_books?
-- param: user_id: &str
SELECT book_title FROM library WHERE loaned_to = :user_id
/

Method with the following signature is generated:

fn get_loaned_books<F>(&self, user_id: &str, row_callback: F) -> -> rusqlite::Result<()>
where F: FnMut(&rusqlite::Row) -> rusqlite::Result<()>;

For non-select statements (!) - INSERT, UPDATE, DELETE, etc. - like:

-- name: loan_books!
-- param: book_ids: i32
-- param: user_id: &str
UPDATE library
   SET loaned_to = :user_id
     , loaned_on = current_timestamp
 WHERE book_id IN (:book_ids)
/

Method with the following signature is generated:

fn loan_books( &self, book_ids: &[i32], user_id: &str ) -> rusqlite::Result<usize>;

Note that the loan_books signature also shows that parameter order follows param order in the SQL file. However, if param are not specified, the method parameters will be ordered using netural order of the SQL statement parameters.

For batches of statements (&) like:

-- name: create_tables &
-- Note that SQL statemetns in a batch cannot have any parameters.
BEGIN;
CREATE TABLE foo(x INTEGER);
CREATE TABLE bar(y TEXT);
COMMIT;
/

Method with the following signature is generated:

fn create_tables(&self) -> rusqlite::Result<()>;

For DELETE, INSERT, and UPDATE statements that return data via RETURNING clause (->) like:

-- name: add_book ->
-- param: book_author: &str
-- param: book_title: &str
INSERT INTO library (book_author, book_title) VALUES (:book_author, :book_title)
RETURNING book_id
/

Method with the following signature is generated:

fn add_book<F,R>( &self, book_author: &str, book_title: &str, row_callback: F ) -> rusqlite::Result<R>
where F: FnOnce(&rusqlite::Row) -> rusqlite::Result<R>;