]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44079: Strip superfluous statement cache from sqlite3.Connection (GH-25998)
authorErlend Egeberg Aasland <erlend.aasland@innova.no>
Wed, 18 Aug 2021 23:37:53 +0000 (01:37 +0200)
committerGitHub <noreply@github.com>
Wed, 18 Aug 2021 23:37:53 +0000 (00:37 +0100)
Modules/_sqlite/connection.c
Modules/_sqlite/connection.h
Modules/_sqlite/statement.c
Modules/_sqlite/statement.h

index 67160c4c449aa1608e798ef6566664760748b8d6..0645367988e630508f11ba3c7a7cc0e2cbe358bb 100644 (file)
@@ -29,9 +29,6 @@
 #include "prepare_protocol.h"
 #include "util.h"
 
-#define ACTION_FINALIZE 1
-#define ACTION_RESET 2
-
 #if SQLITE_VERSION_NUMBER >= 3014000
 #define HAVE_TRACE_V2
 #endif
@@ -114,7 +111,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
     self->begin_statement = NULL;
 
     Py_CLEAR(self->statement_cache);
-    Py_CLEAR(self->statements);
     Py_CLEAR(self->cursors);
 
     Py_INCREF(Py_None);
@@ -159,13 +155,11 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
         return -1;
     }
 
-    self->created_statements = 0;
     self->created_cursors = 0;
 
-    /* Create lists of weak references to statements/cursors */
-    self->statements = PyList_New(0);
+    /* Create list of weak references to cursors */
     self->cursors = PyList_New(0);
-    if (!self->statements || !self->cursors) {
+    if (self->cursors == NULL) {
         return -1;
     }
 
@@ -198,37 +192,24 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
     return 0;
 }
 
-/* action in (ACTION_RESET, ACTION_FINALIZE) */
 static void
-pysqlite_do_all_statements(pysqlite_Connection *self, int action,
-                           int reset_cursors)
+pysqlite_do_all_statements(pysqlite_Connection *self)
 {
-    int i;
-    PyObject* weakref;
-    PyObject* statement;
-    pysqlite_Cursor* cursor;
-
-    for (i = 0; i < PyList_Size(self->statements); i++) {
-        weakref = PyList_GetItem(self->statements, i);
-        statement = PyWeakref_GetObject(weakref);
-        if (statement != Py_None) {
-            Py_INCREF(statement);
-            if (action == ACTION_RESET) {
-                (void)pysqlite_statement_reset((pysqlite_Statement*)statement);
-            } else {
-                (void)pysqlite_statement_finalize((pysqlite_Statement*)statement);
-            }
-            Py_DECREF(statement);
+    // Reset all statements
+    sqlite3_stmt *stmt = NULL;
+    while ((stmt = sqlite3_next_stmt(self->db, stmt))) {
+        if (sqlite3_stmt_busy(stmt)) {
+            (void)sqlite3_reset(stmt);
         }
     }
 
-    if (reset_cursors) {
-        for (i = 0; i < PyList_Size(self->cursors); i++) {
-            weakref = PyList_GetItem(self->cursors, i);
-            cursor = (pysqlite_Cursor*)PyWeakref_GetObject(weakref);
-            if ((PyObject*)cursor != Py_None) {
-                cursor->reset = 1;
-            }
+    // Reset all cursors
+    for (int i = 0; i < PyList_Size(self->cursors); i++) {
+        PyObject *weakref = PyList_GetItem(self->cursors, i);
+        PyObject *object = PyWeakref_GetObject(weakref);
+        if (object != Py_None) {
+            pysqlite_Cursor *cursor = (pysqlite_Cursor *)object;
+            cursor->reset = 1;
         }
     }
 }
@@ -239,7 +220,6 @@ connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
     Py_VISIT(Py_TYPE(self));
     Py_VISIT(self->isolation_level);
     Py_VISIT(self->statement_cache);
-    Py_VISIT(self->statements);
     Py_VISIT(self->cursors);
     Py_VISIT(self->row_factory);
     Py_VISIT(self->text_factory);
@@ -254,7 +234,6 @@ connection_clear(pysqlite_Connection *self)
 {
     Py_CLEAR(self->isolation_level);
     Py_CLEAR(self->statement_cache);
-    Py_CLEAR(self->statements);
     Py_CLEAR(self->cursors);
     Py_CLEAR(self->row_factory);
     Py_CLEAR(self->text_factory);
@@ -378,7 +357,7 @@ pysqlite_connection_close_impl(pysqlite_Connection *self)
         return NULL;
     }
 
-    pysqlite_do_all_statements(self, ACTION_FINALIZE, 1);
+    Py_CLEAR(self->statement_cache);
     connection_close(self);
 
     Py_RETURN_NONE;
@@ -474,7 +453,7 @@ pysqlite_connection_rollback_impl(pysqlite_Connection *self)
     }
 
     if (!sqlite3_get_autocommit(self->db)) {
-        pysqlite_do_all_statements(self, ACTION_RESET, 1);
+        pysqlite_do_all_statements(self);
 
         Py_BEGIN_ALLOW_THREADS
         rc = sqlite3_prepare_v2(self->db, "ROLLBACK", 9, &statement, NULL);
@@ -774,37 +753,6 @@ error:
     PyGILState_Release(threadstate);
 }
 
-static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self)
-{
-    PyObject* new_list;
-    PyObject* weakref;
-    int i;
-
-    /* we only need to do this once in a while */
-    if (self->created_statements++ < 200) {
-        return;
-    }
-
-    self->created_statements = 0;
-
-    new_list = PyList_New(0);
-    if (!new_list) {
-        return;
-    }
-
-    for (i = 0; i < PyList_Size(self->statements); i++) {
-        weakref = PyList_GetItem(self->statements, i);
-        if (PyWeakref_GetObject(weakref) != Py_None) {
-            if (PyList_Append(new_list, weakref) != 0) {
-                Py_DECREF(new_list);
-                return;
-            }
-        }
-    }
-
-    Py_SETREF(self->statements, new_list);
-}
-
 static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
 {
     PyObject* new_list;
@@ -1358,7 +1306,6 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args,
 {
     PyObject* sql;
     pysqlite_Statement* statement;
-    PyObject* weakref;
 
     if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
         return NULL;
@@ -1370,27 +1317,12 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args,
     if (!PyArg_ParseTuple(args, "U", &sql))
         return NULL;
 
-    _pysqlite_drop_unused_statement_references(self);
-
     statement = pysqlite_statement_create(self, sql);
     if (statement == NULL) {
         return NULL;
     }
 
-    weakref = PyWeakref_NewRef((PyObject*)statement, NULL);
-    if (weakref == NULL)
-        goto error;
-    if (PyList_Append(self->statements, weakref) != 0) {
-        Py_DECREF(weakref);
-        goto error;
-    }
-    Py_DECREF(weakref);
-
     return (PyObject*)statement;
-
-error:
-    Py_DECREF(statement);
-    return NULL;
 }
 
 /*[clinic input]
index edf565020420d301313b6d3f65eb7cef4425a643..4f08a6d5f7b21d65c3d263a190fbc69f11e6fe14 100644 (file)
@@ -60,12 +60,10 @@ typedef struct
     PyObject *statement_cache;
 
     /* Lists of weak references to statements and cursors used within this connection */
-    PyObject* statements;
     PyObject* cursors;
 
-    /* Counters for how many statements/cursors were created in the connection. May be
+    /* Counters for how many cursors were created in the connection. May be
      * reset to 0 at certain intervals */
-    int created_statements;
     int created_cursors;
 
     PyObject* row_factory;
index 2d5c72d13b7edb3ea67102d98442edbe28645528..b20c91da3179c49f6aae1f670b863cb63960c68a 100644 (file)
@@ -118,7 +118,6 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
     self->st = stmt;
     self->in_use = 0;
     self->is_dml = is_dml;
-    self->in_weakreflist = NULL;
 
     PyObject_GC_Track(self);
     return self;
@@ -361,23 +360,6 @@ pysqlite_statement_bind_parameters(pysqlite_state *state,
     }
 }
 
-int pysqlite_statement_finalize(pysqlite_Statement* self)
-{
-    int rc;
-
-    rc = SQLITE_OK;
-    if (self->st) {
-        Py_BEGIN_ALLOW_THREADS
-        rc = sqlite3_finalize(self->st);
-        Py_END_ALLOW_THREADS
-        self->st = NULL;
-    }
-
-    self->in_use = 0;
-
-    return rc;
-}
-
 int pysqlite_statement_reset(pysqlite_Statement* self)
 {
     int rc;
@@ -407,9 +389,6 @@ stmt_dealloc(pysqlite_Statement *self)
 {
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
-    if (self->in_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject*)self);
-    }
     if (self->st) {
         Py_BEGIN_ALLOW_THREADS
         sqlite3_finalize(self->st);
@@ -497,12 +476,7 @@ static int pysqlite_check_remaining_sql(const char* tail)
     return 0;
 }
 
-static PyMemberDef stmt_members[] = {
-    {"__weaklistoffset__", T_PYSSIZET, offsetof(pysqlite_Statement, in_weakreflist), READONLY},
-    {NULL},
-};
 static PyType_Slot stmt_slots[] = {
-    {Py_tp_members, stmt_members},
     {Py_tp_dealloc, stmt_dealloc},
     {Py_tp_traverse, stmt_traverse},
     {0, NULL},
index dc692d7df99fd76874db541fcc13a3123bc34b45..b901c43c479ae22957c5fcf30872d4271609b1fc 100644 (file)
@@ -35,7 +35,6 @@ typedef struct
     sqlite3_stmt* st;
     int in_use;
     int is_dml;
-    PyObject* in_weakreflist; /* List of weak references */
 } pysqlite_Statement;
 
 pysqlite_Statement *pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql);
@@ -45,7 +44,6 @@ void pysqlite_statement_bind_parameters(pysqlite_state *state,
                                         pysqlite_Statement *self,
                                         PyObject *parameters);
 
-int pysqlite_statement_finalize(pysqlite_Statement* self);
 int pysqlite_statement_reset(pysqlite_Statement* self);
 void pysqlite_statement_mark_dirty(pysqlite_Statement* self);