Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit e8d9df0

Browse filesBrowse files
miss-islingtonErlend Egeberg Aasland
and
Erlend Egeberg Aasland
authored
bpo-42972: Fully implement GC protocol for sqlite3 heap types (GH-26104)
(cherry picked from commit d3c277a) Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
1 parent 05f8ad0 commit e8d9df0
Copy full SHA for e8d9df0

File tree

Expand file treeCollapse file tree

6 files changed

+190
-72
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+190
-72
lines changed

‎Modules/_sqlite/cache.c

Copy file name to clipboardExpand all lines: Modules/_sqlite/cache.c
+60-23Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,29 @@ pysqlite_new_node(PyObject *key, PyObject *data)
4444
return node;
4545
}
4646

47+
static int
48+
node_traverse(pysqlite_Node *self, visitproc visit, void *arg)
49+
{
50+
Py_VISIT(self->key);
51+
Py_VISIT(self->data);
52+
Py_VISIT(Py_TYPE(self));
53+
return 0;
54+
}
55+
56+
static int
57+
node_clear(pysqlite_Node *self)
58+
{
59+
Py_CLEAR(self->key);
60+
Py_CLEAR(self->data);
61+
return 0;
62+
}
63+
4764
static void
4865
pysqlite_node_dealloc(pysqlite_Node *self)
4966
{
5067
PyTypeObject *tp = Py_TYPE(self);
51-
52-
Py_DECREF(self->key);
53-
Py_DECREF(self->data);
54-
68+
PyObject_GC_UnTrack(self);
69+
tp->tp_clear((PyObject *)self);
5570
tp->tp_free(self);
5671
Py_DECREF(tp);
5772
}
@@ -88,31 +103,51 @@ pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs)
88103
return 0;
89104
}
90105

91-
static void
92-
pysqlite_cache_dealloc(pysqlite_Cache *self)
106+
static int
107+
cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg)
93108
{
94-
PyTypeObject *tp = Py_TYPE(self);
95-
pysqlite_Node* node;
96-
pysqlite_Node* delete_node;
97-
98-
if (!self->factory) {
99-
/* constructor failed, just get out of here */
100-
return;
109+
pysqlite_Node *node = self->first;
110+
while (node) {
111+
Py_VISIT(node);
112+
node = node->next;
113+
}
114+
Py_VISIT(self->mapping);
115+
if (self->decref_factory) {
116+
Py_VISIT(self->factory);
101117
}
118+
Py_VISIT(Py_TYPE(self));
119+
return 0;
120+
}
102121

122+
static int
123+
cache_clear(pysqlite_Cache *self)
124+
{
103125
/* iterate over all nodes and deallocate them */
104-
node = self->first;
126+
pysqlite_Node *node = self->first;
127+
self->first = NULL;
105128
while (node) {
106-
delete_node = node;
129+
pysqlite_Node *delete_node = node;
107130
node = node->next;
108-
Py_DECREF(delete_node);
131+
Py_CLEAR(delete_node);
109132
}
110-
111133
if (self->decref_factory) {
112-
Py_DECREF(self->factory);
134+
Py_CLEAR(self->factory);
135+
}
136+
Py_CLEAR(self->mapping);
137+
return 0;
138+
}
139+
140+
static void
141+
pysqlite_cache_dealloc(pysqlite_Cache *self)
142+
{
143+
if (!self->factory) {
144+
/* constructor failed, just get out of here */
145+
return;
113146
}
114-
Py_DECREF(self->mapping);
115147

148+
PyObject_GC_UnTrack(self);
149+
PyTypeObject *tp = Py_TYPE(self);
150+
tp->tp_clear((PyObject *)self);
116151
tp->tp_free(self);
117152
Py_DECREF(tp);
118153
}
@@ -260,14 +295,15 @@ pysqlite_cache_display(pysqlite_Cache *self, PyObject *args)
260295

261296
static PyType_Slot node_slots[] = {
262297
{Py_tp_dealloc, pysqlite_node_dealloc},
263-
{Py_tp_new, PyType_GenericNew},
298+
{Py_tp_traverse, node_traverse},
299+
{Py_tp_clear, node_clear},
264300
{0, NULL},
265301
};
266302

267303
static PyType_Spec node_spec = {
268304
.name = MODULE_NAME ".Node",
269305
.basicsize = sizeof(pysqlite_Node),
270-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
306+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
271307
.slots = node_slots,
272308
};
273309
PyTypeObject *pysqlite_NodeType = NULL;
@@ -283,15 +319,16 @@ static PyMethodDef cache_methods[] = {
283319
static PyType_Slot cache_slots[] = {
284320
{Py_tp_dealloc, pysqlite_cache_dealloc},
285321
{Py_tp_methods, cache_methods},
286-
{Py_tp_new, PyType_GenericNew},
287322
{Py_tp_init, pysqlite_cache_init},
323+
{Py_tp_traverse, cache_traverse},
324+
{Py_tp_clear, cache_clear},
288325
{0, NULL},
289326
};
290327

291328
static PyType_Spec cache_spec = {
292329
.name = MODULE_NAME ".Cache",
293330
.basicsize = sizeof(pysqlite_Cache),
294-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
331+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
295332
.slots = cache_slots,
296333
};
297334
PyTypeObject *pysqlite_CacheType = NULL;

‎Modules/_sqlite/connection.c

Copy file name to clipboardExpand all lines: Modules/_sqlite/connection.c
+41-17Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -225,28 +225,51 @@ pysqlite_do_all_statements(pysqlite_Connection *self, int action,
225225
}
226226
}
227227

228+
static int
229+
connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
230+
{
231+
Py_VISIT(self->statement_cache);
232+
Py_VISIT(self->isolation_level);
233+
Py_VISIT(self->function_pinboard_trace_callback);
234+
Py_VISIT(self->function_pinboard_progress_handler);
235+
Py_VISIT(self->function_pinboard_authorizer_cb);
236+
Py_VISIT(self->row_factory);
237+
Py_VISIT(self->text_factory);
238+
Py_VISIT(self->collations);
239+
Py_VISIT(self->statements);
240+
Py_VISIT(self->cursors);
241+
Py_VISIT(Py_TYPE(self));
242+
return 0;
243+
}
244+
245+
static int
246+
connection_clear(pysqlite_Connection *self)
247+
{
248+
Py_CLEAR(self->statement_cache);
249+
Py_CLEAR(self->isolation_level);
250+
Py_CLEAR(self->function_pinboard_trace_callback);
251+
Py_CLEAR(self->function_pinboard_progress_handler);
252+
Py_CLEAR(self->function_pinboard_authorizer_cb);
253+
Py_CLEAR(self->row_factory);
254+
Py_CLEAR(self->text_factory);
255+
Py_CLEAR(self->collations);
256+
Py_CLEAR(self->statements);
257+
Py_CLEAR(self->cursors);
258+
return 0;
259+
}
260+
228261
static void
229-
pysqlite_connection_dealloc(pysqlite_Connection *self)
262+
connection_dealloc(pysqlite_Connection *self)
230263
{
231264
PyTypeObject *tp = Py_TYPE(self);
232-
233-
Py_XDECREF(self->statement_cache);
265+
PyObject_GC_UnTrack(self);
266+
tp->tp_clear((PyObject *)self);
234267

235268
/* Clean up if user has not called .close() explicitly. */
236269
if (self->db) {
237270
sqlite3_close_v2(self->db);
238271
}
239272

240-
Py_XDECREF(self->isolation_level);
241-
Py_XDECREF(self->function_pinboard_trace_callback);
242-
Py_XDECREF(self->function_pinboard_progress_handler);
243-
Py_XDECREF(self->function_pinboard_authorizer_cb);
244-
Py_XDECREF(self->row_factory);
245-
Py_XDECREF(self->text_factory);
246-
Py_XDECREF(self->collations);
247-
Py_XDECREF(self->statements);
248-
Py_XDECREF(self->cursors);
249-
250273
tp->tp_free(self);
251274
Py_DECREF(tp);
252275
}
@@ -1328,7 +1351,7 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args,
13281351

13291352
_pysqlite_drop_unused_statement_references(self);
13301353

1331-
statement = PyObject_New(pysqlite_Statement, pysqlite_StatementType);
1354+
statement = PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType);
13321355
if (!statement) {
13331356
return NULL;
13341357
}
@@ -1909,21 +1932,22 @@ static struct PyMemberDef connection_members[] =
19091932
};
19101933

19111934
static PyType_Slot connection_slots[] = {
1912-
{Py_tp_dealloc, pysqlite_connection_dealloc},
1935+
{Py_tp_dealloc, connection_dealloc},
19131936
{Py_tp_doc, (void *)connection_doc},
19141937
{Py_tp_methods, connection_methods},
19151938
{Py_tp_members, connection_members},
19161939
{Py_tp_getset, connection_getset},
1917-
{Py_tp_new, PyType_GenericNew},
19181940
{Py_tp_init, pysqlite_connection_init},
19191941
{Py_tp_call, pysqlite_connection_call},
1942+
{Py_tp_traverse, connection_traverse},
1943+
{Py_tp_clear, connection_clear},
19201944
{0, NULL},
19211945
};
19221946

19231947
static PyType_Spec connection_spec = {
19241948
.name = MODULE_NAME ".Connection",
19251949
.basicsize = sizeof(pysqlite_Connection),
1926-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1950+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
19271951
.slots = connection_slots,
19281952
};
19291953

‎Modules/_sqlite/cursor.c

Copy file name to clipboardExpand all lines: Modules/_sqlite/cursor.c
+33-13Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,27 +81,46 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self,
8181
return 0;
8282
}
8383

84-
static void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
84+
static int
85+
cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg)
8586
{
86-
PyTypeObject *tp = Py_TYPE(self);
87+
Py_VISIT(self->connection);
88+
Py_VISIT(self->row_cast_map);
89+
Py_VISIT(self->row_factory);
90+
Py_VISIT(self->next_row);
91+
Py_VISIT(Py_TYPE(self));
92+
return 0;
93+
}
8794

95+
static int
96+
cursor_clear(pysqlite_Cursor *self)
97+
{
8898
/* Reset the statement if the user has not closed the cursor */
8999
if (self->statement) {
90100
pysqlite_statement_reset(self->statement);
91-
Py_DECREF(self->statement);
101+
Py_CLEAR(self->statement);
92102
}
93103

94-
Py_XDECREF(self->connection);
95-
Py_XDECREF(self->row_cast_map);
96-
Py_XDECREF(self->description);
97-
Py_XDECREF(self->lastrowid);
98-
Py_XDECREF(self->row_factory);
99-
Py_XDECREF(self->next_row);
104+
Py_CLEAR(self->connection);
105+
Py_CLEAR(self->row_cast_map);
106+
Py_CLEAR(self->description);
107+
Py_CLEAR(self->lastrowid);
108+
Py_CLEAR(self->row_factory);
109+
Py_CLEAR(self->next_row);
100110

101111
if (self->in_weakreflist != NULL) {
102112
PyObject_ClearWeakRefs((PyObject*)self);
103113
}
104114

115+
return 0;
116+
}
117+
118+
static void
119+
cursor_dealloc(PyObject *self)
120+
{
121+
PyTypeObject *tp = Py_TYPE(self);
122+
PyObject_GC_UnTrack(self);
123+
tp->tp_clear(self);
105124
tp->tp_free(self);
106125
Py_DECREF(tp);
107126
}
@@ -487,7 +506,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
487506

488507
if (self->statement->in_use) {
489508
Py_SETREF(self->statement,
490-
PyObject_New(pysqlite_Statement, pysqlite_StatementType));
509+
PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType));
491510
if (!self->statement) {
492511
goto error;
493512
}
@@ -1006,21 +1025,22 @@ static const char cursor_doc[] =
10061025
PyDoc_STR("SQLite database cursor class.");
10071026

10081027
static PyType_Slot cursor_slots[] = {
1009-
{Py_tp_dealloc, pysqlite_cursor_dealloc},
1028+
{Py_tp_dealloc, cursor_dealloc},
10101029
{Py_tp_doc, (void *)cursor_doc},
10111030
{Py_tp_iter, PyObject_SelfIter},
10121031
{Py_tp_iternext, pysqlite_cursor_iternext},
10131032
{Py_tp_methods, cursor_methods},
10141033
{Py_tp_members, cursor_members},
1015-
{Py_tp_new, PyType_GenericNew},
10161034
{Py_tp_init, pysqlite_cursor_init},
1035+
{Py_tp_traverse, cursor_traverse},
1036+
{Py_tp_clear, cursor_clear},
10171037
{0, NULL},
10181038
};
10191039

10201040
static PyType_Spec cursor_spec = {
10211041
.name = MODULE_NAME ".Cursor",
10221042
.basicsize = sizeof(pysqlite_Cursor),
1023-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1043+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
10241044
.slots = cursor_slots,
10251045
};
10261046

‎Modules/_sqlite/prepare_protocol.c

Copy file name to clipboardExpand all lines: Modules/_sqlite/prepare_protocol.c
+10-3Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,33 @@ pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args,
3030
return 0;
3131
}
3232

33+
static int
34+
pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg)
35+
{
36+
Py_VISIT(Py_TYPE(self));
37+
return 0;
38+
}
39+
3340
static void
3441
pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self)
3542
{
3643
PyTypeObject *tp = Py_TYPE(self);
37-
44+
PyObject_GC_UnTrack(self);
3845
tp->tp_free(self);
3946
Py_DECREF(tp);
4047
}
4148

4249
static PyType_Slot type_slots[] = {
4350
{Py_tp_dealloc, pysqlite_prepare_protocol_dealloc},
44-
{Py_tp_new, PyType_GenericNew},
4551
{Py_tp_init, pysqlite_prepare_protocol_init},
52+
{Py_tp_traverse, pysqlite_prepare_protocol_traverse},
4653
{0, NULL},
4754
};
4855

4956
static PyType_Spec type_spec = {
5057
.name = MODULE_NAME ".PrepareProtocol",
5158
.basicsize = sizeof(pysqlite_PrepareProtocol),
52-
.flags = Py_TPFLAGS_DEFAULT,
59+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
5360
.slots = type_slots,
5461
};
5562

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.