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(¶m, 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 _, // TODO SQLITE_UTF8_ZT
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 #[inline]
695 #[allow(clippy::unnecessary_wraps)]
696 fn check_update(&self) -> Result<()> {
697 cfg_select! {
698 feature = "extra_check" => {
699 if self.column_count() > 0 && self.stmt.readonly() {
700 return Err(Error::ExecuteReturnedResults);
701 }
702 }
703 _ => {}
704 }
705 Ok(())
706 }
707
708 /// Returns a string containing the SQL text of prepared statement with
709 /// bound parameters expanded.
710 pub fn expanded_sql(&self) -> Option<String> {
711 self.stmt
712 .expanded_sql()
713 .map(|s| s.to_string_lossy().to_string())
714 }
715
716 /// Get the value for one of the status counters for this statement.
717 #[inline]
718 pub fn get_status(&self, status: StatementStatus) -> i32 {
719 self.stmt.get_status(status, false)
720 }
721
722 /// Reset the value of one of the status counters for this statement,
723 #[inline]
724 /// returning the value it had before resetting.
725 pub fn reset_status(&self, status: StatementStatus) -> i32 {
726 self.stmt.get_status(status, true)
727 }
728
729 /// Returns 1 if the prepared statement is an EXPLAIN statement,
730 /// or 2 if the statement is an EXPLAIN QUERY PLAN,
731 /// or 0 if it is an ordinary statement or a NULL pointer.
732 #[inline]
733 pub fn is_explain(&self) -> i32 {
734 self.stmt.is_explain()
735 }
736
737 /// Returns true if the statement is read only.
738 #[inline]
739 pub fn readonly(&self) -> bool {
740 self.stmt.readonly()
741 }
742
743 /// Safety: This is unsafe, because using `sqlite3_stmt` after the
744 /// connection has closed is illegal, but `RawStatement` does not enforce
745 /// this, as it loses our protective `'conn` lifetime bound.
746 #[inline]
747 #[cfg(feature = "cache")]
748 pub(crate) unsafe fn into_raw(mut self) -> RawStatement {
749 let mut stmt = RawStatement::new(ptr::null_mut());
750 mem::swap(&mut stmt, &mut self.stmt);
751 stmt
752 }
753
754 /// Reset all bindings
755 pub fn clear_bindings(&mut self) {
756 self.stmt.clear_bindings();
757 }
758
759 pub(crate) unsafe fn ptr(&self) -> *mut ffi::sqlite3_stmt {
760 self.stmt.ptr()
761 }
762}
763
764impl fmt::Debug for Statement<'_> {
765 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
766 let sql = if self.stmt.is_null() {
767 Ok("")
768 } else {
769 self.stmt.sql().unwrap().to_str()
770 };
771 f.debug_struct("Statement")
772 .field("conn", self.conn)
773 .field("stmt", &self.stmt)
774 .field("sql", &sql)
775 .finish()
776 }
777}
778
779impl Drop for Statement<'_> {
780 #[expect(unused_must_use)]
781 #[inline]
782 fn drop(&mut self) {
783 self.finalize_();
784 }
785}
786
787impl Statement<'_> {
788 #[inline]
789 pub(super) fn new(conn: &Connection, stmt: RawStatement) -> Statement<'_> {
790 Statement { conn, stmt }
791 }
792
793 pub(super) fn value_ref(&self, col: usize) -> ValueRef<'_> {
794 let raw = unsafe { self.stmt.ptr() };
795
796 match self.stmt.column_type(col) {
797 ffi::SQLITE_NULL => ValueRef::Null,
798 ffi::SQLITE_INTEGER => {
799 ValueRef::Integer(unsafe { ffi::sqlite3_column_int64(raw, col as c_int) })
800 }
801 ffi::SQLITE_FLOAT => {
802 ValueRef::Real(unsafe { ffi::sqlite3_column_double(raw, col as c_int) })
803 }
804 ffi::SQLITE_TEXT => {
805 let s = unsafe {
806 // Quoting from "Using SQLite" book:
807 // To avoid problems, an application should first extract the desired type using
808 // a sqlite3_column_xxx() function, and then call the
809 // appropriate sqlite3_column_bytes() function.
810 let text = ffi::sqlite3_column_text(raw, col as c_int);
811 let len = ffi::sqlite3_column_bytes(raw, col as c_int);
812 assert!(
813 !text.is_null(),
814 "unexpected SQLITE_TEXT column type with NULL data"
815 );
816 from_raw_parts(text.cast::<u8>(), len as usize)
817 };
818
819 ValueRef::Text(s)
820 }
821 ffi::SQLITE_BLOB => {
822 let (blob, len) = unsafe {
823 (
824 ffi::sqlite3_column_blob(raw, col as c_int),
825 ffi::sqlite3_column_bytes(raw, col as c_int),
826 )
827 };
828
829 assert!(
830 len >= 0,
831 "unexpected negative return from sqlite3_column_bytes"
832 );
833 if len > 0 {
834 assert!(
835 !blob.is_null(),
836 "unexpected SQLITE_BLOB column type with NULL data"
837 );
838 ValueRef::Blob(unsafe { from_raw_parts(blob.cast::<u8>(), len as usize) })
839 } else {
840 // The return value from sqlite3_column_blob() for a zero-length BLOB
841 // is a NULL pointer.
842 ValueRef::Blob(&[])
843 }
844 }
845 _ => unreachable!("sqlite3_column_type returned invalid value"),
846 }
847 }
848
849 #[inline]
850 pub(super) fn step(&self) -> Result<bool> {
851 match self.stmt.step() {
852 ffi::SQLITE_ROW => Ok(true),
853 ffi::SQLITE_DONE => Ok(false),
854 code => Err(self.conn.decode_result(code).unwrap_err()),
855 }
856 }
857
858 #[inline]
859 pub(super) fn reset(&self) -> Result<()> {
860 match self.stmt.reset() {
861 ffi::SQLITE_OK => Ok(()),
862 code => Err(self.conn.decode_result(code).unwrap_err()),
863 }
864 }
865}
866
867/// Prepared statement status counters.
868///
869/// See `https://www.sqlite.org/c3ref/c_stmtstatus_counter.html`
870/// for explanations of each.
871///
872/// Note that depending on your version of SQLite, all of these
873/// may not be available.
874#[repr(i32)]
875#[derive(Clone, Copy, PartialEq, Eq)]
876#[non_exhaustive]
877pub enum StatementStatus {
878 /// Equivalent to `SQLITE_STMTSTATUS_FULLSCAN_STEP`
879 FullscanStep = 1,
880 /// Equivalent to `SQLITE_STMTSTATUS_SORT`
881 Sort = 2,
882 /// Equivalent to `SQLITE_STMTSTATUS_AUTOINDEX`
883 AutoIndex = 3,
884 /// Equivalent to `SQLITE_STMTSTATUS_VM_STEP`
885 VmStep = 4,
886 /// Equivalent to `SQLITE_STMTSTATUS_REPREPARE` (3.20.0)
887 RePrepare = 5,
888 /// Equivalent to `SQLITE_STMTSTATUS_RUN` (3.20.0)
889 Run = 6,
890 /// Equivalent to `SQLITE_STMTSTATUS_FILTER_MISS`
891 FilterMiss = 7,
892 /// Equivalent to `SQLITE_STMTSTATUS_FILTER_HIT`
893 FilterHit = 8,
894 /// Equivalent to `SQLITE_STMTSTATUS_MEMUSED` (3.20.0)
895 MemUsed = 99,
896}
897
898#[cfg(all(test, not(miri)))]
899mod test {
900 #[cfg(all(target_family = "wasm", target_os = "unknown"))]
901 use wasm_bindgen_test::wasm_bindgen_test as test;
902
903 use crate::types::ToSql;
904 use crate::{params_from_iter, Connection, Error, Result};
905
906 #[test]
907 fn test_execute_named() -> Result<()> {
908 let db = Connection::open_in_memory()?;
909 db.execute_batch("CREATE TABLE foo(x INTEGER)")?;
910
911 assert_eq!(
912 db.execute("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)])?,
913 1
914 );
915 assert_eq!(
916 db.execute("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)])?,
917 1
918 );
919 assert_eq!(
920 db.execute(
921 "INSERT INTO foo(x) VALUES (:x)",
922 crate::named_params! {":x": 3i32}
923 )?,
924 1
925 );
926
927 assert_eq!(
928 6i32,
929 db.query_row::<i32, _, _>(
930 "SELECT SUM(x) FROM foo WHERE x > :x",
931 &[(":x", &0i32)],
932 |r| r.get(0)
933 )?
934 );
935 assert_eq!(
936 5i32,
937 db.query_row::<i32, _, _>(
938 "SELECT SUM(x) FROM foo WHERE x > :x",
939 &[(":x", &1i32)],
940 |r| r.get(0)
941 )?
942 );
943 Ok(())
944 }
945
946 #[test]
947 fn test_stmt_execute_named() -> Result<()> {
948 let db = Connection::open_in_memory()?;
949 let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
950 INTEGER)";
951 db.execute_batch(sql)?;
952
953 let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)")?;
954 stmt.execute(&[(":name", "one")])?;
955 stmt.execute(vec![(":name", "one")].as_slice())?;
956
957 let mut stmt = db.prepare("SELECT COUNT(*) FROM test WHERE name = :name")?;
958 assert_eq!(
959 2i32,
960 stmt.query_row::<i32, _, _>(&[(":name", "one")], |r| r.get(0))?
961 );
962 Ok(())
963 }
964
965 #[test]
966 fn test_query_named() -> Result<()> {
967 let db = Connection::open_in_memory()?;
968 let sql = r#"
969 CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
970 INSERT INTO test(id, name) VALUES (1, "one");
971 "#;
972 db.execute_batch(sql)?;
973
974 let mut stmt = db.prepare("SELECT id FROM test where name = :name")?;
975 let mut rows = stmt.query(&[(":name", "one")])?;
976 let id: Result<i32> = rows.next()?.unwrap().get(0);
977 assert_eq!(Ok(1), id);
978 Ok(())
979 }
980
981 #[test]
982 fn test_query_map_named() -> Result<()> {
983 let db = Connection::open_in_memory()?;
984 let sql = r#"
985 CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
986 INSERT INTO test(id, name) VALUES (1, "one");
987 "#;
988 db.execute_batch(sql)?;
989
990 let mut stmt = db.prepare("SELECT id FROM test where name = :name")?;
991 let mut rows = stmt.query_map(&[(":name", "one")], |row| {
992 let id: Result<i32> = row.get(0);
993 id.map(|i| 2 * i)
994 })?;
995
996 let doubled_id: i32 = rows.next().unwrap()?;
997 assert_eq!(2, doubled_id);
998 Ok(())
999 }
1000
1001 #[test]
1002 fn test_query_and_then_by_name() -> Result<()> {
1003 let db = Connection::open_in_memory()?;
1004 let sql = r#"
1005 CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag INTEGER);
1006 INSERT INTO test(id, name) VALUES (1, "one");
1007 INSERT INTO test(id, name) VALUES (2, "one");
1008 "#;
1009 db.execute_batch(sql)?;
1010
1011 let mut stmt = db.prepare("SELECT id FROM test where name = :name ORDER BY id ASC")?;
1012 let mut rows = stmt.query_and_then(&[(":name", "one")], |row| {
1013 let id: i32 = row.get(0)?;
1014 if id == 1 {
1015 Ok(id)
1016 } else {
1017 Err(Error::SqliteSingleThreadedMode)
1018 }
1019 })?;
1020
1021 // first row should be Ok
1022 let doubled_id: i32 = rows.next().unwrap()?;
1023 assert_eq!(1, doubled_id);
1024
1025 // second row should be an `Err`
1026 #[expect(clippy::match_wild_err_arm)]
1027 match rows.next().unwrap() {
1028 Ok(_) => panic!("invalid Ok"),
1029 Err(Error::SqliteSingleThreadedMode) => (),
1030 Err(_) => panic!("invalid Err"),
1031 }
1032 Ok(())
1033 }
1034
1035 #[test]
1036 fn test_unbound_parameters_are_null() -> Result<()> {
1037 let db = Connection::open_in_memory()?;
1038 let sql = "CREATE TABLE test (x TEXT, y TEXT)";
1039 db.execute_batch(sql)?;
1040
1041 let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")?;
1042 stmt.execute(&[(":x", "one")])?;
1043
1044 let result: Option<String> = db.one_column("SELECT y FROM test WHERE x = 'one'", [])?;
1045 assert!(result.is_none());
1046 Ok(())
1047 }
1048
1049 #[test]
1050 fn test_raw_binding() -> Result<()> {
1051 let db = Connection::open_in_memory()?;
1052 db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?;
1053 {
1054 let mut stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?;
1055
1056 stmt.raw_bind_parameter(c":name", "example")?;
1057 stmt.raw_bind_parameter(":name", "example")?;
1058 stmt.raw_bind_parameter(3, 50i32)?;
1059 let n = stmt.raw_execute()?;
1060 assert_eq!(n, 1);
1061 }
1062
1063 {
1064 let mut stmt = db.prepare("SELECT name, value FROM test WHERE value = ?2")?;
1065 stmt.raw_bind_parameter(2, 50)?;
1066 let mut rows = stmt.raw_query();
1067 {
1068 let row = rows.next()?.unwrap();
1069 let name: String = row.get(0)?;
1070 assert_eq!(name, "example");
1071 let value: i32 = row.get(1)?;
1072 assert_eq!(value, 50);
1073 }
1074 assert!(rows.next()?.is_none());
1075 }
1076
1077 Ok(())
1078 }
1079
1080 #[test]
1081 fn test_unbound_parameters_are_reused() -> Result<()> {
1082 let db = Connection::open_in_memory()?;
1083 let sql = "CREATE TABLE test (x TEXT, y TEXT)";
1084 db.execute_batch(sql)?;
1085
1086 let mut stmt = db.prepare("INSERT INTO test (x, y) VALUES (:x, :y)")?;
1087 stmt.execute(&[(":x", "one")])?;
1088 stmt.execute(&[(c":y", "two")])?;
1089
1090 let result: String = db.one_column("SELECT x FROM test WHERE y = 'two'", [])?;
1091 assert_eq!(result, "one");
1092 Ok(())
1093 }
1094
1095 #[test]
1096 fn test_insert() -> Result<()> {
1097 let db = Connection::open_in_memory()?;
1098 db.execute_batch("CREATE TABLE foo(x INTEGER UNIQUE)")?;
1099 let mut stmt = db.prepare("INSERT OR IGNORE INTO foo (x) VALUES (?1)")?;
1100 assert_eq!(stmt.insert([1i32])?, 1);
1101 assert_eq!(stmt.insert([2i32])?, 2);
1102 match stmt.insert([1i32]).unwrap_err() {
1103 Error::StatementChangedRows(0) => (),
1104 err => panic!("Unexpected error {err}"),
1105 }
1106 let mut multi = db.prepare("INSERT INTO foo (x) SELECT 3 UNION ALL SELECT 4")?;
1107 match multi.insert([]).unwrap_err() {
1108 Error::StatementChangedRows(2) => (),
1109 err => panic!("Unexpected error {err}"),
1110 }
1111 Ok(())
1112 }
1113
1114 #[test]
1115 fn test_insert_different_tables() -> Result<()> {
1116 // Test for https://github.com/rusqlite/rusqlite/issues/171
1117 let db = Connection::open_in_memory()?;
1118 db.execute_batch(
1119 r"
1120 CREATE TABLE foo(x INTEGER);
1121 CREATE TABLE bar(x INTEGER);
1122 ",
1123 )?;
1124
1125 assert_eq!(db.prepare("INSERT INTO foo VALUES (10)")?.insert([])?, 1);
1126 assert_eq!(db.prepare("INSERT INTO bar VALUES (10)")?.insert([])?, 1);
1127 Ok(())
1128 }
1129
1130 #[test]
1131 fn test_exists() -> Result<()> {
1132 let db = Connection::open_in_memory()?;
1133 let sql = "BEGIN;
1134 CREATE TABLE foo(x INTEGER);
1135 INSERT INTO foo VALUES(1);
1136 INSERT INTO foo VALUES(2);
1137 END;";
1138 db.execute_batch(sql)?;
1139 let mut stmt = db.prepare("SELECT 1 FROM foo WHERE x = ?1")?;
1140 assert!(stmt.exists([1i32])?);
1141 assert!(stmt.exists([2i32])?);
1142 assert!(!stmt.exists([0i32])?);
1143 Ok(())
1144 }
1145 #[test]
1146 fn test_tuple_params() -> Result<()> {
1147 let db = Connection::open_in_memory()?;
1148 let s = db.query_row("SELECT printf('[%s]', ?1)", ("abc",), |r| {
1149 r.get::<_, String>(0)
1150 })?;
1151 assert_eq!(s, "[abc]");
1152 let s = db.query_row(
1153 "SELECT printf('%d %s %d', ?1, ?2, ?3)",
1154 (1i32, "abc", 2i32),
1155 |r| r.get::<_, String>(0),
1156 )?;
1157 assert_eq!(s, "1 abc 2");
1158 let s = db.query_row(
1159 "SELECT printf('%d %s %d %d', ?1, ?2, ?3, ?4)",
1160 (1, "abc", 2i32, 4i64),
1161 |r| r.get::<_, String>(0),
1162 )?;
1163 assert_eq!(s, "1 abc 2 4");
1164 #[rustfmt::skip]
1165 let bigtup = (
1166 0, "a", 1, "b", 2, "c", 3, "d",
1167 4, "e", 5, "f", 6, "g", 7, "h",
1168 );
1169 let query = "SELECT printf(
1170 '%d %s | %d %s | %d %s | %d %s || %d %s | %d %s | %d %s | %d %s',
1171 ?1, ?2, ?3, ?4,
1172 ?5, ?6, ?7, ?8,
1173 ?9, ?10, ?11, ?12,
1174 ?13, ?14, ?15, ?16
1175 )";
1176 let s = db.query_row(query, bigtup, |r| r.get::<_, String>(0))?;
1177 assert_eq!(s, "0 a | 1 b | 2 c | 3 d || 4 e | 5 f | 6 g | 7 h");
1178 Ok(())
1179 }
1180
1181 #[test]
1182 fn test_query_row() -> Result<()> {
1183 let db = Connection::open_in_memory()?;
1184 let sql = "BEGIN;
1185 CREATE TABLE foo(x INTEGER, y INTEGER);
1186 INSERT INTO foo VALUES(1, 3);
1187 INSERT INTO foo VALUES(2, 4);
1188 END;";
1189 db.execute_batch(sql)?;
1190 let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?1")?;
1191 let y: Result<i64> = stmt.query_row([1i32], |r| r.get(0));
1192 assert_eq!(3i64, y?);
1193 Ok(())
1194 }
1195
1196 #[test]
1197 fn query_one() -> Result<()> {
1198 let db = Connection::open_in_memory()?;
1199 db.execute_batch("CREATE TABLE foo(x INTEGER, y INTEGER);")?;
1200 let mut stmt = db.prepare("SELECT y FROM foo WHERE x = ?1")?;
1201 let y: Result<i64> = stmt.query_one([1i32], |r| r.get(0));
1202 assert_eq!(Error::QueryReturnedNoRows, y.unwrap_err());
1203 db.execute_batch("INSERT INTO foo VALUES(1, 3);")?;
1204 let y: Result<i64> = stmt.query_one([1i32], |r| r.get(0));
1205 assert_eq!(3i64, y?);
1206 db.execute_batch("INSERT INTO foo VALUES(1, 3);")?;
1207 let y: Result<i64> = stmt.query_one([1i32], |r| r.get(0));
1208 assert_eq!(Error::QueryReturnedMoreThanOneRow, y.unwrap_err());
1209 Ok(())
1210 }
1211
1212 #[test]
1213 fn test_query_by_column_name() -> Result<()> {
1214 let db = Connection::open_in_memory()?;
1215 let sql = "BEGIN;
1216 CREATE TABLE foo(x INTEGER, y INTEGER);
1217 INSERT INTO foo VALUES(1, 3);
1218 END;";
1219 db.execute_batch(sql)?;
1220 let mut stmt = db.prepare("SELECT y FROM foo")?;
1221 let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
1222 assert_eq!(3i64, y?);
1223 Ok(())
1224 }
1225
1226 #[test]
1227 fn test_query_by_column_name_ignore_case() -> Result<()> {
1228 let db = Connection::open_in_memory()?;
1229 let sql = "BEGIN;
1230 CREATE TABLE foo(x INTEGER, y INTEGER);
1231 INSERT INTO foo VALUES(1, 3);
1232 END;";
1233 db.execute_batch(sql)?;
1234 let mut stmt = db.prepare("SELECT y as Y FROM foo")?;
1235 let y: Result<i64> = stmt.query_row([], |r| r.get("y"));
1236 assert_eq!(3i64, y?);
1237 Ok(())
1238 }
1239
1240 #[test]
1241 fn test_expanded_sql() -> Result<()> {
1242 let db = Connection::open_in_memory()?;
1243 let stmt = db.prepare("SELECT ?1")?;
1244 stmt.bind_parameter(&1, 1)?;
1245 assert_eq!(Some("SELECT 1".to_owned()), stmt.expanded_sql());
1246 Ok(())
1247 }
1248
1249 #[test]
1250 fn test_bind_parameters() -> Result<()> {
1251 let db = Connection::open_in_memory()?;
1252 // dynamic slice:
1253 db.query_row(
1254 "SELECT ?1, ?2, ?3",
1255 [&1u8 as &dyn ToSql, &"one", &Some("one")],
1256 |row| row.get::<_, u8>(0),
1257 )?;
1258 // existing collection:
1259 let data = vec![1, 2, 3];
1260 db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
1261 row.get::<_, u8>(0)
1262 })?;
1263 db.query_row(
1264 "SELECT ?1, ?2, ?3",
1265 params_from_iter(data.as_slice()),
1266 |row| row.get::<_, u8>(0),
1267 )?;
1268 db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data), |row| {
1269 row.get::<_, u8>(0)
1270 })?;
1271
1272 use std::collections::BTreeSet;
1273 let data: BTreeSet<String> = ["one", "two", "three"]
1274 .iter()
1275 .map(|s| (*s).to_string())
1276 .collect();
1277 db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
1278 row.get::<_, String>(0)
1279 })?;
1280
1281 let data = [0; 3];
1282 db.query_row("SELECT ?1, ?2, ?3", params_from_iter(&data), |row| {
1283 row.get::<_, u8>(0)
1284 })?;
1285 db.query_row("SELECT ?1, ?2, ?3", params_from_iter(data.iter()), |row| {
1286 row.get::<_, u8>(0)
1287 })?;
1288 Ok(())
1289 }
1290
1291 #[test]
1292 fn test_parameter_name() -> Result<()> {
1293 let db = Connection::open_in_memory()?;
1294 db.execute_batch("CREATE TABLE test (name TEXT, value INTEGER)")?;
1295 let stmt = db.prepare("INSERT INTO test (name, value) VALUES (:name, ?3)")?;
1296 assert_eq!(stmt.parameter_name(0), None);
1297 assert_eq!(stmt.parameter_name(1), Some(":name"));
1298 assert_eq!(stmt.parameter_name(2), None);
1299 Ok(())
1300 }
1301
1302 #[test]
1303 fn test_empty_stmt() -> Result<()> {
1304 let conn = Connection::open_in_memory()?;
1305 let mut stmt = conn.prepare("")?;
1306 assert_eq!(0, stmt.column_count());
1307 stmt.parameter_index("test")?;
1308 let err = stmt.step().unwrap_err();
1309 assert_eq!(err.sqlite_error_code(), Some(crate::ErrorCode::ApiMisuse));
1310 assert_eq!(
1311 err.sqlite_extended_error_code(),
1312 Some(crate::ffi::SQLITE_MISUSE)
1313 );
1314 // error msg is different with sqlcipher, so we use assert_ne:
1315 assert_ne!(err.to_string(), "not an error".to_owned());
1316 stmt.reset()?; // SQLITE_OMIT_AUTORESET = false
1317 stmt.execute([]).unwrap_err();
1318 Ok(())
1319 }
1320
1321 #[test]
1322 fn test_comment_stmt() -> Result<()> {
1323 let conn = Connection::open_in_memory()?;
1324 conn.prepare("/*SELECT 1;*/")?;
1325 Ok(())
1326 }
1327
1328 #[test]
1329 fn test_comment_and_sql_stmt() -> Result<()> {
1330 let conn = Connection::open_in_memory()?;
1331 let stmt = conn.prepare("/*...*/ SELECT 1;")?;
1332 assert_eq!(1, stmt.column_count());
1333 Ok(())
1334 }
1335
1336 #[test]
1337 fn test_semi_colon_stmt() -> Result<()> {
1338 let conn = Connection::open_in_memory()?;
1339 let stmt = conn.prepare(";")?;
1340 assert_eq!(0, stmt.column_count());
1341 Ok(())
1342 }
1343
1344 #[test]
1345 fn test_utf16_conversion() -> Result<()> {
1346 let db = Connection::open_in_memory()?;
1347 db.pragma_update(None, "encoding", "UTF-16le")?;
1348 let encoding: String = db.pragma_query_value(None, "encoding", |row| row.get(0))?;
1349 assert_eq!("UTF-16le", encoding);
1350 db.execute_batch("CREATE TABLE foo(x TEXT)")?;
1351 let expected = "ใในใ";
1352 db.execute("INSERT INTO foo(x) VALUES (?1)", [&expected])?;
1353 let actual: String = db.one_column("SELECT x FROM foo", [])?;
1354 assert_eq!(expected, actual);
1355 Ok(())
1356 }
1357
1358 #[test]
1359 fn test_nul_byte() -> Result<()> {
1360 let db = Connection::open_in_memory()?;
1361 let expected = "a\x00b";
1362 let actual: String = db.one_column("SELECT ?1", [expected])?;
1363 assert_eq!(expected, actual);
1364 Ok(())
1365 }
1366
1367 #[test]
1368 fn is_explain() -> Result<()> {
1369 let db = Connection::open_in_memory()?;
1370 let stmt = db.prepare("SELECT 1;")?;
1371 assert_eq!(0, stmt.is_explain());
1372 Ok(())
1373 }
1374
1375 #[test]
1376 fn readonly() -> Result<()> {
1377 let db = Connection::open_in_memory()?;
1378 let stmt = db.prepare("SELECT 1;")?;
1379 assert!(stmt.readonly());
1380 Ok(())
1381 }
1382
1383 #[test]
1384 #[cfg(feature = "modern_sqlite")] // SQLite >= 3.38.0
1385 fn test_error_offset() -> Result<()> {
1386 use crate::ffi::ErrorCode;
1387 let db = Connection::open_in_memory()?;
1388 let r = db.execute_batch("SELECT INVALID_FUNCTION;");
1389 match r.unwrap_err() {
1390 Error::SqlInputError { error, offset, .. } => {
1391 assert_eq!(error.code, ErrorCode::Unknown);
1392 assert_eq!(offset, 7);
1393 }
1394 err => panic!("Unexpected error {err}"),
1395 }
1396 Ok(())
1397 }
1398}