include_postgres_sql/
sync.rs

1/**
2Generates Rust code to use included SQL.
3
4This macro defines a trait with methods to access data and implements it for `postgres::Client` and `postgres::Transaction`.
5
6This macro recognizes and generates 5 variants of database access methods using the following selectors:
7* `?` - methods that process rows retrieved by `SELECT`,
8* `^` - methods that return raw rows retrieved by `SELECT`,
9* `%` - methods that return vector of structs (a struct per returned row)
10* `!` - methods that execute all other non-`SELECT` methods, and
11* `->` - methods that execute `RETURNING` statements and provide access to returned data.
12
13For `SELECT` statements (`?`) like:
14
15```sql
16-- name: get_loaned_books?
17-- param: user_id: &str
18SELECT book_title FROM library WHERE loaned_to = :user_id
19```
20
21The method with the following signature is generated:
22
23```rust , ignore
24fn get_loaned_books<F>(&self, user_id: &str, row_callback: F) -> Result<(),postgres::Error>
25where F: FnMut(postgres::Row) -> Result<(),postgres::Error>;
26```
27
28For `SELECT` statements (`^`):
29
30```sql
31-- name: get_loaned_books^
32-- param: user_id: &str
33SELECT book_title FROM library WHERE loaned_to = :user_id
34```
35
36The method with the following signature is generated:
37
38```rust , ignore
39fn get_loaned_books<'a>(&'a self, user_id: &str) -> Result<postgres::RowIter<'a>,postgres::Error>;
40```
41
42For `SELECT` statements (`%`):
43
44```sql
45-- name: get_loaned_books%
46-- param: user_id: &str
47SELECT book_title FROM library WHERE loaned_to = :user_id
48```
49
50The method with the following signature is generated:
51
52```rust , ignore
53fn get_loaned_books<R>(&self, user_id: &str) -> Result<Vec<R>,postgres::Error>
54where R: TryFrom<postres::Row>, postgres::Error: From<R::Error>;
55```
56
57For non-select statements (`!`) - INSERT, UPDATE, DELETE, etc. - like:
58
59```sql
60-- name: loan_books!
61-- param: user_id: &str
62-- param: book_ids: i32
63UPDATE library
64   SET loaned_to = :user_id
65     , loaned_on = current_timestamp
66 WHERE book_id IN (:book_ids)
67```
68
69The method with the following signature is generated:
70
71```rust , ignore
72fn loan_books(&self, user_id: &str, book_ids: &[i32]) -> Result<u64,postgres::Error>;
73```
74
75For DELETE, INSERT, and UPDATE statements that return data via `RETURNING` clause (`->`) like:
76
77```sql
78-- name: add_new_book->
79-- param: isbn: &str
80-- param: book_title: &str
81INSERT INTO library (isbn, book_title)
82VALUES (:isbn, :book_title)
83RETURNING book_id
84```
85
86The method with the following signature is generated:
87
88```rust , ignore
89fn add_new_book(&self, isbn: &str, book_title: &str) -> Result<postgres::Row,postgres::Error>;
90```
91
92### Tokio-Postgres
93
94**Note** that when **include-postgres-sql** is used with the `tokio` feature, the generated methods will be `async`.
95*/
96#[macro_export]
97macro_rules! impl_sql {
98    ( $sql_name:ident = $( { $kind:tt $name:ident ($($variant:tt $param:ident $ptype:tt)*) $doc:literal $s:tt $( $text:tt )+ } ),+ ) => {
99        trait $sql_name {
100            $( $crate::decl_method!{ $kind $name $doc () () $($param $variant $ptype)* } )+
101        }
102        impl $sql_name for ::postgres::Client {
103            $( $crate::impl_method!{ $kind $name () () ($($param $variant $ptype)*) => ($($variant $param)*) $($text)+ } )+
104        }
105        impl $sql_name for ::postgres::Transaction<'_> {
106            $( $crate::impl_method!{ $kind $name () () ($($param $variant $ptype)*) => ($($variant $param)*) $($text)+ } )+
107        }
108    };
109}
110
111#[macro_export]
112#[doc(hidden)]
113macro_rules! decl_method {
114    ( ? $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
115        #[doc=$doc]
116        fn $name<$($gen_type : ::postgres::types::ToSql ,)* F>(&mut self $($fn_params)* , row_cb: F) -> ::std::result::Result<(),::postgres::Error>
117        where F: FnMut(::postgres::Row) -> ::std::result::Result<(),::postgres::Error>;
118    };
119    ( ^ $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
120        #[doc=$doc]
121        fn $name<'a $(, $gen_type : ::postgres::types::ToSql)*>(&'a mut self $($fn_params)*) -> ::std::result::Result<::postgres::RowIter<'a>,::postgres::Error>;
122    };
123    ( % $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
124        #[doc=$doc]
125        fn $name<$($gen_type : ::postgres::types::ToSql ,)* R>(&mut self $($fn_params)*) -> ::std::result::Result<::std::vec::Vec<R>,::postgres::Error>
126        where R: ::std::convert::TryFrom<::postgres::Row>, ::postgres::Error: ::std::convert::From<R::Error>;
127    };
128    ( ! $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
129        #[doc=$doc]
130        fn $name<$($gen_type : ::postgres::types::ToSql),*>(&mut self $($fn_params)*) -> ::std::result::Result<u64,::postgres::Error>;
131    };
132    ( -> $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
133        #[doc=$doc]
134        fn $name<$($gen_type : ::postgres::types::ToSql),*>(&mut self $($fn_params)*) -> ::std::result::Result<::postgres::Row,::postgres::Error>;
135    };
136    ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident : _ $($tail:tt)* ) => {
137        $crate::decl_method!{
138            $kind
139            $name
140            $doc
141            ($($gen_type)*)
142            ($($fn_params)* , $param : impl ::postgres::types::ToSql + Sync)
143            $($tail)*
144        }
145    };
146    ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident : ($ptype:ty) $($tail:tt)* ) => {
147        $crate::decl_method!{
148            $kind
149            $name
150            $doc
151            ($($gen_type)*)
152            ($($fn_params)* , $param : $ptype)
153            $($tail)*
154        }
155    };
156    ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident # [$gtype:ident] $($tail:tt)* ) => {
157        $crate::decl_method!{
158            $kind
159            $name
160            $doc
161            ($($gen_type)* $gtype)
162            ($($fn_params)* , $param : & [ $gtype ] )
163            $($tail)*
164        }
165    };
166    ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident # ($ptype:ty) $($tail:tt)* ) => {
167        $crate::decl_method!{
168            $kind
169            $name
170            $doc
171            ($($gen_type)*)
172            ($($fn_params)* , $param : & [ $ptype ] )
173            $($tail)*
174        }
175    };
176}
177
178#[macro_export]
179#[doc(hidden)]
180macro_rules! impl_method {
181    ( ? $name:ident () () () => () $text:literal ) => {
182        fn $name<F>(&mut self, mut row_cb: F) -> ::std::result::Result<(),::postgres::Error>
183        where F: FnMut(::postgres::Row) -> ::std::result::Result<(),::postgres::Error>
184        {
185            use ::postgres::fallible_iterator::FallibleIterator;
186
187            let mut rows = self.query_raw( $text, [] as [&dyn ::postgres::types::ToSql; 0] )?;
188            while let Some(row) = rows.next()? {
189                row_cb(row)?;
190            }
191            Ok(())
192        }
193    };
194    ( ? $name:ident () ($($fn_params:tt)+) () => (: $head:ident $(: $tail:ident)*) $($text:tt)+) => {
195        fn $name<F>(&mut self $($fn_params)+ , mut row_cb: F) -> ::std::result::Result<(),::postgres::Error>
196        where F: FnMut(::postgres::Row) -> ::std::result::Result<(),::postgres::Error>
197        {
198            use ::postgres::fallible_iterator::FallibleIterator;
199
200            let mut rows = self.query_raw(
201                $crate::sql_literal!( $head $($tail)* => $($text)+ ) ,
202                [& $head as &(dyn ::postgres::types::ToSql + Sync) $(, & $tail)* ]
203            )?;
204            while let Some(row) = rows.next()? {
205                row_cb(row)?;
206            }
207            Ok(())
208        }
209    };
210    ( ? $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
211        fn $name<$($gen_type : ::postgres::types::ToSql ,)* F>(&mut self $($fn_params)+, mut row_cb: F) -> ::std::result::Result<(),::postgres::Error>
212        where F: FnMut(::postgres::Row) -> ::std::result::Result<(),::postgres::Error>
213        {
214            use ::postgres::fallible_iterator::FallibleIterator;
215
216            let mut stmt = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
217            let mut args = ::std::vec::Vec::<&dyn ::postgres::types::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
218            let mut i = 0;
219            $crate::dynamic_sql!(stmt args i $($text)+);
220            let mut rows = self.query_raw(&stmt, args)?;
221            while let Some(row) = rows.next()? {
222                row_cb(row)?;
223            }
224            Ok(())
225        }
226    };
227    ( ^ $name:ident () () () => () $text:literal ) => {
228        fn $name<'a>(&'a mut self) -> ::std::result::Result<::postgres::RowIter<'a>,::postgres::Error> {
229            self.query_raw( $text, [] as [&dyn ::postgres::types::ToSql; 0] )
230        }
231    };
232    ( ^ $name:ident () ($($fn_params:tt)+) () => (: $head:ident $(: $tail:ident)*) $($text:tt)+) => {
233        fn $name<'a>(&'a mut self $($fn_params)+) -> ::std::result::Result<::postgres::RowIter<'a>,::postgres::Error> {
234            self.query_raw(
235                $crate::sql_literal!( $head $($tail)* => $($text)+ ) ,
236                [& $head as &(dyn ::postgres::types::ToSql + Sync) $(, & $tail)* ]
237            )
238        }
239    };
240    ( ^ $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
241        fn $name<'a $(, $gen_type : ::postgres::types::ToSql)*>(&'a mut self $($fn_params)+) -> ::std::result::Result<::postgres::RowIter<'a>,::postgres::Error> {
242            let mut stmt = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
243            let mut args = ::std::vec::Vec::<&dyn ::postgres::types::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
244            let mut i = 0;
245            $crate::dynamic_sql!(stmt args i $($text)+);
246            self.query_raw(&stmt, args)
247        }
248    };
249    ( % $name:ident () () () => () $text:literal ) => {
250        fn $name<R>(&mut self) -> ::std::result::Result<::std::vec::Vec<R>,::postgres::Error>
251        where R: ::std::convert::TryFrom<::postgres::Row>, ::postgres::Error: ::std::convert::From<R::Error>
252        {
253            use ::postgres::fallible_iterator::FallibleIterator;
254            let mut data = ::std::vec::Vec::new();
255            let mut rows = self.query_raw( $text, [] as [&dyn ::postgres::types::ToSql; 0] )?;
256            while let Some(row) = rows.next()? {
257                let item = R::try_from(row)?;
258                data.push(item);
259            }
260            Ok(data)
261        }
262    };
263    ( % $name:ident () ($($fn_params:tt)+) () => (: $head:ident $(: $tail:ident)*) $($text:tt)+) => {
264        fn $name<R>(&mut self $($fn_params)+) -> ::std::result::Result<::std::vec::Vec<R>,::postgres::Error>
265        where R: ::std::convert::TryFrom<::postgres::Row>, ::postgres::Error: ::std::convert::From<R::Error>
266        {
267            use ::postgres::fallible_iterator::FallibleIterator;
268            let mut data = ::std::vec::Vec::new();
269            let mut rows = self.query_raw(
270                $crate::sql_literal!( $head $($tail)* => $($text)+ ) ,
271                [& $head as &(dyn ::postgres::types::ToSql + Sync) $(, & $tail)* ]
272            )?;
273            while let Some(row) = rows.next()? {
274                let item = R::try_from(row)?;
275                data.push(item);
276            }
277            Ok(data)
278        }
279    };
280    ( % $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
281        fn $name<$($gen_type : ::postgres::types::ToSql ,)* R>(&mut self $($fn_params)+) -> ::std::result::Result<::std::vec::Vec<R>,::postgres::Error>
282        where R: ::std::convert::TryFrom<::postgres::Row>, ::postgres::Error: ::std::convert::From<R::Error>
283        {
284            use ::postgres::fallible_iterator::FallibleIterator;
285            let mut data = ::std::vec::Vec::new();
286            let mut stmt = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
287            let mut args = ::std::vec::Vec::<&dyn ::postgres::types::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
288            let mut i = 0;
289            $crate::dynamic_sql!(stmt args i $($text)+);
290            let mut rows = self.query_raw(&stmt, args)?;
291            while let Some(row) = rows.next()? {
292                let item = R::try_from(row)?;
293                data.push(item);
294            }
295            Ok(data)
296        }
297    };
298    ( ! $name:ident () () () => () $text:literal ) => {
299        fn $name(&mut self) -> ::std::result::Result<u64,::postgres::Error> {
300            self.execute( $text, &[] )
301        }
302    };
303    ( ! $name:ident () ($($fn_params:tt)+) () => (: $head:ident $(: $tail:ident)*) $($text:tt)+) => {
304        fn $name(&mut self $($fn_params)+ ) -> ::std::result::Result<u64,::postgres::Error> {
305            self.execute(
306                $crate::sql_literal!( $head $($tail)* => $($text)+ ) ,
307                &[& $head as &(dyn ::postgres::types::ToSql + Sync) $(, & $tail)* ]
308            )
309        }
310    };
311    ( ! $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
312        fn $name<$($gen_type : ::postgres::types::ToSql),*>(&mut self $($fn_params)+ ) -> ::std::result::Result<u64,::postgres::Error> {
313            let mut stmt = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
314            let mut args = ::std::vec::Vec::<&(dyn ::postgres::types::ToSql + Sync)>::with_capacity($crate::num_args!($($pv $param)+));
315            let mut i = 0;
316            $crate::dynamic_sql!(stmt args i $($text)+);
317            self.execute(&stmt, args.as_slice())
318        }
319    };
320    ( -> $name:ident () () () => () $text:literal ) => {
321        fn $name(&mut self) -> ::std::result::Result<::postgres::Row,::postgres::Error> {
322            self.query_one( $text, &[] )
323        }
324    };
325    ( -> $name:ident () ($($fn_params:tt)+) () => (: $head:ident $(: $tail:ident)*) $($text:tt)+) => {
326        fn $name(&mut self $($fn_params)+ ) -> ::std::result::Result<::postgres::Row,::postgres::Error> {
327            self.query_one(
328                $crate::sql_literal!( $head $($tail)* => $($text)+ ) ,
329                &[& $head as &(dyn ::postgres::types::ToSql + Sync) $(, & $tail)* ]
330            )
331        }
332    };
333    ( -> $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
334        fn $name<$($gen_type : ::postgres::types::ToSql),*>(&mut self $($fn_params)+ ) -> ::std::result::Result<::postgres::Row,::postgres::Error> {
335            let mut stmt = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
336            let mut args = ::std::vec::Vec::<&dyn ::postgres::types::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
337            let mut i = 0;
338            $crate::dynamic_sql!(stmt args i $($text)+);
339            self.query_one(&stmt, &args)
340        }
341    };
342    ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident : _ $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+)  => {
343        $crate::impl_method!{
344            $kind
345            $name
346            ($($gen_type)*)
347            ($($fn_params)* , $param : impl ::postgres::types::ToSql + Sync)
348            ($($tail)*)
349            =>
350            ($($pv $param_name)+)
351            $($text)+
352        }
353    };
354    ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident : ($ptype:ty) $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+)  => {
355        $crate::impl_method!{
356            $kind
357            $name
358            ($($gen_type)*)
359            ($($fn_params)* , $param : $ptype)
360            ($($tail)*)
361            =>
362            ($($pv $param_name)+)
363            $($text)+
364        }
365    };
366    ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident # [$gtype:ident] $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+)  => {
367        $crate::impl_method!{
368            $kind
369            $name
370            ($($gen_type)* $gtype)
371            ($($fn_params)* , $param : & [ $gtype ])
372            ($($tail)*)
373            =>
374            ($($pv $param_name)+)
375            $($text)+
376        }
377    };
378    ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident # ($ptype:ty) $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+)  => {
379        $crate::impl_method!{
380            $kind
381            $name
382            ($($gen_type)*)
383            ($($fn_params)* , $param : & [ $ptype ])
384            ($($tail)*)
385            =>
386            ($($pv $param_name)+)
387            $($text)+
388        }
389    };
390}