Skip to content

Commit 666fa2e

Browse files
committed
consolidate sqlite3_finalize and sqlite3_reset usages
1 parent c7b11b7 commit 666fa2e

File tree

4 files changed

+71
-16
lines changed

4 files changed

+71
-16
lines changed

Modules/_sqlite/cursor.c

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,13 @@ cursor_clear(PyObject *op)
173173
Py_CLEAR(self->row_factory);
174174
if (self->statement) {
175175
/* Reset the statement if the user has not closed the cursor */
176-
stmt_reset(self->statement);
176+
int rc = stmt_reset(self->statement);
177177
Py_CLEAR(self->statement);
178+
if (rc != SQLITE_OK) {
179+
pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self));
180+
PyErr_SetString(state->InternalError, "cannot reset statement");
181+
PyErr_FormatUnraisable("Exception ignored in cursor_clear()");
182+
}
178183
}
179184

180185
return 0;
@@ -834,7 +839,9 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
834839

835840
if (self->statement) {
836841
// Reset pending statements on this cursor.
837-
(void)stmt_reset(self->statement);
842+
if (stmt_reset(self->statement) != SQLITE_OK) {
843+
goto reset_failure;
844+
}
838845
}
839846

840847
PyObject *stmt = get_statement_from_cache(self, operation);
@@ -858,7 +865,9 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
858865
}
859866
}
860867

861-
(void)stmt_reset(self->statement);
868+
if (stmt_reset(self->statement) != SQLITE_OK) {
869+
goto reset_failure;
870+
}
862871
self->rowcount = self->statement->is_dml ? 0L : -1L;
863872

864873
/* We start a transaction implicitly before a DML statement.
@@ -940,7 +949,9 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
940949
if (self->statement->is_dml) {
941950
self->rowcount += (long)sqlite3_changes(self->connection->db);
942951
}
943-
stmt_reset(self->statement);
952+
if (stmt_reset(self->statement) != SQLITE_OK) {
953+
goto reset_failure;
954+
}
944955
}
945956
Py_XDECREF(parameters);
946957
}
@@ -964,9 +975,11 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
964975
self->locked = 0;
965976

966977
if (PyErr_Occurred()) {
967-
if (self->statement) {
968-
(void)stmt_reset(self->statement);
978+
if (self->statement && stmt_reset(self->statement) != SQLITE_OK) {
969979
Py_CLEAR(self->statement);
980+
PyObject *exc = PyErr_GetRaisedException();
981+
PyErr_SetString(state->InternalError, "cannot reset statement");
982+
PyErr_SetRaisedException(exc);
970983
}
971984
self->rowcount = -1L;
972985
return NULL;
@@ -975,6 +988,20 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
975988
Py_CLEAR(self->statement);
976989
}
977990
return Py_NewRef((PyObject *)self);
991+
992+
reset_failure:
993+
/* suite to execute when stmt_reset() failed and no exception is set */
994+
assert(!PyErr_Occurred());
995+
996+
Py_XDECREF(parameters);
997+
Py_XDECREF(parameters_iter);
998+
Py_XDECREF(parameters_list);
999+
1000+
self->locked = 0;
1001+
self->rowcount = -1L;
1002+
Py_CLEAR(self->statement);
1003+
PyErr_SetString(state->InternalError, "cannot reset statement");
1004+
return NULL;
9781005
}
9791006

9801007
/*[clinic input]
@@ -1117,14 +1144,20 @@ pysqlite_cursor_iternext(PyObject *op)
11171144
if (self->statement->is_dml) {
11181145
self->rowcount = (long)sqlite3_changes(self->connection->db);
11191146
}
1120-
(void)stmt_reset(self->statement);
1147+
int rc = stmt_reset(self->statement);
11211148
Py_CLEAR(self->statement);
1149+
if (rc != SQLITE_OK) {
1150+
goto reset_failure;
1151+
}
11221152
}
11231153
else if (rc != SQLITE_ROW) {
1124-
set_error_from_db(self->connection->state, self->connection->db);
1125-
(void)stmt_reset(self->statement);
1154+
rc = set_error_from_db(self->connection->state, self->connection->db);
1155+
int reset_ok = stmt_reset(self->statement);
11261156
Py_CLEAR(self->statement);
11271157
Py_DECREF(row);
1158+
if (rc == SQLITE_OK && reset_ok != SQLITE_OK) {
1159+
goto reset_failure;
1160+
}
11281161
return NULL;
11291162
}
11301163
if (!Py_IsNone(self->row_factory)) {
@@ -1134,6 +1167,12 @@ pysqlite_cursor_iternext(PyObject *op)
11341167
Py_SETREF(row, new_row);
11351168
}
11361169
return row;
1170+
1171+
reset_failure:
1172+
assert(!PyErr_Occurred());
1173+
PyErr_SetString(self->connection->state->InternalError,
1174+
"cannot reset statement");
1175+
return NULL;
11371176
}
11381177

11391178
/*[clinic input]
@@ -1292,7 +1331,11 @@ pysqlite_cursor_close_impl(pysqlite_Cursor *self)
12921331
}
12931332

12941333
if (self->statement) {
1295-
(void)stmt_reset(self->statement);
1334+
if (stmt_reset(self->statement) != SQLITE_OK) {
1335+
PyErr_SetString(self->connection->state->InternalError,
1336+
"cannot close cursor");
1337+
return NULL;
1338+
}
12961339
Py_CLEAR(self->statement);
12971340
}
12981341

Modules/_sqlite/statement.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,12 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
9696
return self;
9797

9898
error:
99-
(void)sqlite3_finalize(stmt);
99+
assert(PyErr_Occurred());
100+
if (sqlite3_finalize(stmt) != SQLITE_OK) {
101+
PyObject *exc = PyErr_GetRaisedException();
102+
PyErr_SetString(connection->InternalError, "cannot finalize statement");
103+
_PyErr_ChainExceptions1(exc);
104+
}
100105
return NULL;
101106
}
102107

@@ -107,10 +112,16 @@ stmt_dealloc(PyObject *op)
107112
PyTypeObject *tp = Py_TYPE(self);
108113
PyObject_GC_UnTrack(op);
109114
if (self->st) {
115+
int rc;
110116
Py_BEGIN_ALLOW_THREADS
111-
sqlite3_finalize(self->st);
117+
rc = sqlite3_finalize(self->st);
112118
Py_END_ALLOW_THREADS
113-
self->st = 0;
119+
self->st = NULL;
120+
if (rc != SQLITE_OK) {
121+
pysqlite_state *state = PyType_GetModuleState(Py_TYPE(op));
122+
PyErr_SetString(state->InternalError, "cannot finalize statement");
123+
PyErr_FormatUnraisable("Exception ignored in stmt_dealloc()");
124+
}
114125
}
115126
tp->tp_free(self);
116127
Py_DECREF(tp);

Modules/_sqlite/util.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,22 @@ set_error_from_code(pysqlite_state *state, int code)
135135
/**
136136
* Checks the SQLite error code and sets the appropriate DB-API exception.
137137
*/
138-
void
138+
int
139139
set_error_from_db(pysqlite_state *state, sqlite3 *db)
140140
{
141141
int errorcode = sqlite3_errcode(db);
142142
PyObject *exc_class = get_exception_class(state, errorcode);
143143
if (exc_class == NULL) {
144144
// No new exception need be raised.
145-
return;
145+
return SQLITE_OK;
146146
}
147147

148148
/* Create and set the exception. */
149149
int extended_errcode = sqlite3_extended_errcode(db);
150150
// sqlite3_errmsg() always returns an UTF-8 encoded message
151151
const char *errmsg = sqlite3_errmsg(db);
152152
raise_exception(exc_class, extended_errcode, errmsg);
153+
return errorcode;
153154
}
154155

155156
#ifdef WORDS_BIGENDIAN

Modules/_sqlite/util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/**
3232
* Checks the SQLite error code and sets the appropriate DB-API exception.
3333
*/
34-
void set_error_from_db(pysqlite_state *state, sqlite3 *db);
34+
int set_error_from_db(pysqlite_state *state, sqlite3 *db);
3535
void set_error_from_code(pysqlite_state *state, int code);
3636

3737
sqlite_int64 _pysqlite_long_as_int64(PyObject * value);

0 commit comments

Comments
 (0)