Skip to content

Commit 7250b1f

Browse files
authored
refactor(sqlite): add check_cursor_valid method for cursor state validation (RustPython#6342)
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 7250b1f

File tree

1 file changed

+25
-16
lines changed

1 file changed

+25
-16
lines changed

crates/stdlib/src/sqlite.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,26 +1589,35 @@ 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 check_cursor_state(inner: Option<&CursorInner>, vm: &VirtualMachine) -> PyResult<()> {
1593+
match inner {
1594+
Some(inner) if inner.closed => Err(new_programming_error(
1595+
vm,
1596+
"Cannot operate on a closed cursor.".to_owned(),
1597+
)),
1598+
Some(_) => Ok(()),
1599+
None => Err(new_programming_error(
16061600
vm,
16071601
"Base Cursor.__init__ not called.".to_owned(),
1608-
))
1602+
)),
16091603
}
16101604
}
16111605

1606+
fn inner(&self, vm: &VirtualMachine) -> PyResult<PyMappedMutexGuard<'_, CursorInner>> {
1607+
let guard = self.inner.lock();
1608+
Self::check_cursor_state(guard.as_ref(), vm)?;
1609+
Ok(PyMutexGuard::map(guard, |x| unsafe {
1610+
x.as_mut().unwrap_unchecked()
1611+
}))
1612+
}
1613+
1614+
/// Check if cursor is valid without retaining the lock.
1615+
/// Use this when you only need to verify the cursor state but don't need to modify it.
1616+
fn check_cursor_valid(&self, vm: &VirtualMachine) -> PyResult<()> {
1617+
let guard = self.inner.lock();
1618+
Self::check_cursor_state(guard.as_ref(), vm)
1619+
}
1620+
16121621
#[pymethod]
16131622
fn execute(
16141623
zelf: PyRef<Self>,
@@ -1771,7 +1780,7 @@ mod _sqlite {
17711780
script: PyUtf8StrRef,
17721781
vm: &VirtualMachine,
17731782
) -> PyResult<PyRef<Self>> {
1774-
let _ = zelf.clone().inner(vm)?;
1783+
zelf.check_cursor_valid(vm)?;
17751784

17761785
let db = zelf.connection.db_lock(vm)?;
17771786

0 commit comments

Comments
 (0)