1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
//! Write SQL queries inside Rust functions.
//!
//! The `inline-sql` crate lets you annotate a function to directly write an SQL query as the function body.
//! You can use the function parameters as placeholders in your query,
//! and the query result will automatically be converted to the return type.
//!
//! See the documentation of the [`#[inline_sql]`][`inline_sql`] macro for more details.
//!
//! Currently, only [`tokio-postgres`][`tokio_postgres`] is supported as backend.
//!
//! # Example: Ignore the query output.
//! ```
//! use inline_sql::inline_sql;
//!
//! #[inline_sql]
//! async fn create_pets_table(
//! client: &tokio_postgres::Client
//! ) -> Result<(), tokio_postgres::Error> {
//! query! {
//! CREATE TABLE pets (
//! name TEXT PRIMARY KEY,
//! species TEXT NOT NULL
//! )
//! }
//! }
//! ```
//!
//! # Example: Return a [`Vec`] of rows.
//! ```
//! # #[derive(pg_mapper::TryFromRow)]
//! # struct Pet {
//! # name: String,
//! # species: String,
//! # }
//! use inline_sql::inline_sql;
//!
//! #[inline_sql]
//! async fn get_pets_by_species(
//! client: &tokio_postgres::Client,
//! species: &str,
//! ) -> Result<Vec<Pet>, tokio_postgres::Error> {
//! query!(SELECT * FROM pets WHERE species = #species)
//! }
//! ```
//!
//! # Example: Return an [`Option`].
//! ```
//! # #[derive(pg_mapper::TryFromRow)]
//! # struct Pet {
//! # name: String,
//! # species: String,
//! # }
//! use inline_sql::inline_sql;
//!
//! #[inline_sql]
//! async fn get_pet_by_name(
//! client: &tokio_postgres::Client,
//! name: &str,
//! ) -> Result<Option<Pet>, tokio_postgres::Error> {
//! query!(SELECT * FROM pets WHERE name = #name)
//! }
//! ```
//!
//! # Example: Return the number of affected rows.
//! ```
//! # #[derive(pg_mapper::TryFromRow)]
//! # struct Pet {
//! # name: String,
//! # species: String,
//! # }
//! use inline_sql::inline_sql;
//!
//! #[inline_sql]
//! async fn rename_species(
//! client: &tokio_postgres::Client,
//! old_species: &str,
//! new_species: &str,
//! ) -> Result<u64, tokio_postgres::Error> {
//! query!(UPDATE pets SET species = #new_species WHERE species = #old_species)
//! }
//! ```
//!
//! # Planned features:
//! * Support for more backends, including synchronous backends.
//! * Parsing the function arguments to determine the name of the `client` object.
//! * Support for queries that return exactly one row or an error.
//! * More attribute arguments to allow:
//! * Specifying the query type instead of deducing it from the return type.
//! * Changing how the `client` is obtained in the generated code (for example, from a member of `self`).
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
/// Mark a function that executes an SQL query.
///
/// The function body must follow the form
/// `query! { ... }` or `query!(...)`.
///
/// The return type of the function determines the behavior of the function.
/// There are a few options for the return type:
/// * [`Result`]`<(), E>`: Execute the query without returning anything. Errors are still reported.
/// * [`Result`]`<`[`u64`]`, E>`: Execute the query and return the number of affected rows.
/// * [`Result`]`<`[`Vec`]`<T>, E>`: Execute the query and return the rows as a vector.
/// * [`Result`]`<`[`Option`]`<T>, E>`: Execute the query and return a single optional row.
/// * [`Result`]`<`[`RowStream`][`tokio_postgres::RowStream`]`, E>`: Execute the query and return a [`RowStream`][`tokio_postgres::RowStream`].
///
/// The row type `T` must implement [`TryFrom<`][TryFrom][`tokio_postgres::Row`]`>`.
/// The [`TryFrom::Error`] type must implement [`Into<E>`].
///
/// The error type `E` must implement [`From<`][From][`tokio_postgres::Error`]>`.
///
/// For functions that return a `Result<Option<T>, E>`, an error is reported if the query returned more than one row.
///
/// You can generally not use a type alias in the return type of the function.
/// The proc macro can not resolve the alias, and will not know which variant to generate.
/// # Example 1: Ignore the query output.
/// ```
/// use inline_sql::inline_sql;
///
/// #[inline_sql]
/// async fn create_pets_table(
/// client: &tokio_postgres::Client
/// ) -> Result<(), tokio_postgres::Error> {
/// query! {
/// CREATE TABLE pets (
/// name TEXT PRIMARY KEY,
/// species TEXT NOT NULL
/// )
/// }
/// }
/// ```
///
/// # Example: Return a [`Vec`] of rows.
/// ```
/// use inline_sql::inline_sql;
///
/// # #[derive(pg_mapper::TryFromRow)]
/// # struct Pet {
/// # name: String,
/// # species: String,
/// # }
///
/// #[inline_sql]
/// async fn get_pets_by_species(
/// client: &tokio_postgres::Client,
/// species: &str,
/// ) -> Result<Vec<Pet>, tokio_postgres::Error> {
/// query!(SELECT * FROM pets WHERE species = #species)
/// }
/// ```
///
/// # Example: Return an [`Option`].
/// ```
/// use inline_sql::inline_sql;
///
/// # #[derive(pg_mapper::TryFromRow)]
/// # struct Pet {
/// # name: String,
/// # species: String,
/// # }
///
/// #[inline_sql]
/// async fn get_pet_by_name(
/// client: &tokio_postgres::Client,
/// name: &str,
/// ) -> Result<Option<Pet>, tokio_postgres::Error> {
/// query!(SELECT * FROM pets WHERE name = #name)
/// }
/// ```
///
/// # Example: Return the number of affected rows.
/// ```
/// use inline_sql::inline_sql;
///
/// # #[derive(pg_mapper::TryFromRow)]
/// # struct Pet {
/// # name: String,
/// # species: String,
/// # }
///
/// #[inline_sql]
/// async fn rename_species(
/// client: &tokio_postgres::Client,
/// old_species: &str,
/// new_species: &str,
/// ) -> Result<u64, tokio_postgres::Error> {
/// query!(UPDATE pets SET species = #new_species WHERE species = #old_species)
/// }
/// ```
pub use inline_sql_macros::inline_sql;
#[doc(hidden)]
pub mod macro_export__ {
pub mod prelude {
pub use futures::StreamExt;
}
}