• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::os::raw::{c_int, c_void};
2 #[cfg(feature = "array")]
3 use std::rc::Rc;
4 use std::slice::from_raw_parts;
5 use std::{fmt, mem, ptr, str};
6 
7 use super::ffi;
8 use super::{len_as_c_int, str_for_sqlite};
9 use super::{
10     AndThenRows, Connection, Error, MappedRows, Params, RawStatement, Result, Row, Rows, ValueRef,
11 };
12 use crate::types::{ToSql, ToSqlOutput};
13 #[cfg(feature = "array")]
14 use crate::vtab::array::{free_array, ARRAY_TYPE};
15 
16 /// A prepared statement.
17 pub struct Statement<'conn> {
18     conn: &'conn Connection,
19     pub(crate) stmt: RawStatement,
20 }
21 
22 impl Statement<'_> {
23     /// Execute the prepared statement.
24     ///
25     /// On success, returns the number of rows that were changed or inserted or
26     /// deleted (via `sqlite3_changes`).
27     ///
28     /// ## Example
29     ///
30     /// ### Use with positional parameters
31     ///
32     /// ```rust,no_run
33     /// # use rusqlite::{Connection, Result, params};
34     /// fn update_rows(conn: &Connection) -> Result<()> {
35     ///     let mut stmt = conn.prepare("UPDATE foo SET bar = ?1 WHERE qux = ?2")?;
36     ///     // For a single parameter, or a parameter where all the values have
37     ///     // the same type, just passing an array is simplest.
38     ///     stmt.execute([2i32])?;
39     ///     // The `rusqlite::params!` macro is mostly useful when the parameters do not
40     ///     // all have the same type, or if there are more than 32 parameters
41     ///     // at once, but it can be used in other cases.
42     ///     stmt.execute(params![1i32])?;
43     ///     // However, it's not required, many cases are fine as:
44     ///     stmt.execute(&[&2i32])?;
45     ///     // Or even:
46     ///     stmt.execute([2i32])?;
47     ///     // If you really want to, this is an option as well.
48     ///     stmt.execute((2i32,))?;
49     ///     Ok(())
50     /// }
51     /// ```
52     ///
53     /// #### Heterogeneous positional parameters
54     ///
55     /// ```
56     /// use rusqlite::{Connection, Result};
57     /// fn store_file(conn: &Connection, path: &str, data: &[u8]) -> Result<()> {
58     ///     # // no need to do it for real.
59     ///     # fn sha256(_: &[u8]) -> [u8; 32] { [0; 32] }
60     ///     let query = "INSERT OR REPLACE INTO files(path, hash, data) VALUES (?1, ?2, ?3)";
61     ///     let mut stmt = conn.prepare_cached(query)?;
62     ///     let hash: [u8; 32] = sha256(data);
63     ///     // The easiest way to pass positional parameters of have several
64     ///     // different types is by using a tuple.
65     ///     stmt.execute((path, hash, data))?;
66     ///     // Using the `params!` macro also works, and supports longer parameter lists:
67     ///     stmt.execute(rusqlite::params![path, hash, data])?;
68     ///     Ok(())
69     /// }
70     /// # let c = Connection::open_in_memory().unwrap();
71     /// # c.execute_batch("CREATE TABLE files(path TEXT PRIMARY KEY, hash BLOB, data BLOB)").unwrap();
72     /// # store_file(&c, "foo/bar.txt", b"bibble").unwrap();
73     /// # store_file(&c, "foo/baz.txt", b"bobble").unwrap();
74     /// ```
75     ///
76     /// ### Use with named parameters
77     ///
78     /// ```rust,no_run
79     /// # use rusqlite::{Connection, Result, named_params};
80     /// fn insert(conn: &Connection) -> Result<()> {
81     ///     let mut stmt = conn.prepare("INSERT INTO test (key, value) VALUES (:key, :value)")?;
82     ///     // The `rusqlite::named_params!` macro (like `params!`) is useful for heterogeneous
83     ///     // sets of parameters (where all parameters are not the same type), or for queries
84     ///     // with many (more than 32) statically known parameters.
85     ///     stmt.execute(named_params! { ":key": "one", ":val": 2 })?;
86     ///     // However, named parameters can also be passed like:
87     ///     stmt.execute(&[(":key", "three"), (":val", "four")])?;
88     ///     // Or even: (note that a &T is required for the value type, currently)
89     ///     stmt.execute(&[(":key", &100), (":val", &200)])?;
90     ///     Ok(())
91     /// }
92     /// ```
93     ///
94     /// ### Use without parameters
95     ///
96     /// ```rust,no_run
97     /// # use rusqlite::{Connection, Result, params};
98     /// fn delete_all(conn: &Connection) -> Result<()> {
99     ///     let mut stmt = conn.prepare("DELETE FROM users")?;
100     ///     stmt.execute([])?;
101     ///     Ok(())
102     /// }
103     /// ```
104     ///
105     /// # Failure
106     ///
107     /// Will return `Err` if binding parameters fails, the executed statement
108     /// returns rows (in which case `query` should be used instead), or the
109     /// underlying SQLite call fails.
110     #[inline]
execute<P: Params>(&mut self, params: P) -> Result<usize>111     pub fn execute<P: Params>(&mut self, params: P) -> Result<usize> {
112         params.__bind_in(self)?;
113         self.execute_with_bound_parameters()
114     }
115 
116     /// Execute an INSERT and return the ROWID.
117     ///
118     /// # Note
119     ///
120     /// This function is a convenience wrapper around
121     /// [`execute()`](Statement::execute) intended for queries that insert a
122     /// single item. It is possible to misuse this function in a way that it
123     /// cannot detect, such as by calling it on a statement which _updates_
124     /// a single item rather than inserting one. Please don't do that.
125     ///
126     /// # Failure
127     ///
128     /// Will return `Err` if no row is inserted or many rows are inserted.
129     #[inline]
insert<P: Params>(&mut self, params: P) -> Result<i64>130     pub fn insert<P: Params>(&mut self, params: P) -> Result<i64> {
131         let changes = self.execute(params)?;
132         match changes {
133             1 => Ok(self.conn.last_insert_rowid()),
134             _ => Err(Error::StatementChangedRows(changes)),
135         }
136     }
137 
138     /// Execute the prepared statement, returning a handle to the resulting
139     /// rows.
140     ///
141     /// Due to lifetime restrictions, the rows handle returned by `query` does
142     /// not implement the `Iterator` trait. Consider using
143     /// [`query_map`](Statement::query_map) or
144     /// [`query_and_then`](Statement::query_and_then) instead, which do.
145     ///
146     /// ## Example
147     ///
148     /// ### Use without parameters
149     ///
150     /// ```rust,no_run
151     /// # use rusqlite::{Connection, Result};
152     /// fn get_names(conn: &Connection) -> Result<Vec<String>> {
153     ///     let mut stmt = conn.prepare("SELECT name FROM people")?;
154     ///     let mut rows = stmt.query([])?;
155     ///
156     ///     let mut names = Vec::new();
157     ///     while let Some(row) = rows.next()? {
158     ///         names.push(row.get(0)?);
159     ///     }
160     ///
161     ///     Ok(names)
162     /// }
163     /// ```
164     ///
165     /// ### Use with positional parameters
166     ///
167     /// ```rust,no_run
168     /// # use rusqlite::{Connection, Result};
169     /// fn query(conn: &Connection, name: &str) -> Result<()> {
170     ///     let mut stmt = conn.prepare("SELECT * FROM test where name = ?1")?;
171     ///     let mut rows = stmt.query(rusqlite::params![name])?;
172     ///     while let Some(row) = rows.next()? {
173     ///         // ...
174     ///     }
175     ///     Ok(())
176     /// }
177     /// ```
178     ///
179     /// Or, equivalently (but without the [`crate::params!`] macro).
180     ///
181     /// ```rust,no_run
182     /// # use rusqlite::{Connection, Result};
183     /// fn query(conn: &Connection, name: &str) -> Result<()> {
184     ///     let mut stmt = conn.prepare("SELECT * FROM test where name = ?1")?;
185     ///     let mut rows = stmt.query([name])?;
186     ///     while let Some(row) = rows.next()? {
187     ///         // ...
188     ///     }
189     ///     Ok(())
190     /// }
191     /// ```
192     ///
193     /// ### Use with named parameters
194     ///
195     /// ```rust,no_run
196     /// # use rusqlite::{Connection, Result};
197     /// fn query(conn: &Connection) -> Result<()> {
198     ///     let mut stmt = conn.prepare("SELECT * FROM test where name = :name")?;
199     ///     let mut rows = stmt.query(&[(":name", "one")])?;
200     ///     while let Some(row) = rows.next()? {
201     ///         // ...
202     ///     }
203     ///     Ok(())
204     /// }
205     /// ```
206     ///
207     /// Note, the `named_params!` macro is provided for syntactic convenience,
208     /// and so the above example could also be written as:
209     ///
210     /// ```rust,no_run
211     /// # use rusqlite::{Connection, Result, named_params};
212     /// fn query(conn: &Connection) -> Result<()> {
213     ///     let mut stmt = conn.prepare("SELECT * FROM test where name = :name")?;
214     ///     let mut rows = stmt.query(named_params! { ":name": "one" })?;
215     ///     while let Some(row) = rows.next()? {
216     ///         // ...
217     ///     }
218     ///     Ok(())
219     /// }
220     /// ```
221     ///
222     /// ## Failure
223     ///
224     /// Will return `Err` if binding parameters fails.
225     #[inline]
query<P: Params>(&mut self, params: P) -> Result<Rows<'_>>226     pub fn query<P: Params>(&mut self, params: P) -> Result<Rows<'_>> {
227         params.__bind_in(self)?;
228         Ok(Rows::new(self))
229     }
230 
231     /// Executes the prepared statement and maps a function over the resulting
232     /// rows, returning an iterator over the mapped function results.
233     ///
234     /// `f` is used to transform the _streaming_ iterator into a _standard_
235     /// iterator.
236     ///
237     /// This is equivalent to `stmt.query(params)?.mapped(f)`.
238     ///
239     /// ## Example
240     ///
241     /// ### Use with positional params
242     ///
243     /// ```rust,no_run
244     /// # use rusqlite::{Connection, Result};
245     /// fn get_names(conn: &Connection) -> Result<Vec<String>> {
246     ///     let mut stmt = conn.prepare("SELECT name FROM people")?;
247     ///     let rows = stmt.query_map([], |row| row.get(0))?;
248     ///
249     ///     let mut names = Vec::new();
250     ///     for name_result in rows {
251     ///         names.push(name_result?);
252     ///     }
253     ///
254     ///     Ok(names)
255     /// }
256     /// ```
257     ///
258     /// ### Use with named params
259     ///
260     /// ```rust,no_run
261     /// # use rusqlite::{Connection, Result};
262     /// fn get_names(conn: &Connection) -> Result<Vec<String>> {
263     ///     let mut stmt = conn.prepare("SELECT name FROM people WHERE id = :id")?;
264     ///     let rows = stmt.query_map(&[(":id", &"one")], |row| row.get(0))?;
265     ///
266     ///     let mut names = Vec::new();
267     ///     for name_result in rows {
268     ///         names.push(name_result?);
269     ///     }
270     ///
271     ///     Ok(names)
272     /// }
273     /// ```
274     /// ## Failure
275     ///
276     /// Will return `Err` if binding parameters fails.
query_map<T, P, F>(&mut self, params: P, f: F) -> Result<MappedRows<'_, F>> where P: Params, F: FnMut(&Row<'_>) -> Result<T>,277     pub fn query_map<T, P, F>(&mut self, params: P, f: F) -> Result<MappedRows<'_, F>>
278     where
279         P: Params,
280         F: FnMut(&Row<'_>) -> Result<T>,
281     {
282         self.query(params).map(|rows| rows.mapped(f))
283     }
284 
285     /// Executes the prepared statement and maps a function over the resulting
286     /// rows, where the function returns a `Result` with `Error` type
287     /// implementing `std::convert::From<Error>` (so errors can be unified).
288     ///
289     /// This is equivalent to `stmt.query(params)?.and_then(f)`.
290     ///
291     /// ## Example
292     ///
293     /// ### Use with named params
294     ///
295     /// ```rust,no_run
296     /// # use rusqlite::{Connection, Result};
297     /// struct Person {
298     ///     name: String,
299     /// };
300     ///
301     /// fn name_to_person(name: String) -> Result<Person> {
302     ///     // ... check for valid name
303     ///     Ok(Person { name })
304     /// }
305     ///
306     /// fn get_names(conn: &Connection) -> Result<Vec<Person>> {
307     ///     let mut stmt = conn.prepare("SELECT name FROM people WHERE id = :id")?;
308     ///     let rows = stmt.query_and_then(&[(":id", "one")], |row| name_to_person(row.get(0)?))?;
309     ///
310     ///     let mut persons = Vec::new();
311     ///     for person_result in rows {
312     ///         persons.push(person_result?);
313     ///     }
314     ///
315     ///     Ok(persons)
316     /// }
317     /// ```
318     ///
319     /// ### Use with positional params
320     ///
321     /// ```rust,no_run
322     /// # use rusqlite::{Connection, Result};
323     /// fn get_names(conn: &Connection) -> Result<Vec<String>> {
324     ///     let mut stmt = conn.prepare("SELECT name FROM people WHERE id = ?1")?;
325     ///     let rows = stmt.query_and_then(["one"], |row| row.get::<_, String>(0))?;
326     ///
327     ///     let mut persons = Vec::new();
328     ///     for person_result in rows {
329     ///         persons.push(person_result?);
330     ///     }
331     ///
332     ///     Ok(persons)
333     /// }
334     /// ```
335     ///
336     /// # Failure
337     ///
338     /// Will return `Err` if binding parameters fails.
339     #[inline]
query_and_then<T, E, P, F>(&mut self, params: P, f: F) -> Result<AndThenRows<'_, F>> where P: Params, E: From<Error>, F: FnMut(&Row<'_>) -> Result<T, E>,340     pub fn query_and_then<T, E, P, F>(&mut self, params: P, f: F) -> Result<AndThenRows<'_, F>>
341     where
342         P: Params,
343         E: From<Error>,
344         F: FnMut(&Row<'_>) -> Result<T, E>,
345     {
346         self.query(params).map(|rows| rows.and_then(f))
347     }
348 
349     /// Return `true` if a query in the SQL statement it executes returns one
350     /// or more rows and `false` if the SQL returns an empty set.
351     #[inline]
exists<P: Params>(&mut self, params: P) -> Result<bool>352     pub fn exists<P: Params>(&mut self, params: P) -> Result<bool> {
353         let mut rows = self.query(params)?;
354         let exists = rows.next()?.is_some();
355         Ok(exists)
356     }
357 
358     /// Convenience method to execute a query that is expected to return a
359     /// single row.
360     ///
361     /// If the query returns more than one row, all rows except the first are
362     /// ignored.
363     ///
364     /// Returns `Err(QueryReturnedNoRows)` if no results are returned. If the
365     /// query truly is optional, you can call
366     /// [`.optional()`](crate::OptionalExtension::optional) on the result of
367     /// this to get a `Result<Option<T>>` (requires that the trait
368     /// `rusqlite::OptionalExtension` is imported).
369     ///
370     /// # Failure
371     ///
372     /// Will return `Err` if the underlying SQLite call fails.
query_row<T, P, F>(&mut self, params: P, f: F) -> Result<T> where P: Params, F: FnOnce(&Row<'_>) -> Result<T>,373     pub fn query_row<T, P, F>(&mut self, params: P, f: F) -> Result<T>
374     where
375         P: Params,
376         F: FnOnce(&Row<'_>) -> Result<T>,
377     {
378         let mut rows = self.query(params)?;
379 
380         rows.get_expected_row().and_then(f)
381     }
382 
383     /// Consumes the statement.
384     ///
385     /// Functionally equivalent to the `Drop` implementation, but allows
386     /// callers to see any errors that occur.
387     ///
388     /// # Failure
389     ///
390     /// Will return `Err` if the underlying SQLite call fails.
391     #[inline]
finalize(mut self) -> Result<()>392     pub fn finalize(mut self) -> Result<()> {
393         self.finalize_()
394     }
395 
396     /// Return the (one-based) index of an SQL parameter given its name.
397     ///
398     /// Note that the initial ":" or "$" or "@" or "?" used to specify the
399     /// parameter is included as part of the name.
400     ///
401     /// ```rust,no_run
402     /// # use rusqlite::{Connection, Result};
403     /// fn example(conn: &Connection) -> Result<()> {
404     ///     let stmt = conn.prepare("SELECT * FROM test WHERE name = :example")?;
405     ///     let index = stmt.parameter_index(":example")?;
406     ///     assert_eq!(index, Some(1));
407     ///     Ok(())
408     /// }
409     /// ```
410     ///
411     /// # Failure
412     ///
413     /// Will return Err if `name` is invalid. Will return Ok(None) if the name
414     /// is valid but not a bound parameter of this statement.
415     #[inline]
parameter_index(&self, name: &str) -> Result<Option<usize>>416     pub fn parameter_index(&self, name: &str) -> Result<Option<usize>> {
417         Ok(self.stmt.bind_parameter_index(name))
418     }
419 
420     /// Return the SQL parameter name given its (one-based) index (the inverse
421     /// of [`Statement::parameter_index`]).
422     ///
423     /// ```rust,no_run
424     /// # use rusqlite::{Connection, Result};
425     /// fn example(conn: &Connection) -> Result<()> {
426     ///     let stmt = conn.prepare("SELECT * FROM test WHERE name = :example")?;
427     ///     let index = stmt.parameter_name(1);
428     ///     assert_eq!(index, Some(":example"));
429     ///     Ok(())
430     /// }
431     /// ```
432     ///
433     /// # Failure
434     ///
435     /// Will return `None` if the column index is out of bounds or if the
436     /// parameter is positional.
437     ///
438     /// # Panics
439     ///
440     /// Panics when parameter name is not valid UTF-8.
441     #[inline]
parameter_name(&self, index: usize) -> Option<&'_ str>442     pub fn parameter_name(&self, index: usize) -> Option<&'_ str> {
443         self.stmt.bind_parameter_name(index as i32).map(|name| {
444             name.to_str()
445                 .expect("Invalid UTF-8 sequence in parameter name")
446         })
447     }
448 
449     #[inline]
bind_parameters<P>(&mut self, params: P) -> Result<()> where P: IntoIterator, P::Item: ToSql,450     pub(crate) fn bind_parameters<P>(&mut self, params: P) -> Result<()>
451     where
452         P: IntoIterator,
453         P::Item: ToSql,
454     {
455         let expected = self.stmt.bind_parameter_count();
456         let mut index = 0;
457         for p in params {
458             index += 1; // The leftmost SQL parameter has an index of 1.
459             if index > expected {
460                 break;
461             }
462             self.bind_parameter(&p, index)?;
463         }
464         if index != expected {
465             Err(Error::InvalidParameterCount(index, expected))
466         } else {
467             Ok(())
468         }
469     }
470 
471     #[inline]
ensure_parameter_count(&self, n: usize) -> Result<()>472     pub(crate) fn ensure_parameter_count(&self, n: usize) -> Result<()> {
473         let count = self.parameter_count();
474         if count != n {
475             Err(Error::InvalidParameterCount(n, count))
476         } else {
477             Ok(())
478         }
479     }
480 
481     #[inline]
bind_parameters_named<T: ?Sized + ToSql>( &mut self, params: &[(&str, &T)], ) -> Result<()>482     pub(crate) fn bind_parameters_named<T: ?Sized + ToSql>(
483         &mut self,
484         params: &[(&str, &T)],
485     ) -> Result<()> {
486         for &(name, value) in params {
487             if let Some(i) = self.parameter_index(name)? {
488                 let ts: &dyn ToSql = &value;
489                 self.bind_parameter(ts, i)?;
490             } else {
491                 return Err(Error::InvalidParameterName(name.into()));
492             }
493         }
494         Ok(())
495     }
496 
497     /// Return the number of parameters that can be bound to this statement.
498     #[inline]
parameter_count(&self) -> usize499     pub fn parameter_count(&self) -> usize {
500         self.stmt.bind_parameter_count()
501     }
502 
503     /// Low level API to directly bind a parameter to a given index.
504     ///
505     /// Note that the index is one-based, that is, the first parameter index is
506     /// 1 and not 0. This is consistent with the SQLite API and the values given
507     /// to parameters bound as `?NNN`.
508     ///
509     /// The valid values for `one_based_col_index` begin at `1`, and end at
510     /// [`Statement::parameter_count`], inclusive.
511     ///
512     /// # Caveats
513     ///
514     /// This should not generally be used, but is available for special cases
515     /// such as:
516     ///
517     /// - binding parameters where a gap exists.
518     /// - binding named and positional parameters in the same query.
519     /// - separating parameter binding from query execution.
520     ///
521     /// In general, statements that have had *any* parameters bound this way
522     /// should have *all* parameters bound this way, and be queried or executed
523     /// by [`Statement::raw_query`] or [`Statement::raw_execute`], other usage
524     /// is unsupported and will likely, probably in surprising ways.
525     ///
526     /// That is: Do not mix the "raw" statement functions with the rest of the
527     /// API, or the results may be surprising, and may even change in future
528     /// versions without comment.
529     ///
530     /// # Example
531     ///
532     /// ```rust,no_run
533     /// # use rusqlite::{Connection, Result};
534     /// fn query(conn: &Connection) -> Result<()> {
535     ///     let mut stmt = conn.prepare("SELECT * FROM test WHERE name = :name AND value > ?2")?;
536     ///     let name_index = stmt.parameter_index(":name")?.expect("No such parameter");
537     ///     stmt.raw_bind_parameter(name_index, "foo")?;
538     ///     stmt.raw_bind_parameter(2, 100)?;
539     ///     let mut rows = stmt.raw_query();
540     ///     while let Some(row) = rows.next()? {
541     ///         // ...
542     ///     }
543     ///     Ok(())
544     /// }
545     /// ```
546     #[inline]
raw_bind_parameter<T: ToSql>( &mut self, one_based_col_index: usize, param: T, ) -> Result<()>547     pub fn raw_bind_parameter<T: ToSql>(
548         &mut self,
549         one_based_col_index: usize,
550         param: T,
551     ) -> Result<()> {
552         // This is the same as `bind_parameter` but slightly more ergonomic and
553         // correctly takes `&mut self`.
554         self.bind_parameter(&param, one_based_col_index)
555     }
556 
557     /// Low level API to execute a statement given that all parameters were
558     /// bound explicitly with the [`Statement::raw_bind_parameter`] API.
559     ///
560     /// # Caveats
561     ///
562     /// Any unbound parameters will have `NULL` as their value.
563     ///
564     /// This should not generally be used outside special cases, and
565     /// functions in the [`Statement::execute`] family should be preferred.
566     ///
567     /// # Failure
568     ///
569     /// Will return `Err` if the executed statement returns rows (in which case
570     /// `query` should be used instead), or the underlying SQLite call fails.
571     #[inline]
raw_execute(&mut self) -> Result<usize>572     pub fn raw_execute(&mut self) -> Result<usize> {
573         self.execute_with_bound_parameters()
574     }
575 
576     /// Low level API to get `Rows` for this query given that all parameters
577     /// were bound explicitly with the [`Statement::raw_bind_parameter`] API.
578     ///
579     /// # Caveats
580     ///
581     /// Any unbound parameters will have `NULL` as their value.
582     ///
583     /// This should not generally be used outside special cases, and
584     /// functions in the [`Statement::query`] family should be preferred.
585     ///
586     /// Note that if the SQL does not return results, [`Statement::raw_execute`]
587     /// should be used instead.
588     #[inline]
raw_query(&mut self) -> Rows<'_>589     pub fn raw_query(&mut self) -> Rows<'_> {
590         Rows::new(self)
591     }
592 
593     // generic because many of these branches can constant fold away.
bind_parameter<P: ?Sized + ToSql>(&self, param: &P, col: usize) -> Result<()>594     fn bind_parameter<P: ?Sized + ToSql>(&self, param: &P, col: usize) -> Result<()> {
595         let value = param.to_sql()?;
596 
597         let ptr = unsafe { self.stmt.ptr() };
598         let value = match value {
599             ToSqlOutput::Borrowed(v) => v,
600             ToSqlOutput::Owned(ref v) => ValueRef::from(v),
601 
602             #[cfg(feature = "blob")]
603             ToSqlOutput::ZeroBlob(len) => {
604                 // TODO sqlite3_bind_zeroblob64 // 3.8.11
605                 return self
606                     .conn
607                     .decode_result(unsafe { ffi::sqlite3_bind_zeroblob(ptr, col as c_int, len) });
608             }
609             #[cfg(feature = "functions")]
610             ToSqlOutput::Arg(_) => {
611                 return Err(Error::SqliteFailure(
612                     ffi::Error::new(ffi::SQLITE_MISUSE),
613                     Some(format!("Unsupported value \"{value:?}\"")),
614                 ));
615             }
616             #[cfg(feature = "array")]
617             ToSqlOutput::Array(a) => {
618                 return self.conn.decode_result(unsafe {
619                     ffi::sqlite3_bind_pointer(
620                         ptr,
621                         col as c_int,
622                         Rc::into_raw(a) as *mut c_void,
623                         ARRAY_TYPE,
624                         Some(free_array),
625                     )
626                 });
627             }
628         };
629         self.conn.decode_result(match value {
630             ValueRef::Null => unsafe { ffi::sqlite3_bind_null(ptr, col as c_int) },
631             ValueRef::Integer(i) => unsafe { ffi::sqlite3_bind_int64(ptr, col as c_int, i) },
632             ValueRef::Real(r) => unsafe { ffi::sqlite3_bind_double(ptr, col as c_int, r) },
633             ValueRef::Text(s) => unsafe {
634                 let (c_str, len, destructor) = str_for_sqlite(s)?;
635                 // TODO sqlite3_bind_text64 // 3.8.7
636                 ffi::sqlite3_bind_text(ptr, col as c_int, c_str, len, destructor)
637             },
638             ValueRef::Blob(b) => unsafe {
639                 let length = len_as_c_int(b.len())?;
640                 if length == 0 {
641                     ffi::sqlite3_bind_zeroblob(ptr, col as c_int, 0)
642                 } else {
643                     // TODO sqlite3_bind_blob64 // 3.8.7
644                     ffi::sqlite3_bind_blob(
645                         ptr,
646                         col as c_int,
647                         b.as_ptr().cast::<c_void>(),
648                         length,
649                         ffi::SQLITE_TRANSIENT(),
650                     )
651                 }
652             },
653         })
654     }
655 
656     #[inline]
execute_with_bound_parameters(&mut self) -> Result<usize>657     fn execute_with_bound_parameters(&mut self) -> Result<usize> {
658         self.check_update()?;
659         let r = self.stmt.step();
660         let rr = self.stmt.reset();
661         match r {
662             ffi::SQLITE_DONE => match rr {
663                 ffi::SQLITE_OK => Ok(self.conn.changes() as usize),
664                 _ => Err(self.conn.decode_result(rr).unwrap_err()),
665             },
666             ffi::SQLITE_ROW => Err(Error::ExecuteReturnedResults),
667             _ => Err(self.conn.decode_result(r).unwrap_err()),
668         }
669     }
670 
671     #[inline]
finalize_(&mut self) -> Result<()>672     fn finalize_(&mut self) -> Result<()> {
673         let mut stmt = unsafe { RawStatement::new(ptr::null_mut(), 0) };
674         mem::swap(&mut stmt, &mut self.stmt);
675         self.conn.decode_result(stmt.finalize())
676     }
677 
678     #[cfg(feature = "extra_check")]
679     #[inline]
check_update(&self) -> Result<()>680     fn check_update(&self) -> Result<()> {
681         // sqlite3_column_count works for DML but not for DDL (ie ALTER)
682         if self.column_count() > 0 && self.stmt.readonly() {
683             return Err(Error::ExecuteReturnedResults);
684         }
685         Ok(())
686     }
687 
688     #[cfg(not(feature = "extra_check"))]
689     #[inline]
690     #[allow(clippy::unnecessary_wraps)]
check_update(&self) -> Result<()>691     fn check_update(&self) -> Result<()> {
692         Ok(())
693     }
694 
695     /// Returns a string containing the SQL text of prepared statement with
696     /// bound parameters expanded.
expanded_sql(&self) -> Option<String>697     pub fn expanded_sql(&self) -> Option<String> {
698         self.stmt
699             .expanded_sql()
700             .map(|s| s.to_string_lossy().to_string())
701     }
702 
703     /// Get the value for one of the status counters for this statement.
704     #[inline]
get_status(&self, status: StatementStatus) -> i32705     pub fn get_status(&self, status: StatementStatus) -> i32 {
706         self.stmt.get_status(status, false)
707     }
708 
709     /// Reset the value of one of the status counters for this statement,
710     #[inline]
711     /// returning the value it had before resetting.
reset_status(&self, status: StatementStatus) -> i32712     pub fn reset_status(&self, status: StatementStatus) -> i32 {
713         self.stmt.get_status(status, true)
714     }
715 
716     /// Returns 1 if the prepared statement is an EXPLAIN statement,
717     /// or 2 if the statement is an EXPLAIN QUERY PLAN,
718     /// or 0 if it is an ordinary statement or a NULL pointer.
719     #[inline]
720     #[cfg(feature = "modern_sqlite")] // 3.28.0
721     #[cfg_attr(docsrs, doc(cfg(feature = "modern_sqlite")))]
is_explain(&self) -> i32722     pub fn is_explain(&self) -> i32 {
723         self.stmt.is_explain()
724     }
725 
726     /// Returns true if the statement is read only.
727     #[inline]
readonly(&self) -> bool728     pub fn readonly(&self) -> bool {
729         self.stmt.readonly()
730     }
731 
732     #[cfg(feature = "extra_check")]
733     #[inline]
check_no_tail(&self) -> Result<()>734     pub(crate) fn check_no_tail(&self) -> Result<()> {
735         if self.stmt.has_tail() {
736             Err(Error::MultipleStatement)
737         } else {
738             Ok(())
739         }
740     }
741 
742     #[cfg(not(feature = "extra_check"))]
743     #[inline]
744     #[allow(clippy::unnecessary_wraps)]
check_no_tail(&self) -> Result<()>745     pub(crate) fn check_no_tail(&self) -> Result<()> {
746         Ok(())
747     }
748 
749     /// Safety: This is unsafe, because using `sqlite3_stmt` after the
750     /// connection has closed is illegal, but `RawStatement` does not enforce
751     /// this, as it loses our protective `'conn` lifetime bound.
752     #[inline]
into_raw(mut self) -> RawStatement753     pub(crate) unsafe fn into_raw(mut self) -> RawStatement {
754         let mut stmt = RawStatement::new(ptr::null_mut(), 0);
755         mem::swap(&mut stmt, &mut self.stmt);
756         stmt
757     }
758 
759     /// Reset all bindings
clear_bindings(&mut self)760     pub fn clear_bindings(&mut self) {
761         self.stmt.clear_bindings();
762     }
763 }
764 
765 impl fmt::Debug for Statement<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result766     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
767         let sql = if self.stmt.is_null() {
768             Ok("")
769         } else {
770             self.stmt.sql().unwrap().to_str()
771         };
772         f.debug_struct("Statement")
773             .field("conn", self.conn)
774             .field("stmt", &self.stmt)
775             .field("sql", &sql)
776             .finish()
777     }
778 }
779 
780 impl Drop for Statement<'_> {
781     #[allow(unused_must_use)]
782     #[inline]
drop(&mut self)783     fn drop(&mut self) {
784         self.finalize_();
785     }
786 }
787 
788 impl Statement<'_> {
789     #[inline]
new(conn: &Connection, stmt: RawStatement) -> Statement<'_>790     pub(super) fn new(conn: &Connection, stmt: RawStatement) -> Statement<'_> {
791         Statement { conn, stmt }
792     }
793 
value_ref(&self, col: usize) -> ValueRef<'_>794     pub(super) fn value_ref(&self, col: usize) -> ValueRef<'_> {
795         let raw = unsafe { self.stmt.ptr() };
796 
797         match self.stmt.column_type(col) {
798             ffi::SQLITE_NULL => ValueRef::Null,
799             ffi::SQLITE_INTEGER => {
800                 ValueRef::Integer(unsafe { ffi::sqlite3_column_int64(raw, col as c_int) })
801             }
802             ffi::SQLITE_FLOAT => {
803                 ValueRef::Real(unsafe { ffi::sqlite3_column_double(raw, col as c_int) })
804             }
805             ffi::SQLITE_TEXT => {
806                 let s = unsafe {
807                     // Quoting from "Using SQLite" book:
808                     // To avoid problems, an application should first extract the desired type using
809                     // a sqlite3_column_xxx() function, and then call the
810                     // appropriate sqlite3_column_bytes() function.
811                     let text = ffi::sqlite3_column_text(raw, col as c_int);
812                     let len = ffi::sqlite3_column_bytes(raw, col as c_int);
813                     assert!(
814                         !text.is_null(),
815                         "unexpected SQLITE_TEXT column type with NULL data"
816                     );
817                     from_raw_parts(text.cast::<u8>(), len as usize)
818                 };
819 
820                 ValueRef::Text(s)
821             }
822             ffi::SQLITE_BLOB => {
823                 let (blob, len) = unsafe {
824                     (
825                         ffi::sqlite3_column_blob(raw, col as c_int),
826                         ffi::sqlite3_column_bytes(raw, col as c_int),
827                     )
828                 };
829 
830                 assert!(
831                     len >= 0,
832                     "unexpected negative return from sqlite3_column_bytes"
833                 );
834                 if len > 0 {
835                     assert!(
836                         !blob.is_null(),
837                         "unexpected SQLITE_BLOB column type with NULL data"
838                     );
839                     ValueRef::Blob(unsafe { from_raw_parts(blob.cast::<u8>(), len as usize) })
840                 } else {
841                     // The return value from sqlite3_column_blob() for a zero-length BLOB
842                     // is a NULL pointer.
843                     ValueRef::Blob(&[])
844                 }
845             }
846             _ => unreachable!("sqlite3_column_type returned invalid value"),
847         }
848     }
849 
850     #[inline]
step(&self) -> Result<bool>851     pub(super) fn step(&self) -> Result<bool> {
852         match self.stmt.step() {
853             ffi::SQLITE_ROW => Ok(true),
854             ffi::SQLITE_DONE => Ok(false),
855             code => Err(self.conn.decode_result(code).unwrap_err()),
856         }
857     }
858 
859     #[inline]
reset(&self) -> Result<()>860     pub(super) fn reset(&self) -> Result<()> {
861         match self.stmt.reset() {
862             ffi::SQLITE_OK => Ok(()),
863             code => Err(self.conn.decode_result(code).unwrap_err()),
864         }
865     }
866 }
867 
868 /// Prepared statement status counters.
869 ///
870 /// See `https://www.sqlite.org/c3ref/c_stmtstatus_counter.html`
871 /// for explanations of each.
872 ///
873 /// Note that depending on your version of SQLite, all of these
874 /// may not be available.
875 #[repr(i32)]
876 #[derive(Clone, Copy, PartialEq, Eq)]
877 #[non_exhaustive]
878 pub enum StatementStatus {
879     /// Equivalent to SQLITE_STMTSTATUS_FULLSCAN_STEP
880     FullscanStep = 1,
881     /// Equivalent to SQLITE_STMTSTATUS_SORT
882     Sort = 2,
883     /// Equivalent to SQLITE_STMTSTATUS_AUTOINDEX
884     AutoIndex = 3,
885     /// Equivalent to SQLITE_STMTSTATUS_VM_STEP
886     VmStep = 4,
887     /// Equivalent to SQLITE_STMTSTATUS_REPREPARE (3.20.0)
888     RePrepare = 5,
889     /// Equivalent to SQLITE_STMTSTATUS_RUN (3.20.0)
890     Run = 6,
891     /// Equivalent to SQLITE_STMTSTATUS_FILTER_MISS
892     FilterMiss = 7,
893     /// Equivalent to SQLITE_STMTSTATUS_FILTER_HIT
894     FilterHit = 8,
895     /// Equivalent to SQLITE_STMTSTATUS_MEMUSED (3.20.0)
896     MemUsed = 99,
897 }
898 
899 #[cfg(test)]
900 mod test {
901     use crate::types::ToSql;
902     use crate::{params_from_iter, Connection, Error, Result};
903 
904     #[test]
test_execute_named() -> Result<()>905     fn test_execute_named() -> Result<()> {
906         let db = Connection::open_in_memory()?;
907         db.execute_batch("CREATE TABLE foo(x INTEGER)")?;
908 
909         assert_eq!(
910             db.execute("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)])?,
911             1
912         );
913         assert_eq!(
914             db.execute("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)])?,
915             1
916         );
917         assert_eq!(
918             db.execute(
919                 "INSERT INTO foo(x) VALUES (:x)",
920                 crate::named_params! {":x": 3i32}
921             )?,
922             1
923         );
924 
925         assert_eq!(
926             6i32,
927             db.query_row::<i32, _, _>(
928                 "SELECT SUM(x) FROM foo WHERE x > :x",
929                 &[(":x", &0i32)],
930                 |r| r.get(0)
931             )?
932         );
933         assert_eq!(
934             5i32,
935             db.query_row::<i32, _, _>(
936                 "SELECT SUM(x) FROM foo WHERE x > :x",
937                 &[(":x", &1i32)],
938                 |r| r.get(0)
939             )?
940         );
941         Ok(())
942     }
943 
944     #[test]
test_stmt_execute_named() -> Result<()>945     fn test_stmt_execute_named() -> Result<()> {
946         let db = Connection::open_in_memory()?;
947         let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
948                    INTEGER)";
949         db.execute_batch(sql)?;
950 
951         let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)")?;
952         stmt.execute(&[(":name", &"one")])?;
953 
954         let mut stmt = db.prepare("SELECT COUNT(*) FROM test WHERE name = :name")?;
955         assert_eq!(
956             1i32,
957             stmt.query_row::<i32, _, _>(&[(":name", "one")], |r| r.get(0))?
958         );
959         Ok(())
960     }
961 
962     #[test]
test_query_named() -> Result<()>963     fn test_query_named() -> Result<()> {
964         let db = Connection::open_in_memory()?;
965         let sql = r#"
966         CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
967         INSERT INTO test(id, name) VALUES (1, "one");
968         "#;
969         db.execute_batch(sql)?;
970 
971         let mut stmt = db.prepare("SELECT id FROM test where name = :name")?;
972         let mut rows = stmt.query(&[(":name", "one")])?;
973         let id: Result<i32> = rows.next()?.unwrap().get(0);
974         assert_eq!(Ok(1), id);
975         Ok(())
976     }
977 
978     #[test]
test_query_map_named() -> Result<()>979     fn test_query_map_named() -> Result<()> {
980         let db = Connection::open_in_memory()?;
981         let sql = r#"
982         CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
983         INSERT INTO test(id, name) VALUES (1, "one");
984         "#;
985         db.execute_batch(sql)?;
986 
987         let mut stmt = db.prepare("SELECT id FROM test where name = :name")?;
988         let mut rows = stmt.query_map(&[(":name", "one")], |row| {
989             let id: Result<i32> = row.get(0);
990             id.map(|i| 2 * i)
991         })?;
992 
993         let doubled_id: i32 = rows.next().unwrap()?;
994         assert_eq!(2, doubled_id);
995         Ok(())
996     }
997 
998     #[test]
test_query_and_then_by_name() -> Result<()>999     fn test_query_and_then_by_name() -> Result<()> {
1000         let db = Connection::open_in_memory()?;
1001         let sql = r#"
1002         CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
1003         INSERT INTO test(id, name) VALUES (1, "one");
1004         INSERT INTO test(id, name) VALUES (2, "one");
1005         "#;
1006         db.execute_batch(sql)?;
1007 
1008         let mut stmt = db.prepare("SELECT id FROM test where name = :name ORDER BY id ASC")?;
1009         let mut rows = stmt.query_and_then(&[(":name", "one")], |row| {
1010             let id: i32 = row.get(0)?;
1011             if id == 1 {
1012                 Ok(id)
1013             } else {
1014                 Err(Error::SqliteSingleThreadedMode)
1015             }
1016         })?;
1017 
1018         // first row should be Ok
1019         let doubled_id: i32 = rows.next().unwrap()?;
1020         assert_eq!(1, doubled_id);
1021 
1022         // second row should be an `Err`
1023         #[allow(clippy::match_wild_err_arm)]
1024         match rows.next().unwrap() {
1025             Ok(_) => panic!("invalid Ok"),
1026             Err(Error::SqliteSingleThreadedMode) => (),
1027             Err(_) => panic!("invalid Err"),
1028         }
1029         Ok(())
1030     }
1031 
1032     #[test]
test_unbound_parameters_are_null() -> Result<()>1033     fn test_unbound_parameters_are_null() -> Result<()> {
1034         let db = Connection::open_in_memory()?;
1035         let sql = "CREATE TABLE test (x TEXT, y TEXT)";
1036         db.execute_batch(sql)?;
1037 
1038         let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")?;
1039         stmt.execute(&[(":x", &"one")])?;
1040 
1041         let result: Option<String> = db.one_column("SELECT y FROM test WHERE x = 'one'")?;
1042         assert!(result.is_none());
1043         Ok(())
1044     }
1045 
1046     #[test]
test_raw_binding() -> Result<()>1047     fn test_raw_binding() -> Result<()> {
1048         let db = Connection::open_in_memory()?;
1049         db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?;
1050         {
1051             let mut stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?;
1052 
1053             let name_idx = stmt.parameter_index(":name")?.unwrap();
1054             stmt.raw_bind_parameter(name_idx, "example")?;
1055             stmt.raw_bind_parameter(3, 50i32)?;
1056             let n = stmt.raw_execute()?;
1057             assert_eq!(n, 1);
1058         }
1059 
1060         {
1061             let mut stmt = db.prepare("SELECT name, value FROM test WHERE value = ?2")?;
1062             stmt.raw_bind_parameter(2, 50)?;
1063             let mut rows = stmt.raw_query();
1064             {
1065                 let row = rows.next()?.unwrap();
1066                 let name: String = row.get(0)?;
1067                 assert_eq!(name, "example");
1068                 let value: i32 = row.get(1)?;
1069                 assert_eq!(value, 50);
1070             }
1071             assert!(rows.next()?.is_none());
1072         }
1073 
1074         Ok(())
1075     }
1076 
1077     #[test]
test_unbound_parameters_are_reused() -> Result<()>1078     fn test_unbound_parameters_are_reused() -> Result<()> {
1079         let db = Connection::open_in_memory()?;
1080         let sql = "CREATE TABLE test (x TEXT, y TEXT)";
1081         db.execute_batch(sql)?;
1082 
1083         let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")?;
1084         stmt.execute(&[(":x", "one")])?;
1085         stmt.execute(&[(":y", "two")])?;
1086 
1087         let result: String = db.one_column("SELECT x FROM test WHERE y = 'two'")?;
1088         assert_eq!(result, "one");
1089         Ok(())
1090     }
1091 
1092     #[test]
test_insert() -> Result<()>1093     fn test_insert() -> Result<()> {
1094         let db = Connection::open_in_memory()?;
1095         db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)")?;
1096         let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?1)")?;
1097         assert_eq!(stmt.insert([1i32])?, 1);
1098         assert_eq!(stmt.insert([2i32])?, 2);
1099         match stmt.insert([1i32]).unwrap_err() {
1100             Error::StatementChangedRows(0) => (),
1101             err => panic!("Unexpected error {err}"),
1102         }
1103         let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")?;
1104         match multi.insert([]).unwrap_err() {
1105             Error::StatementChangedRows(2) => (),
1106             err => panic!("Unexpected error {err}"),
1107         }
1108         Ok(())
1109     }
1110 
1111     #[test]
test_insert_different_tables() -> Result<()>1112     fn test_insert_different_tables() -> Result<()> {
1113         // Test for https://github.com/rusqlite/rusqlite/issues/171
1114         let db = Connection::open_in_memory()?;
1115         db.execute_batch(
1116             r"
1117             CREATE TABLE foo(x INTEGER);
1118             CREATE TABLE bar(x INTEGER);
1119         ",
1120         )?;
1121 
1122         assert_eq!(db.prepare("INSERT INTO foo VALUES (10)")?.insert([])?, 1);
1123         assert_eq!(db.prepare("INSERT INTO bar VALUES (10)")?.insert([])?, 1);
1124         Ok(())
1125     }
1126 
1127     #[test]
test_exists() -> Result<()>1128     fn test_exists() -> Result<()> {
1129         let db = Connection::open_in_memory()?;
1130         let sql = "BEGIN;
1131                    CREATE TABLE foo(x INTEGER);
1132                    INSERT INTO foo VALUES(1);
1133                    INSERT INTO foo VALUES(2);
1134                    END;";
1135         db.execute_batch(sql)?;
1136         let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?1")?;
1137         assert!(stmt.exists([1i32])?);
1138         assert!(stmt.exists([2i32])?);
1139         assert!(!stmt.exists([0i32])?);
1140         Ok(())
1141     }
1142     #[test]
test_tuple_params() -> Result<()>1143     fn test_tuple_params() -> Result<()> {
1144         let db = Connection::open_in_memory()?;
1145         let s = db.query_row("SELECT printf('[%s]', ?1)", ("abc",), |r| {
1146             r.get::<_, String>(0)
1147         })?;
1148         assert_eq!(s, "[abc]");
1149         let s = db.query_row(
1150             "SELECT printf('%d %s %d', ?1, ?2, ?3)",
1151             (1i32, "abc", 2i32),
1152             |r| r.get::<_, String>(0),
1153         )?;
1154         assert_eq!(s, "1 abc 2");
1155         let s = db.query_row(
1156             "SELECT printf('%d %s %d %d', ?1, ?2, ?3, ?4)",
1157             (1, "abc", 2i32, 4i64),
1158             |r| r.get::<_, String>(0),
1159         )?;
1160         assert_eq!(s, "1 abc 2 4");
1161         #[rustfmt::skip]
1162         let bigtup = (
1163             0, "a", 1, "b", 2, "c", 3, "d",
1164             4, "e", 5, "f", 6, "g", 7, "h",
1165         );
1166         let query = "SELECT printf(
1167             '%d %s | %d %s | %d %s | %d %s || %d %s | %d %s | %d %s | %d %s',
1168             ?1, ?2, ?3, ?4,
1169             ?5, ?6, ?7, ?8,
1170             ?9, ?10, ?11, ?12,
1171             ?13, ?14, ?15, ?16
1172         )";
1173         let s = db.query_row(query, bigtup, |r| r.get::<_, String>(0))?;
1174         assert_eq!(s, "0 a | 1 b | 2 c | 3 d || 4 e | 5 f | 6 g | 7 h");
1175         Ok(())
1176     }
1177 
1178     #[test]
test_query_row() -> Result<()>1179     fn test_query_row() -> Result<()> {
1180         let db = Connection::open_in_memory()?;
1181         let sql = "BEGIN;
1182                    CREATE TABLE foo(x INTEGER, y INTEGER);
1183                    INSERT INTO foo VALUES(1, 3);
1184                    INSERT INTO foo VALUES(2, 4);
1185                    END;";
1186         db.execute_batch(sql)?;
1187         let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?1")?;
1188         let y: Result<i64> = stmt.query_row([1i32], |r| r.get(0));
1189         assert_eq!(3i64, y?);
1190         Ok(())
1191     }
1192 
1193     #[test]
test_query_by_column_name() -> Result<()>1194     fn test_query_by_column_name() -> Result<()> {
1195         let db = Connection::open_in_memory()?;
1196         let sql = "BEGIN;
1197                    CREATE TABLE foo(x INTEGER, y INTEGER);
1198                    INSERT INTO foo VALUES(1, 3);
1199                    END;";
1200         db.execute_batch(sql)?;
1201         let mut stmt = db.prepare("SELECT y FROM foo")?;
1202         let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
1203         assert_eq!(3i64, y?);
1204         Ok(())
1205     }
1206 
1207     #[test]
test_query_by_column_name_ignore_case() -> Result<()>1208     fn test_query_by_column_name_ignore_case() -> Result<()> {
1209         let db = Connection::open_in_memory()?;
1210         let sql = "BEGIN;
1211                    CREATE TABLE foo(x INTEGER, y INTEGER);
1212                    INSERT INTO foo VALUES(1, 3);
1213                    END;";
1214         db.execute_batch(sql)?;
1215         let mut stmt = db.prepare("SELECT y as Y FROM foo")?;
1216         let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
1217         assert_eq!(3i64, y?);
1218         Ok(())
1219     }
1220 
1221     #[test]
test_expanded_sql() -> Result<()>1222     fn test_expanded_sql() -> Result<()> {
1223         let db = Connection::open_in_memory()?;
1224         let stmt = db.prepare("SELECT ?1")?;
1225         stmt.bind_parameter(&1, 1)?;
1226         assert_eq!(Some("SELECT 1".to_owned()), stmt.expanded_sql());
1227         Ok(())
1228     }
1229 
1230     #[test]
test_bind_parameters() -> Result<()>1231     fn test_bind_parameters() -> Result<()> {
1232         let db = Connection::open_in_memory()?;
1233         // dynamic slice:
1234         db.query_row(
1235             "SELECT ?1, ?2, ?3",
1236             [&1u8 as &dyn ToSql, &"one", &Some("one")],
1237             |row| row.get::<_, u8>(0),
1238         )?;
1239         // existing collection:
1240         let data = vec![1, 2, 3];
1241         db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
1242             row.get::<_, u8>(0)
1243         })?;
1244         db.query_row(
1245             "SELECT ?1, ?2, ?3",
1246             params_from_iter(data.as_slice()),
1247             |row| row.get::<_, u8>(0),
1248         )?;
1249         db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data), |row| {
1250             row.get::<_, u8>(0)
1251         })?;
1252 
1253         use std::collections::BTreeSet;
1254         let data: BTreeSet<String> = ["one", "two", "three"]
1255             .iter()
1256             .map(|s| (*s).to_string())
1257             .collect();
1258         db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
1259             row.get::<_, String>(0)
1260         })?;
1261 
1262         let data = [0; 3];
1263         db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
1264             row.get::<_, u8>(0)
1265         })?;
1266         db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data.iter()), |row| {
1267             row.get::<_, u8>(0)
1268         })?;
1269         Ok(())
1270     }
1271 
1272     #[test]
test_parameter_name() -> Result<()>1273     fn test_parameter_name() -> Result<()> {
1274         let db = Connection::open_in_memory()?;
1275         db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?;
1276         let stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?;
1277         assert_eq!(stmt.parameter_name(0), None);
1278         assert_eq!(stmt.parameter_name(1), Some(":name"));
1279         assert_eq!(stmt.parameter_name(2), None);
1280         Ok(())
1281     }
1282 
1283     #[test]
test_empty_stmt() -> Result<()>1284     fn test_empty_stmt() -> Result<()> {
1285         let conn = Connection::open_in_memory()?;
1286         let mut stmt = conn.prepare("")?;
1287         assert_eq!(0, stmt.column_count());
1288         stmt.parameter_index("test").unwrap();
1289         stmt.step().unwrap_err();
1290         stmt.reset().unwrap(); // SQLITE_OMIT_AUTORESET = false
1291         stmt.execute([]).unwrap_err();
1292         Ok(())
1293     }
1294 
1295     #[test]
test_comment_stmt() -> Result<()>1296     fn test_comment_stmt() -> Result<()> {
1297         let conn = Connection::open_in_memory()?;
1298         conn.prepare("/*SELECT 1;*/")?;
1299         Ok(())
1300     }
1301 
1302     #[test]
test_comment_and_sql_stmt() -> Result<()>1303     fn test_comment_and_sql_stmt() -> Result<()> {
1304         let conn = Connection::open_in_memory()?;
1305         let stmt = conn.prepare("/*...*/ SELECT 1;")?;
1306         assert_eq!(1, stmt.column_count());
1307         Ok(())
1308     }
1309 
1310     #[test]
test_semi_colon_stmt() -> Result<()>1311     fn test_semi_colon_stmt() -> Result<()> {
1312         let conn = Connection::open_in_memory()?;
1313         let stmt = conn.prepare(";")?;
1314         assert_eq!(0, stmt.column_count());
1315         Ok(())
1316     }
1317 
1318     #[test]
test_utf16_conversion() -> Result<()>1319     fn test_utf16_conversion() -> Result<()> {
1320         let db = Connection::open_in_memory()?;
1321         db.pragma_update(None, "encoding", "UTF-16le")?;
1322         let encoding: String = db.pragma_query_value(None, "encoding", |row| row.get(0))?;
1323         assert_eq!("UTF-16le", encoding);
1324         db.execute_batch("CREATE TABLE foo(x TEXT)")?;
1325         let expected = "テスト";
1326         db.execute("INSERT INTO foo(x) VALUES (?1)", [&expected])?;
1327         let actual: String = db.one_column("SELECT x FROM foo")?;
1328         assert_eq!(expected, actual);
1329         Ok(())
1330     }
1331 
1332     #[test]
test_nul_byte() -> Result<()>1333     fn test_nul_byte() -> Result<()> {
1334         let db = Connection::open_in_memory()?;
1335         let expected = "a\x00b";
1336         let actual: String = db.query_row("SELECT ?1", [expected], |row| row.get(0))?;
1337         assert_eq!(expected, actual);
1338         Ok(())
1339     }
1340 
1341     #[test]
1342     #[cfg(feature = "modern_sqlite")]
is_explain() -> Result<()>1343     fn is_explain() -> Result<()> {
1344         let db = Connection::open_in_memory()?;
1345         let stmt = db.prepare("SELECT 1;")?;
1346         assert_eq!(0, stmt.is_explain());
1347         Ok(())
1348     }
1349 
1350     #[test]
readonly() -> Result<()>1351     fn readonly() -> Result<()> {
1352         let db = Connection::open_in_memory()?;
1353         let stmt = db.prepare("SELECT 1;")?;
1354         assert!(stmt.readonly());
1355         Ok(())
1356     }
1357 
1358     #[test]
1359     #[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0
test_error_offset() -> Result<()>1360     fn test_error_offset() -> Result<()> {
1361         use crate::ffi::ErrorCode;
1362         let db = Connection::open_in_memory()?;
1363         let r = db.execute_batch("SELECT INVALID_FUNCTION;");
1364         match r.unwrap_err() {
1365             Error::SqlInputError { error, offset, .. } => {
1366                 assert_eq!(error.code, ErrorCode::Unknown);
1367                 assert_eq!(offset, 7);
1368             }
1369             err => panic!("Unexpected error {err}"),
1370         }
1371         Ok(())
1372     }
1373 }
1374