include_sqlite_sql/
lib.rs1#![cfg_attr(docsrs, doc = include_str!("../docs/index.md"))]
2
3pub use ::include_sql::{include_sql, index_of};
4
5#[macro_export]
91macro_rules! impl_sql {
92 ( $sql_name:ident = $( { $kind:tt $name:ident ($($variant:tt $param:ident $ptype:tt)*) $doc:literal $s:tt $( $text:tt )+ } ),+ ) => {
93 trait $sql_name {
94 $( $crate::decl_method!{ $kind $name $doc () () $($param $variant $ptype)* } )+
95 }
96 impl $sql_name for ::rusqlite::Connection {
97 $( $crate::impl_method!{ $kind $name () () ($($param $variant $ptype)*) => ($($variant $param)*) $($text)+ } )+
98 }
99 };
100}
101
102#[macro_export]
103#[doc(hidden)]
104macro_rules! decl_method {
105 ( ? $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
106 #[doc=$doc]
107 fn $name<$($gen_type : ::rusqlite::ToSql ,)* F>(&self $($fn_params)* , row_cb: F) -> ::rusqlite::Result<()>
108 where F: FnMut(&::rusqlite::Row) -> ::rusqlite::Result<()>;
109 };
110 ( ! $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
111 #[doc=$doc]
112 fn $name<$($gen_type : ::rusqlite::ToSql),*>(&self $($fn_params)*) -> ::rusqlite::Result<usize>;
113 };
114 ( & $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
115 #[doc=$doc]
116 fn $name<$($gen_type : ::rusqlite::ToSql),*>(&self $($fn_params)*) -> ::rusqlite::Result<()>;
117 };
118 ( -> $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) ) => {
119 #[doc=$doc]
120 fn $name<$($gen_type : ::rusqlite::ToSql ,)* F, R>(&self $($fn_params)* , row_cb: F) -> ::rusqlite::Result<R>
121 where F: FnOnce(&::rusqlite::Row) -> ::rusqlite::Result<R>;
122 };
123 ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident : _ $($tail:tt)* ) => {
124 $crate::decl_method!{
125 $kind
126 $name
127 $doc
128 ($($gen_type)*)
129 ($($fn_params)* , $param : impl ::rusqlite::ToSql)
130 $($tail)*
131 }
132 };
133 ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident : ($ptype:ty) $($tail:tt)* ) => {
134 $crate::decl_method!{
135 $kind
136 $name
137 $doc
138 ($($gen_type)*)
139 ($($fn_params)* , $param : $ptype)
140 $($tail)*
141 }
142 };
143 ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident # [$gtype:ident] $($tail:tt)* ) => {
144 $crate::decl_method!{
145 $kind
146 $name
147 $doc
148 ($($gen_type)* $gtype)
149 ($($fn_params)* , $param : & [ $gtype ] )
150 $($tail)*
151 }
152 };
153 ( $kind:tt $name:ident $doc:literal ($($gen_type:ident)*) ($($fn_params:tt)*) $param:ident # ($ptype:ty) $($tail:tt)* ) => {
154 $crate::decl_method!{
155 $kind
156 $name
157 $doc
158 ($($gen_type)*)
159 ($($fn_params)* , $param : & [ $ptype ] )
160 $($tail)*
161 }
162 };
163}
164
165#[macro_export]
166#[doc(hidden)]
167macro_rules! impl_method {
168 ( ? $name:ident () () () => () $text:literal ) => {
169 fn $name<F>(&self, mut row_cb: F) -> ::rusqlite::Result<()>
170 where F: FnMut(&::rusqlite::Row) -> ::rusqlite::Result<()>
171 {
172 let mut stmt = self.prepare( $text )?;
173 let mut rows = stmt.raw_query();
174 while let Some(row) = rows.next()? {
175 row_cb(row)?;
176 }
177 Ok(())
178 }
179 };
180 ( ? $name:ident () ($($fn_params:tt)+) () => ( $(: $param:ident)+ ) $($text:tt)+) => {
181 fn $name<F>(&self $($fn_params)+ , mut row_cb: F) -> ::rusqlite::Result<()>
182 where F: FnMut(&::rusqlite::Row) -> ::rusqlite::Result<()>
183 {
184 let mut stmt = self.prepare( $crate::sql_literal!( $($param)+ => $($text)+ ) )?;
185 $crate::bind_args!($($param)+ => stmt 1usize);
186 let mut rows = stmt.raw_query();
187 while let Some(row) = rows.next()? {
188 row_cb(row)?;
189 }
190 Ok(())
191 }
192 };
193 ( ? $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
194 fn $name<$($gen_type : ::rusqlite::ToSql ,)* F>(&self $($fn_params)+, mut row_cb: F) -> ::rusqlite::Result<()>
195 where F: FnMut(&::rusqlite::Row) -> ::rusqlite::Result<()>
196 {
197 let mut sql = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
198 let mut args = ::std::vec::Vec::<&dyn ::rusqlite::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
199 let mut i = 0;
200 $crate::dynamic_sql!(sql args i $($text)+);
201 let mut stmt = self.prepare(&sql)?;
202 let mut rows = stmt.query(args.as_slice())?;
203 while let Some(row) = rows.next()? {
204 row_cb(row)?;
205 }
206 Ok(())
207 }
208 };
209 ( ! $name:ident () () () => () $text:literal ) => {
210 fn $name(&self) -> ::rusqlite::Result<usize> {
211 let mut stmt = self.prepare( $text )?;
212 stmt.raw_execute()
213 }
214 };
215 ( ! $name:ident () ($($fn_params:tt)+) () => ( $(: $param:ident)+ ) $($text:tt)+) => {
216 fn $name(&self $($fn_params)+ ) -> ::rusqlite::Result<usize> {
217 let mut stmt = self.prepare( $crate::sql_literal!( $($param)+ => $($text)+ ) )?;
218 $crate::bind_args!($($param)+ => stmt 1usize);
219 stmt.raw_execute()
220 }
221 };
222 ( ! $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
223 fn $name<$($gen_type : ::rusqlite::ToSql),*>(&self $($fn_params)+ ) -> ::rusqlite::Result<usize> {
224 let mut sql = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
225 let mut args = ::std::vec::Vec::<&dyn ::rusqlite::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
226 let mut i = 0;
227 $crate::dynamic_sql!(sql args i $($text)+);
228 let mut stmt = self.prepare(&sql)?;
229 stmt.execute(args.as_slice())
230 }
231 };
232 ( & $name:ident () () () => () $text:literal ) => {
233 fn $name(&self) -> ::rusqlite::Result<()> {
234 self.execute_batch( $text )
235 }
236 };
237 ( -> $name:ident () () () => () $text:literal ) => {
238 fn $name<F,R>(&self, row_cb: F) -> ::rusqlite::Result<R>
239 where F: FnOnce(&::rusqlite::Row) -> ::rusqlite::Result<R>
240 {
241 let mut stmt = self.prepare( $text )?;
242 let mut rows = stmt.raw_query();
243 match rows.next()? {
244 Some(row) => row_cb(row),
245 _ => Err(::rusqlite::Error::QueryReturnedNoRows)
246 }
247 }
248 };
249 ( -> $name:ident () ($($fn_params:tt)+) () => ( $(: $param:ident)+ ) $($text:tt)+) => {
250 fn $name<F,R>(&self $($fn_params)+ , row_cb: F) -> ::rusqlite::Result<R>
251 where F: FnOnce(&::rusqlite::Row) -> ::rusqlite::Result<R>
252 {
253 let mut stmt = self.prepare( $crate::sql_literal!( $($param)+ => $($text)+ ) )?;
254 $crate::bind_args!($($param)+ => stmt 1usize);
255 let mut rows = stmt.raw_query();
256 match rows.next()? {
257 Some(row) => row_cb(row),
258 _ => Err(::rusqlite::Error::QueryReturnedNoRows)
259 }
260 }
261 };
262 ( -> $name:ident ($($gen_type:ident)*) ($($fn_params:tt)+) () => ($($pv:tt $param:ident)+) $($text:tt)+) => {
263 fn $name<$($gen_type : ::rusqlite::ToSql ,)* F,R>(&self $($fn_params)+, row_cb: F) -> ::rusqlite::Result<R>
264 where F: FnOnce(&::rusqlite::Row) -> ::rusqlite::Result<R>
265 {
266 let mut sql = ::std::string::String::with_capacity($crate::sql_len!($($text)+));
267 let mut args = ::std::vec::Vec::<&dyn ::rusqlite::ToSql>::with_capacity($crate::num_args!($($pv $param)+));
268 let mut i = 0;
269 $crate::dynamic_sql!(sql args i $($text)+);
270 let mut stmt = self.prepare(&sql)?;
271 let mut rows = stmt.query(args.as_slice())?;
272 match rows.next()? {
273 Some(row) => row_cb(row),
274 _ => Err(::rusqlite::Error::QueryReturnedNoRows)
275 }
276 }
277 };
278 ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident : _ $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+) => {
279 $crate::impl_method!{
280 $kind
281 $name
282 ($($gen_type)*)
283 ($($fn_params)* , $param : impl ::rusqlite::ToSql)
284 ($($tail)*)
285 =>
286 ($($pv $param_name)+)
287 $($text)+
288 }
289 };
290 ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident : ($ptype:ty) $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+) => {
291 $crate::impl_method!{
292 $kind
293 $name
294 ($($gen_type)*)
295 ($($fn_params)* , $param : $ptype)
296 ($($tail)*)
297 =>
298 ($($pv $param_name)+)
299 $($text)+
300 }
301 };
302 ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident # [$gtype:ident] $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+) => {
303 $crate::impl_method!{
304 $kind
305 $name
306 ($($gen_type)* $gtype)
307 ($($fn_params)* , $param : & [ $gtype ])
308 ($($tail)*)
309 =>
310 ($($pv $param_name)+)
311 $($text)+
312 }
313 };
314 ( $kind:tt $name:ident ($($gen_type:ident)*) ($($fn_params:tt)*) ($param:ident # ($ptype:ty) $($tail:tt)*) => ($($pv:tt $param_name:ident)+) $($text:tt)+) => {
315 $crate::impl_method!{
316 $kind
317 $name
318 ($($gen_type)*)
319 ($($fn_params)* , $param : & [ $ptype ])
320 ($($tail)*)
321 =>
322 ($($pv $param_name)+)
323 $($text)+
324 }
325 };
326}
327
328#[macro_export]
329#[doc(hidden)]
330macro_rules! sql_literal {
331 ($($name:ident)+ => $text:literal) => {
332 $text
333 };
334 ($($name:ident)+ => $text:literal : $param:ident) => {
335 ::std::concat!( $text, '?', $crate::index_of!($param in [ $( $name ),+ ] + 1) )
336 };
337 ($($name:ident)+ => $text:literal : $param:ident $($tail:tt)+) => {
338 ::std::concat!(
339 $text, '?', $crate::index_of!($param in [ $( $name ),+ ] + 1),
340 $crate::sql_literal!($($name)+ => $($tail)+)
341 )
342 };
343}
344
345#[macro_export]
346#[doc(hidden)]
347macro_rules! bind_args {
348 ($head:ident $($tail:ident)* => $stmt:ident $idx:expr) => {
349 $stmt.raw_bind_parameter($idx, $head)?;
350 $crate::bind_args!($($tail)* => $stmt $idx+1usize);
351 };
352 (=> $stmt:ident $idx:expr) => {};
353}
354
355#[macro_export]
356#[doc(hidden)]
357macro_rules! num_args {
358 () => { 0 };
359 (: $head:ident $($tail:tt)*) => { 1 + $crate::num_args!($($tail)*) };
360 (# $head:ident $($tail:tt)*) => { $head.len() + $crate::num_args!($($tail)*) };
361}
362
363#[macro_export]
364#[doc(hidden)]
365macro_rules! sql_len {
366 () => { 0 };
367 ($text:literal $($tail:tt)*) => { $text.len() + $crate::sql_len!($($tail)*) };
368 (: $head:ident $($tail:tt)*) => { 3 + $crate::sql_len!($($tail)*) };
369 (# $head:ident $($tail:tt)*) => { $head.len() * 5 + $crate::sql_len!($($tail)*) };
370}
371
372#[macro_export]
373#[doc(hidden)]
374macro_rules! dynamic_sql {
375 ($stmt:ident $args:ident $i:ident) => {};
376 ($stmt:ident $args:ident $i:ident $text:literal $($tail:tt)*) => {
377 $stmt.push_str($text);
378 $crate::dynamic_sql!($stmt $args $i $($tail)*);
379 };
380 ($stmt:ident $args:ident $i:ident : $param:ident $($tail:tt)*) => {
381 $i += 1;
382 $stmt.push_str(&::std::format!("?{}", $i));
383 $args.push(&$param);
384 $crate::dynamic_sql!($stmt $args $i $($tail)*);
385 };
386 ($stmt:ident $args:ident $i:ident # $param:ident $($tail:tt)*) => {
387 let mut iter = $param.into_iter();
388 if let Some(arg) = iter.next() {
389 $i += 1;
390 $stmt.push_str(&::std::format!("?{}", $i));
391 $args.push(arg);
392 while let Some(arg) = iter.next() {
393 $i += 1;
394 $stmt.push_str(&::std::format!(", ?{}", $i));
395 $args.push(arg);
396 }
397 } else {
398 $stmt.push_str("NULL");
399 }
400 $crate::dynamic_sql!($stmt $args $i $($tail)*);
401 };
402}