Skip to content

Commit

Permalink
gh-89121: Keep the number of pending SQLite statements to a minimum (#…
Browse files Browse the repository at this point in the history
…30379)

Make sure statements that have run to completion or errored are
reset and cleared off the cursor for all paths in execute() and
executemany().
  • Loading branch information
erlend-aasland authored Jun 23, 2022
1 parent 11e865c commit 8928531
Showing 1 changed file with 12 additions and 22 deletions.
34 changes: 12 additions & 22 deletions Modules/_sqlite/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,16 +830,12 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}

if (self->statement != NULL) {
/* There is an active statement */
stmt_reset(self->statement);
}

/* reset description */
Py_INCREF(Py_None);
Py_SETREF(self->description, Py_None);

if (self->statement) {
// Reset pending statements on this cursor.
(void)stmt_reset(self->statement);
}

Expand Down Expand Up @@ -879,6 +875,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}

assert(!sqlite3_stmt_busy(self->statement->st));
while (1) {
parameters = PyIter_Next(parameters_iter);
if (!parameters) {
Expand All @@ -902,7 +899,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
PyErr_Clear();
}
}
(void)stmt_reset(self->statement);
_pysqlite_seterror(state, self->connection->db);
goto error;
}
Expand Down Expand Up @@ -944,16 +940,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
}
}

if (rc == SQLITE_DONE && !multiple) {
if (rc == SQLITE_DONE) {
if (self->statement->is_dml) {
self->rowcount = (long)sqlite3_changes(self->connection->db);
}
stmt_reset(self->statement);
Py_CLEAR(self->statement);
}

if (multiple) {
if (self->statement->is_dml && rc == SQLITE_DONE) {
self->rowcount += (long)sqlite3_changes(self->connection->db);
}
stmt_reset(self->statement);
Expand All @@ -980,11 +968,17 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
self->locked = 0;

if (PyErr_Occurred()) {
if (self->statement) {
(void)stmt_reset(self->statement);
Py_CLEAR(self->statement);
}
self->rowcount = -1L;
return NULL;
} else {
return Py_NewRef((PyObject *)self);
}
if (self->statement && !sqlite3_stmt_busy(self->statement->st)) {
Py_CLEAR(self->statement);
}
return Py_NewRef((PyObject *)self);
}

/*[clinic input]
Expand Down Expand Up @@ -1111,11 +1105,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)

sqlite3_stmt *stmt = self->statement->st;
assert(stmt != NULL);
if (sqlite3_data_count(stmt) == 0) {
(void)stmt_reset(self->statement);
Py_CLEAR(self->statement);
return NULL;
}
assert(sqlite3_data_count(stmt) != 0);

self->locked = 1; // GH-80254: Prevent recursive use of cursors.
PyObject *row = _pysqlite_fetch_one_row(self);
Expand Down

0 comments on commit 8928531

Please sign in to comment.