bpo-42064: Move sqlite3 types to global state (GH-26537)

* Move connection type to global state
* Move cursor type to global state
* Move prepare protocol type to global state
* Move row type to global state
* Move statement type to global state
* ADD_TYPE takes a pointer
* pysqlite_get_state is now static inline
This commit is contained in:
Erlend Egeberg Aasland 2021-06-15 14:47:34 +02:00 committed by GitHub
parent 8ebd9447e9
commit 10a5c806d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 103 additions and 70 deletions

View file

@ -552,8 +552,8 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *const *args, Py_
if (!args) { if (!args) {
goto exit; goto exit;
} }
if (!PyObject_TypeCheck(args[0], pysqlite_ConnectionType)) { if (!PyObject_TypeCheck(args[0], clinic_state()->ConnectionType)) {
_PyArg_BadArgument("backup", "argument 'target'", (pysqlite_ConnectionType)->tp_name, args[0]); _PyArg_BadArgument("backup", "argument 'target'", (clinic_state()->ConnectionType)->tp_name, args[0]);
goto exit; goto exit;
} }
target = (pysqlite_Connection *)args[0]; target = (pysqlite_Connection *)args[0];
@ -710,4 +710,4 @@ exit:
#ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #ifndef PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
#define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF #define PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF
#endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */ #endif /* !defined(PYSQLITE_CONNECTION_LOAD_EXTENSION_METHODDEF) */
/*[clinic end generated code: output=c1bf09db3bcd0105 input=a9049054013a1b77]*/ /*[clinic end generated code: output=1ee2f6173f4acec3 input=a9049054013a1b77]*/

View file

@ -12,15 +12,15 @@ pysqlite_cursor_init(PyObject *self, PyObject *args, PyObject *kwargs)
int return_value = -1; int return_value = -1;
pysqlite_Connection *connection; pysqlite_Connection *connection;
if (Py_IS_TYPE(self, pysqlite_CursorType) && if (Py_IS_TYPE(self, clinic_state()->CursorType) &&
!_PyArg_NoKeywords("Cursor", kwargs)) { !_PyArg_NoKeywords("Cursor", kwargs)) {
goto exit; goto exit;
} }
if (!_PyArg_CheckPositional("Cursor", PyTuple_GET_SIZE(args), 1, 1)) { if (!_PyArg_CheckPositional("Cursor", PyTuple_GET_SIZE(args), 1, 1)) {
goto exit; goto exit;
} }
if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), pysqlite_ConnectionType)) { if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), clinic_state()->ConnectionType)) {
_PyArg_BadArgument("Cursor", "argument 1", (pysqlite_ConnectionType)->tp_name, PyTuple_GET_ITEM(args, 0)); _PyArg_BadArgument("Cursor", "argument 1", (clinic_state()->ConnectionType)->tp_name, PyTuple_GET_ITEM(args, 0));
goto exit; goto exit;
} }
connection = (pysqlite_Connection *)PyTuple_GET_ITEM(args, 0); connection = (pysqlite_Connection *)PyTuple_GET_ITEM(args, 0);
@ -259,4 +259,4 @@ pysqlite_cursor_close(pysqlite_Cursor *self, PyObject *Py_UNUSED(ignored))
{ {
return pysqlite_cursor_close_impl(self); return pysqlite_cursor_close_impl(self);
} }
/*[clinic end generated code: output=6a2d4d49784aa686 input=a9049054013a1b77]*/ /*[clinic end generated code: output=e3a502bb26aaefa5 input=a9049054013a1b77]*/

View file

@ -198,7 +198,7 @@ pysqlite_adapt(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyObject *obj; PyObject *obj;
PyObject *proto = (PyObject*)pysqlite_PrepareProtocolType; PyObject *proto = (PyObject *)clinic_state()->PrepareProtocolType;
PyObject *alt = NULL; PyObject *alt = NULL;
if (!_PyArg_CheckPositional("adapt", nargs, 1, 3)) { if (!_PyArg_CheckPositional("adapt", nargs, 1, 3)) {
@ -219,4 +219,4 @@ skip_optional:
exit: exit:
return return_value; return return_value;
} }
/*[clinic end generated code: output=d87990f941c209fa input=a9049054013a1b77]*/ /*[clinic end generated code: output=e9c2442673289cab input=a9049054013a1b77]*/

View file

@ -13,15 +13,15 @@ pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
pysqlite_Cursor *cursor; pysqlite_Cursor *cursor;
PyObject *data; PyObject *data;
if ((type == pysqlite_RowType) && if ((type == clinic_state()->RowType) &&
!_PyArg_NoKeywords("Row", kwargs)) { !_PyArg_NoKeywords("Row", kwargs)) {
goto exit; goto exit;
} }
if (!_PyArg_CheckPositional("Row", PyTuple_GET_SIZE(args), 2, 2)) { if (!_PyArg_CheckPositional("Row", PyTuple_GET_SIZE(args), 2, 2)) {
goto exit; goto exit;
} }
if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), pysqlite_CursorType)) { if (!PyObject_TypeCheck(PyTuple_GET_ITEM(args, 0), clinic_state()->CursorType)) {
_PyArg_BadArgument("Row", "argument 1", (pysqlite_CursorType)->tp_name, PyTuple_GET_ITEM(args, 0)); _PyArg_BadArgument("Row", "argument 1", (clinic_state()->CursorType)->tp_name, PyTuple_GET_ITEM(args, 0));
goto exit; goto exit;
} }
cursor = (pysqlite_Cursor *)PyTuple_GET_ITEM(args, 0); cursor = (pysqlite_Cursor *)PyTuple_GET_ITEM(args, 0);
@ -53,4 +53,4 @@ pysqlite_row_keys(pysqlite_Row *self, PyObject *Py_UNUSED(ignored))
{ {
return pysqlite_row_keys_impl(self); return pysqlite_row_keys_impl(self);
} }
/*[clinic end generated code: output=8d29220b9cde035d input=a9049054013a1b77]*/ /*[clinic end generated code: output=0382771b4fc85f36 input=a9049054013a1b77]*/

View file

@ -36,12 +36,15 @@
#define HAVE_TRACE_V2 #define HAVE_TRACE_V2
#endif #endif
#define clinic_state() (pysqlite_get_state(NULL))
#include "clinic/connection.c.h" #include "clinic/connection.c.h"
#undef clinic_state
/*[clinic input] /*[clinic input]
module _sqlite3 module _sqlite3
class _sqlite3.Connection "pysqlite_Connection *" "pysqlite_ConnectionType" class _sqlite3.Connection "pysqlite_Connection *" "clinic_state()->ConnectionType"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=aa796073bd8f69db]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=67369db2faf80891]*/
_Py_IDENTIFIER(cursor); _Py_IDENTIFIER(cursor);
@ -339,14 +342,15 @@ pysqlite_connection_cursor_impl(pysqlite_Connection *self, PyObject *factory)
return NULL; return NULL;
} }
pysqlite_state *state = pysqlite_get_state(NULL);
if (factory == NULL) { if (factory == NULL) {
factory = (PyObject*)pysqlite_CursorType; factory = (PyObject *)state->CursorType;
} }
cursor = PyObject_CallOneArg(factory, (PyObject *)self); cursor = PyObject_CallOneArg(factory, (PyObject *)self);
if (cursor == NULL) if (cursor == NULL)
return NULL; return NULL;
if (!PyObject_TypeCheck(cursor, pysqlite_CursorType)) { if (!PyObject_TypeCheck(cursor, state->CursorType)) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"factory must return a cursor, not %.100s", "factory must return a cursor, not %.100s",
Py_TYPE(cursor)->tp_name); Py_TYPE(cursor)->tp_name);
@ -1592,7 +1596,7 @@ finally:
/*[clinic input] /*[clinic input]
_sqlite3.Connection.backup as pysqlite_connection_backup _sqlite3.Connection.backup as pysqlite_connection_backup
target: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType') target: object(type='pysqlite_Connection *', subclass_of='clinic_state()->ConnectionType')
* *
pages: int = -1 pages: int = -1
progress: object = None progress: object = None
@ -1607,7 +1611,7 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self,
pysqlite_Connection *target, int pages, pysqlite_Connection *target, int pages,
PyObject *progress, const char *name, PyObject *progress, const char *name,
double sleep) double sleep)
/*[clinic end generated code: output=306a3e6a38c36334 input=30ae45fc420bfd3b]*/ /*[clinic end generated code: output=306a3e6a38c36334 input=c759627ab1ad46ff]*/
{ {
int rc; int rc;
int sleep_ms = (int)(sleep * 1000.0); int sleep_ms = (int)(sleep * 1000.0);
@ -1914,14 +1918,14 @@ static PyType_Spec connection_spec = {
.slots = connection_slots, .slots = connection_slots,
}; };
PyTypeObject *pysqlite_ConnectionType = NULL;
int int
pysqlite_connection_setup_types(PyObject *module) pysqlite_connection_setup_types(PyObject *module)
{ {
pysqlite_ConnectionType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &connection_spec, NULL); PyObject *type = PyType_FromModuleAndSpec(module, &connection_spec, NULL);
if (pysqlite_ConnectionType == NULL) { if (type == NULL) {
return -1; return -1;
} }
pysqlite_state *state = pysqlite_get_state(module);
state->ConnectionType = (PyTypeObject *)type;
return 0; return 0;
} }

View file

@ -24,20 +24,23 @@
#include "cursor.h" #include "cursor.h"
#include "module.h" #include "module.h"
#include "util.h" #include "util.h"
#define clinic_state() (pysqlite_get_state(NULL))
#include "clinic/cursor.c.h" #include "clinic/cursor.c.h"
#undef clinic_state
/*[clinic input] /*[clinic input]
module _sqlite3 module _sqlite3
class _sqlite3.Cursor "pysqlite_Cursor *" "pysqlite_CursorType" class _sqlite3.Cursor "pysqlite_Cursor *" "clinic_state()->CursorType"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b2072d8db95411d5]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c5b8115c5cf30f1]*/
static const char errmsg_fetch_across_rollback[] = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; static const char errmsg_fetch_across_rollback[] = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from.";
/*[clinic input] /*[clinic input]
_sqlite3.Cursor.__init__ as pysqlite_cursor_init _sqlite3.Cursor.__init__ as pysqlite_cursor_init
connection: object(type='pysqlite_Connection *', subclass_of='pysqlite_ConnectionType') connection: object(type='pysqlite_Connection *', subclass_of='clinic_state()->ConnectionType')
/ /
[clinic start generated code]*/ [clinic start generated code]*/
@ -45,7 +48,7 @@ _sqlite3.Cursor.__init__ as pysqlite_cursor_init
static int static int
pysqlite_cursor_init_impl(pysqlite_Cursor *self, pysqlite_cursor_init_impl(pysqlite_Cursor *self,
pysqlite_Connection *connection) pysqlite_Connection *connection)
/*[clinic end generated code: output=ac59dce49a809ca8 input=a8a4f75ac90999b2]*/ /*[clinic end generated code: output=ac59dce49a809ca8 input=23d4265b534989fb]*/
{ {
Py_INCREF(connection); Py_INCREF(connection);
Py_XSETREF(self->connection, connection); Py_XSETREF(self->connection, connection);
@ -1079,14 +1082,14 @@ static PyType_Spec cursor_spec = {
.slots = cursor_slots, .slots = cursor_slots,
}; };
PyTypeObject *pysqlite_CursorType = NULL;
int int
pysqlite_cursor_setup_types(PyObject *module) pysqlite_cursor_setup_types(PyObject *module)
{ {
pysqlite_CursorType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &cursor_spec, NULL); PyObject *type = PyType_FromModuleAndSpec(module, &cursor_spec, NULL);
if (pysqlite_CursorType == NULL) { if (type == NULL) {
return -1; return -1;
} }
pysqlite_state *state = pysqlite_get_state(module);
state->CursorType = (PyTypeObject *)type;
return 0; return 0;
} }

View file

@ -58,8 +58,8 @@ pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
PyObject* key; PyObject* key;
int rc; int rc;
if (proto == NULL) proto = (PyObject*)pysqlite_PrepareProtocolType; assert(type != NULL);
assert(proto != NULL);
key = Py_BuildValue("(OO)", (PyObject*)type, proto); key = Py_BuildValue("(OO)", (PyObject*)type, proto);
if (!key) { if (!key) {
return -1; return -1;
@ -81,7 +81,7 @@ pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
PyObject *adapter, *key, *adapted; PyObject *adapter, *key, *adapted;
/* we don't check for exact type conformance as specified in PEP 246 /* we don't check for exact type conformance as specified in PEP 246
because the pysqlite_PrepareProtocolType type is abstract and there is no because the PrepareProtocolType type is abstract and there is no
way to get a quotable object to be its instance */ way to get a quotable object to be its instance */
/* look for an adapter in the registry */ /* look for an adapter in the registry */

View file

@ -32,7 +32,10 @@
#error "SQLite 3.7.15 or higher required" #error "SQLite 3.7.15 or higher required"
#endif #endif
#define clinic_state() (pysqlite_get_state(NULL))
#include "clinic/module.c.h" #include "clinic/module.c.h"
#undef clinic_state
/*[clinic input] /*[clinic input]
module _sqlite3 module _sqlite3
[clinic start generated code]*/ [clinic start generated code]*/
@ -57,12 +60,6 @@ int pysqlite_BaseTypeAdapted = 0;
pysqlite_state pysqlite_global_state; pysqlite_state pysqlite_global_state;
pysqlite_state *
pysqlite_get_state(PyObject *Py_UNUSED(module))
{
return &pysqlite_global_state;
}
static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
kwargs) kwargs)
{ {
@ -93,7 +90,8 @@ static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
} }
if (factory == NULL) { if (factory == NULL) {
factory = (PyObject*)pysqlite_ConnectionType; pysqlite_state *state = pysqlite_get_state(self);
factory = (PyObject *)state->ConnectionType;
} }
return PyObject_Call(factory, args, kwargs); return PyObject_Call(factory, args, kwargs);
@ -176,9 +174,12 @@ pysqlite_register_adapter_impl(PyObject *module, PyTypeObject *type,
pysqlite_BaseTypeAdapted = 1; pysqlite_BaseTypeAdapted = 1;
} }
rc = pysqlite_microprotocols_add(type, (PyObject*)pysqlite_PrepareProtocolType, caster); pysqlite_state *state = pysqlite_get_state(NULL);
if (rc == -1) PyObject *protocol = (PyObject *)state->PrepareProtocolType;
rc = pysqlite_microprotocols_add(type, protocol, caster);
if (rc == -1) {
return NULL; return NULL;
}
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -240,7 +241,7 @@ pysqlite_enable_callback_trace_impl(PyObject *module, int enable)
_sqlite3.adapt as pysqlite_adapt _sqlite3.adapt as pysqlite_adapt
obj: object obj: object
proto: object(c_default='(PyObject*)pysqlite_PrepareProtocolType') = PrepareProtocolType proto: object(c_default='(PyObject *)clinic_state()->PrepareProtocolType') = PrepareProtocolType
alt: object = NULL alt: object = NULL
/ /
@ -250,7 +251,7 @@ Adapt given object to given protocol. Non-standard.
static PyObject * static PyObject *
pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto, pysqlite_adapt_impl(PyObject *module, PyObject *obj, PyObject *proto,
PyObject *alt) PyObject *alt)
/*[clinic end generated code: output=0c3927c5fcd23dd9 input=a58ab77fb5ae22dd]*/ /*[clinic end generated code: output=0c3927c5fcd23dd9 input=c8995aeb25d0e542]*/
{ {
return pysqlite_microprotocols_adapt(obj, proto, alt); return pysqlite_microprotocols_adapt(obj, proto, alt);
} }
@ -358,7 +359,7 @@ static struct PyModuleDef _sqlite3module = {
#define ADD_TYPE(module, type) \ #define ADD_TYPE(module, type) \
do { \ do { \
if (PyModule_AddType(module, &type) < 0) { \ if (PyModule_AddType(module, type) < 0) { \
goto error; \ goto error; \
} \ } \
} while (0) } while (0)
@ -392,6 +393,7 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
} }
module = PyModule_Create(&_sqlite3module); module = PyModule_Create(&_sqlite3module);
pysqlite_state *state = pysqlite_get_state(module);
if (!module || if (!module ||
(pysqlite_row_setup_types(module) < 0) || (pysqlite_row_setup_types(module) < 0) ||
@ -403,10 +405,10 @@ PyMODINIT_FUNC PyInit__sqlite3(void)
goto error; goto error;
} }
ADD_TYPE(module, *pysqlite_ConnectionType); ADD_TYPE(module, state->ConnectionType);
ADD_TYPE(module, *pysqlite_CursorType); ADD_TYPE(module, state->CursorType);
ADD_TYPE(module, *pysqlite_PrepareProtocolType); ADD_TYPE(module, state->PrepareProtocolType);
ADD_TYPE(module, *pysqlite_RowType); ADD_TYPE(module, state->RowType);
/*** Create DB-API Exception hierarchy */ /*** Create DB-API Exception hierarchy */
ADD_EXCEPTION(module, "Error", pysqlite_Error, PyExc_Exception); ADD_EXCEPTION(module, "Error", pysqlite_Error, PyExc_Exception);

View file

@ -31,9 +31,20 @@
typedef struct { typedef struct {
PyObject *lru_cache; PyObject *lru_cache;
PyTypeObject *ConnectionType;
PyTypeObject *CursorType;
PyTypeObject *PrepareProtocolType;
PyTypeObject *RowType;
PyTypeObject *StatementType;
} pysqlite_state; } pysqlite_state;
extern pysqlite_state *pysqlite_get_state(PyObject *module); extern pysqlite_state pysqlite_global_state;
static inline pysqlite_state *
pysqlite_get_state(PyObject *Py_UNUSED(module))
{
return &pysqlite_global_state;
}
extern PyObject* pysqlite_Error; extern PyObject* pysqlite_Error;
extern PyObject* pysqlite_Warning; extern PyObject* pysqlite_Warning;

View file

@ -60,14 +60,14 @@ static PyType_Spec type_spec = {
.slots = type_slots, .slots = type_slots,
}; };
PyTypeObject *pysqlite_PrepareProtocolType = NULL;
int int
pysqlite_prepare_protocol_setup_types(PyObject *module) pysqlite_prepare_protocol_setup_types(PyObject *module)
{ {
pysqlite_PrepareProtocolType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &type_spec, NULL); PyObject *type = PyType_FromModuleAndSpec(module, &type_spec, NULL);
if (pysqlite_PrepareProtocolType == NULL) { if (type == NULL) {
return -1; return -1;
} }
pysqlite_state *state = pysqlite_get_state(module);
state->PrepareProtocolType = (PyTypeObject *)type;
return 0; return 0;
} }

View file

@ -23,13 +23,16 @@
#include "row.h" #include "row.h"
#include "cursor.h" #include "cursor.h"
#define clinic_state() (pysqlite_get_state(NULL))
#include "clinic/row.c.h" #include "clinic/row.c.h"
#undef clinic_state
/*[clinic input] /*[clinic input]
module _sqlite3 module _sqlite3
class _sqlite3.Row "pysqlite_Row *" "pysqlite_RowType" class _sqlite3.Row "pysqlite_Row *" "clinic_state()->RowType"
[clinic start generated code]*/ [clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=384227da65f250fd]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=966c53403d7f3a40]*/
static int static int
row_clear(pysqlite_Row *self) row_clear(pysqlite_Row *self)
@ -62,7 +65,7 @@ pysqlite_row_dealloc(PyObject *self)
@classmethod @classmethod
_sqlite3.Row.__new__ as pysqlite_row_new _sqlite3.Row.__new__ as pysqlite_row_new
cursor: object(type='pysqlite_Cursor *', subclass_of='pysqlite_CursorType') cursor: object(type='pysqlite_Cursor *', subclass_of='clinic_state()->CursorType')
data: object(subclass_of='&PyTuple_Type') data: object(subclass_of='&PyTuple_Type')
/ /
@ -71,7 +74,7 @@ _sqlite3.Row.__new__ as pysqlite_row_new
static PyObject * static PyObject *
pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor, pysqlite_row_new_impl(PyTypeObject *type, pysqlite_Cursor *cursor,
PyObject *data) PyObject *data)
/*[clinic end generated code: output=10d58b09a819a4c1 input=f6cd7e6e0935828d]*/ /*[clinic end generated code: output=10d58b09a819a4c1 input=b9e954ca31345dbf]*/
{ {
pysqlite_Row *self; pysqlite_Row *self;
@ -216,7 +219,8 @@ static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other,
if (opid != Py_EQ && opid != Py_NE) if (opid != Py_EQ && opid != Py_NE)
Py_RETURN_NOTIMPLEMENTED; Py_RETURN_NOTIMPLEMENTED;
if (PyObject_TypeCheck(_other, pysqlite_RowType)) { pysqlite_state *state = pysqlite_get_state(NULL);
if (PyObject_TypeCheck(_other, state->RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other; pysqlite_Row *other = (pysqlite_Row *)_other;
int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ); int eq = PyObject_RichCompareBool(self->description, other->description, Py_EQ);
if (eq < 0) { if (eq < 0) {
@ -258,14 +262,14 @@ static PyType_Spec row_spec = {
.slots = row_slots, .slots = row_slots,
}; };
PyTypeObject *pysqlite_RowType = NULL;
int int
pysqlite_row_setup_types(PyObject *module) pysqlite_row_setup_types(PyObject *module)
{ {
pysqlite_RowType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &row_spec, NULL); PyObject *type = PyType_FromModuleAndSpec(module, &row_spec, NULL);
if (pysqlite_RowType == NULL) { if (type == NULL) {
return -1; return -1;
} }
pysqlite_state *state = pysqlite_get_state(module);
state->RowType = (PyTypeObject *)type;
return 0; return 0;
} }

View file

@ -110,8 +110,9 @@ pysqlite_statement_create(pysqlite_Connection *connection, PyObject *sql)
break; break;
} }
pysqlite_state *state = pysqlite_get_state(NULL);
pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement, pysqlite_Statement *self = PyObject_GC_New(pysqlite_Statement,
pysqlite_StatementType); state->StatementType);
if (self == NULL) { if (self == NULL) {
goto error; goto error;
} }
@ -223,6 +224,7 @@ static int _need_adapt(PyObject* obj)
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters) void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters)
{ {
pysqlite_state *state = pysqlite_get_state(NULL);
PyObject* current_param; PyObject* current_param;
PyObject* adapted; PyObject* adapted;
const char* binding_name; const char* binding_name;
@ -271,7 +273,10 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
if (!_need_adapt(current_param)) { if (!_need_adapt(current_param)) {
adapted = current_param; adapted = current_param;
} else { } else {
adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)pysqlite_PrepareProtocolType, current_param); PyObject *protocol = (PyObject *)state->PrepareProtocolType;
adapted = pysqlite_microprotocols_adapt(current_param,
protocol,
current_param);
Py_DECREF(current_param); Py_DECREF(current_param);
if (!adapted) { if (!adapted) {
return; return;
@ -322,7 +327,10 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para
if (!_need_adapt(current_param)) { if (!_need_adapt(current_param)) {
adapted = current_param; adapted = current_param;
} else { } else {
adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)pysqlite_PrepareProtocolType, current_param); PyObject *protocol = (PyObject *)state->PrepareProtocolType;
adapted = pysqlite_microprotocols_adapt(current_param,
protocol,
current_param);
Py_DECREF(current_param); Py_DECREF(current_param);
if (!adapted) { if (!adapted) {
return; return;
@ -497,14 +505,15 @@ static PyType_Spec stmt_spec = {
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.slots = stmt_slots, .slots = stmt_slots,
}; };
PyTypeObject *pysqlite_StatementType = NULL;
int int
pysqlite_statement_setup_types(PyObject *module) pysqlite_statement_setup_types(PyObject *module)
{ {
pysqlite_StatementType = (PyTypeObject *)PyType_FromModuleAndSpec(module, &stmt_spec, NULL); PyObject *type = PyType_FromModuleAndSpec(module, &stmt_spec, NULL);
if (pysqlite_StatementType == NULL) { if (type == NULL) {
return -1; return -1;
} }
pysqlite_state *state = pysqlite_get_state(module);
state->StatementType = (PyTypeObject *)type;
return 0; return 0;
} }