From a47ba75471529153b5691aacf16e818f87a1bd00 Mon Sep 17 00:00:00 2001 From: Jiseok CHOI Date: Wed, 20 Aug 2025 17:44:50 +0900 Subject: [PATCH] sqlite: Fix missing ProgrammingError for parameter mismatch --- Lib/test/test_sqlite3/test_dbapi.py | 6 ------ stdlib/src/sqlite.rs | 23 ++++++++++++++++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 53cec8a11f..65821020a6 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -836,15 +836,11 @@ def test_execute_wrong_no_of_args1(self): with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("insert into test(id) values (?)", (17, "Egon")) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_execute_wrong_no_of_args2(self): # too little parameters with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("insert into test(id) values (?)") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_execute_wrong_no_of_args3(self): # no parameters, parameters are needed with self.assertRaises(sqlite.ProgrammingError): @@ -911,8 +907,6 @@ def test_execute_dict_mapping_too_little_args(self): with self.assertRaises(sqlite.ProgrammingError): self.cu.execute("select name from test where name=:name and id=:id", {"name": "foo"}) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_execute_dict_mapping_no_args(self): self.cu.execute("insert into test(name) values ('foo')") with self.assertRaises(sqlite.ProgrammingError): diff --git a/stdlib/src/sqlite.rs b/stdlib/src/sqlite.rs index 054da28aef..8bba155612 100644 --- a/stdlib/src/sqlite.rs +++ b/stdlib/src/sqlite.rs @@ -1533,8 +1533,16 @@ mod _sqlite { } let st = stmt.lock(); + let params_needed = st.bind_parameter_count(); + if let OptionalArg::Present(parameters) = parameters { st.bind_parameters(¶meters, vm)?; + } else if params_needed > 0 { + let msg = format!( + "Incorrect number of bindings supplied. The current statement uses {}, and 0 were supplied.", + params_needed + ); + return Err(new_programming_error(vm, msg)); } let ret = st.step(); @@ -2848,16 +2856,25 @@ mod _sqlite { Ok(()) } + fn bind_parameter_count(self) -> c_int { + unsafe { sqlite3_bind_parameter_count(self.st) } + } + fn bind_parameters_sequence( self, seq: PySequence<'_>, vm: &VirtualMachine, ) -> PyResult<()> { - let num_needed = unsafe { sqlite3_bind_parameter_count(self.st) }; - if seq.length(vm)? != num_needed as usize { + let num_needed = self.bind_parameter_count(); + let num_supplied = seq.length(vm)?; + + if num_supplied != num_needed as usize { return Err(new_programming_error( vm, - "Incorrect number of binding supplied".to_owned(), + format!( + "Incorrect number of bindings supplied. The current statement uses {}, and {} were supplied.", + num_needed, num_supplied + ), )); }