aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Modules/_sqlite
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r--Modules/_sqlite/connection.c84
-rw-r--r--Modules/_sqlite/cursor.c37
-rw-r--r--Modules/_sqlite/cursor.h1
-rw-r--r--Modules/_sqlite/row.c10
-rw-r--r--Modules/_sqlite/statement.c4
5 files changed, 102 insertions, 34 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 7d12d5ef61f..310a27c42a2 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -675,7 +675,6 @@ void _pysqlite_final_callback(sqlite3_context* context)
{
PyObject* function_result = NULL;
PyObject** aggregate_instance;
- PyObject* aggregate_class;
#ifdef WITH_THREAD
PyGILState_STATE threadstate;
@@ -683,8 +682,6 @@ void _pysqlite_final_callback(sqlite3_context* context)
threadstate = PyGILState_Ensure();
#endif
- aggregate_class = (PyObject*)sqlite3_user_data(context);
-
aggregate_instance = (PyObject**)sqlite3_aggregate_context(context, sizeof(PyObject*));
if (!*aggregate_instance) {
/* this branch is executed if there was an exception in the aggregate's
@@ -909,6 +906,38 @@ static int _progress_handler(void* user_arg)
return rc;
}
+static void _trace_callback(void* user_arg, const char* statement_string)
+{
+ PyObject *py_statement = NULL;
+ PyObject *ret = NULL;
+
+#ifdef WITH_THREAD
+ PyGILState_STATE gilstate;
+
+ gilstate = PyGILState_Ensure();
+#endif
+ py_statement = PyUnicode_DecodeUTF8(statement_string,
+ strlen(statement_string), "replace");
+ if (py_statement) {
+ ret = PyObject_CallFunctionObjArgs((PyObject*)user_arg, py_statement, NULL);
+ Py_DECREF(py_statement);
+ }
+
+ if (ret) {
+ Py_DECREF(ret);
+ } else {
+ if (_enable_callback_tracebacks) {
+ PyErr_Print();
+ } else {
+ PyErr_Clear();
+ }
+ }
+
+#ifdef WITH_THREAD
+ PyGILState_Release(gilstate);
+#endif
+}
+
static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
{
PyObject* authorizer_cb;
@@ -968,6 +997,34 @@ static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* s
return Py_None;
}
+static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
+{
+ PyObject* trace_callback;
+
+ static char *kwlist[] = { "trace_callback", NULL };
+
+ if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+ return NULL;
+ }
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_trace_callback",
+ kwlist, &trace_callback)) {
+ return NULL;
+ }
+
+ if (trace_callback == Py_None) {
+ /* None clears the trace callback previously set */
+ sqlite3_trace(self->db, 0, (void*)0);
+ } else {
+ if (PyDict_SetItem(self->function_pinboard, trace_callback, Py_None) == -1)
+ return NULL;
+ sqlite3_trace(self->db, _trace_callback, trace_callback);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
#ifdef HAVE_LOAD_EXTENSION
static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObject* args)
{
@@ -1379,10 +1436,11 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
PyObject* uppercase_name = 0;
PyObject* name;
PyObject* retval;
- Py_UNICODE* chk;
Py_ssize_t i, len;
char *uppercase_name_str;
int rc;
+ unsigned int kind;
+ void *data;
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
goto finally;
@@ -1397,12 +1455,16 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
goto finally;
}
- len = PyUnicode_GET_SIZE(uppercase_name);
- chk = PyUnicode_AS_UNICODE(uppercase_name);
- for (i=0; i<len; i++, chk++) {
- if ((*chk >= '0' && *chk <= '9')
- || (*chk >= 'A' && *chk <= 'Z')
- || (*chk == '_'))
+ if (PyUnicode_READY(uppercase_name))
+ goto finally;
+ len = PyUnicode_GET_LENGTH(uppercase_name);
+ kind = PyUnicode_KIND(uppercase_name);
+ data = PyUnicode_DATA(uppercase_name);
+ for (i=0; i<len; i++) {
+ Py_UCS4 ch = PyUnicode_READ(kind, data, i);
+ if ((ch >= '0' && ch <= '9')
+ || (ch >= 'A' && ch <= 'Z')
+ || (ch == '_'))
{
continue;
} else {
@@ -1521,6 +1583,8 @@ static PyMethodDef connection_methods[] = {
#endif
{"set_progress_handler", (PyCFunction)pysqlite_connection_set_progress_handler, METH_VARARGS|METH_KEYWORDS,
PyDoc_STR("Sets progress handler callback. Non-standard.")},
+ {"set_trace_callback", (PyCFunction)pysqlite_connection_set_trace_callback, METH_VARARGS|METH_KEYWORDS,
+ PyDoc_STR("Sets a trace callback called for each SQL statement (passed as unicode). Non-standard.")},
{"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS,
PyDoc_STR("Executes a SQL statement. Non-standard.")},
{"executemany", (PyCFunction)pysqlite_connection_executemany, METH_VARARGS,
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index b9a4358b1a9..264ae451ad5 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -126,11 +126,9 @@ static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject*
static void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
{
- int rc;
-
/* Reset the statement if the user has not closed the cursor */
if (self->statement) {
- rc = pysqlite_statement_reset(self->statement);
+ pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
}
@@ -432,9 +430,14 @@ static int check_cursor(pysqlite_Cursor* cur)
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)
@@ -457,9 +460,10 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
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 */
@@ -472,12 +476,12 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
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)) {
@@ -488,23 +492,23 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
/* 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) {
@@ -529,7 +533,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
if (self->statement != NULL) {
/* There is an active statement */
- rc = pysqlite_statement_reset(self->statement);
+ pysqlite_statement_reset(self->statement);
}
operation_cstr = _PyUnicode_AsStringAndSize(operation, &operation_len);
@@ -734,7 +738,7 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
}
if (multiple) {
- rc = pysqlite_statement_reset(self->statement);
+ pysqlite_statement_reset(self->statement);
}
Py_XDECREF(parameters);
}
@@ -744,7 +748,8 @@ error:
* 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
@@ -752,6 +757,8 @@ error:
Py_XDECREF(parameters_iter);
Py_XDECREF(parameters_list);
+ self->locked = 0;
+
if (PyErr_Occurred()) {
self->rowcount = -1L;
return NULL;
diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h
index 5d8b5c160d5..118ba388a41 100644
--- a/Modules/_sqlite/cursor.h
+++ b/Modules/_sqlite/cursor.h
@@ -42,6 +42,7 @@ typedef struct
pysqlite_Statement* statement;
int closed;
int reset;
+ int locked;
int initialized;
/* the next row to be returned, NULL if no next row available */
diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c
index 3d440942f9d..b50658c220d 100644
--- a/Modules/_sqlite/row.c
+++ b/Modules/_sqlite/row.c
@@ -173,10 +173,9 @@ static Py_hash_t pysqlite_row_hash(pysqlite_Row *self)
static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
{
- if (opid != Py_EQ && opid != Py_NE) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
+ if (opid != Py_EQ && opid != Py_NE)
+ Py_RETURN_NOTIMPLEMENTED;
+
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other;
PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
@@ -186,8 +185,7 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
return PyObject_RichCompare(self->data, other->data, opid);
}
}
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
+ Py_RETURN_NOTIMPLEMENTED;
}
PyMappingMethods pysqlite_row_as_mapping = {
diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c
index f89fc9abf19..4e039c19852 100644
--- a/Modules/_sqlite/statement.c
+++ b/Modules/_sqlite/statement.c
@@ -369,11 +369,9 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self)
void pysqlite_statement_dealloc(pysqlite_Statement* self)
{
- int rc;
-
if (self->st) {
Py_BEGIN_ALLOW_THREADS
- rc = sqlite3_finalize(self->st);
+ sqlite3_finalize(self->st);
Py_END_ALLOW_THREADS
}