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