postgres_query/lib.rs
1//! Helper macros and traits built around
2//! [tokio-postgres](https://docs.rs/tokio-postgres/0.5.1/tokio_postgres/index.html) to define
3//! queries with human readable parameters and return values.
4//!
5//! # Example
6//!
7//! ```
8//! # use tokio_postgres::Client;
9//! # use postgres_query::{query, FromSqlRow, Result};
10//! # fn connect() -> Client { unimplemented!() }
11//! # async fn foo() -> Result<()> {
12//! // Connect to the database
13//! let client: Client = connect(/* ... */);
14//!
15//! // Construct the query
16//! let query = query!(
17//! "SELECT age, name FROM people WHERE age >= $min_age",
18//! min_age = 18
19//! );
20//!
21//! // Define the structure of the data returned from the query
22//! #[derive(FromSqlRow)]
23//! struct Person {
24//! age: i32,
25//! name: String,
26//! }
27//!
28//! // Execute the query
29//! let people: Vec<Person> = query.fetch(&client).await?;
30//!
31//! for person in people {
32//! println!("{} is {} years young", person.name, person.age);
33//! }
34//! # Ok(())
35//! # }
36//! ```
37//!
38//! # Queries
39//!
40//! The preferred way of constructing a new [`Query`] is through the [`query!`] macro. It uses a
41//! syntax similar to the `format!(...)` family of macros from the standard library. The first
42//! parameter is the SQL query and is always given as a string literal (this might be relaxed in the
43//! future). This string literal may contain parameter bindings on the form `$ident` where `ident`
44//! is any valid Rust identifier (`$abc`, `$value_123`, etc.).
45//!
46//! ```
47//! # use postgres_query::query;
48//! let age = 42;
49//! let insert_person = query!(
50//! "INSERT INTO people VALUES ($age, $name)",
51//! name = "John Wick", // Binds "$name" to "John Wick"
52//! age, // Binds "$age" to the value of `age`
53//! );
54//! ```
55//!
56//! During compilation the query is converted into the format expected by PostgreSQL: parameter
57//! bindings are converted to using numbers ($1, $2, etc.) and the actual parameter values are put
58//! into a 1-indexed array. The code snippet above would be expanded into the following:
59//!
60//! ```
61//! # use postgres_query::*;
62//! let age = 42;
63//! let insert_person = Query::new_static(
64//! "INSERT INTO people VALUES ($1, $2)",
65//! vec![&age, &"John Wick"],
66//! );
67//! ```
68//!
69//!
70//! ## Dynamic Queries
71//!
72//! If necessary, queries may be constructed from `&str`s at runtime instead of the usual
73//! compile-time string literals expected by the `query!` macro. This is achieved by using the
74//! [`query_dyn!`] macro instead. In addition to dynamic queries, parameter bindings may also be
75//! dynamically:
76//!
77//! ```
78//! # use postgres_query::*;
79//! let mut sql = "SELECT * FROM people WHERE name = $name".to_string();
80//! let mut bindings = Vec::new();
81//!
82//! // Add a filter at runtime
83//! sql += " AND age > $min_age";
84//! bindings.push(("min_age", &42 as Parameter));
85//!
86//! let query: Result<Query> = query_dyn!(
87//! &sql,
88//! name = "John",
89//! ..bindings,
90//! );
91//! ```
92//!
93//! Using dynamic queries does introduce some errors that cannot be caught at runtime: such as some
94//! parameters in the query not having a matching binding. Because of this the value returned by the
95//! [`query_dyn!`] macro is not a `Query` but a `Result<Query>` which carries an error you must
96//! handle:
97//!
98//! ```
99//! # use postgres_query::*;
100//! let mut sql = "SELECT * FROM people".to_string();
101//! sql += " WHERE age <= $max_age AND name = $name";
102//!
103//! let query: Result<Query> = query_dyn!(
104//! &sql,
105//! name = "John",
106//! // Forgot to bind the parameter `max_age`.
107//! // Will result in an error.
108//! );
109//!
110//! assert!(query.is_err());
111//! ```
112//!
113//!
114//! # Data Extraction
115//!
116//! In addition to helping you define new queries this crate provides the [`FromSqlRow`] trait which
117//! makes it easy to extract typed values from the resulting rows. The easiest way to implement this
118//! trait for new `struct`s is to use the included [`derive(FromSqlRow)`] macro.
119//!
120//! - If used on a tuple struct, values will be extracted from the corresponding columns based on
121//! their position in the tuple.
122//! - If used on a stuct with named fields, values will be extracted from the column with the same
123//! name as the field.
124//!
125//! ```
126//! # use postgres_query::*;
127//! #[derive(FromSqlRow)]
128//! struct TupleData(i32, String);
129//!
130//! #[derive(FromSqlRow)]
131//! struct NamedData {
132//! age: i32,
133//! name: String,
134//! };
135//! ```
136//!
137//! ## Multi-mapping
138//!
139//! If you query the same table multiple times it gets tedious to have to redefine structs with the
140//! same fields over and over. Preferably we would like to reuse the same definition multiple times.
141//! We can do this be utilizing "multi-mapping".
142//!
143//!
144//! ### Partitions
145//!
146//! Multi-mapping works by splitting the columns of rows returned by a query into multiple
147//! partitions (or slices). For example, if we had the query `SELECT books.*, authors.* FROM ...`,
148//! we would like to extract the data into two structs: `Book` and `Author`. We accomplish this by
149//! looking at the columns returned by the database and splitting them into partitions:
150//!
151//! ```text
152//! Columns: id, title, release_date, genre, id, name, birthyear
153//! Partitions: +------------Book-------------+ +------Author-----+
154//! ```
155//!
156//!
157//! ### Partitioning schemes
158//!
159//! There are two supported ways to partition a row: either we specify the number of columns
160//! required to populate each struct (in the example above: 4 columns for Book and 3 for author), or
161//! we split on the name of a column. The former should generally only be used when you know the
162//! number of columns isn't going to change. The latter is less prone to break provided you choose
163//! an appropriate column to split on (a good candidate is usually `id` as almost all tables have
164//! this as their first
165//! column).
166//!
167//! You choose which partitioning scheme you want to use by using the provided
168//! [attributes](./derive.FromSqlRow.html#attributes). In order to accomplish the partitioning in
169//! the example above we could split on the column name `id`:
170//!
171//! ```
172//! # use postgres_query::FromSqlRow;
173//! #[derive(FromSqlRow)]
174//! struct Book {
175//! id: i32,
176//! title: String,
177//! release_date: String,
178//! genre: String,
179//! }
180//!
181//! #[derive(FromSqlRow)]
182//! struct Author {
183//! id: i32,
184//! name: String,
185//! birthyear: i32,
186//! }
187//!
188//! #[derive(FromSqlRow)]
189//! #[row(split)]
190//! struct BookAuthor {
191//! #[row(flatten, split = "id")]
192//! book: Book,
193//! #[row(flatten, split = "id")]
194//! author: Author,
195//! }
196//! ```
197//!
198//! Alternatively, we can make `Author` a part of the `Book` struct:
199//!
200//! ```
201//! # use postgres_query::FromSqlRow;
202//! #[derive(FromSqlRow)]
203//! struct Author {
204//! id: i32,
205//! name: String,
206//! birthyear: i32,
207//! }
208//!
209//! #[derive(FromSqlRow)]
210//! #[row(split)]
211//! struct Book {
212//! #[row(split = "id")]
213//! id: i32,
214//! title: String,
215//! release_date: String,
216//! genre: String,
217//!
218//! #[row(flatten, split = "id")]
219//! author: Author,
220//! }
221//! ```
222//!
223//! ### Many-to-one Relationships
224//!
225//! In the previous examples we had a `Book` that contained an `Author`. This is what is called a
226//! many-to-one relationship, since one book only has one author, but many books may share the same
227//! author (or so we assume anyway). What if you instead had `Author` an author that contained many
228//! `Book`s? We know that one author may write many books, so that is a one-to-many relationship. We
229//! can write an extractor for that case as well:
230//!
231//! ```
232//! # use postgres_query::*;
233//! # use tokio_postgres::Client;
234//! # async fn foo() -> Result<()> {
235//! # let client: Client = unimplemented!();
236//! #[derive(FromSqlRow)]
237//! #[row(split, group)]
238//! struct Author {
239//! #[row(split = "id", key)]
240//! id: i32,
241//! name: String,
242//! birthyear: i32,
243//!
244//! #[row(split = "id", merge)]
245//! books: Vec<Book>,
246//! }
247//!
248//! #[derive(FromSqlRow)]
249//! struct Book {
250//! id: i32,
251//! title: String,
252//! release_date: String,
253//! genre: String,
254//! }
255//!
256//! let authors: Vec<Author> = query!(
257//! "SELECT authors.*, books.*
258//! INNER JOIN books ON books.author = authors.id
259//! GROUP BY authors.id"
260//! )
261//! .fetch(&client)
262//! .await?;
263//! # Ok(())
264//! # }
265//! ```
266//!
267//! See the section on [attributes](./derive.FromSqlRow.html#attributes) for a more advanced
268//! in-depth explanation of multi-mapping.
269//!
270//!
271//! # Caching queries
272//!
273//! From time to time you probably want to execute the same query multiple times, but with different
274//! parameters. In times like these we can decrease the load on the database by preparing our
275//! queries before executing them. By wrapping a client in a [`Caching`] struct this behaviour is
276//! automatically provided for all queries that originate from this crate:
277//!
278//! ```
279//! # use tokio_postgres::Client;
280//! # use postgres_query::{query, Result, Caching};
281//! # fn connect() -> Client { unimplemented!() }
282//! # async fn foo() -> Result<()> {
283//! // Connect to the database
284//! let client: Client = connect(/* ... */);
285//!
286//! // Wrap the client in a query cache
287//! let cached_client = Caching::new(client);
288//!
289//! for age in 0..100i32 {
290//! let query = query!("SELECT name, weight FROM people WHERE age = $age", age);
291//!
292//! // The query is prepared and cached the first time it's executed.
293//! // All subsequent fetches will use the cached Statement.
294//! let people: Vec<(String, i32)> = query.fetch(&cached_client).await?;
295//!
296//! /* Do something with people */
297//! }
298//! # Ok(())
299//! # }
300//! ```
301//!
302//! [`Query`]: struct.Query.html
303//! [`query!`]: macro.query.html
304//! [`query_dyn!`]: macro.query_dyn.html
305//! [`FromSqlRow`]: extract/trait.FromSqlRow.html
306//! [`derive(FromSqlRow)`]: derive.FromSqlRow.html
307//! [`Caching`]: client/struct.Caching.html
308
309pub mod client;
310pub mod execute;
311pub mod extract;
312
313mod error;
314mod parse;
315
316use postgres_types::ToSql;
317use proc_macro_hack::proc_macro_hack;
318use std::ops::Deref;
319
320pub use crate::client::Caching;
321pub use crate::error::{Error, Result};
322pub use crate::extract::FromSqlRow;
323
324/// Extract values from a row.
325///
326/// - If used on a tuple struct, values will be extracted from the corresponding columns based on
327/// their position in the tuple.
328/// - If used on a stuct with named fields, values will be extracted from the column with the same
329/// name as the field.
330///
331/// # Example
332///
333/// ```
334/// # use postgres_query::*;
335/// #[derive(FromSqlRow)]
336/// struct TupleData(i32, String);
337///
338/// #[derive(FromSqlRow)]
339/// struct NamedData {
340/// age: i32,
341/// name: String,
342/// };
343/// ```
344///
345///
346/// # Attributes
347///
348/// Data extraction can be customized by using the `#[row(...)]` attribute. Attributes can be
349/// separated into two categories, those which go on the container itself:
350///
351/// - [`#[row(exact)]`](#rowexact)
352/// - [`#[row(split)]`](#rowsplit)
353/// - [`#[row(group)]`](#rowgroup)
354/// - [`#[row(hash)]`](#rowhash)
355///
356/// and those which are placed on the container's fields:
357///
358/// - [`#[row(rename = "...")]`](#rowrename--)
359/// - [`#[row(flatten)]`](#rowflatten)
360/// - [`#[row(stride = N)]`](#rowstride--n)
361/// - [`#[row(split = "...")]`](#rowsplit--)
362/// - [`#[row(key)]`](#rowkey)
363/// - [`#[row(merge)]`](#rowmerge)
364///
365///
366/// ## Container attributes
367///
368/// These attributes are put on the struct itself.
369///
370///
371/// ### `#[row(exact)]`
372///
373/// [Partition](./index.html#multi-mapping) the row according to the number of columns matched by
374/// each group.
375///
376/// Note that no order is forced upon fields within any group. In the example below, that means that
377/// even though the `generation` and `origin` fields are flipped relative to the query, the
378/// extraction will be successful:
379///
380/// ```
381/// # use postgres_query::{FromSqlRow, Result, query};
382/// # use tokio_postgres::Client;
383/// # async fn foo() -> Result<()> {
384/// # let client: Client = unimplemented!();
385/// #[derive(FromSqlRow)]
386/// #[row(exact)]
387/// struct Family {
388/// generation: i32,
389/// origin: String,
390/// #[row(flatten)]
391/// parent: Person,
392/// #[row(flatten)]
393/// child: Person,
394/// }
395///
396/// #[derive(FromSqlRow)]
397/// struct Person {
398/// id: i32,
399/// name: String,
400/// }
401///
402/// let family = query!(
403/// "SELECT
404/// 'Germany' as origin, 7 as generation,
405/// 1 as id, 'Bob' as name,
406/// 2 as id, 'Ike' as name"
407/// )
408/// .fetch_one::<Family, _>(&client)
409/// .await?;
410/// # Ok(())
411/// # }
412/// ```
413///
414/// ### `#[row(split)]`
415///
416/// [Partition](./index.html#multi-mapping) the row according to the field's [split
417/// points](extract/fn.split_columns_many.html#split-points).
418///
419/// Split points are introduced by using the [`#[row(split = "...")]`](#rowsplit---1) attribute on
420/// fields.
421///
422/// ```
423/// # use postgres_query::{FromSqlRow, Result, query};
424/// # use tokio_postgres::Client;
425/// # async fn foo() -> Result<()> {
426/// # let client: Client = unimplemented!();
427/// #[derive(FromSqlRow)]
428/// #[row(split)]
429/// struct Family {
430/// generation: i32,
431/// origin: String,
432/// #[row(flatten, split = "id")]
433/// parent: Person,
434/// #[row(flatten, split = "id")]
435/// child: Person,
436/// }
437///
438/// #[derive(FromSqlRow)]
439/// struct Person {
440/// id: i32,
441/// name: String,
442/// }
443///
444/// let family = query!(
445/// "SELECT
446/// 'Germany' as origin, 7 as generation,
447/// 1 as id, 'Bob' as name,
448/// 2 as id, 'Ike' as name"
449/// )
450/// .fetch_one::<Family, _>(&client)
451/// .await?;
452/// # Ok(())
453/// # }
454/// ```
455///
456///
457/// ### `#[row(group)]`
458///
459/// Enables one-to-many mapping for the container. One-to-many mapping requires that at least one
460/// field has the `#[row(key)]` attribute and that one other field has the `#[row(merge)]` attribute.
461///
462/// When extracting values from multiple rows, any two **adjacent** rows that are identical on their
463/// fields marked with `#[row(key)]` will have their fields tagged with `#[row(merge)]` merged. This
464/// means that in order to get the expected relation back, you may need to include a `GROUP BY`
465/// statement in your SQL query, hence the name `group`.
466///
467/// ```
468/// # use postgres_query::*;
469/// # use tokio_postgres::Client;
470/// # async fn foo() -> Result<()> {
471/// # let client: Client = unimplemented!();
472/// #[derive(Debug, FromSqlRow)]
473/// #[row(group)]
474/// struct Author {
475/// #[row(key)]
476/// name: String,
477///
478/// #[row(merge)]
479/// books: Vec<Book>,
480/// }
481///
482/// #[derive(Debug, FromSqlRow)]
483/// struct Book {
484/// title: String,
485/// }
486///
487/// let authors = query!(
488/// "SELECT 'J.R.R. Tolkien' as name, 'The Fellowship of the Ring' as title
489/// UNION ALL SELECT 'J.R.R. Tolkien', 'The Two Towers'
490/// UNION ALL SELECT 'Andrzej Sapkowski', 'The Last Wish'
491/// UNION ALL SELECT 'J.R.R. Tolkien', 'Return of the King'")
492/// .fetch::<Author, _>(&client)
493/// .await?;
494///
495/// assert_eq!(authors[0].name, "J.R.R. Tolkien");
496/// assert_eq!(authors[0].books[0].title, "The Fellowship of the Ring");
497/// assert_eq!(authors[0].books[1].title, "The Two Towers");
498///
499/// assert_eq!(authors[1].name, "Andrzej Sapkowski");
500/// assert_eq!(authors[1].books[0].title, "The Last Wish");
501///
502/// assert_eq!(authors[2].name, "J.R.R. Tolkien");
503/// assert_eq!(authors[2].books[0].title, "Return of the King");
504/// # Ok(())
505/// # }
506/// ```
507///
508///
509/// ### `#[row(hash)]`
510///
511/// Like `#[row(group)]`, but all previous rows are considered when merging. This is accomplished by
512/// using a `HashMap`, hence the name. This implies that all keys have to implement the `Hash` and
513/// `Eq` traits:
514///
515/// ```
516/// # use postgres_query::*;
517/// # use tokio_postgres::Client;
518/// # async fn foo() -> Result<()> {
519/// # let client: Client = unimplemented!();
520/// #[derive(Debug, FromSqlRow)]
521/// #[row(hash)]
522/// struct Author {
523/// #[row(key)]
524/// name: String,
525///
526/// #[row(merge)]
527/// books: Vec<Book>,
528/// }
529///
530/// #[derive(Debug, FromSqlRow)]
531/// struct Book {
532/// title: String,
533/// }
534///
535/// let authors = query!(
536/// "SELECT 'J.R.R. Tolkien' as name, 'The Fellowship of the Ring' as title
537/// UNION ALL SELECT 'J.R.R. Tolkien', 'The Two Towers'
538/// UNION ALL SELECT 'Andrzej Sapkowski', 'The Last Wish'
539/// UNION ALL SELECT 'J.R.R. Tolkien', 'Return of the King'")
540/// .fetch::<Author, _>(&client)
541/// .await?;
542///
543/// assert_eq!(authors[0].name, "J.R.R. Tolkien");
544/// assert_eq!(authors[0].books[0].title, "The Fellowship of the Ring");
545/// assert_eq!(authors[0].books[1].title, "The Two Towers");
546/// assert_eq!(authors[0].books[2].title, "Return of the King");
547///
548/// assert_eq!(authors[1].name, "Andrzej Sapkowski");
549/// assert_eq!(authors[1].books[0].title, "The Last Wish");
550/// # Ok(())
551/// # }
552/// ```
553///
554/// ## Field attributes
555///
556/// These attributes are put on the fields of a container.
557///
558///
559/// ### `#[row(rename = "...")]`
560///
561/// Use a name other than that of the field when looking up the name of the column.
562///
563/// ```
564/// # use postgres_query::FromSqlRow;
565/// #[derive(FromSqlRow)]
566/// struct Person {
567/// age: i32,
568/// // matches the column named "first_name" instead of "name"
569/// #[row(rename = "first_name")]
570/// name: String,
571/// }
572/// ```
573///
574/// ### `#[row(flatten)]`
575///
576/// Flatten the contents of this field into its container by recursively calling `FromSqlRow` on the
577/// field's type. This removes one level of nesting:
578///
579/// ```
580/// # use postgres_query::{FromSqlRow, query, Result};
581/// # use tokio_postgres::Client;
582/// # async fn foo() -> Result<()> {
583/// # let client: Client = unimplemented!();
584/// #[derive(FromSqlRow)]
585/// struct Customer {
586/// id: i32,
587/// #[row(flatten)]
588/// info: Person,
589/// }
590///
591/// #[derive(FromSqlRow)]
592/// struct Person {
593/// name: String,
594/// age: i32
595/// }
596///
597/// let customer: Customer = query!("SELECT 14 as id, 'Bob' as name, 47 as age")
598/// .fetch_one(&client)
599/// .await?;
600///
601/// assert_eq!(customer.id, 14);
602/// assert_eq!(customer.info.name, "Bob");
603/// assert_eq!(customer.info.age, 47);
604/// # Ok(())
605/// # }
606/// ```
607///
608/// ### `#[row(stride = N)]`
609///
610/// Puts this field into a partition with exactly `N` columns. Only available when using the
611/// `#[row(exact)]` attribute on the container,
612///
613/// ```
614/// # use postgres_query::{FromSqlRow, query, Result};
615/// # use tokio_postgres::Client;
616/// # async fn foo() -> Result<()> {
617/// # let client: Client = unimplemented!();
618/// #[derive(Debug, FromSqlRow)]
619/// struct Person {
620/// id: i32,
621/// name: String,
622/// }
623///
624/// #[derive(Debug, FromSqlRow)]
625/// #[row(exact)]
626/// struct Family {
627/// // Matches first 4 columns
628/// #[row(flatten, stride = 4)]
629/// parent: Person,
630/// // Matches last 3 columns
631/// #[row(flatten, stride = 3)]
632/// child: Person,
633/// }
634///
635/// let family = query!(
636/// "SELECT
637/// 11 as generation,
638/// 1 as id, 'Bob' as name, 42 as age,
639/// 2 as id, 'Ike' as name, 14 as age"
640/// )
641/// .fetch_one::<Family, _>(&client)
642/// .await?;
643///
644/// assert_eq!(family.parent.id, 1);
645/// assert_eq!(family.parent.name, "Bob");
646/// assert_eq!(family.child.id, 2);
647/// assert_eq!(family.child.name, "Ike");
648/// # Ok(())
649/// # }
650/// ```
651///
652/// ### `#[row(split = "...")]`
653///
654/// Introduce an additional [split](extract/fn.split_columns_many.html#split-points) right
655/// before this field. Requires that the container has the `split` attribute as well.
656///
657/// Intuitively this splits the row in two parts: every field before this attribute matches the
658/// columns before the split and every field afterwards matches the second remaining columns.
659///
660/// ```
661/// # use postgres_query::{FromSqlRow};
662/// #[derive(FromSqlRow)]
663/// #[row(split)]
664/// struct User {
665/// // `id` and `name` will only match the columns before `email`
666/// id: i32,
667/// name: String,
668/// #[row(split = "email")]
669/// // `email`, `address` and `shoe_size` will only
670/// // match the columns after and including `email`
671/// email: String,
672/// address: String,
673/// shoe_size: i32,
674/// }
675/// ```
676///
677/// Note that the first split always matches first occurence of that column. This can result in some
678/// subtle bugs:
679///
680/// ```
681/// # use postgres_query::{FromSqlRow, query};
682/// #[derive(FromSqlRow)]
683/// #[row(split)]
684/// struct Family {
685/// #[row(flatten)]
686/// parent: Person,
687/// #[row(flatten, split = "id")]
688/// child: Person,
689/// }
690///
691/// #[derive(FromSqlRow)]
692/// struct Person {
693/// name: String,
694/// age: i32
695/// }
696///
697/// let query = query!("SELECT parent.*, child.* FROM ...");
698///
699/// // Imagine the query above results in the following columns:
700/// //
701/// // Columns: id, name, id, name
702/// // Splits: |
703/// // Partitions: +-parent-+ +-----child------+
704/// ```
705///
706/// The split causes `parent` to match against all columns before the first `id`, ie. an empty
707/// partition. This would cause an error when executing the query.
708///
709/// A correct split would look like this:
710///
711/// ```
712/// # use postgres_query::{FromSqlRow, query};
713/// # #[derive(FromSqlRow)] struct Person;
714/// #[derive(FromSqlRow)]
715/// #[row(split)]
716/// struct Family {
717/// #[row(flatten, split = "id")]
718/// parent: Person,
719/// #[row(flatten, split = "id")]
720/// child: Person,
721/// }
722/// ```
723///
724///
725/// ### `#[row(key)]`
726///
727/// Specifies this field to be a `key` field. `key` fields are compared against each other when
728/// extracting values from multiple rows. Rows are merged if the key fields in each row are
729/// identical. You may have multiple `key` fields within a single container, but none of them may
730/// have the `#[row(merge)]` attribute. Multiple `key` fields will be treated as a tuple in
731/// comparisons.
732///
733///
734/// ### `#[row(merge)]`
735///
736/// Specifies this field to be a `merge` field. This requires that the field's type implements the
737/// [`Merge`] trait. When two rows have been deemed to be equal based on the `key` fields, the
738/// corresponding `merge` fields in those rows will be merged. You may specify multiple `merge`
739/// fields within one container, but none of them may have the `#[row(key)]` attribute.
740///
741/// [`Merge`]: extract/trait.Merge.html
742pub use postgres_query_macro::FromSqlRow;
743
744/// Constructs a new query at compile-time. See also `query_dyn!`.
745///
746/// # Usage
747///
748/// This macro expands to an expression with the type `Query`.
749///
750/// The first parameter is the SQL query and is always given as a string literal. This string
751/// literal may contain parameter bindings on the form `$ident` where `ident` is any valid Rust
752/// identifier (`$abc`, `$value_123`, etc.). The order of the parameters does not matter.
753///
754/// ```
755/// # use postgres_query::query;
756/// let age = 42;
757/// let insert_person = query!(
758/// "INSERT INTO people VALUES ($age, $name)",
759/// name = "John Wick", // Binds "$name" to "John Wick"
760/// age, // Binds "$age" to the value of `age`
761/// );
762/// ```
763///
764/// During compilation the query is converted into the format expected by PostgreSQL: parameter
765/// bindings are converted to using numbers (`$1`, `$2`, etc.) and the actual parameter values are
766/// put into a 1-indexed array. The code snippet above would be expanded into the following:
767///
768/// ```
769/// # use postgres_query::*;
770/// let age = 42;
771/// let insert_person = Query::new_static(
772/// "INSERT INTO people VALUES ($1, $2)",
773/// vec![&age, &"John Wick"],
774/// );
775/// ```
776#[macro_export]
777macro_rules! query {
778 ($($tt:tt)*) => {
779 $crate::__query_static!($($tt)*)
780 };
781}
782
783/// Constructs a new query dynamically at runtime. See also `query!`.
784///
785/// # Usage
786///
787/// This macro expands to an expression with the type `Result<Query>`.
788///
789/// The first parameter is the SQL query and is always given as a `&str`. This string may contain
790/// parameter bindings on the form `$ident` where `ident` is any valid Rust identifier (`$abc`,
791/// `$value_123`, etc.). The order of the parameters does not matter.
792///
793/// ```
794/// # use postgres_query::{query_dyn, Result};
795/// # fn foo() -> Result<()> {
796/// // We can construct the actual query at runtime
797/// let mut sql = "INSERT INTO people VALUES".to_owned();
798/// sql.push_str("($age, $name)");
799///
800/// let age = 42;
801///
802/// let insert_person = query_dyn!(
803/// &sql,
804/// name = "John Wick", // Binds "$name" to "John Wick"
805/// age, // Binds "$age" to the value of `age`
806/// )?;
807/// # Ok(())
808/// # }
809/// ```
810///
811/// The query and all the parameters are passed into `Query::parse`, so the above would be expanded
812/// into:
813///
814/// ```
815/// # use postgres_query::Query;
816/// // We can construct the actual query at runtime
817/// let mut sql = "INSERT INTO people VALUES".to_string();
818/// sql.push_str("($age, $name)");
819///
820/// let age = 42;
821///
822/// let insert_person = Query::parse(
823/// &sql,
824/// &[("name", &"John Wick"), ("age", &age)],
825/// );
826/// ```
827///
828///
829/// ## Dynamic Binding
830///
831/// Optionally, you may also choose to include additional bindings at runtime by using the
832/// `..bindings` syntax. This is supported for any type that implements `IntoIterator<Item = (&str,
833/// Parameter)>`, ie. `Vec<(&str, Parameter)>`, `HashMap<&str, Parameter>`, `Option<(&str,
834/// Parameter)>`, iterators, and so on.
835///
836/// Dynamic bindings may be mixed with static bindings:
837///
838/// ```
839/// # use postgres_query::{query_dyn, Parameter, Result};
840/// # fn foo() -> Result<()> {
841/// let mut bindings = Vec::new();
842///
843/// // We use the `as Parameter` to please the type checker.
844/// // Alternatively, we could specify the type for bindings: `Vec<(&str, Parameter)>`.
845/// bindings.push(("age", &42 as Parameter));
846/// bindings.push(("name", &"John Wick" as Parameter));
847///
848/// let sql = "INSERT INTO people VALUES ($age, $name, $height)".to_string();
849/// let insert_person = query_dyn!(
850/// &sql,
851/// height = 192,
852/// ..bindings,
853/// )?;
854/// # Ok(())
855/// # }
856/// ```
857///
858///
859/// # A larger example
860///
861/// Let's say that we wanted to dynamically add filters to our query:
862///
863/// ```
864/// # use postgres_query::{query_dyn, Parameter, Query, Result};
865/// # fn foo() -> Result<()> {
866/// // We have the query we want to execute
867/// let mut sql = "SELECT * FROM people".to_string();
868///
869/// // and some filters we got from the user.
870/// let age_filter: Option<i32> = Some(32);
871/// let name_filter: Option<&str> = None;
872///
873/// // Then we dynamically build a list of filters and bindings to use:
874/// let mut filters = Vec::new();
875/// let mut bindings = Vec::new();
876///
877/// // We add the filters as needed.
878/// if let Some(age) = age_filter.as_ref() {
879/// filters.push("age > $min_age");
880/// bindings.push(("min_age", age as Parameter));
881/// }
882///
883/// if let Some(name) = name_filter.as_ref() {
884/// filters.push("name LIKE $name");
885/// bindings.push(("name", name as Parameter));
886/// }
887///
888/// // And add them to the query.
889/// if filters.len() > 0 {
890/// sql += &format!(" WHERE {}", filters.join(" AND "));
891/// }
892///
893/// // Then we can use it as normal.
894/// let query: Query = query_dyn!(&sql, ..bindings)?;
895/// # Ok(())
896/// # }
897/// ```
898#[macro_export]
899macro_rules! query_dyn {
900 ($($tt:tt)*) => {
901 $crate::__query_dynamic!($($tt)*)
902 };
903}
904
905#[proc_macro_hack]
906#[doc(hidden)]
907pub use postgres_query_macro::{query_dynamic as __query_dynamic, query_static as __query_static};
908
909/// A shorthand for types that can be treated as SQL parameters.
910///
911/// A common use case for this type alias is when using dynamic bindings and you have to please the
912/// type checker:
913///
914/// ```
915/// # use postgres_query::{Parameter, query_dyn, Result};
916/// # fn foo() -> Result<()> {
917/// let mut bindings = Vec::new();
918///
919/// // Without the `as Parameter` the compiler assumes the type to be `&i32`.
920/// bindings.push(("age", &32 as Parameter));
921///
922/// // Which would cause problems when adding something that is not an integer.
923/// bindings.push(("name", &"John" as Parameter));
924///
925/// let query = query_dyn!(
926/// "SELECT * FROM people WHERE age > $age AND name = $name",
927/// ..bindings
928/// )?;
929/// # Ok(())
930/// # }
931/// ```
932///
933/// Alternatively we could just set the type on the container explicitly:
934///
935/// ```
936/// # use postgres_query::Parameter;
937/// let mut bindings: Vec<(&str, Parameter)> = Vec::new();
938/// ```
939pub type Parameter<'a> = &'a (dyn ToSql + Sync);
940
941/// A static query with dynamic parameters.
942///
943/// # Usage
944///
945/// ## Constructing
946///
947/// The preferred way of constructing a [`Query`] is by using the [`query!`] and [`query_dyn!`]
948/// macros.
949///
950/// You may also use the `Query::parse`, `Query::new_static` or `Query::new` methods.
951///
952///
953/// ## Executing
954///
955/// When executing the query you have two options, either:
956///
957/// 1. use the provided methods: `execute`, `fetch`, `query`, etc.
958/// 2. use the `sql` and `parameters` fields as arguments to the standard [`Client`] methods
959///
960/// ```
961/// # use tokio_postgres::{Client, Row};
962/// # use postgres_query::{query, FromSqlRow, Result};
963/// # fn connect() -> Client { unimplemented!() }
964/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
965/// #[derive(FromSqlRow)]
966/// struct Person {
967/// age: i32,
968/// name: String,
969/// }
970///
971/// let client: Client = connect(/* ... */);
972/// let query = query!("SELECT age, name FROM people");
973///
974/// // Option 1
975/// let people: Vec<Person> = query.fetch(&client).await?;
976///
977/// // Option 2
978/// let rows: Vec<Row> = client.query(query.sql(), query.parameters()).await?;
979/// let people: Vec<Person> = Person::from_row_multi(&rows)?;
980/// # Ok(())
981/// # }
982/// ```
983///
984/// [`Query`]: struct.Query.html
985/// [`query!`]: macro.query.html
986/// [`query_dyn!`]: macro.query_dyn.html
987/// [`Client`]: https://docs.rs/tokio-postgres/0.5.1/tokio_postgres/struct.Client.html
988#[derive(Debug, Clone)]
989pub struct Query<'a> {
990 sql: Sql,
991 parameters: Vec<Parameter<'a>>,
992}
993
994#[derive(Debug, Clone)]
995enum Sql {
996 Static(&'static str),
997 Dynamic(String),
998}
999
1000impl<'a> Query<'a> {
1001 /// Create a new query an already prepared string.
1002 ///
1003 /// IMPORTANT: This does not allow you to pass named parameter bindings (`$name`, `$abc_123`,
1004 /// etc.). For that behaviour, refer to the `query!` macro. Instead bindings and parameters are
1005 /// given in the same format required by `tokio_postgres` (`$1`, `$2`, ...).
1006 pub fn new(sql: String, parameters: Vec<Parameter<'a>>) -> Query<'a> {
1007 Query {
1008 sql: Sql::Dynamic(sql),
1009 parameters,
1010 }
1011 }
1012
1013 /// Create a new query with a static query string.
1014 ///
1015 /// IMPORTANT: This does not allow you to pass named parameter bindings (`$name`, `$abc_123`,
1016 /// etc.), For that behaviour, refer to the `query_dyn!` macro. Instead bindings and parameters
1017 /// are given in the same format required by `tokio_postgres` (`$1`, `$2`, ...).
1018 pub fn new_static(sql: &'static str, parameters: Vec<Parameter<'a>>) -> Query<'a> {
1019 Query {
1020 sql: Sql::Static(sql),
1021 parameters,
1022 }
1023 }
1024
1025 /// Parses a string that may contain parameter bindings on the form `$abc_123`. This is the same
1026 /// function that is called when passing dynamically generated strings to the `query_dyn!`
1027 /// macro.
1028 ///
1029 /// Because this is a function there will some runtime overhead unlike the `query!` macro which
1030 /// has zero overhead when working with string literals.
1031 pub fn parse(text: &str, bindings: &[(&str, Parameter<'a>)]) -> Result<Query<'a>> {
1032 let (sql, parameters) = parse::parse(text, bindings)?;
1033
1034 Ok(Query {
1035 sql: Sql::Dynamic(sql),
1036 parameters,
1037 })
1038 }
1039
1040 /// Get this query as an SQL string.
1041 pub fn sql(&'a self) -> &'a str {
1042 &self.sql
1043 }
1044
1045 /// Get the parameters of this query in the order expected by the query returned by
1046 /// `Query::sql`.
1047 pub fn parameters(&'a self) -> &[Parameter<'a>] {
1048 &self.parameters
1049 }
1050}
1051
1052impl Deref for Sql {
1053 type Target = str;
1054
1055 fn deref(&self) -> &Self::Target {
1056 match self {
1057 Sql::Static(text) => text,
1058 Sql::Dynamic(text) => &text,
1059 }
1060 }
1061}
1062
1063#[cfg(test)]
1064mod tests {
1065 use super::*;
1066 use crate::error::ParseError;
1067
1068 macro_rules! is_match {
1069 ($expr:expr, $pattern:pat) => {
1070 match $expr {
1071 $pattern => true,
1072 _ => false,
1073 }
1074 };
1075 }
1076
1077 #[test]
1078 fn parse_query_without_bindings() {
1079 let query = Query::parse("SELECT 123, 'abc'", &[]).unwrap();
1080 assert_eq!(query.sql(), "SELECT 123, 'abc'");
1081 }
1082
1083 #[test]
1084 fn parse_query_single_binding() {
1085 let query = Query::parse("SELECT $number", &[("number", &123)]).unwrap();
1086 assert_eq!(query.sql(), "SELECT $1");
1087 }
1088
1089 #[test]
1090 fn parse_query_missing_identifier_eof() {
1091 let query = Query::parse("SELECT $", &[]);
1092 assert!(is_match!(
1093 query.unwrap_err(),
1094 Error::Parse(ParseError::EmptyIdentifier { found: None })
1095 ));
1096 }
1097
1098 #[test]
1099 fn parse_query_missing_identifier() {
1100 let query = Query::parse("SELECT $ FROM users", &[]);
1101 assert!(is_match!(
1102 query.unwrap_err(),
1103 Error::Parse(ParseError::EmptyIdentifier { found: Some(' ') })
1104 ));
1105 }
1106}