bpo-45138: Expand traced SQL statements in sqlite3 trace callback (GH-28240)

This commit is contained in:
Erlend Egeberg Aasland 2022-03-09 03:46:40 +01:00 committed by GitHub
parent b33a1ae703
commit d1777515f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 109 additions and 16 deletions

View file

@ -1079,11 +1079,10 @@ progress_callback(void *ctx)
* to ensure future compatibility.
*/
static int
trace_callback(unsigned int type, void *ctx, void *prepared_statement,
void *statement_string)
trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
#else
static void
trace_callback(void *ctx, const char *statement_string)
trace_callback(void *ctx, const char *sql)
#endif
{
#ifdef HAVE_TRACE_V2
@ -1094,24 +1093,46 @@ trace_callback(void *ctx, const char *statement_string)
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *py_statement = NULL;
PyObject *ret = NULL;
py_statement = PyUnicode_DecodeUTF8(statement_string,
strlen(statement_string), "replace");
assert(ctx != NULL);
if (py_statement) {
PyObject *callable = ((callback_context *)ctx)->callable;
ret = PyObject_CallOneArg(callable, py_statement);
Py_DECREF(py_statement);
}
PyObject *py_statement = NULL;
#ifdef HAVE_TRACE_V2
assert(stmt != NULL);
const char *expanded_sql = sqlite3_expanded_sql((sqlite3_stmt *)stmt);
if (expanded_sql == NULL) {
sqlite3 *db = sqlite3_db_handle((sqlite3_stmt *)stmt);
if (sqlite3_errcode(db) == SQLITE_NOMEM) {
(void)PyErr_NoMemory();
goto exit;
}
if (ret) {
Py_DECREF(ret);
pysqlite_state *state = ((callback_context *)ctx)->state;
assert(state != NULL);
PyErr_SetString(state->DataError,
"Expanded SQL string exceeds the maximum string "
"length");
print_or_clear_traceback((callback_context *)ctx);
// Fall back to unexpanded sql
py_statement = PyUnicode_FromString((const char *)sql);
}
else {
print_or_clear_traceback(ctx);
py_statement = PyUnicode_FromString(expanded_sql);
sqlite3_free((void *)expanded_sql);
}
#else
py_statement = PyUnicode_FromString(sql);
#endif
if (py_statement) {
PyObject *callable = ((callback_context *)ctx)->callable;
PyObject *ret = PyObject_CallOneArg(callable, py_statement);
Py_DECREF(py_statement);
Py_XDECREF(ret);
}
exit:
if (PyErr_Occurred()) {
print_or_clear_traceback((callback_context *)ctx);
}
PyGILState_Release(gilstate);
#ifdef HAVE_TRACE_V2
return 0;