Skip to content

bpo-45138: Fix regression in GH-28240 #31783

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,6 @@ sqlite3
Instead we leave it to the SQLite library to handle these cases.
(Contributed by Erlend E. Aasland in :issue:`44092`.)

* For SQLite 3.14.0 and newer, bound parameters are expanded in the statement
string passed to the trace callback. See :meth:`~sqlite3.Connection.set_trace_callback`.
(Contributed by Erlend E. Aasland in :issue:`45138`.)


sys
---
Expand Down
10 changes: 6 additions & 4 deletions Lib/test/test_sqlite3/test_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,6 @@ def trace(statement):
con2.close()
self.assertEqual(traced_statements, queries)

@unittest.skipIf(sqlite.sqlite_version_info < (3, 14, 0),
"Requires SQLite 3.14.0 or newer")
def test_trace_expanded_sql(self):
expected = [
"create table t(t)",
Expand All @@ -325,7 +323,8 @@ def test_trace_expanded_sql(self):
)
def test_trace_too_much_expanded_sql(self):
# If the expanded string is too large, we'll fall back to the
# unexpanded SQL statement. The resulting string length is limited by
# unexpanded SQL statement (for SQLite 3.14.0 and newer).
# The resulting string length is limited by the runtime limit
# SQLITE_LIMIT_LENGTH.
template = "select 'b' as \"a\" from sqlite_master where \"a\"="
category = sqlite.SQLITE_LIMIT_LENGTH
Expand All @@ -335,7 +334,10 @@ def test_trace_too_much_expanded_sql(self):
bad_param = "a" * (nextra + 1)

unexpanded_query = template + "?"
with self.check_stmt_trace(cx, [unexpanded_query]):
expected = [unexpanded_query]
if sqlite.sqlite_version_info < (3, 14, 0):
expected = []
with self.check_stmt_trace(cx, expected):
cx.execute(unexpanded_query, (bad_param,))

expanded_query = f"{template}'{ok_param}'"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
For SQLite 3.14.0 and newer, bound parameters are expanded in the statement
string passed to the :mod:`sqlite3` trace callback. Patch by Erlend E.
Aasland.
Fix a regression in the :mod:`sqlite3` trace callback where bound parameters
were not expanded in the passed statement string. The regression was introduced
in Python 3.10 by :issue:`40318`. Patch by Erlend E. Aasland.
14 changes: 11 additions & 3 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,9 @@ trace_callback(void *ctx, const char *sql)
PyGILState_STATE gilstate = PyGILState_Ensure();

assert(ctx != NULL);
pysqlite_state *state = ((callback_context *)ctx)->state;
assert(state != NULL);

PyObject *py_statement = NULL;
#ifdef HAVE_TRACE_V2
assert(stmt != NULL);
Expand All @@ -1105,8 +1108,6 @@ trace_callback(void *ctx, const char *sql)
goto exit;
}

pysqlite_state *state = ((callback_context *)ctx)->state;
assert(state != NULL);
PyErr_SetString(state->DataError,
"Expanded SQL string exceeds the maximum string "
"length");
Expand All @@ -1120,7 +1121,14 @@ trace_callback(void *ctx, const char *sql)
sqlite3_free((void *)expanded_sql);
}
#else
py_statement = PyUnicode_FromString(sql);
if (sql == NULL) {
PyErr_SetString(state->DataError,
"Expanded SQL string exceeds the maximum string length");
print_or_clear_traceback((callback_context *)ctx);
}
else {
py_statement = PyUnicode_FromString(sql);
}
#endif
if (py_statement) {
PyObject *callable = ((callback_context *)ctx)->callable;
Expand Down