1 unstable release
0.1.0 | Jun 18, 2024 |
---|
#1298 in Database interfaces
13KB
53 lines
write SQL code inline in your Rust program!
Example
You can write SQL almost like you are used to.
use inline_postgres as pg;
use pg::prelude::*;
fn main() -> Result<(), pg::Error> {
// connect to the database
let mut db = pg::Client::connect("host=localhost, user=postgres", pg::NoTls)?;
// we can execute arbitrary code on the database, like creating a table.
db.exec(stmt! {
CREATE TABLE PERSON (
FIRST_NAME VARCHAR(100),
LAST_NAME VARCHAR(100)
)
})?;
// we can also use values from the surrounding scope to in the query like so:
let max = 4;
db.exec(stmt! {
DELETE FROM PERSON
WHERE LENGTH(LAST_NAME) > {max}
})?;
// note that we need to use double-quotes to write SQL string literals.
let given_name = "Wanda";
db.exec(stmt! {
INSERT INTO PERSON(FIRST_NAME, LAST_NAME) VALUES({given_name}, "Maximoff")
})?;
// to query values from the database we can use the `Client::fetch` method.
// instead of returning a record object, the values are directly inserted into
// a generated struct which has all the queried fields.
//
// the field names and types are written in the query like so:
let rows = db.fetch(sql! {
SELECT FIRST_NAME AS [name: String] FROM PERSON
})?;
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].name, "Wanda");
Ok(())
}
Limitations
The Rust tokenizer is designed for Rust, not SQL.
Hence, it does not know what to do with string literals delimited by single quotes ('
).
Any creation of such string literals like 'Peter Parker'
cannot be parsed by Rust and cause a compile error.
To work around this limitation, it was decided to use Rusts syntax of double quotes for the embedded SQL strings as well.
Safety
A query like SELECT * FROM PERSON WHERE FIRST_NAME = {name}
looks like it would concatenate the value directly into the query, which would be quite unsafe.
Luckily it does not do that, but instead runs the query like a prepared statement, and passes the parameters separately.
In fact, no use of the sql!
macro (and related ones) can result in an SQL injection attack.
It generates the SQL statements at compile time, and thus no runtime value can sneak into the query.
Dependencies
~9–21MB
~323K SLoC