Skip to content

Commit 890e229

Browse files
author
Erlend Egeberg Aasland
authored
bpo-42064: Migrate to sqlite3_create_collation_v2 (GH-27156)
This implies that SQLite now takes care of destroying the callback context (the PyObject callable it has been passed), so we can strip the collation dict from the connection object.
1 parent 2e41df4 commit 890e229

File tree

2 files changed

+17
-27
lines changed

2 files changed

+17
-27
lines changed

‎Modules/_sqlite/connection.c‎

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
177177
self->function_pinboard_progress_handler = NULL;
178178
self->function_pinboard_authorizer_cb = NULL;
179179

180-
Py_XSETREF(self->collations, PyDict_New());
181-
if (!self->collations) {
182-
return -1;
183-
}
184-
185180
pysqlite_state *state = pysqlite_get_state(NULL);
186181
self->Warning = state->Warning;
187182
self->Error = state->Error;
@@ -249,7 +244,6 @@ connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
249244
Py_VISIT(self->function_pinboard_trace_callback);
250245
Py_VISIT(self->function_pinboard_progress_handler);
251246
Py_VISIT(self->function_pinboard_authorizer_cb);
252-
Py_VISIT(self->collations);
253247
return 0;
254248
}
255249

@@ -265,7 +259,6 @@ connection_clear(pysqlite_Connection *self)
265259
Py_CLEAR(self->function_pinboard_trace_callback);
266260
Py_CLEAR(self->function_pinboard_progress_handler);
267261
Py_CLEAR(self->function_pinboard_authorizer_cb);
268-
Py_CLEAR(self->collations);
269262
return 0;
270263
}
271264

@@ -1780,29 +1773,29 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self,
17801773
if (!uppercase_name_str)
17811774
goto finally;
17821775

1783-
if (callable != Py_None && !PyCallable_Check(callable)) {
1784-
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
1785-
goto finally;
1776+
int flags = SQLITE_UTF8;
1777+
if (callable == Py_None) {
1778+
rc = sqlite3_create_collation_v2(self->db, uppercase_name_str, flags,
1779+
NULL, NULL, NULL);
17861780
}
1787-
1788-
if (callable != Py_None) {
1789-
if (PyDict_SetItem(self->collations, uppercase_name, callable) == -1)
1790-
goto finally;
1791-
} else {
1792-
if (PyDict_DelItem(self->collations, uppercase_name) == -1)
1781+
else {
1782+
if (!PyCallable_Check(callable)) {
1783+
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
17931784
goto finally;
1785+
}
1786+
rc = sqlite3_create_collation_v2(self->db, uppercase_name_str, flags,
1787+
Py_NewRef(callable),
1788+
&pysqlite_collation_callback,
1789+
&_destructor);
17941790
}
17951791

1796-
rc = sqlite3_create_collation(self->db,
1797-
uppercase_name_str,
1798-
SQLITE_UTF8,
1799-
(callable != Py_None) ? callable : NULL,
1800-
(callable != Py_None) ? pysqlite_collation_callback : NULL);
18011792
if (rc != SQLITE_OK) {
1793+
/* Unlike other sqlite3_* functions, the destructor callback is _not_
1794+
* called if sqlite3_create_collation_v2() fails, so we have to free
1795+
* the context before returning.
1796+
*/
18021797
if (callable != Py_None) {
1803-
if (PyDict_DelItem(self->collations, uppercase_name) < 0) {
1804-
PyErr_Clear();
1805-
}
1798+
Py_DECREF(callable);
18061799
}
18071800
_pysqlite_seterror(self->db);
18081801
goto finally;

‎Modules/_sqlite/connection.h‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,6 @@ typedef struct
8282
PyObject* function_pinboard_progress_handler;
8383
PyObject* function_pinboard_authorizer_cb;
8484

85-
/* a dictionary of registered collation name => collation callable mappings */
86-
PyObject* collations;
87-
8885
/* Exception objects: borrowed refs. */
8986
PyObject* Warning;
9087
PyObject* Error;

0 commit comments

Comments
 (0)