diff --git a/Cargo.toml b/Cargo.toml index 13ea44f..8d631a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -146,6 +146,8 @@ tempfile = "3.1.0" regex = "1.5.5" uuid = { version = "1.0", features = ["v4"] } unicase = "2.6.0" +ouroboros = "0.18" +self_cell = "1.1.0" # Use `bencher` over criterion because it builds much faster, # and we don't have many benchmarks bencher = "0.1" diff --git a/codecov.yml b/codecov.yml index 7a4789e..639cb2b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,4 +1,5 @@ ignore: + - "examples" - "libsqlite3-sys/bindgen-bindings" - "libsqlite3-sys/sqlite3" coverage: diff --git a/examples/owning_rows.rs b/examples/owning_rows.rs new file mode 100644 index 0000000..38ba3ff --- /dev/null +++ b/examples/owning_rows.rs @@ -0,0 +1,29 @@ +extern crate rusqlite; + +use ouroboros::self_referencing; +use rusqlite::{CachedStatement, Connection, Result, Rows}; + +#[self_referencing] +struct OwningRows<'conn> { + stmt: CachedStatement<'conn>, + #[borrows(mut stmt)] + #[covariant] + rows: Rows<'this>, +} + +fn main() -> Result<()> { + let conn = Connection::open_in_memory()?; + let stmt = conn.prepare_cached("SELECT 1")?; + let mut or = OwningRowsTryBuilder { + stmt, + rows_builder: |s| s.query([]), + } + .try_build()?; + or.with_rows_mut(|rows| -> Result<()> { + while let Some(row) = rows.next()? { + assert_eq!(Ok(1), row.get(0)); + } + Ok(()) + })?; + Ok(()) +} diff --git a/examples/owning_rows_self_cell.rs b/examples/owning_rows_self_cell.rs new file mode 100644 index 0000000..1e42212 --- /dev/null +++ b/examples/owning_rows_self_cell.rs @@ -0,0 +1,27 @@ +extern crate rusqlite; + +use rusqlite::{CachedStatement, Connection, Result, Rows}; +use self_cell::{self_cell, MutBorrow}; + +type RowsRef<'a> = Rows<'a>; + +self_cell!( + struct OwningRows<'conn> { + owner: MutBorrow>, + #[covariant] + dependent: RowsRef, + } +); + +fn main() -> Result<()> { + let conn = Connection::open_in_memory()?; + let stmt = conn.prepare_cached("SELECT 1")?; + let mut or = OwningRows::try_new(MutBorrow::new(stmt), |s| s.borrow_mut().query([]))?; + or.with_dependent_mut(|_stmt, rows| -> Result<()> { + while let Some(row) = rows.next()? { + assert_eq!(Ok(1), row.get(0)); + } + Ok(()) + })?; + Ok(()) +} diff --git a/examples/owning_statement.rs b/examples/owning_statement.rs new file mode 100644 index 0000000..cc45c33 --- /dev/null +++ b/examples/owning_statement.rs @@ -0,0 +1,30 @@ +extern crate rusqlite; +use ouroboros::self_referencing; +use rusqlite::{CachedStatement, Connection, Result, Rows}; + +/// Caveat: single statement at a time for one connection. +/// But if you need multiple statements, you can still create your own struct +/// with multiple fields (one for each statement). +#[self_referencing] +struct OwningStatement { + conn: Connection, + #[borrows(conn)] + #[covariant] + stmt: CachedStatement<'this>, +} + +fn main() -> Result<()> { + let conn = Connection::open_in_memory()?; + + let mut os = OwningStatementTryBuilder { + conn, + stmt_builder: |c| c.prepare_cached("SELECT 1"), + } + .try_build()?; + + let mut rows = os.with_stmt_mut(|stmt| -> Result> { stmt.query([]) })?; + while let Some(row) = rows.next()? { + assert_eq!(Ok(1), row.get(0)); + } + Ok(()) +}