summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlend Egeberg Aasland <erlend.aasland@innova.no>2021-07-27 13:54:20 (GMT)
committerGitHub <noreply@github.com>2021-07-27 13:54:20 (GMT)
commit890e22957d427ee994b85d62dfe4d5a7cbd34ec5 (patch)
treeb20dad5ada209730b02ba55722288c4049dacaf0
parent2e41df4d60d71a2551b9605d07321f75cfb52adf (diff)
downloadcpython-890e22957d427ee994b85d62dfe4d5a7cbd34ec5.zip
cpython-890e22957d427ee994b85d62dfe4d5a7cbd34ec5.tar.gz
cpython-890e22957d427ee994b85d62dfe4d5a7cbd34ec5.tar.bz2
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.
-rw-r--r--Modules/_sqlite/connection.c41
-rw-r--r--Modules/_sqlite/connection.h3
2 files changed, 17 insertions, 27 deletions
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 33d3d4c..af093c3 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -177,11 +177,6 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
self->function_pinboard_progress_handler = NULL;
self->function_pinboard_authorizer_cb = NULL;
- Py_XSETREF(self->collations, PyDict_New());
- if (!self->collations) {
- return -1;
- }
-
pysqlite_state *state = pysqlite_get_state(NULL);
self->Warning = state->Warning;
self->Error = state->Error;
@@ -249,7 +244,6 @@ connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
Py_VISIT(self->function_pinboard_trace_callback);
Py_VISIT(self->function_pinboard_progress_handler);
Py_VISIT(self->function_pinboard_authorizer_cb);
- Py_VISIT(self->collations);
return 0;
}
@@ -265,7 +259,6 @@ connection_clear(pysqlite_Connection *self)
Py_CLEAR(self->function_pinboard_trace_callback);
Py_CLEAR(self->function_pinboard_progress_handler);
Py_CLEAR(self->function_pinboard_authorizer_cb);
- Py_CLEAR(self->collations);
return 0;
}
@@ -1780,29 +1773,29 @@ pysqlite_connection_create_collation_impl(pysqlite_Connection *self,
if (!uppercase_name_str)
goto finally;
- if (callable != Py_None && !PyCallable_Check(callable)) {
- PyErr_SetString(PyExc_TypeError, "parameter must be callable");
- goto finally;
+ int flags = SQLITE_UTF8;
+ if (callable == Py_None) {
+ rc = sqlite3_create_collation_v2(self->db, uppercase_name_str, flags,
+ NULL, NULL, NULL);
}
-
- if (callable != Py_None) {
- if (PyDict_SetItem(self->collations, uppercase_name, callable) == -1)
- goto finally;
- } else {
- if (PyDict_DelItem(self->collations, uppercase_name) == -1)
+ else {
+ if (!PyCallable_Check(callable)) {
+ PyErr_SetString(PyExc_TypeError, "parameter must be callable");
goto finally;
+ }
+ rc = sqlite3_create_collation_v2(self->db, uppercase_name_str, flags,
+ Py_NewRef(callable),
+ &pysqlite_collation_callback,
+ &_destructor);
}
- rc = sqlite3_create_collation(self->db,
- uppercase_name_str,
- SQLITE_UTF8,
- (callable != Py_None) ? callable : NULL,
- (callable != Py_None) ? pysqlite_collation_callback : NULL);
if (rc != SQLITE_OK) {
+ /* Unlike other sqlite3_* functions, the destructor callback is _not_
+ * called if sqlite3_create_collation_v2() fails, so we have to free
+ * the context before returning.
+ */
if (callable != Py_None) {
- if (PyDict_DelItem(self->collations, uppercase_name) < 0) {
- PyErr_Clear();
- }
+ Py_DECREF(callable);
}
_pysqlite_seterror(self->db);
goto finally;
diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h
index 5e7e7e5..50c2015 100644
--- a/Modules/_sqlite/connection.h
+++ b/Modules/_sqlite/connection.h
@@ -82,9 +82,6 @@ typedef struct
PyObject* function_pinboard_progress_handler;
PyObject* function_pinboard_authorizer_cb;
- /* a dictionary of registered collation name => collation callable mappings */
- PyObject* collations;
-
/* Exception objects: borrowed refs. */
PyObject* Warning;
PyObject* Error;