diff options
author | Erlend Egeberg Aasland <erlend.aasland@innova.no> | 2021-07-14 11:26:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-14 11:26:44 (GMT) |
commit | 05162993fe62e7fa3acebdd0062586b9bf63d46a (patch) | |
tree | 136be9cca99943560f320c11e43d3fde38a41d10 /Modules/_sqlite | |
parent | e5862f79c16e28f1ec51d179698739a9b2d8c1d2 (diff) | |
download | cpython-05162993fe62e7fa3acebdd0062586b9bf63d46a.zip cpython-05162993fe62e7fa3acebdd0062586b9bf63d46a.tar.gz cpython-05162993fe62e7fa3acebdd0062586b9bf63d46a.tar.bz2 |
bpo-42064: Move `sqlite3` exceptions to global state, part 2 of 2 (GH-26884)
Automerge-Triggered-By: GH:encukou
Diffstat (limited to 'Modules/_sqlite')
-rw-r--r-- | Modules/_sqlite/connection.c | 42 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.c | 30 | ||||
-rw-r--r-- | Modules/_sqlite/microprotocols.c | 3 | ||||
-rw-r--r-- | Modules/_sqlite/module.c | 55 | ||||
-rw-r--r-- | Modules/_sqlite/module.h | 13 | ||||
-rw-r--r-- | Modules/_sqlite/statement.c | 21 | ||||
-rw-r--r-- | Modules/_sqlite/util.c | 8 |
7 files changed, 90 insertions, 82 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 6e7101a..a067556 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -187,12 +187,12 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, self->Error = state->Error; self->InterfaceError = state->InterfaceError; self->DatabaseError = state->DatabaseError; - self->DataError = pysqlite_DataError; - self->OperationalError = pysqlite_OperationalError; - self->IntegrityError = pysqlite_IntegrityError; + self->DataError = state->DataError; + self->OperationalError = state->OperationalError; + self->IntegrityError = state->IntegrityError; self->InternalError = state->InternalError; - self->ProgrammingError = pysqlite_ProgrammingError; - self->NotSupportedError = pysqlite_NotSupportedError; + self->ProgrammingError = state->ProgrammingError; + self->NotSupportedError = state->NotSupportedError; if (PySys_Audit("sqlite3.connect/handle", "O", self) < 0) { return -1; @@ -390,13 +390,16 @@ pysqlite_connection_close_impl(pysqlite_Connection *self) */ int pysqlite_check_connection(pysqlite_Connection* con) { + pysqlite_state *state = pysqlite_get_state(NULL); if (!con->initialized) { - PyErr_SetString(pysqlite_ProgrammingError, "Base Connection.__init__ not called."); + PyErr_SetString(state->ProgrammingError, + "Base Connection.__init__ not called."); return 0; } if (!con->db) { - PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed database."); + PyErr_SetString(state->ProgrammingError, + "Cannot operate on a closed database."); return 0; } else { return 1; @@ -858,12 +861,12 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, if (deterministic) { #if SQLITE_VERSION_NUMBER < 3008003 - PyErr_SetString(pysqlite_NotSupportedError, + PyErr_SetString(self->NotSupportedError, "deterministic=True requires SQLite 3.8.3 or higher"); return NULL; #else if (sqlite3_libversion_number() < 3008003) { - PyErr_SetString(pysqlite_NotSupportedError, + PyErr_SetString(self->NotSupportedError, "deterministic=True requires SQLite 3.8.3 or higher"); return NULL; } @@ -882,7 +885,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self, if (rc != SQLITE_OK) { /* Workaround for SQLite bug: no error code or string is available here */ - PyErr_SetString(pysqlite_OperationalError, "Error creating function"); + PyErr_SetString(self->OperationalError, "Error creating function"); return NULL; } Py_RETURN_NONE; @@ -921,7 +924,7 @@ pysqlite_connection_create_aggregate_impl(pysqlite_Connection *self, &_destructor); // will decref func if (rc != SQLITE_OK) { /* Workaround for SQLite bug: no error code or string is available here */ - PyErr_SetString(pysqlite_OperationalError, "Error creating aggregate"); + PyErr_SetString(self->OperationalError, "Error creating aggregate"); return NULL; } Py_RETURN_NONE; @@ -1068,7 +1071,8 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self, rc = sqlite3_set_authorizer(self->db, _authorizer_callback, authorizer_cb); } if (rc != SQLITE_OK) { - PyErr_SetString(pysqlite_OperationalError, "Error setting authorizer callback"); + PyErr_SetString(self->OperationalError, + "Error setting authorizer callback"); Py_XSETREF(self->function_pinboard_authorizer_cb, NULL); return NULL; } @@ -1181,7 +1185,8 @@ pysqlite_connection_enable_load_extension_impl(pysqlite_Connection *self, rc = sqlite3_enable_load_extension(self->db, onoff); if (rc != SQLITE_OK) { - PyErr_SetString(pysqlite_OperationalError, "Error enabling load extension"); + PyErr_SetString(self->OperationalError, + "Error enabling load extension"); return NULL; } else { Py_RETURN_NONE; @@ -1215,7 +1220,7 @@ pysqlite_connection_load_extension_impl(pysqlite_Connection *self, rc = sqlite3_load_extension(self->db, extension_name, 0, &errmsg); if (rc != 0) { - PyErr_SetString(pysqlite_OperationalError, errmsg); + PyErr_SetString(self->OperationalError, errmsg); return NULL; } else { Py_RETURN_NONE; @@ -1227,7 +1232,7 @@ int pysqlite_check_thread(pysqlite_Connection* self) { if (self->check_same_thread) { if (PyThread_get_thread_ident() != self->thread_ident) { - PyErr_Format(pysqlite_ProgrammingError, + PyErr_Format(self->ProgrammingError, "SQLite objects created in a thread can only be used in that same thread. " "The object was created in thread id %lu and this is thread id %lu.", self->thread_ident, PyThread_get_thread_ident()); @@ -1579,7 +1584,7 @@ pysqlite_connection_iterdump_impl(pysqlite_Connection *self) pyfn_iterdump = _PyDict_GetItemIdWithError(module_dict, &PyId__iterdump); if (!pyfn_iterdump) { if (!PyErr_Occurred()) { - PyErr_SetString(pysqlite_OperationalError, + PyErr_SetString(self->OperationalError, "Failed to obtain _iterdump() reference"); } goto finally; @@ -1634,7 +1639,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self, /* Since 3.8.8 this is already done, per commit https://www.sqlite.org/src/info/169b5505498c0a7e */ if (!sqlite3_get_autocommit(target->db)) { - PyErr_SetString(pysqlite_OperationalError, "target is in transaction"); + PyErr_SetString(self->OperationalError, "target is in transaction"); return NULL; } #endif @@ -1746,7 +1751,8 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self, { continue; } else { - PyErr_SetString(pysqlite_ProgrammingError, "invalid character in collation name"); + PyErr_SetString(self->ProgrammingError, + "invalid character in collation name"); goto finally; } } diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 451742b..0f821c7 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -351,10 +351,12 @@ _pysqlite_fetch_one_row(pysqlite_Cursor* self) PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column '%s' with text '%s'", colname , text); error_msg = PyUnicode_Decode(buf, strlen(buf), "ascii", "replace"); + + PyObject *exc = self->connection->OperationalError; if (!error_msg) { - PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8"); + PyErr_SetString(exc, "Could not decode to UTF-8"); } else { - PyErr_SetObject(pysqlite_OperationalError, error_msg); + PyErr_SetObject(exc, error_msg); Py_DECREF(error_msg); } } @@ -401,18 +403,23 @@ error: */ static int check_cursor(pysqlite_Cursor* cur) { + pysqlite_state *state = pysqlite_get_state(NULL); + if (!cur->initialized) { - PyErr_SetString(pysqlite_ProgrammingError, "Base Cursor.__init__ not called."); + PyErr_SetString(state->ProgrammingError, + "Base Cursor.__init__ not called."); return 0; } if (cur->closed) { - PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor."); + PyErr_SetString(state->ProgrammingError, + "Cannot operate on a closed cursor."); return 0; } if (cur->locked) { - PyErr_SetString(pysqlite_ProgrammingError, "Recursive use of cursors not allowed."); + PyErr_SetString(state->ProgrammingError, + "Recursive use of cursors not allowed."); return 0; } @@ -588,7 +595,8 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation } if (pysqlite_build_row_cast_map(self) != 0) { - _PyErr_FormatFromCause(pysqlite_OperationalError, "Error while building row_cast_map"); + _PyErr_FormatFromCause(self->connection->OperationalError, + "Error while building row_cast_map"); goto error; } @@ -641,7 +649,9 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (rc == SQLITE_ROW) { if (multiple) { - PyErr_SetString(pysqlite_ProgrammingError, "executemany() can only execute DML statements."); + PyErr_SetString(self->connection->ProgrammingError, + "executemany() can only execute DML " + "statements."); goto error; } @@ -745,7 +755,8 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) int max_length = sqlite3_limit(self->connection->db, SQLITE_LIMIT_LENGTH, -1); if (sql_len >= max_length) { - PyErr_SetString(pysqlite_DataError, "query string is too large"); + PyErr_SetString(self->connection->DataError, + "query string is too large"); return NULL; } } else { @@ -1018,7 +1029,8 @@ pysqlite_cursor_close_impl(pysqlite_Cursor *self) /*[clinic end generated code: output=b6055e4ec6fe63b6 input=08b36552dbb9a986]*/ { if (!self->connection) { - PyErr_SetString(pysqlite_ProgrammingError, + pysqlite_state *state = pysqlite_get_state(NULL); + PyErr_SetString(state->ProgrammingError, "Base Cursor.__init__ not called."); return NULL; } diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index b2d6e7c..e72fc92 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -143,6 +143,7 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) return Py_NewRef(alt); } /* else set the right exception and return NULL */ - PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); + 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 2607c6e..3d81ad8 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -42,13 +42,6 @@ module _sqlite3 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=81e330492d57488e]*/ /* static objects at module-level */ - -PyObject *pysqlite_OperationalError = NULL; -PyObject *pysqlite_ProgrammingError = NULL; -PyObject *pysqlite_IntegrityError = NULL; -PyObject *pysqlite_DataError = NULL; -PyObject *pysqlite_NotSupportedError = NULL; - PyObject* _pysqlite_converters = NULL; int _pysqlite_enable_callback_tracebacks = 0; int pysqlite_BaseTypeAdapted = 0; @@ -137,7 +130,8 @@ pysqlite_enable_shared_cache_impl(PyObject *module, int do_enable) rc = sqlite3_enable_shared_cache(do_enable); if (rc != SQLITE_OK) { - PyErr_SetString(pysqlite_OperationalError, "Changing the shared_cache flag failed"); + pysqlite_state *state = pysqlite_get_state(module); + PyErr_SetString(state->OperationalError, "Changing the shared_cache flag failed"); return NULL; } else { Py_RETURN_NONE; @@ -357,17 +351,13 @@ do { \ } \ } while (0) -#define ADD_EXCEPTION(module, name, exc, base) \ -do { \ - exc = PyErr_NewException(MODULE_NAME "." name, base, NULL); \ - if (!exc) { \ - goto error; \ - } \ - int res = PyModule_AddObjectRef(module, name, exc); \ - Py_DECREF(exc); \ - if (res < 0) { \ - goto error; \ - } \ +#define ADD_EXCEPTION(module, state, exc, base) \ +do { \ + state->exc = PyErr_NewException(MODULE_NAME "." #exc, base, NULL); \ + if (state->exc == NULL) { \ + goto error; \ + } \ + ADD_TYPE(module, (PyTypeObject *)state->exc); \ } while (0) PyMODINIT_FUNC PyInit__sqlite3(void) @@ -404,27 +394,20 @@ PyMODINIT_FUNC PyInit__sqlite3(void) ADD_TYPE(module, state->RowType); /*** Create DB-API Exception hierarchy */ - ADD_EXCEPTION(module, "Error", state->Error, PyExc_Exception); - ADD_EXCEPTION(module, "Warning", state->Warning, PyExc_Exception); + ADD_EXCEPTION(module, state, Error, PyExc_Exception); + ADD_EXCEPTION(module, state, Warning, PyExc_Exception); /* Error subclasses */ - ADD_EXCEPTION(module, "InterfaceError", state->InterfaceError, - state->Error); - ADD_EXCEPTION(module, "DatabaseError", state->DatabaseError, state->Error); + ADD_EXCEPTION(module, state, InterfaceError, state->Error); + ADD_EXCEPTION(module, state, DatabaseError, state->Error); /* DatabaseError subclasses */ - ADD_EXCEPTION(module, "InternalError", state->InternalError, - state->DatabaseError); - ADD_EXCEPTION(module, "OperationalError", pysqlite_OperationalError, - state->DatabaseError); - ADD_EXCEPTION(module, "ProgrammingError", pysqlite_ProgrammingError, - state->DatabaseError); - ADD_EXCEPTION(module, "IntegrityError", pysqlite_IntegrityError, - state->DatabaseError); - ADD_EXCEPTION(module, "DataError", pysqlite_DataError, - state->DatabaseError); - ADD_EXCEPTION(module, "NotSupportedError", pysqlite_NotSupportedError, - state->DatabaseError); + ADD_EXCEPTION(module, state, InternalError, state->DatabaseError); + ADD_EXCEPTION(module, state, OperationalError, state->DatabaseError); + ADD_EXCEPTION(module, state, ProgrammingError, state->DatabaseError); + ADD_EXCEPTION(module, state, IntegrityError, state->DatabaseError); + ADD_EXCEPTION(module, state, DataError, state->DatabaseError); + ADD_EXCEPTION(module, state, NotSupportedError, state->DatabaseError); /* Set integer constants */ if (add_integer_constants(module) < 0) { diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h index a745096..7ce8381 100644 --- a/Modules/_sqlite/module.h +++ b/Modules/_sqlite/module.h @@ -30,12 +30,19 @@ #define MODULE_NAME "sqlite3" typedef struct { + PyObject *DataError; PyObject *DatabaseError; PyObject *Error; + PyObject *IntegrityError; PyObject *InterfaceError; PyObject *InternalError; + PyObject *NotSupportedError; + PyObject *OperationalError; + PyObject *ProgrammingError; PyObject *Warning; + PyObject *lru_cache; + PyTypeObject *ConnectionType; PyTypeObject *CursorType; PyTypeObject *PrepareProtocolType; @@ -51,12 +58,6 @@ pysqlite_get_state(PyObject *Py_UNUSED(module)) return &pysqlite_global_state; } -extern PyObject* pysqlite_OperationalError; -extern PyObject* pysqlite_ProgrammingError; -extern PyObject* pysqlite_IntegrityError; -extern PyObject* pysqlite_DataError; -extern PyObject* pysqlite_NotSupportedError; - /* 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. diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 035023d..cca8616 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -56,8 +56,8 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) Py_ssize_t size; const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size); if (sql_cstr == NULL) { - PyObject *exc = connection->Warning; - PyErr_Format(exc, "SQL is of wrong type ('%s'). Must be string.", + PyErr_Format(connection->Warning, + "SQL is of wrong type ('%s'). Must be string.", Py_TYPE(sql)->tp_name); return NULL; } @@ -65,7 +65,8 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) sqlite3 *db = connection->db; int max_length = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1); if (size >= max_length) { - PyErr_SetString(pysqlite_DataError, "query string is too large"); + PyErr_SetString(connection->DataError, + "query string is too large"); return NULL; } if (strlen(sql_cstr) != (size_t)size) { @@ -87,8 +88,8 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) } if (pysqlite_check_remaining_sql(tail)) { - PyObject *exc = connection->Warning; - PyErr_SetString(exc, "You can only execute one statement at a time."); + PyErr_SetString(connection->Warning, + "You can only execute one statement at a time."); goto error; } @@ -250,7 +251,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para } } if (num_params != num_params_needed) { - PyErr_Format(pysqlite_ProgrammingError, + PyErr_Format(state->ProgrammingError, "Incorrect number of bindings supplied. The current " "statement uses %d, and there are %zd supplied.", num_params_needed, num_params); @@ -303,7 +304,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para binding_name = sqlite3_bind_parameter_name(self->st, i); Py_END_ALLOW_THREADS if (!binding_name) { - PyErr_Format(pysqlite_ProgrammingError, "Binding %d has no name, but you supplied a dictionary (which has only names).", i); + PyErr_Format(state->ProgrammingError, + "Binding %d has no name, but you supplied a " + "dictionary (which has only names).", i); return; } @@ -321,7 +324,9 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para Py_DECREF(binding_name_obj); if (!current_param) { if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) { - PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding parameter :%s.", binding_name); + PyErr_Format(state->ProgrammingError, + "You did not supply a value for binding " + "parameter :%s.", binding_name); } return; } diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index 2684773..6ddf0c7 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -71,20 +71,20 @@ _pysqlite_seterror(sqlite3 *db) case SQLITE_PROTOCOL: case SQLITE_EMPTY: case SQLITE_SCHEMA: - PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(db)); + PyErr_SetString(state->OperationalError, sqlite3_errmsg(db)); break; case SQLITE_CORRUPT: PyErr_SetString(state->DatabaseError, sqlite3_errmsg(db)); break; case SQLITE_TOOBIG: - PyErr_SetString(pysqlite_DataError, sqlite3_errmsg(db)); + PyErr_SetString(state->DataError, sqlite3_errmsg(db)); break; case SQLITE_CONSTRAINT: case SQLITE_MISMATCH: - PyErr_SetString(pysqlite_IntegrityError, sqlite3_errmsg(db)); + PyErr_SetString(state->IntegrityError, sqlite3_errmsg(db)); break; case SQLITE_MISUSE: - PyErr_SetString(pysqlite_ProgrammingError, sqlite3_errmsg(db)); + PyErr_SetString(state->ProgrammingError, sqlite3_errmsg(db)); break; default: PyErr_SetString(state->DatabaseError, sqlite3_errmsg(db)); |