Skip to content

Commit 84891c6

Browse files
Calculate rowcount using sqlite3_total_changes() diff
1 parent 5436db7 commit 84891c6

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

Modules/_sqlite/cursor.c

+29-16
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self,
107107

108108
self->arraysize = 1;
109109
self->closed = 0;
110+
self->rowcount = -1L;
110111

111112
Py_INCREF(Py_None);
112113
Py_XSETREF(self->row_factory, Py_None);
@@ -855,7 +856,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
855856
goto error;
856857
}
857858

858-
if (self->statement->in_use) {
859+
if (sqlite3_stmt_readonly(self->statement->st)) {
859860
Py_SETREF(self->statement,
860861
pysqlite_statement_create(self->connection, operation));
861862
if (self->statement == NULL) {
@@ -866,6 +867,14 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
866867
stmt_reset(self->statement);
867868
stmt_mark_dirty(self->statement);
868869

870+
// Save current row count
871+
if (sqlite3_stmt_readonly(self->statement->st)) {
872+
self->rowcount = -1L;
873+
}
874+
else {
875+
self->rowcount = (long)sqlite3_total_changes(self->connection->db);
876+
}
877+
869878
/* We start a transaction implicitly before a DML statement.
870879
SELECT is the only exception. See #9924. */
871880
if (self->connection->isolation_level
@@ -972,6 +981,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
972981
self->locked = 0;
973982

974983
if (PyErr_Occurred()) {
984+
self->rowcount = -1L;
975985
return NULL;
976986
} else {
977987
return Py_NewRef((PyObject *)self);
@@ -1299,6 +1309,19 @@ pysqlite_cursor_close_impl(pysqlite_Cursor *self)
12991309
Py_RETURN_NONE;
13001310
}
13011311

1312+
static PyObject *
1313+
get_rowcount(pysqlite_Cursor *self, void *Py_UNUSED(closure))
1314+
{
1315+
if (!check_cursor(self)) {
1316+
return -1;
1317+
}
1318+
if (self->rowcount != -1L) {
1319+
long changes = (long)sqlite3_total_changes(self->connection->db);
1320+
return PyLong_FromLong(changes - self->rowcount);
1321+
}
1322+
return PyLong_FromLong(-1L);
1323+
}
1324+
13021325
static PyMethodDef cursor_methods[] = {
13031326
PYSQLITE_CURSOR_CLOSE_METHODDEF
13041327
PYSQLITE_CURSOR_EXECUTEMANY_METHODDEF
@@ -1312,21 +1335,6 @@ static PyMethodDef cursor_methods[] = {
13121335
{NULL, NULL}
13131336
};
13141337

1315-
static PyObject *
1316-
get_rowcount(pysqlite_Cursor *self, void *Py_UNUSED(unused))
1317-
{
1318-
if (!check_cursor(self)) {
1319-
return NULL;
1320-
}
1321-
int changes = sqlite3_changes(self->connection->db);
1322-
return PyLong_FromLong(changes);
1323-
}
1324-
1325-
static PyGetSetDef cursor_getset[] = {
1326-
{"rowcount", (getter)get_rowcount, (setter)NULL},
1327-
{NULL},
1328-
};
1329-
13301338
static struct PyMemberDef cursor_members[] =
13311339
{
13321340
{"connection", T_OBJECT, offsetof(pysqlite_Cursor, connection), READONLY},
@@ -1338,6 +1346,11 @@ static struct PyMemberDef cursor_members[] =
13381346
{NULL}
13391347
};
13401348

1349+
static PyGetSetDef cursor_getset[] = {
1350+
{"rowcount", (getter)get_rowcount, (setter)NULL},
1351+
{NULL},
1352+
};
1353+
13411354
static const char cursor_doc[] =
13421355
PyDoc_STR("SQLite database cursor class.");
13431356

Modules/_sqlite/cursor.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef struct
3838
PyObject* row_cast_map;
3939
int arraysize;
4040
PyObject* lastrowid;
41+
long rowcount; // saved row count
4142
PyObject* row_factory;
4243
pysqlite_Statement* statement;
4344
int closed;

0 commit comments

Comments
 (0)