sqlite3: raise ProgrammingError when named param receives sequence (#8363)

CPython raises ProgrammingError with "Binding N is a named parameter"
when a query uses named placeholders (, , ) but
the caller passes a sequence instead of a mapping.

RustPython's bind_parameters_sequence() did not check whether each
binding slot is a named parameter, so no error was raised.

Fix: call sqlite3_bind_parameter_name() for each slot in
bind_parameters_sequence(). If the first byte of the returned name is
not '?' (i.e. it is a named placeholder), raise ProgrammingError before
attempting to bind.

Assisted-by: GitHub Copilot:claude-sonnet-4-6
This commit is contained in:
Jiseok CHOI authored and GitHub committed 2026-07-26 13:02:25 +09:00
1 parent c6bb4a8f52
commit 375051ddf8
3 files changed
+11 -1

No files matched your search

+1
View File
@@ -83,6 +83,7 @@
"opargs",
"pointee",
"pyc",
"qmark",
"reborrow",
"reborrows",
"reparenting",
-1
View File
@@ -875,7 +875,6 @@ class CursorTests(unittest.TestCase):
with self.assertRaises(ZeroDivisionError):
self.cu.execute("select name from test where name=?", L())
@unittest.expectedFailure # TODO: RUSTPYTHON; mixed named and positional parameters not validated
def test_execute_named_param_and_sequence(self):
dataset = (
("select :a", (1,)),
+10
View File
@@ -3208,6 +3208,16 @@ mod _sqlite3 {
}
for i in 1..=num_needed {
let name = unsafe { sqlite3_bind_parameter_name(self.st, i) };
if !name.is_null() && unsafe { *name } != b'?' as libc::c_char {
let name_str = ptr_to_str(name, vm)?;
return Err(new_programming_error(
vm,
format!(
"Binding {i} ('{name_str}') is a named parameter, but you supplied a sequence which requires nameless (qmark) placeholders."
),
));
}
let val = seq.get_item(i as isize - 1, vm)?;
self.bind_parameter(i, &val, vm)?;
}