mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-129928: Raise more accurate exception for incorrect sqlite3 UDF creation (#129941)
Consistently raise ProgrammingError if the user tries to create an UDF with an invalid number of parameters.
This commit is contained in:
parent
0dbe543d70
commit
3a2e7aacf6
3 changed files with 29 additions and 6 deletions
|
@ -171,7 +171,7 @@ class FunctionTests(unittest.TestCase):
|
||||||
self.con.close()
|
self.con.close()
|
||||||
|
|
||||||
def test_func_error_on_create(self):
|
def test_func_error_on_create(self):
|
||||||
with self.assertRaises(sqlite.OperationalError):
|
with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"):
|
||||||
self.con.create_function("bla", -100, lambda x: 2*x)
|
self.con.create_function("bla", -100, lambda x: 2*x)
|
||||||
|
|
||||||
def test_func_too_many_args(self):
|
def test_func_too_many_args(self):
|
||||||
|
@ -507,9 +507,8 @@ class WindowFunctionTests(unittest.TestCase):
|
||||||
self.assertEqual(self.cur.fetchall(), self.expected)
|
self.assertEqual(self.cur.fetchall(), self.expected)
|
||||||
|
|
||||||
def test_win_error_on_create(self):
|
def test_win_error_on_create(self):
|
||||||
self.assertRaises(sqlite.ProgrammingError,
|
with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"):
|
||||||
self.con.create_window_function,
|
self.con.create_window_function("shouldfail", -100, WindowSumInt)
|
||||||
"shouldfail", -100, WindowSumInt)
|
|
||||||
|
|
||||||
@with_tracebacks(BadWindow)
|
@with_tracebacks(BadWindow)
|
||||||
def test_win_exception_in_method(self):
|
def test_win_exception_in_method(self):
|
||||||
|
@ -638,7 +637,7 @@ class AggregateTests(unittest.TestCase):
|
||||||
self.con.close()
|
self.con.close()
|
||||||
|
|
||||||
def test_aggr_error_on_create(self):
|
def test_aggr_error_on_create(self):
|
||||||
with self.assertRaises(sqlite.OperationalError):
|
with self.assertRaisesRegex(sqlite.ProgrammingError, "not -100"):
|
||||||
self.con.create_function("bla", -100, AggrSum)
|
self.con.create_function("bla", -100, AggrSum)
|
||||||
|
|
||||||
@with_tracebacks(AttributeError, msg_regex="AggrNoStep")
|
@with_tracebacks(AttributeError, msg_regex="AggrNoStep")
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Raise :exc:`sqlite3.ProgrammingError` if a user-defined SQL function with
|
||||||
|
invalid number of parameters is created. Patch by Erlend Aasland.
|
|
@ -1139,6 +1139,20 @@ destructor_callback(void *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_num_params(pysqlite_Connection *self, const int n, const char *name)
|
||||||
|
{
|
||||||
|
int limit = sqlite3_limit(self->db, SQLITE_LIMIT_FUNCTION_ARG, -1);
|
||||||
|
assert(limit >= 0);
|
||||||
|
if (n < -1 || n > limit) {
|
||||||
|
PyErr_Format(self->ProgrammingError,
|
||||||
|
"'%s' must be between -1 and %d, not %d",
|
||||||
|
name, limit, n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_sqlite3.Connection.create_function as pysqlite_connection_create_function
|
_sqlite3.Connection.create_function as pysqlite_connection_create_function
|
||||||
|
|
||||||
|
@ -1167,6 +1181,9 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
|
||||||
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (check_num_params(self, narg, "narg") < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (deterministic) {
|
if (deterministic) {
|
||||||
flags |= SQLITE_DETERMINISTIC;
|
flags |= SQLITE_DETERMINISTIC;
|
||||||
|
@ -1307,10 +1324,12 @@ create_window_function_impl(pysqlite_Connection *self, PyTypeObject *cls,
|
||||||
"SQLite 3.25.0 or higher");
|
"SQLite 3.25.0 or higher");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (check_num_params(self, num_params, "num_params") < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int flags = SQLITE_UTF8;
|
int flags = SQLITE_UTF8;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -1367,6 +1386,9 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self,
|
||||||
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (check_num_params(self, n_arg, "n_arg") < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
callback_context *ctx = create_callback_context(cls, aggregate_class);
|
callback_context *ctx = create_callback_context(cls, aggregate_class);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue