libsql-experimental
Advanced tools
+1
-1
@@ -872,3 +872,3 @@ # This file is automatically @generated by Cargo. | ||
| name = "libsql-python" | ||
| version = "0.0.48" | ||
| version = "0.0.49" | ||
| dependencies = [ | ||
@@ -875,0 +875,0 @@ "libsql", |
+1
-1
| [package] | ||
| name = "libsql-python" | ||
| version = "0.0.48" | ||
| version = "0.0.49" | ||
| edition = "2021" | ||
@@ -5,0 +5,0 @@ |
+1
-1
| Metadata-Version: 2.4 | ||
| Name: libsql-experimental | ||
| Version: 0.0.48 | ||
| Version: 0.0.49 | ||
| Classifier: Programming Language :: Rust | ||
@@ -5,0 +5,0 @@ Classifier: Programming Language :: Python :: Implementation :: CPython |
+1
-1
@@ -7,3 +7,3 @@ [build-system] | ||
| name = "libsql-experimental" | ||
| version = "0.0.48" | ||
| version = "0.0.49" | ||
| requires-python = ">=3.7" | ||
@@ -10,0 +10,0 @@ classifiers = [ |
+75
-21
@@ -163,6 +163,6 @@ use ::libsql as libsql_core; | ||
| db, | ||
| conn: Arc::new(ConnectionGuard { | ||
| conn: RefCell::new(Some(Arc::new(ConnectionGuard { | ||
| conn: Some(conn), | ||
| handle: rt.clone(), | ||
| }), | ||
| }))), | ||
| isolation_level, | ||
@@ -203,3 +203,3 @@ autocommit, | ||
| db: libsql_core::Database, | ||
| conn: Arc<ConnectionGuard>, | ||
| conn: RefCell<Option<Arc<ConnectionGuard>>>, | ||
| isolation_level: Option<String>, | ||
@@ -214,6 +214,11 @@ autocommit: i32, | ||
| impl Connection { | ||
| fn close(self_: PyRef<'_, Self>, py: Python<'_>) -> PyResult<()> { | ||
| self_.conn.replace(None); | ||
| Ok(()) | ||
| } | ||
| fn cursor(&self) -> PyResult<Cursor> { | ||
| Ok(Cursor { | ||
| arraysize: 1, | ||
| conn: self.conn.clone(), | ||
| conn: RefCell::new(Some(self.conn.borrow().as_ref().unwrap().clone())), | ||
| stmt: RefCell::new(None), | ||
@@ -241,5 +246,13 @@ rows: RefCell::new(None), | ||
| // TODO: Switch to libSQL transaction API | ||
| if !self_.conn.is_autocommit() { | ||
| rt().block_on(async { self_.conn.execute("COMMIT", ()).await }) | ||
| .map_err(to_py_err)?; | ||
| if !self_.conn.borrow().as_ref().unwrap().is_autocommit() { | ||
| rt().block_on(async { | ||
| self_ | ||
| .conn | ||
| .borrow() | ||
| .as_ref() | ||
| .unwrap() | ||
| .execute("COMMIT", ()) | ||
| .await | ||
| }) | ||
| .map_err(to_py_err)?; | ||
| } | ||
@@ -251,5 +264,13 @@ Ok(()) | ||
| // TODO: Switch to libSQL transaction API | ||
| if !self_.conn.is_autocommit() { | ||
| rt().block_on(async { self_.conn.execute("ROLLBACK", ()).await }) | ||
| .map_err(to_py_err)?; | ||
| if !self_.conn.borrow().as_ref().unwrap().is_autocommit() { | ||
| rt().block_on(async { | ||
| self_ | ||
| .conn | ||
| .borrow() | ||
| .as_ref() | ||
| .unwrap() | ||
| .execute("ROLLBACK", ()) | ||
| .await | ||
| }) | ||
| .map_err(to_py_err)?; | ||
| } | ||
@@ -284,3 +305,11 @@ Ok(()) | ||
| let _ = rt() | ||
| .block_on(async { self_.conn.execute_batch(&script).await }) | ||
| .block_on(async { | ||
| self_ | ||
| .conn | ||
| .borrow() | ||
| .as_ref() | ||
| .unwrap() | ||
| .execute_batch(&script) | ||
| .await | ||
| }) | ||
| .map_err(to_py_err); | ||
@@ -299,5 +328,7 @@ Ok(()) | ||
| { | ||
| return Ok(!self_.conn.is_autocommit() || self_.autocommit == 0); | ||
| return Ok( | ||
| !self_.conn.borrow().as_ref().unwrap().is_autocommit() || self_.autocommit == 0 | ||
| ); | ||
| } | ||
| Ok(!self_.conn.is_autocommit()) | ||
| Ok(!self_.conn.borrow().as_ref().unwrap().is_autocommit()) | ||
| } | ||
@@ -328,3 +359,3 @@ | ||
| arraysize: usize, | ||
| conn: Arc<ConnectionGuard>, | ||
| conn: RefCell<Option<Arc<ConnectionGuard>>>, | ||
| stmt: RefCell<Option<libsql_core::Statement>>, | ||
@@ -343,2 +374,4 @@ rows: RefCell<Option<libsql_core::Rows>>, | ||
| fn drop(&mut self) { | ||
| let _enter = rt().enter(); | ||
| self.conn.replace(None); | ||
| self.stmt.replace(None); | ||
@@ -354,2 +387,3 @@ self.rows.replace(None); | ||
| let cursor: &Cursor = &self_; | ||
| cursor.conn.replace(None); | ||
| cursor.stmt.replace(None); | ||
@@ -386,4 +420,12 @@ cursor.rows.replace(None); | ||
| ) -> PyResult<pyo3::PyRef<'a, Self>> { | ||
| rt().block_on(async { self_.conn.execute_batch(&script).await }) | ||
| .map_err(to_py_err)?; | ||
| rt().block_on(async { | ||
| self_ | ||
| .conn | ||
| .borrow() | ||
| .as_ref() | ||
| .unwrap() | ||
| .execute_batch(&script) | ||
| .await | ||
| }) | ||
| .map_err(to_py_err)?; | ||
| Ok(self_) | ||
@@ -495,3 +537,5 @@ } | ||
| match stmt.as_ref() { | ||
| Some(_) => Ok(Some(self_.conn.last_insert_rowid())), | ||
| Some(_) => Ok(Some( | ||
| self_.conn.borrow().as_ref().unwrap().last_insert_rowid(), | ||
| )), | ||
| None => Ok(None), | ||
@@ -513,6 +557,9 @@ } | ||
| async fn execute(cursor: &Cursor, sql: String, parameters: Option<&PyTuple>) -> PyResult<()> { | ||
| if cursor.conn.borrow().as_ref().is_none() { | ||
| return Err(PyValueError::new_err("Connection already closed")); | ||
| } | ||
| let stmt_is_dml = stmt_is_dml(&sql); | ||
| let autocommit = determine_autocommit(cursor); | ||
| if !autocommit && stmt_is_dml && cursor.conn.is_autocommit() { | ||
| begin_transaction(&cursor.conn).await?; | ||
| if !autocommit && stmt_is_dml && cursor.conn.borrow().as_ref().unwrap().is_autocommit() { | ||
| begin_transaction(&cursor.conn.borrow().as_ref().unwrap()).await?; | ||
| } | ||
@@ -542,7 +589,14 @@ let params = match parameters { | ||
| }; | ||
| let mut stmt = cursor.conn.prepare(&sql).await.map_err(to_py_err)?; | ||
| let mut stmt = cursor | ||
| .conn | ||
| .borrow() | ||
| .as_ref() | ||
| .unwrap() | ||
| .prepare(&sql) | ||
| .await | ||
| .map_err(to_py_err)?; | ||
| let rows = stmt.query(params).await.map_err(to_py_err)?; | ||
| if stmt_is_dml { | ||
| let mut rowcount = cursor.rowcount.borrow_mut(); | ||
| *rowcount += cursor.conn.changes() as i64; | ||
| *rowcount += cursor.conn.borrow().as_ref().unwrap().changes() as i64; | ||
| } else { | ||
@@ -549,0 +603,0 @@ cursor.rowcount.replace(-1); |
+17
-0
@@ -10,2 +10,7 @@ #!/usr/bin/env python3 | ||
| @pytest.mark.parametrize("provider", ["libsql", "sqlite"]) | ||
| def test_connection_close(provider): | ||
| conn = connect(provider, ":memory:") | ||
| conn.close() | ||
| @pytest.mark.parametrize("provider", ["libsql", "sqlite"]) | ||
| def test_execute(provider): | ||
@@ -28,2 +33,14 @@ conn = connect(provider, ":memory:") | ||
| @pytest.mark.parametrize("provider", ["libsql", "sqlite"]) | ||
| def test_cursor_close(provider): | ||
| conn = connect(provider, ":memory:") | ||
| cur = conn.cursor() | ||
| cur.execute("CREATE TABLE users (id INTEGER, email TEXT)") | ||
| cur.execute("INSERT INTO users VALUES (1, 'alice@example.com')") | ||
| cur.execute("INSERT INTO users VALUES (2, 'bob@example.com')") | ||
| res = cur.execute("SELECT * FROM users") | ||
| assert [(1, "alice@example.com"), (2, "bob@example.com")] == res.fetchall() | ||
| cur.close() | ||
| with pytest.raises(Exception): | ||
| cur.execute("SELECT * FROM users") | ||
@@ -30,0 +47,0 @@ @pytest.mark.parametrize("provider", ["libsql", "sqlite"]) |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
123293
1.85%634
2.59%