From 2f6c11e6c022d9f64f2a3640e5df008da36fb637 Mon Sep 17 00:00:00 2001 From: Jiseok CHOI Date: Mon, 8 Dec 2025 16:59:46 +0900 Subject: [PATCH] refactor(sqlite): add check_cursor_valid method for cursor state validation Extract cursor validity check into a separate method that doesn't hold the lock. This is useful for executescript which only needs to verify the cursor state but doesn't need to modify CursorInner. - Add check_cursor_valid() method that checks if cursor is initialized and not closed without retaining the mutex guard - Use check_cursor_valid() in executescript instead of inner() since executescript doesn't modify CursorInner --- crates/stdlib/src/sqlite.rs | 41 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/crates/stdlib/src/sqlite.rs b/crates/stdlib/src/sqlite.rs index 12af619dba..7650221fb9 100644 --- a/crates/stdlib/src/sqlite.rs +++ b/crates/stdlib/src/sqlite.rs @@ -1589,26 +1589,35 @@ mod _sqlite { Ok(()) } - fn inner(&self, vm: &VirtualMachine) -> PyResult> { - let guard = self.inner.lock(); - if guard.is_some() { - let inner_guard = - PyMutexGuard::map(guard, |x| unsafe { x.as_mut().unwrap_unchecked() }); - if inner_guard.closed { - return Err(new_programming_error( - vm, - "Cannot operate on a closed cursor.".to_owned(), - )); - } - Ok(inner_guard) - } else { - Err(new_programming_error( + fn check_cursor_state(inner: Option<&CursorInner>, vm: &VirtualMachine) -> PyResult<()> { + match inner { + Some(inner) if inner.closed => Err(new_programming_error( + vm, + "Cannot operate on a closed cursor.".to_owned(), + )), + Some(_) => Ok(()), + None => Err(new_programming_error( vm, "Base Cursor.__init__ not called.".to_owned(), - )) + )), } } + fn inner(&self, vm: &VirtualMachine) -> PyResult> { + let guard = self.inner.lock(); + Self::check_cursor_state(guard.as_ref(), vm)?; + Ok(PyMutexGuard::map(guard, |x| unsafe { + x.as_mut().unwrap_unchecked() + })) + } + + /// Check if cursor is valid without retaining the lock. + /// Use this when you only need to verify the cursor state but don't need to modify it. + fn check_cursor_valid(&self, vm: &VirtualMachine) -> PyResult<()> { + let guard = self.inner.lock(); + Self::check_cursor_state(guard.as_ref(), vm) + } + #[pymethod] fn execute( zelf: PyRef, @@ -1771,7 +1780,7 @@ mod _sqlite { script: PyUtf8StrRef, vm: &VirtualMachine, ) -> PyResult> { - let _ = zelf.clone().inner(vm)?; + zelf.check_cursor_valid(vm)?; let db = zelf.connection.db_lock(vm)?;