diff options
Diffstat (limited to 'Modules/_sqlite/connection.c')
-rw-r--r-- | Modules/_sqlite/connection.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 28bd647..551431c 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -60,7 +60,11 @@ static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { - static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL}; + static char *kwlist[] = { + "database", "timeout", "detect_types", "isolation_level", + "check_same_thread", "factory", "cached_statements", "uri", + NULL + }; char* database; int detect_types = 0; @@ -68,11 +72,14 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject PyObject* factory = NULL; int check_same_thread = 1; int cached_statements = 100; + int uri = 0; double timeout = 5.0; int rc; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOi", kwlist, - &database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist, + &database, &timeout, &detect_types, + &isolation_level, &check_same_thread, + &factory, &cached_statements, &uri)) { return -1; } @@ -91,8 +98,19 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject Py_INCREF(&PyUnicode_Type); self->text_factory = (PyObject*)&PyUnicode_Type; +#ifdef SQLITE_OPEN_URI + Py_BEGIN_ALLOW_THREADS + rc = sqlite3_open_v2(database, &self->db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + (uri ? SQLITE_OPEN_URI : 0), NULL); +#else + if (uri) { + PyErr_SetString(pysqlite_NotSupportedError, "URIs not supported"); + return -1; + } Py_BEGIN_ALLOW_THREADS rc = sqlite3_open(database, &self->db); +#endif Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { @@ -679,6 +697,7 @@ void _pysqlite_final_callback(sqlite3_context* context) PyObject** aggregate_instance; _Py_IDENTIFIER(finalize); int ok; + PyObject *exception, *value, *tb; #ifdef WITH_THREAD PyGILState_STATE threadstate; @@ -694,7 +713,11 @@ void _pysqlite_final_callback(sqlite3_context* context) goto error; } + /* Keep the exception (if any) of the last call to step() */ + PyErr_Fetch(&exception, &value, &tb); + function_result = _PyObject_CallMethodId(*aggregate_instance, &PyId_finalize, ""); + Py_DECREF(*aggregate_instance); ok = 0; @@ -711,6 +734,10 @@ void _pysqlite_final_callback(sqlite3_context* context) _sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); } + /* Restore the exception (if any) of the last call to step(), + but clear also the current exception if finalize() failed */ + PyErr_Restore(exception, value, tb); + error: #ifdef WITH_THREAD PyGILState_Release(threadstate); @@ -856,25 +883,33 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co gilstate = PyGILState_Ensure(); #endif - ret = PyObject_CallFunction((PyObject*)user_arg, "issss", action, arg1, arg2, dbname, access_attempt_source); - if (!ret) { - if (_enable_callback_tracebacks) { - PyErr_Print(); - } else { - PyErr_Clear(); - } + if (!PyErr_Occurred()) { + ret = PyObject_CallFunction((PyObject*)user_arg, "issss", action, arg1, arg2, dbname, access_attempt_source); + + if (!ret) { + if (_enable_callback_tracebacks) { + PyErr_Print(); + } else { + PyErr_Clear(); + } - rc = SQLITE_DENY; - } else { - if (PyLong_Check(ret)) { - rc = _PyLong_AsInt(ret); - if (rc == -1 && PyErr_Occurred()) - rc = SQLITE_DENY; - } else { rc = SQLITE_DENY; + } else { + if (PyLong_Check(ret)) { + rc = _PyLong_AsInt(ret); + if (rc == -1 && PyErr_Occurred()) + rc = SQLITE_DENY; + } else { + rc = SQLITE_DENY; + } + Py_DECREF(ret); } - Py_DECREF(ret); + } + else { + /* A previous call to the authorizer callback failed and raised an + exception: don't call the Python authorizer callback */ + rc = SQLITE_DENY; } #ifdef WITH_THREAD |