include-sqlite-sql is an extension of include-sql for using SQLite SQL in Rust. It completes include-sql by providing impl_sql
macro to generate database access methods from the included SQL. include-sqlite-sql uses Rusqlite for database access.
Usage
Include include-sqlite-sql
as a dependency:
[]
= "0.1"
Write your SQL and save it in a file. For example, let's say the following is the content of the library.sql
file that is saved in the project's src
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: user_id: &str - user ID
-- param: book_ids: u32 - book IDs
UPDATE library
SET loaned_to = :user_id
, loaned_on = current_timestamp
WHERE book_id IN (:book_ids);
And then use it in Rust as:
use ;
use ;
include_sql!;
Note that the path to the SQL file must be specified relative to the project root, i.e. relative to
CARGO_MANIFEST_DIR
, even if you keep your SQL file alongside rust module that includes it. Because include-sql targets stable Rust this requirement will persist until SourceFile stabilizes.
Anatomy of the Included SQL File
Please see the Anatomy of the Included SQL File in include-sql documentation for the description of the format that include-sql can parse.
Generated Methods
include-sqlite-sql generates 3 variants of database access methods using the following selectors:
?
- methods that process rows retrieved bySELECT
,!
- methods that execute all other non-SELECT
methods, and->
- methods that executeRETURNING
statements and provide access to returned data.
Process Selected Rows
For the SELECT
statement like:
-- name: get_loaned_books?
-- param: user_id: &str
SELECT book_title FROM library WHERE loaned_to = :user_id;
The method with the following signature is generated:
Where:
user_id
is a parameter that has the same name as the SQL parameter with the declared (in the SQL) type as&str
.F
is a type of a callback (closure) that the method implementation will call to process each row.
Execute Non-Select Statements
For non-select statements - INSERT, UPDATE, DELETE, etc. - like the following:
-- name: loan_books!
-- param: user_id: &str
-- param: book_ids: u32
UPDATE library
SET loaned_to = :user_id
, loaned_on = current_timestamp
WHERE book_id IN (:book_ids);
The method with the following signature is generated:
;
Where:
user_id
is a parameter that has the same name as the SQL parameter with the declared (in the SQL) type as&str
,book_ids
is a parameter for the matching IN-list parameter where each item in a collection has typeu32
.
RETURNING Statements
For DELETE, INSERT, and UPDATE statements that return data via RETURNING
clause like:
-- name: add_new_book->
-- param: isbn: &str
-- param: book_title: &str
INSERT INTO library (isbn, book_title)
VALUES (:isbn, :book_title)
RETURNING book_id;
The method with the following signature is generated:
Inferred Parameter Types
If a statement parameter type is not explicitly specified via param:
, include-sqlite-sql will use impl rusqlite::ToSql
for the corresponding method parameters. For example, if the SQL from the example above has not provided its parameter type:
-- name: get_loaned_books?
-- Returns the list of books loaned to a patron
SELECT book_title
FROM library
WHERE loaned_to = :user_id
ORDER BY 1;
Then the signature of the generated method would be:
/// Returns the list of books loaned to a patron