From e801e88744f34508aa338f9f7f3f3baee012f813 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Wed, 9 Mar 2022 18:39:49 +0100 Subject: bpo-45138: Revert GH-28240: Expand traced SQL statements (GH-31788) This reverts commit d1777515f9f53b452a4231d68196a7c0e5deb879. Automerge-Triggered-By: GH:JelleZijlstra --- Doc/library/sqlite3.rst | 6 --- Doc/whatsnew/3.11.rst | 4 -- Lib/test/test_sqlite3/test_hooks.py | 61 +--------------------- .../2021-09-08-16-21-03.bpo-45138.yghUrK.rst | 3 -- Modules/_sqlite/connection.c | 49 +++++------------ 5 files changed, 15 insertions(+), 108 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-08-16-21-03.bpo-45138.yghUrK.rst diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 296b188..c456905 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -560,9 +560,6 @@ Connection Objects Passing :const:`None` as *trace_callback* will disable the trace callback. - For SQLite 3.14.0 and newer, bound parameters are expanded in the passed - statement string. - .. note:: Exceptions raised in the trace callback are not propagated. As a development and debugging aid, use @@ -571,9 +568,6 @@ Connection Objects .. versionadded:: 3.3 - .. versionchanged:: 3.11 - Added support for expanded SQL statements. - .. method:: enable_load_extension(enabled) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 628d4c0..4514de9 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -334,10 +334,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 --- diff --git a/Lib/test/test_sqlite3/test_hooks.py b/Lib/test/test_sqlite3/test_hooks.py index 38126b6..d4790cf 100644 --- a/Lib/test/test_sqlite3/test_hooks.py +++ b/Lib/test/test_sqlite3/test_hooks.py @@ -20,16 +20,12 @@ # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. -import contextlib -import sqlite3 as sqlite import unittest +import sqlite3 as sqlite from test.support.os_helper import TESTFN, unlink - -from test.test_sqlite3.test_dbapi import memory_database, cx_limit from test.test_sqlite3.test_userfunctions import with_tracebacks - class CollationTests(unittest.TestCase): def test_create_collation_not_string(self): con = sqlite.connect(":memory:") @@ -228,16 +224,6 @@ class ProgressTests(unittest.TestCase): class TraceCallbackTests(unittest.TestCase): - @contextlib.contextmanager - def check_stmt_trace(self, cx, expected): - try: - traced = [] - cx.set_trace_callback(lambda stmt: traced.append(stmt)) - yield - finally: - self.assertEqual(traced, expected) - cx.set_trace_callback(None) - def test_trace_callback_used(self): """ Test that the trace callback is invoked once it is set. @@ -303,51 +289,6 @@ class TraceCallbackTests(unittest.TestCase): 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)", - "BEGIN ", - "insert into t values(0)", - "insert into t values(1)", - "insert into t values(2)", - "COMMIT", - ] - with memory_database() as cx, self.check_stmt_trace(cx, expected): - with cx: - cx.execute("create table t(t)") - cx.executemany("insert into t values(?)", ((v,) for v in range(3))) - - @with_tracebacks( - sqlite.DataError, - regex="Expanded SQL string exceeds the maximum string length" - ) - 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 - # SQLITE_LIMIT_LENGTH. - template = "select 'b' as \"a\" from sqlite_master where \"a\"=" - category = sqlite.SQLITE_LIMIT_LENGTH - with memory_database() as cx, cx_limit(cx, category=category) as lim: - nextra = lim - (len(template) + 2) - 1 - ok_param = "a" * nextra - bad_param = "a" * (nextra + 1) - - unexpanded_query = template + "?" - with self.check_stmt_trace(cx, [unexpanded_query]): - cx.execute(unexpanded_query, (bad_param,)) - - expanded_query = f"{template}'{ok_param}'" - with self.check_stmt_trace(cx, [expanded_query]): - cx.execute(unexpanded_query, (ok_param,)) - - @with_tracebacks(ZeroDivisionError, regex="division by zero") - def test_trace_bad_handler(self): - with memory_database() as cx: - cx.set_trace_callback(lambda stmt: 5/0) - cx.execute("select 1") - if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2021-09-08-16-21-03.bpo-45138.yghUrK.rst b/Misc/NEWS.d/next/Library/2021-09-08-16-21-03.bpo-45138.yghUrK.rst deleted file mode 100644 index 7b0b440..0000000 --- a/Misc/NEWS.d/next/Library/2021-09-08-16-21-03.bpo-45138.yghUrK.rst +++ /dev/null @@ -1,3 +0,0 @@ -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. diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 511e8a2..e4b8ecb 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -1079,10 +1079,11 @@ progress_callback(void *ctx) * to ensure future compatibility. */ static int -trace_callback(unsigned int type, void *ctx, void *stmt, void *sql) +trace_callback(unsigned int type, void *ctx, void *prepared_statement, + void *statement_string) #else static void -trace_callback(void *ctx, const char *sql) +trace_callback(void *ctx, const char *statement_string) #endif { #ifdef HAVE_TRACE_V2 @@ -1093,46 +1094,24 @@ trace_callback(void *ctx, const char *sql) PyGILState_STATE gilstate = PyGILState_Ensure(); - assert(ctx != NULL); 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; - } - - 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 { - py_statement = PyUnicode_FromString(expanded_sql); - sqlite3_free((void *)expanded_sql); - } -#else - py_statement = PyUnicode_FromString(sql); -#endif + 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; - PyObject *ret = PyObject_CallOneArg(callable, py_statement); + ret = PyObject_CallOneArg(callable, py_statement); Py_DECREF(py_statement); - Py_XDECREF(ret); } -exit: - if (PyErr_Occurred()) { - print_or_clear_traceback((callback_context *)ctx); + if (ret) { + Py_DECREF(ret); } + else { + print_or_clear_traceback(ctx); + } + PyGILState_Release(gilstate); #ifdef HAVE_TRACE_V2 return 0; -- cgit v0.12