# Lone surrogate cannot be encoded to the default encoding (utf8)
"\uDC80", collation_cb)
+ def CheckRecursiveCursorUse(self):
+ """
+ http://bugs.python.org/issue10811
+
+ Recursively using a cursor, such as when reusing it from a generator led to segfaults.
+ Now we catch recursive cursor usage and raise a ProgrammingError.
+ """
+ con = sqlite.connect(":memory:")
+
+ cur = con.cursor()
+ cur.execute("create table a (bar)")
+ cur.execute("create table b (baz)")
+
+ def foo():
+ cur.execute("insert into a (bar) values (?)", (1,))
+ yield 1
+
+ with self.assertRaises(sqlite.ProgrammingError):
+ cur.executemany("insert into b (baz) values (?)",
+ ((i,) for i in foo()))
+
+
def suite():
regression_suite = unittest.makeSuite(RegressionTests, "Check")
return unittest.TestSuite((regression_suite,))
if (cur->closed) {
PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor.");
return 0;
- } else {
- return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection);
}
+
+ if (cur->locked) {
+ PyErr_SetString(pysqlite_ProgrammingError, "Recursive use of cursors not allowed.");
+ return 0;
+ }
+
+ return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection);
}
PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
int allow_8bit_chars;
if (!check_cursor(self)) {
- return NULL;
+ goto error;
}
+ self->locked = 1;
self->reset = 0;
/* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
if (multiple) {
/* executemany() */
if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) {
- return NULL;
+ goto error;
}
if (!PyUnicode_Check(operation)) {
PyErr_SetString(PyExc_ValueError, "operation parameter must be str");
- return NULL;
+ goto error;
}
if (PyIter_Check(second_argument)) {
/* sequence */
parameters_iter = PyObject_GetIter(second_argument);
if (!parameters_iter) {
- return NULL;
+ goto error;
}
}
} else {
/* execute() */
if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) {
- return NULL;
+ goto error;
}
if (!PyUnicode_Check(operation)) {
PyErr_SetString(PyExc_ValueError, "operation parameter must be str");
- return NULL;
+ goto error;
}
parameters_list = PyList_New(0);
if (!parameters_list) {
- return NULL;
+ goto error;
}
if (second_argument == NULL) {
* ROLLBACK could have happened */
#ifdef SQLITE_VERSION_NUMBER
#if SQLITE_VERSION_NUMBER >= 3002002
- self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
+ if (self->connection && self->connection->db)
+ self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db);
#endif
#endif
Py_XDECREF(parameters_iter);
Py_XDECREF(parameters_list);
+ self->locked = 0;
+
if (PyErr_Occurred()) {
self->rowcount = -1L;
return NULL;