From adf70dc855dccede1ff9d1ecee4b2546c920b838 Mon Sep 17 00:00:00 2001 From: RS2007 Date: Mon, 7 Jul 2025 14:54:15 +0530 Subject: [PATCH 1/2] Return number of rows changed from Connection.execute --- bindings/rust/src/lib.rs | 4 +- bindings/rust/tests/integration_tests.rs | 80 ++++++++++++++++++++++++ core/lib.rs | 4 ++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 13c8eb53c..a3ef69b96 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -312,7 +312,9 @@ impl Statement { return Ok(2); } Ok(turso_core::StepResult::Done) => { - return Ok(0); + let changes = stmt.n_change(); + assert!(changes >= 0); + return Ok(changes as u64); } Ok(turso_core::StepResult::IO) => { let _ = stmt.run_once(); diff --git a/bindings/rust/tests/integration_tests.rs b/bindings/rust/tests/integration_tests.rs index 9a6b9d837..41d0033d2 100644 --- a/bindings/rust/tests/integration_tests.rs +++ b/bindings/rust/tests/integration_tests.rs @@ -115,3 +115,83 @@ async fn test_cacheflush() { fs::remove_file("test.db").await.unwrap(); fs::remove_file("test.db-wal").await.unwrap(); } + +#[tokio::test] +async fn test_rows_returned() { + let db = Builder::new_local(":memory:").build().await.unwrap(); + let conn = db.connect().unwrap(); + + //--- CRUD Operations ---// + conn.execute("CREATE TABLE t(id INTEGER PRIMARY KEY, val TEXT)", ()) + .await + .unwrap(); + let changed = conn + .execute("INSERT INTO t VALUES (1,'hello')", ()) + .await + .unwrap(); + let changed1 = conn + .execute("INSERT INTO t VALUES (2,'hi')", ()) + .await + .unwrap(); + let changed2 = conn + .execute("UPDATE t SET val='hi' WHERE id=1", ()) + .await + .unwrap(); + let changed3 = conn + .execute("DELETE FROM t WHERE val='hi'", ()) + .await + .unwrap(); + assert_eq!(changed, 1); + assert_eq!(changed1, 1); + assert_eq!(changed2, 1); + assert_eq!(changed3, 2); + + //--- A more complicated example of insert with a select join subquery ---// + conn.execute( + "CREATE TABLE authors ( id INTEGER PRIMARY KEY, name TEXT NOT NULL); + ", + (), + ) + .await + .unwrap(); + + conn.execute( + "CREATE TABLE books ( id INTEGER PRIMARY KEY, author_id INTEGER NOT NULL REFERENCES authors(id), title TEXT NOT NULL); " + ,() + ).await.unwrap(); + + conn.execute( + "CREATE TABLE prize_winners ( book_id INTEGER PRIMARY KEY, author_name TEXT NOT NULL);", + (), + ) + .await + .unwrap(); + + conn.execute( + "INSERT INTO authors (id, name) VALUES (1, 'Alice'), (2, 'Bob');", + (), + ) + .await + .unwrap(); + + conn.execute( + "INSERT INTO books (id, author_id, title) VALUES (1, 1, 'Rust in Action'), (2, 1, 'Async Adventures'), (3, 1, 'Fearless Concurrency'), (4, 1, 'Unsafe Tales'), (5, 1, 'Zero-Cost Futures'), (6, 2, 'Learning SQL');", + () + ).await.unwrap(); + + let rows_changed = conn + .execute( + " + INSERT INTO prize_winners (book_id, author_name) + SELECT b.id, a.name + FROM books b + JOIN authors a ON a.id = b.author_id + WHERE a.id = 1; -- Alice’s five books + ", + (), + ) + .await + .unwrap(); + + assert_eq!(rows_changed, 5); +} diff --git a/core/lib.rs b/core/lib.rs index c8666b482..1192cef7f 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -1031,6 +1031,10 @@ impl Statement { } } + pub fn n_change(&self) -> i64 { + return self.program.n_change.get(); + } + pub fn set_mv_tx_id(&mut self, mv_tx_id: Option) { self.state.mv_tx_id = mv_tx_id; } From cd31119972970e5d2917bd1c0e35aad87ae2f73a Mon Sep 17 00:00:00 2001 From: RS2007 Date: Mon, 7 Jul 2025 19:47:14 +0530 Subject: [PATCH 2/2] Fix: cargo clippy warning --- core/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib.rs b/core/lib.rs index 1192cef7f..431a6997d 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -1032,7 +1032,7 @@ impl Statement { } pub fn n_change(&self) -> i64 { - return self.program.n_change.get(); + self.program.n_change.get() } pub fn set_mv_tx_id(&mut self, mv_tx_id: Option) {