diff options
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r-- | Modules/_sqlite/connection.c | 84 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.c | 37 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.h | 1 | ||||
-rw-r--r-- | Modules/_sqlite/row.c | 10 | ||||
-rw-r--r-- | Modules/_sqlite/statement.c | 4 |
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 } |