From d542742128b634264d5b6796297613975211b43b Mon Sep 17 00:00:00 2001 From: Erlend Egeberg Aasland Date: Thu, 29 Jul 2021 11:21:45 +0200 Subject: [PATCH] bpo-42064: Optimise `sqlite3` state access, part 1 (GH-27273) Prepare for module state: - Add "get state by defining class" and "get state by module def" stubs - Add AC defining class when needed - Add state pointer to connection context - Pass state as argument to utility functions Automerge-Triggered-By: GH:encukou --- Modules/_sqlite/clinic/cursor.c.h | 21 +++++++++---- Modules/_sqlite/connection.c | 37 ++++++++++++----------- Modules/_sqlite/connection.h | 1 + Modules/_sqlite/cursor.c | 50 +++++++++++++++++-------------- Modules/_sqlite/microprotocols.c | 4 +-- Modules/_sqlite/microprotocols.h | 5 ++-- Modules/_sqlite/module.c | 5 ++-- Modules/_sqlite/module.h | 13 ++++++++ Modules/_sqlite/row.c | 2 +- Modules/_sqlite/statement.c | 22 +++++++------- Modules/_sqlite/statement.h | 4 ++- Modules/_sqlite/util.c | 3 +- Modules/_sqlite/util.h | 2 +- 13 files changed, 103 insertions(+), 66 deletions(-) diff --git a/Modules/_sqlite/clinic/cursor.c.h b/Modules/_sqlite/clinic/cursor.c.h index 8bcdc1a5d73..d2c453b38b4 100644 --- a/Modules/_sqlite/clinic/cursor.c.h +++ b/Modules/_sqlite/clinic/cursor.c.h @@ -249,14 +249,25 @@ PyDoc_STRVAR(pysqlite_cursor_close__doc__, "Closes the cursor."); #define PYSQLITE_CURSOR_CLOSE_METHODDEF \ - {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, pysqlite_cursor_close__doc__}, + {"close", (PyCFunction)(void(*)(void))pysqlite_cursor_close, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, pysqlite_cursor_close__doc__}, static PyObject * -pysqlite_cursor_close_impl(pysqlite_Cursor *self); +pysqlite_cursor_close_impl(pysqlite_Cursor *self, PyTypeObject *cls); static PyObject * -pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored)) +pysqlite_cursor_close(pysqlite_Cursor *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return pysqlite_cursor_close_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = { NULL}; + static _PyArg_Parser _parser = {":close", _keywords, 0}; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser + )) { + goto exit; + } + return_value = pysqlite_cursor_close_impl(self, cls); + +exit: + return return_value; } -/*[clinic end generated code: output=8f70eac5f8aa8d97 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7b216aba2439f5cf input=a9049054013a1b77]*/ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 85b666a4195..a95b75a0fe1 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -66,8 +66,8 @@ new_statement_cache(pysqlite_Connection *self, int maxsize) if (args[0] == NULL) { return NULL; } - pysqlite_state *state = pysqlite_get_state(NULL); - PyObject *inner = PyObject_Vectorcall(state->lru_cache, args, 1, NULL); + PyObject *lru_cache = self->state->lru_cache; + PyObject *inner = PyObject_Vectorcall(lru_cache, args, 1, NULL); Py_DECREF(args[0]); if (inner == NULL) { return NULL; @@ -106,6 +106,9 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, return -1; } + pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(self)); + self->state = state; + const char *database = PyBytes_AsString(database_obj); self->initialized = 1; @@ -131,7 +134,7 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, Py_DECREF(database_obj); // needed bco. the AC FSConverter if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(state, self->db); return -1; } @@ -177,7 +180,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, self->function_pinboard_progress_handler = NULL; self->function_pinboard_authorizer_cb = NULL; - pysqlite_state *state = pysqlite_get_state(NULL); self->Warning = state->Warning; self->Error = state->Error; self->InterfaceError = state->InterfaceError; @@ -330,15 +332,14 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory) return NULL; } - pysqlite_state *state = pysqlite_get_state(NULL); if (factory == NULL) { - factory = (PyObject *)state->CursorType; + factory = (PyObject *)self->state->CursorType; } cursor = PyObject_CallOneArg(factory, (PyObject *)self); if (cursor == NULL) return NULL; - if (!PyObject_TypeCheck(cursor, state->CursorType)) { + if (!PyObject_TypeCheck(cursor, self->state->CursorType)) { PyErr_Format(PyExc_TypeError, "factory must return a cursor, not %.100s", Py_TYPE(cursor)->tp_name); @@ -383,15 +384,15 @@ pysqlite_connection_close_impl(pysqlite_Connection *self) */ int pysqlite_check_connection(pysqlite_Connection* con) { - pysqlite_state *state = pysqlite_get_state(NULL); if (!con->initialized) { + pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(con)); PyErr_SetString(state->ProgrammingError, "Base Connection.__init__ not called."); return 0; } if (!con->db) { - PyErr_SetString(state->ProgrammingError, + PyErr_SetString(con->state->ProgrammingError, "Cannot operate on a closed database."); return 0; } else { @@ -422,20 +423,20 @@ pysqlite_connection_commit_impl(pysqlite_Connection *self) rc = sqlite3_prepare_v2(self->db, "COMMIT", 7, &statement, NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); goto error; } rc = pysqlite_step(statement); if (rc != SQLITE_DONE) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); } } @@ -472,20 +473,20 @@ pysqlite_connection_rollback_impl(pysqlite_Connection *self) rc = sqlite3_prepare_v2(self->db, "ROLLBACK", 9, &statement, NULL); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); goto error; } rc = pysqlite_step(statement); if (rc != SQLITE_DONE) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); } Py_BEGIN_ALLOW_THREADS rc = sqlite3_finalize(statement); Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); } } @@ -1672,7 +1673,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self, Py_END_ALLOW_THREADS if (bck_handle == NULL) { - _pysqlite_seterror(bck_conn); + _pysqlite_seterror(self->state, bck_conn); return NULL; } @@ -1710,7 +1711,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self, Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(bck_conn); + _pysqlite_seterror(self->state, bck_conn); return NULL; } @@ -1762,7 +1763,7 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self, if (callable != Py_None) { Py_DECREF(callable); } - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); return NULL; } diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h index 50c2015be3e..edf56502042 100644 --- a/Modules/_sqlite/connection.h +++ b/Modules/_sqlite/connection.h @@ -36,6 +36,7 @@ typedef struct { PyObject_HEAD sqlite3* db; + pysqlite_state *state; /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a * bitwise combination thereof makes sense */ diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 24b4a37521d..2f4494690f9 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -130,7 +130,8 @@ cursor_dealloc(pysqlite_Cursor *self) } static PyObject * -_pysqlite_get_converter(const char *keystr, Py_ssize_t keylen) +_pysqlite_get_converter(pysqlite_state *state, const char *keystr, + Py_ssize_t keylen) { PyObject *key; PyObject *upcase_key; @@ -147,7 +148,6 @@ _pysqlite_get_converter(const char *keystr, Py_ssize_t keylen) return NULL; } - pysqlite_state *state = pysqlite_get_state(NULL); retval = PyDict_GetItemWithError(state->converters, upcase_key); Py_DECREF(upcase_key); @@ -187,7 +187,9 @@ pysqlite_build_row_cast_map(pysqlite_Cursor* self) type_start = pos + 1; } else if (*pos == ']' && type_start != NULL) { - converter = _pysqlite_get_converter(type_start, pos - type_start); + pysqlite_state *state = self->connection->state; + converter = _pysqlite_get_converter(state, type_start, + pos - type_start); if (!converter && PyErr_Occurred()) { Py_CLEAR(self->row_cast_map); return -1; @@ -206,7 +208,9 @@ pysqlite_build_row_cast_map(pysqlite_Cursor* self) * 'NUMBER(10)' to be treated as 'NUMBER', for example. * In other words, it will work as people expect it to work.*/ if (*pos == ' ' || *pos == '(' || *pos == 0) { - converter = _pysqlite_get_converter(decltype, pos - decltype); + pysqlite_state *state = self->connection->state; + converter = _pysqlite_get_converter(state, decltype, + pos - decltype); if (!converter && PyErr_Occurred()) { Py_CLEAR(self->row_cast_map); return -1; @@ -404,22 +408,21 @@ error: */ static int check_cursor(pysqlite_Cursor* cur) { - pysqlite_state *state = pysqlite_get_state(NULL); - if (!cur->initialized) { + pysqlite_state *state = pysqlite_get_state_by_type(Py_TYPE(cur)); PyErr_SetString(state->ProgrammingError, "Base Cursor.__init__ not called."); return 0; } if (cur->closed) { - PyErr_SetString(state->ProgrammingError, + PyErr_SetString(cur->connection->state->ProgrammingError, "Cannot operate on a closed cursor."); return 0; } if (cur->locked) { - PyErr_SetString(state->ProgrammingError, + PyErr_SetString(cur->connection->state->ProgrammingError, "Recursive use of cursors not allowed."); return 0; } @@ -439,7 +442,7 @@ begin_transaction(pysqlite_Connection *self) Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); goto error; } @@ -449,7 +452,7 @@ begin_transaction(pysqlite_Connection *self) Py_END_ALLOW_THREADS if (rc != SQLITE_OK && !PyErr_Occurred()) { - _pysqlite_seterror(self->db); + _pysqlite_seterror(self->state, self->db); } error: @@ -470,7 +473,6 @@ 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; @@ -568,6 +570,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation } } + pysqlite_state *state = self->connection->state; while (1) { parameters = PyIter_Next(parameters_iter); if (!parameters) { @@ -576,7 +579,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation pysqlite_statement_mark_dirty(self->statement); - pysqlite_statement_bind_parameters(self->statement, parameters); + pysqlite_statement_bind_parameters(state, self->statement, parameters); if (PyErr_Occurred()) { goto error; } @@ -592,12 +595,12 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation } } (void)pysqlite_statement_reset(self->statement); - _pysqlite_seterror(self->connection->db); + _pysqlite_seterror(state, self->connection->db); goto error; } if (pysqlite_build_row_cast_map(self) != 0) { - _PyErr_FormatFromCause(self->connection->OperationalError, + _PyErr_FormatFromCause(state->OperationalError, "Error while building row_cast_map"); goto error; } @@ -651,7 +654,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (rc == SQLITE_ROW) { if (multiple) { - PyErr_SetString(self->connection->ProgrammingError, + PyErr_SetString(state->ProgrammingError, "executemany() can only execute DML " "statements."); goto error; @@ -773,6 +776,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) } Py_DECREF(result); + pysqlite_state *state = self->connection->state; while (1) { const char *tail; @@ -784,7 +788,7 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) &tail); Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(self->connection->db); + _pysqlite_seterror(state, self->connection->db); goto error; } @@ -799,13 +803,13 @@ pysqlite_cursor_executescript(pysqlite_Cursor *self, PyObject *script_obj) if (rc != SQLITE_DONE) { (void)sqlite3_finalize(statement); - _pysqlite_seterror(self->connection->db); + _pysqlite_seterror(state, self->connection->db); goto error; } rc = sqlite3_finalize(statement); if (rc != SQLITE_OK) { - _pysqlite_seterror(self->connection->db); + _pysqlite_seterror(state, self->connection->db); goto error; } @@ -874,7 +878,7 @@ pysqlite_cursor_iternext(pysqlite_Cursor *self) if (rc != SQLITE_DONE && rc != SQLITE_ROW) { (void)pysqlite_statement_reset(self->statement); Py_DECREF(next_row); - _pysqlite_seterror(self->connection->db); + _pysqlite_seterror(self->connection->state, self->connection->db); return NULL; } @@ -1023,15 +1027,17 @@ pysqlite_cursor_setoutputsize_impl(pysqlite_Cursor *self, PyObject *size, /*[clinic input] _sqlite3.Cursor.close as pysqlite_cursor_close + cls: defining_class + Closes the cursor. [clinic start generated code]*/ static PyObject * -pysqlite_cursor_close_impl(pysqlite_Cursor *self) -/*[clinic end generated code: output=b6055e4ec6fe63b6 input=08b36552dbb9a986]*/ +pysqlite_cursor_close_impl(pysqlite_Cursor *self, PyTypeObject *cls) +/*[clinic end generated code: output=a08ab3d772f45438 input=28ba9b532ab46ba0]*/ { if (!self->connection) { - pysqlite_state *state = pysqlite_get_state(NULL); + pysqlite_state *state = pysqlite_get_state_by_cls(cls); PyErr_SetString(state->ProgrammingError, "Base Cursor.__init__ not called."); return NULL; diff --git a/Modules/_sqlite/microprotocols.c b/Modules/_sqlite/microprotocols.c index 160d7b923d7..68e4f7fb166 100644 --- a/Modules/_sqlite/microprotocols.c +++ b/Modules/_sqlite/microprotocols.c @@ -71,7 +71,8 @@ pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) /* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */ PyObject * -pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) +pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj, + PyObject *proto, PyObject *alt) { _Py_IDENTIFIER(__adapt__); _Py_IDENTIFIER(__conform__); @@ -86,7 +87,6 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) if (!key) { return NULL; } - pysqlite_state *state = pysqlite_get_state(NULL); adapter = PyDict_GetItemWithError(state->psyco_adapters, key); Py_DECREF(key); if (adapter) { diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h index e9adef916e7..e4d9038e89d 100644 --- a/Modules/_sqlite/microprotocols.h +++ b/Modules/_sqlite/microprotocols.h @@ -41,7 +41,8 @@ extern int pysqlite_microprotocols_init(PyObject *module); extern int pysqlite_microprotocols_add( PyTypeObject *type, PyObject *proto, PyObject *cast); -extern PyObject *pysqlite_microprotocols_adapt( - PyObject *obj, PyObject *proto, PyObject *alt); +extern PyObject *pysqlite_microprotocols_adapt(pysqlite_state *state, + PyObject *obj, PyObject *proto, + PyObject *alt); #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index 98b2c90108f..993e572c5cd 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -158,7 +158,7 @@ pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type, state->BaseTypeAdapted = 1; } - pysqlite_state *state = pysqlite_get_state(NULL); + pysqlite_state *state = pysqlite_get_state(module); PyObject *protocol = (PyObject *)state->PrepareProtocolType; rc = pysqlite_microprotocols_add(type, protocol, caster); if (rc == -1) { @@ -239,7 +239,8 @@ pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, PyObject *alt) /*[clinic end generated code: output=0c3927c5fcd23dd9 input=c8995aeb25d0e542]*/ { - return pysqlite_microprotocols_adapt(obj, proto, alt); + pysqlite_state *state = pysqlite_get_state(module); + return pysqlite_microprotocols_adapt(state, obj, proto, alt); } static int converters_init(PyObject* module) diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h index 13444907008..a286739579d 100644 --- a/Modules/_sqlite/module.h +++ b/Modules/_sqlite/module.h @@ -65,6 +65,19 @@ extern pysqlite_state pysqlite_global_state; static inline pysqlite_state * pysqlite_get_state(PyObject *Py_UNUSED(module)) { + return &pysqlite_global_state; // Replace with PyModule_GetState +} + +static inline pysqlite_state * +pysqlite_get_state_by_cls(PyTypeObject *Py_UNUSED(cls)) +{ + return &pysqlite_global_state; // Replace with PyType_GetModuleState +} + +static inline pysqlite_state * +pysqlite_get_state_by_type(PyTypeObject *Py_UNUSED(tp)) +{ + // Replace with _PyType_GetModuleByDef & PyModule_GetState return &pysqlite_global_state; } diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index d2f9bdd00b6..b146c9dc5e3 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -219,7 +219,7 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, if (opid != Py_EQ && opid != Py_NE) Py_RETURN_NOTIMPLEMENTED; - pysqlite_state *state = pysqlite_get_state(NULL); + pysqlite_state *state = pysqlite_get_state_by_cls(Py_TYPE(self)); if (PyObject_TypeCheck(_other, state->RowType)) { pysqlite_Row *other = (pysqlite_Row *)_other; int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ); diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 8add50960f8..983df2d50c9 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -51,7 +51,7 @@ typedef enum { pysqlite_Statement * pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) { - pysqlite_state *state = pysqlite_get_state(NULL); + pysqlite_state *state = connection->state; assert(PyUnicode_Check(sql)); Py_ssize_t size; const char *sql_cstr = PyUnicode_AsUTF8AndSize(sql, &size); @@ -83,7 +83,7 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql) Py_END_ALLOW_THREADS if (rc != SQLITE_OK) { - _pysqlite_seterror(db); + _pysqlite_seterror(state, db); return NULL; } @@ -209,9 +209,9 @@ final: } /* 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) +static int +_need_adapt(pysqlite_state *state, PyObject *obj) { - pysqlite_state *state = pysqlite_get_state(NULL); if (state->BaseTypeAdapted) { return 1; } @@ -224,9 +224,11 @@ static int _need_adapt(PyObject* obj) } } -void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters) +void +pysqlite_statement_bind_parameters(pysqlite_state *state, + pysqlite_Statement *self, + PyObject *parameters) { - pysqlite_state *state = pysqlite_get_state(NULL); PyObject* current_param; PyObject* adapted; const char* binding_name; @@ -272,11 +274,11 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para return; } - if (!_need_adapt(current_param)) { + if (!_need_adapt(state, current_param)) { adapted = current_param; } else { PyObject *protocol = (PyObject *)state->PrepareProtocolType; - adapted = pysqlite_microprotocols_adapt(current_param, + adapted = pysqlite_microprotocols_adapt(state, current_param, protocol, current_param); Py_DECREF(current_param); @@ -332,11 +334,11 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para return; } - if (!_need_adapt(current_param)) { + if (!_need_adapt(state, current_param)) { adapted = current_param; } else { PyObject *protocol = (PyObject *)state->PrepareProtocolType; - adapted = pysqlite_microprotocols_adapt(current_param, + adapted = pysqlite_microprotocols_adapt(state, current_param, protocol, current_param); Py_DECREF(current_param); diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h index 70801cc5ce9..dc692d7df99 100644 --- a/Modules/_sqlite/statement.h +++ b/Modules/_sqlite/statement.h @@ -41,7 +41,9 @@ typedef struct pysqlite_Statement *pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql); int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter); -void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters); +void pysqlite_statement_bind_parameters(pysqlite_state *state, + pysqlite_Statement *self, + PyObject *parameters); int pysqlite_statement_finalize(pysqlite_Statement* self); int pysqlite_statement_reset(pysqlite_Statement* self); diff --git a/Modules/_sqlite/util.c b/Modules/_sqlite/util.c index 6ddf0c732b4..24cefc626b6 100644 --- a/Modules/_sqlite/util.c +++ b/Modules/_sqlite/util.c @@ -41,9 +41,8 @@ pysqlite_step(sqlite3_stmt *statement) * Returns the error code (0 means no error occurred). */ int -_pysqlite_seterror(sqlite3 *db) +_pysqlite_seterror(pysqlite_state *state, sqlite3 *db) { - pysqlite_state *state = pysqlite_get_state(NULL); int errorcode = sqlite3_errcode(db); switch (errorcode) diff --git a/Modules/_sqlite/util.h b/Modules/_sqlite/util.h index f308f03f71f..5eee3fac6f1 100644 --- a/Modules/_sqlite/util.h +++ b/Modules/_sqlite/util.h @@ -35,7 +35,7 @@ int pysqlite_step(sqlite3_stmt *statement); * Checks the SQLite error code and sets the appropriate DB-API exception. * Returns the error code (0 means no error occurred). */ -int _pysqlite_seterror(sqlite3 *db); +int _pysqlite_seterror(pysqlite_state *state, sqlite3 *db); sqlite_int64 _pysqlite_long_as_int64(PyObject * value);