diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-08-06 18:28:47 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-06 18:28:47 (GMT) |
commit | 7d747f26e6cac9f6891d475f3443441ce947697b (patch) | |
tree | 2b21130c1bbc45c410cec55d13bdae26e23df10c /Modules | |
parent | 738ac00a08cb6a9d104ec85ccb1a44c2399d6baa (diff) | |
download | cpython-7d747f26e6cac9f6891d475f3443441ce947697b.zip cpython-7d747f26e6cac9f6891d475f3443441ce947697b.tar.gz cpython-7d747f26e6cac9f6891d475f3443441ce947697b.tar.bz2 |
bpo-44839: Raise more specific errors in sqlite3 (GH-27613)
MemoryError raised in user-defined functions will now preserve
its type. OverflowError will now be converted to DataError.
Previously both were converted to OperationalError.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_sqlite/connection.c | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index aae6c66..0dab3e8 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -619,6 +619,29 @@ error: return NULL; } +// Checks the Python exception and sets the appropriate SQLite error code. +static void +set_sqlite_error(sqlite3_context *context, const char *msg) +{ + assert(PyErr_Occurred()); + if (PyErr_ExceptionMatches(PyExc_MemoryError)) { + sqlite3_result_error_nomem(context); + } + else if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + sqlite3_result_error_toobig(context); + } + else { + sqlite3_result_error(context, msg, -1); + } + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { + PyErr_Print(); + } + else { + PyErr_Clear(); + } +} + static void _pysqlite_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv) { @@ -645,14 +668,7 @@ _pysqlite_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv Py_DECREF(py_retval); } if (!ok) { - pysqlite_state *state = pysqlite_get_state(NULL); - if (state->enable_callback_tracebacks) { - PyErr_Print(); - } - else { - PyErr_Clear(); - } - sqlite3_result_error(context, "user-defined function raised exception", -1); + set_sqlite_error(context, "user-defined function raised exception"); } PyGILState_Release(threadstate); @@ -676,18 +692,9 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ if (*aggregate_instance == NULL) { *aggregate_instance = _PyObject_CallNoArg(aggregate_class); - - if (PyErr_Occurred()) { - *aggregate_instance = 0; - - pysqlite_state *state = pysqlite_get_state(NULL); - if (state->enable_callback_tracebacks) { - PyErr_Print(); - } - else { - PyErr_Clear(); - } - sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); + if (!*aggregate_instance) { + set_sqlite_error(context, + "user-defined aggregate's '__init__' method raised error"); goto error; } } @@ -706,14 +713,8 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ Py_DECREF(args); if (!function_result) { - pysqlite_state *state = pysqlite_get_state(NULL); - if (state->enable_callback_tracebacks) { - PyErr_Print(); - } - else { - PyErr_Clear(); - } - sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); + set_sqlite_error(context, + "user-defined aggregate's 'step' method raised error"); } error: @@ -761,14 +762,8 @@ _pysqlite_final_callback(sqlite3_context *context) Py_DECREF(function_result); } if (!ok) { - pysqlite_state *state = pysqlite_get_state(NULL); - if (state->enable_callback_tracebacks) { - PyErr_Print(); - } - else { - PyErr_Clear(); - } - sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); + set_sqlite_error(context, + "user-defined aggregate's 'finalize' method raised error"); } /* Restore the exception (if any) of the last call to step(), |