Skip to content

Commit 8928531

Browse files
gh-89121: Keep the number of pending SQLite statements to a minimum (#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().
1 parent 11e865c commit 8928531

File tree

1 file changed

+12
-22
lines changed

1 file changed

+12
-22
lines changed

Modules/_sqlite/cursor.c

+12-22
Original file line numberDiff line numberDiff line change
@@ -830,16 +830,12 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
830830
}
831831
}
832832

833-
if (self->statement != NULL) {
834-
/* There is an active statement */
835-
stmt_reset(self->statement);
836-
}
837-
838833
/* reset description */
839834
Py_INCREF(Py_None);
840835
Py_SETREF(self->description, Py_None);
841836

842837
if (self->statement) {
838+
// Reset pending statements on this cursor.
843839
(void)stmt_reset(self->statement);
844840
}
845841

@@ -879,6 +875,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
879875
}
880876
}
881877

878+
assert(!sqlite3_stmt_busy(self->statement->st));
882879
while (1) {
883880
parameters = PyIter_Next(parameters_iter);
884881
if (!parameters) {
@@ -902,7 +899,6 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
902899
PyErr_Clear();
903900
}
904901
}
905-
(void)stmt_reset(self->statement);
906902
_pysqlite_seterror(state, self->connection->db);
907903
goto error;
908904
}
@@ -944,16 +940,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
944940
}
945941
}
946942

947-
if (rc == SQLITE_DONE && !multiple) {
943+
if (rc == SQLITE_DONE) {
948944
if (self->statement->is_dml) {
949-
self->rowcount = (long)sqlite3_changes(self->connection->db);
950-
}
951-
stmt_reset(self->statement);
952-
Py_CLEAR(self->statement);
953-
}
954-
955-
if (multiple) {
956-
if (self->statement->is_dml && rc == SQLITE_DONE) {
957945
self->rowcount += (long)sqlite3_changes(self->connection->db);
958946
}
959947
stmt_reset(self->statement);
@@ -980,11 +968,17 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
980968
self->locked = 0;
981969

982970
if (PyErr_Occurred()) {
971+
if (self->statement) {
972+
(void)stmt_reset(self->statement);
973+
Py_CLEAR(self->statement);
974+
}
983975
self->rowcount = -1L;
984976
return NULL;
985-
} else {
986-
return Py_NewRef((PyObject *)self);
987977
}
978+
if (self->statement && !sqlite3_stmt_busy(self->statement->st)) {
979+
Py_CLEAR(self->statement);
980+
}
981+
return Py_NewRef((PyObject *)self);
988982
}
989983

990984
/*[clinic input]
@@ -1111,11 +1105,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self)
11111105

11121106
sqlite3_stmt *stmt = self->statement->st;
11131107
assert(stmt != NULL);
1114-
if (sqlite3_data_count(stmt) == 0) {
1115-
(void)stmt_reset(self->statement);
1116-
Py_CLEAR(self->statement);
1117-
return NULL;
1118-
}
1108+
assert(sqlite3_data_count(stmt) != 0);
11191109

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

0 commit comments

Comments
 (0)