diff options
author | Erlend Egeberg Aasland <erlend.aasland@innova.no> | 2021-08-18 23:37:53 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-18 23:37:53 (GMT) |
commit | 243b6c3b8fd3144450c477d99f01e31e7c3ebc0f (patch) | |
tree | 30076138b126411515df582c9979e4da2c49abb9 | |
parent | b2f68b190035540872072ac1d2349e7745e85596 (diff) | |
download | cpython-243b6c3b8fd3144450c477d99f01e31e7c3ebc0f.zip cpython-243b6c3b8fd3144450c477d99f01e31e7c3ebc0f.tar.gz cpython-243b6c3b8fd3144450c477d99f01e31e7c3ebc0f.tar.bz2 |
bpo-44079: Strip superfluous statement cache from sqlite3.Connection (GH-25998)
-rw-r--r-- | Modules/_sqlite/connection.c | 102 | ||||
-rw-r--r-- | Modules/_sqlite/connection.h | 4 | ||||
-rw-r--r-- | Modules/_sqlite/statement.c | 26 | ||||
-rw-r--r-- | Modules/_sqlite/statement.h | 2 |
4 files changed, 18 insertions, 116 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 67160c4..0645367 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -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] diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index edf5650..4f08a6d 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -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; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 2d5c72d..b20c91d 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -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}, diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h index dc692d7..b901c43 100644 --- a/Modules/_sqlite/statement.h +++ b/Modules/_sqlite/statement.h @@ -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); |