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