From 4c0deb25ac899fbe4da626ce3cb21f204cdd3aa9 Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Tue, 20 Jul 2021 12:59:18 +0200 Subject: [PATCH] bpo-42064: Finalise establishing sqlite3 global state (GH-27155) With this, all sqlite3 static globals have been moved to the global state. There are a couple of global static strings left, but there should be no need for adding them to the state. https://bugs.python.org/issue42064 --- Modules/_sqlite/connection.c | 51 ++++++++++++++++++++++---------- Modules/_sqlite/cursor.c | 6 ++-- Modules/_sqlite/microprotocols.c | 19 +++++------- Modules/_sqlite/module.c | 24 +++++++-------- Modules/_sqlite/module.h | 19 ++++++------ Modules/_sqlite/statement.c | 3 +- 6 files changed, 69 insertions(+), 53 deletions(-) diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 63b0fb9784a..33d3d4cfbd1 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -637,9 +637,11 @@ _pysqlite_func_callback(sqlite3_context *context, int argc, sqlite3_value **argv Py_DECREF(py_retval); } if (!ok) { - if (_pysqlite_enable_callback_tracebacks) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - } else { + } + else { PyErr_Clear(); } sqlite3_result_error(context, "user-defined function raised exception", -1); @@ -669,9 +671,12 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ if (PyErr_Occurred()) { *aggregate_instance = 0; - if (_pysqlite_enable_callback_tracebacks) { + + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - } else { + } + else { PyErr_Clear(); } sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); @@ -693,9 +698,11 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ Py_DECREF(args); if (!function_result) { - if (_pysqlite_enable_callback_tracebacks) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - } else { + } + else { PyErr_Clear(); } sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); @@ -746,9 +753,11 @@ _pysqlite_final_callback(sqlite3_context *context) Py_DECREF(function_result); } if (!ok) { - if (_pysqlite_enable_callback_tracebacks) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - } else { + } + else { PyErr_Clear(); } sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); @@ -941,10 +950,13 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co ret = PyObject_CallFunction((PyObject*)user_arg, "issss", action, arg1, arg2, dbname, access_attempt_source); if (ret == NULL) { - if (_pysqlite_enable_callback_tracebacks) + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - else + } + else { PyErr_Clear(); + } rc = SQLITE_DENY; } @@ -952,10 +964,13 @@ static int _authorizer_callback(void* user_arg, int action, const char* arg1, co if (PyLong_Check(ret)) { rc = _PyLong_AsInt(ret); if (rc == -1 && PyErr_Occurred()) { - if (_pysqlite_enable_callback_tracebacks) + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - else + } + else { PyErr_Clear(); + } rc = SQLITE_DENY; } } @@ -979,9 +994,11 @@ static int _progress_handler(void* user_arg) ret = _PyObject_CallNoArg((PyObject*)user_arg); if (!ret) { - if (_pysqlite_enable_callback_tracebacks) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - } else { + } + else { PyErr_Clear(); } @@ -1030,9 +1047,11 @@ static void _trace_callback(void* user_arg, const char* statement_string) if (ret) { Py_DECREF(ret); } else { - if (_pysqlite_enable_callback_tracebacks) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->enable_callback_tracebacks) { PyErr_Print(); - } else { + } + else { PyErr_Clear(); } } diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 07202dfbf57..24b4a37521d 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -147,7 +147,8 @@ _pysqlite_get_converter(const char *keystr, Py_ssize_t keylen) return NULL; } - retval = PyDict_GetItemWithError(_pysqlite_converters, upcase_key); + pysqlite_state *state = pysqlite_get_state(NULL); + retval = PyDict_GetItemWithError(state->converters, upcase_key); Py_DECREF(upcase_key); return retval; @@ -469,6 +470,7 @@ get_statement_from_cache(pysqlite_Cursor *self, PyObject *operation) static PyObject * _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument) { + pysqlite_state *state = pysqlite_get_state(NULL); PyObject* parameters_list = NULL; PyObject* parameters_iter = NULL; PyObject* parameters = NULL; @@ -583,7 +585,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (rc != SQLITE_DONE && rc != SQLITE_ROW) { if (PyErr_Occurred()) { /* there was an error that occurred in a user-defined callback */ - if (_pysqlite_enable_callback_tracebacks) { + if (state->enable_callback_tracebacks) { PyErr_Print(); } else { PyErr_Clear(); diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index e72fc929a01..160d7b923d7 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -29,9 +29,6 @@ #include "microprotocols.h" #include "prepare_protocol.h" -/** the adapters registry **/ - -static PyObject *psyco_adapters = NULL; /* pysqlite_microprotocols_init - initialize the adapters dictionary */ @@ -39,14 +36,13 @@ int pysqlite_microprotocols_init(PyObject *module) { /* create adapters dictionary and put it in module namespace */ - if ((psyco_adapters = PyDict_New()) == NULL) { + pysqlite_state *state = pysqlite_get_state(module); + state->psyco_adapters = PyDict_New(); + if (state->psyco_adapters == NULL) { return -1; } - int res = PyModule_AddObjectRef(module, "adapters", psyco_adapters); - Py_DECREF(psyco_adapters); - - return res; + return PyModule_AddObjectRef(module, "adapters", state->psyco_adapters); } @@ -65,7 +61,8 @@ pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) return -1; } - rc = PyDict_SetItem(psyco_adapters, key, cast); + pysqlite_state *state = pysqlite_get_state(NULL); + rc = PyDict_SetItem(state->psyco_adapters, key, cast); Py_DECREF(key); return rc; @@ -89,7 +86,8 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) if (!key) { return NULL; } - adapter = PyDict_GetItemWithError(psyco_adapters, key); + pysqlite_state *state = pysqlite_get_state(NULL); + adapter = PyDict_GetItemWithError(state->psyco_adapters, key); Py_DECREF(key); if (adapter) { Py_INCREF(adapter); @@ -143,7 +141,6 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) return Py_NewRef(alt); } /* else set the right exception and return NULL */ - pysqlite_state *state = pysqlite_get_state(NULL); PyErr_SetString(state->ProgrammingError, "can't adapt"); return NULL; } diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 3d81ad8f140..98b2c90108f 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -41,11 +41,6 @@ module _sqlite3 [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ -/* static objects at module-level */ -PyObject* _pysqlite_converters = NULL; -int _pysqlite_enable_callback_tracebacks = 0; -int pysqlite_BaseTypeAdapted = 0; - pysqlite_state pysqlite_global_state; // NOTE: This must equal sqlite3.Connection.__init__ argument spec! @@ -159,7 +154,8 @@ pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, * (99 % of all usages) */ if (type == &PyLong_Type || type == &PyFloat_Type || type == &PyUnicode_Type || type == &PyByteArray_Type) { - pysqlite_BaseTypeAdapted = 1; + pysqlite_state *state = pysqlite_get_state(module); + state->BaseTypeAdapted = 1; } pysqlite_state *state = pysqlite_get_state(NULL); @@ -197,7 +193,8 @@ pysqlite_register_converter_impl(PyObject *module, PyObject *orig_name, goto error; } - if (PyDict_SetItem(_pysqlite_converters, name, callable) != 0) { + pysqlite_state *state = pysqlite_get_state(module); + if (PyDict_SetItem(state->converters, name, callable) != 0) { goto error; } @@ -220,7 +217,8 @@ static PyObject * pysqlite_enable_callback_trace_impl(PyObject *module, int enable) /*[clinic end generated code: output=4ff1d051c698f194 input=cb79d3581eb77c40]*/ { - _pysqlite_enable_callback_tracebacks = enable; + pysqlite_state *state = pysqlite_get_state(module); + state->enable_callback_tracebacks = enable; Py_RETURN_NONE; } @@ -246,15 +244,13 @@ pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, static int converters_init(PyObject* module) { - _pysqlite_converters = PyDict_New(); - if (!_pysqlite_converters) { + pysqlite_state *state = pysqlite_get_state(module); + state->converters = PyDict_New(); + if (state->converters == NULL) { return -1; } - int res = PyModule_AddObjectRef(module, "converters", _pysqlite_converters); - Py_DECREF(_pysqlite_converters); - - return res; + return PyModule_AddObjectRef(module, "converters", state->converters); } static int diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h index 7ce8381df0c..13444907008 100644 --- a/Modules/_sqlite/module.h +++ b/Modules/_sqlite/module.h @@ -41,7 +41,17 @@ typedef struct { PyObject *ProgrammingError; PyObject *Warning; + + /* A dictionary, mapping column types (INTEGER, VARCHAR, etc.) to converter + * functions, that convert the SQL value to the appropriate Python value. + * The key is uppercase. + */ + PyObject *converters; + PyObject *lru_cache; + PyObject *psyco_adapters; // The adapters registry + int BaseTypeAdapted; + int enable_callback_tracebacks; PyTypeObject *ConnectionType; PyTypeObject *CursorType; @@ -58,15 +68,6 @@ pysqlite_get_state(PyObject *Py_UNUSED(module)) return &pysqlite_global_state; } -/* A dictionary, mapping column types (INTEGER, VARCHAR, etc.) to converter - * functions, that convert the SQL value to the appropriate Python value. - * The key is uppercase. - */ -extern PyObject* _pysqlite_converters; - -extern int _pysqlite_enable_callback_tracebacks; -extern int pysqlite_BaseTypeAdapted; - #define PARSE_DECLTYPES 1 #define PARSE_COLNAMES 2 #endif diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index cca8616fe2e..8add50960f8 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -211,7 +211,8 @@ int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObjec /* returns 0 if the object is one of Python's internal ones that don't need to be adapted */ static int _need_adapt(PyObject* obj) { - if (pysqlite_BaseTypeAdapted) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (state->BaseTypeAdapted) { return 1; }