Bring sqlite3 module up-to-date with what's now in 2.6. Almost. I intentionally
left out the stuff about creating a connection object from a APSW connection.
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 11a14a1..667c3f0 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -1,6 +1,6 @@
/* connection.c - the connection type
*
- * Copyright (C) 2004-2006 Gerhard H�ring <gh@ghaering.de>
+ * Copyright (C) 2004-2007 Gerhard Häring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
@@ -32,6 +32,9 @@
#include "pythread.h"
+#define ACTION_FINALIZE 1
+#define ACTION_RESET 2
+
static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level);
@@ -63,7 +66,7 @@
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist,
&database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
{
- return -1;
+ return -1;
}
self->begin_statement = NULL;
@@ -82,7 +85,7 @@
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
return -1;
}
@@ -169,7 +172,8 @@
self->statement_cache->decref_factory = 0;
}
-void pysqlite_reset_all_statements(pysqlite_Connection* self)
+/* action in (ACTION_RESET, ACTION_FINALIZE) */
+void pysqlite_do_all_statements(pysqlite_Connection* self, int action)
{
int i;
PyObject* weakref;
@@ -179,7 +183,11 @@
weakref = PyList_GetItem(self->statements, i);
statement = PyWeakref_GetObject(weakref);
if (statement != Py_None) {
- (void)pysqlite_statement_reset((pysqlite_Statement*)statement);
+ if (action == ACTION_RESET) {
+ (void)pysqlite_statement_reset((pysqlite_Statement*)statement);
+ } else {
+ (void)pysqlite_statement_finalize((pysqlite_Statement*)statement);
+ }
}
}
}
@@ -247,7 +255,7 @@
return NULL;
}
- pysqlite_flush_statement_cache(self);
+ pysqlite_do_all_statements(self, ACTION_FINALIZE);
if (self->db) {
Py_BEGIN_ALLOW_THREADS
@@ -255,7 +263,7 @@
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
return NULL;
} else {
self->db = NULL;
@@ -292,7 +300,7 @@
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, statement);
goto error;
}
@@ -300,7 +308,7 @@
if (rc == SQLITE_DONE) {
self->inTransaction = 1;
} else {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, statement);
}
Py_BEGIN_ALLOW_THREADS
@@ -308,7 +316,7 @@
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK && !PyErr_Occurred()) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
}
error:
@@ -335,7 +343,7 @@
rc = sqlite3_prepare(self->db, "COMMIT", -1, &statement, &tail);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
goto error;
}
@@ -343,14 +351,14 @@
if (rc == SQLITE_DONE) {
self->inTransaction = 0;
} else {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, statement);
}
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_finalize(statement);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK && !PyErr_Occurred()) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
}
}
@@ -375,13 +383,13 @@
}
if (self->inTransaction) {
- pysqlite_reset_all_statements(self);
+ pysqlite_do_all_statements(self, ACTION_RESET);
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->db, "ROLLBACK", -1, &statement, &tail);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
goto error;
}
@@ -389,14 +397,14 @@
if (rc == SQLITE_DONE) {
self->inTransaction = 0;
} else {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, statement);
}
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_finalize(statement);
Py_END_ALLOW_THREADS
if (rc != SQLITE_OK && !PyErr_Occurred()) {
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
}
}
@@ -746,6 +754,33 @@
return rc;
}
+static int _progress_handler(void* user_arg)
+{
+ int rc;
+ PyObject *ret;
+ PyGILState_STATE gilstate;
+
+ gilstate = PyGILState_Ensure();
+ ret = PyObject_CallFunction((PyObject*)user_arg, "");
+
+ if (!ret) {
+ if (_enable_callback_tracebacks) {
+ PyErr_Print();
+ } else {
+ PyErr_Clear();
+ }
+
+ /* abort query if error occured */
+ rc = 1;
+ } else {
+ rc = (int)PyObject_IsTrue(ret);
+ Py_DECREF(ret);
+ }
+
+ PyGILState_Release(gilstate);
+ return rc;
+}
+
PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
{
PyObject* authorizer_cb;
@@ -771,6 +806,30 @@
}
}
+PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
+{
+ PyObject* progress_handler;
+ int n;
+
+ static char *kwlist[] = { "progress_handler", "n", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:set_progress_handler",
+ kwlist, &progress_handler, &n)) {
+ return NULL;
+ }
+
+ if (progress_handler == Py_None) {
+ /* None clears the progress handler previously set */
+ sqlite3_progress_handler(self->db, 0, 0, (void*)0);
+ } else {
+ sqlite3_progress_handler(self->db, n, _progress_handler, progress_handler);
+ PyDict_SetItem(self->function_pinboard, progress_handler, Py_None);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
int pysqlite_check_thread(pysqlite_Connection* self)
{
if (self->check_same_thread) {
@@ -881,7 +940,8 @@
} else if (rc == PYSQLITE_SQL_WRONG_TYPE) {
PyErr_SetString(pysqlite_Warning, "SQL is of wrong type. Must be string or unicode.");
} else {
- _pysqlite_seterror(self->db);
+ (void)pysqlite_statement_reset(statement);
+ _pysqlite_seterror(self->db, NULL);
}
Py_DECREF(statement);
@@ -1169,7 +1229,7 @@
(callable != Py_None) ? pysqlite_collation_callback : NULL);
if (rc != SQLITE_OK) {
PyDict_DelItem(self->collations, uppercase_name);
- _pysqlite_seterror(self->db);
+ _pysqlite_seterror(self->db, NULL);
goto finally;
}
@@ -1247,6 +1307,8 @@
PyDoc_STR("Creates a new aggregate. Non-standard.")},
{"set_authorizer", (PyCFunction)pysqlite_connection_set_authorizer, METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("Sets authorizer callback. Non-standard.")},
+ {"set_progress_handler", (PyCFunction)pysqlite_connection_set_progress_handler, METH_VARARGS|METH_KEYWORDS,
+ PyDoc_STR("Sets progress handler callback. Non-standard.")},
{"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS,
PyDoc_STR("Executes a SQL statement. Non-standard.")},
{"executemany", (PyCFunction)pysqlite_connection_executemany, METH_VARARGS,