Skip to content

Commit 89d1bdc

Browse files
committed
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
1 parent 42d497a commit 89d1bdc

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

crates/stdlib/src/sqlite.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,24 +1589,41 @@ mod _sqlite {
15891589
Ok(())
15901590
}
15911591

1592-
fn inner(&self, vm: &VirtualMachine) -> PyResult<PyMappedMutexGuard<'_, CursorInner>> {
1593-
let guard = self.inner.lock();
1594-
if guard.is_some() {
1595-
let inner_guard =
1596-
PyMutexGuard::map(guard, |x| unsafe { x.as_mut().unwrap_unchecked() });
1597-
if inner_guard.closed {
1598-
return Err(new_programming_error(
1599-
vm,
1600-
"Cannot operate on a closed cursor.".to_owned(),
1601-
));
1602-
}
1603-
Ok(inner_guard)
1604-
} else {
1605-
Err(new_programming_error(
1592+
fn cursor_state_error(
1593+
inner: Option<&CursorInner>,
1594+
vm: &VirtualMachine,
1595+
) -> Option<PyBaseExceptionRef> {
1596+
match inner {
1597+
Some(inner) if inner.closed => Some(new_programming_error(
1598+
vm,
1599+
"Cannot operate on a closed cursor.".to_owned(),
1600+
)),
1601+
Some(_) => None,
1602+
None => Some(new_programming_error(
16061603
vm,
16071604
"Base Cursor.__init__ not called.".to_owned(),
1608-
))
1605+
)),
1606+
}
1607+
}
1608+
1609+
fn inner(&self, vm: &VirtualMachine) -> PyResult<PyMappedMutexGuard<'_, CursorInner>> {
1610+
let guard = self.inner.lock();
1611+
if let Some(err) = Self::cursor_state_error(guard.as_ref(), vm) {
1612+
return Err(err);
16091613
}
1614+
Ok(PyMutexGuard::map(guard, |x| unsafe {
1615+
x.as_mut().unwrap_unchecked()
1616+
}))
1617+
}
1618+
1619+
/// Check if cursor is valid without holding the lock.
1620+
/// Use this when you only need to verify the cursor state but don't need to modify it.
1621+
fn check_cursor_valid(&self, vm: &VirtualMachine) -> PyResult<()> {
1622+
let guard = self.inner.lock();
1623+
if let Some(err) = Self::cursor_state_error(guard.as_ref(), vm) {
1624+
return Err(err);
1625+
}
1626+
Ok(())
16101627
}
16111628

16121629
#[pymethod]
@@ -1771,7 +1788,7 @@ mod _sqlite {
17711788
script: PyUtf8StrRef,
17721789
vm: &VirtualMachine,
17731790
) -> PyResult<PyRef<Self>> {
1774-
let _ = zelf.clone().inner(vm)?;
1791+
zelf.check_cursor_valid(vm)?;
17751792

17761793
let db = zelf.connection.db_lock(vm)?;
17771794

0 commit comments

Comments
 (0)