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