Skip to main content

rusqlite/
statement.rs

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