Skip to content

Commit 084173a

Browse files
author
Erlend E. Aasland
committed
Use sqlite3_treadsafe() instead of querying compile_options
1 parent da6481f commit 084173a

File tree

3 files changed

+30
-43
lines changed

3 files changed

+30
-43
lines changed

Lib/sqlite3/dbapi2.py

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,38 +28,6 @@
2828

2929
paramstyle = "qmark"
3030

31-
32-
def fetch_compile_options():
33-
try:
34-
cx = connect(":memory:")
35-
res = cx.execute("pragma compile_options")
36-
opts = {i[0] for i in res}
37-
finally:
38-
cx.close()
39-
return opts
40-
41-
_compile_options = fetch_compile_options()
42-
del fetch_compile_options
43-
44-
def _threadsafety():
45-
if "THREADSAFE=0" in _compile_options:
46-
# SQLITE_THREADSAFE=0 (single-thread mode) translates to DB-API
47-
# threadsafety level 0, meaning threads may not share the module.
48-
return 0
49-
elif "THREADSAFE=2" in _compile_options:
50-
# SQLITE_THREADSAFE=2 (multi-thread mode) translates to DB-API
51-
# threadsafety level 1, meaning threads may share the module, but not
52-
# connections.
53-
return 1
54-
55-
# Default to SQLITE_THREADSAFE=1 (serialized mode), which translates to
56-
# DB-API threadsafety level 3, meaning threads may share the module,
57-
# connections and cursors. This is the default threading mode of SQLite.
58-
return 3
59-
60-
threadsafety = _threadsafety()
61-
del _threadsafety
62-
6331
apilevel = "2.0"
6432

6533
Date = datetime.date

Lib/test/test_sqlite3/test_dbapi.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,9 @@ def test_api_level(self):
5454
"apilevel is %s, should be 2.0" % sqlite.apilevel)
5555

5656
def test_thread_safety(self):
57-
from sqlite3.dbapi2 import _compile_options
58-
msg = "threadsafety is %d, should be %d in %s mode"
59-
if "THREADSAFE=0" in _compile_options:
60-
self.assertEqual(sqlite.threadsafety, 0,
61-
msg % (sqlite.threadsafety, 0, "single-thread"))
62-
elif "THREADSAFE=2" in _compile_options:
63-
self.assertEqual(sqlite.threadsafety, 1,
64-
msg % (sqlite.threadsafety, 1, "multi-thread"))
65-
else: # THREADSAFE=1 (default)
66-
self.assertEqual(sqlite.threadsafety, 3,
67-
msg % (sqlite.threadsafety, 3, "serialized"))
57+
self.assertIn(sqlite.threadsafety, {0, 1, 3},
58+
"threadsafety is %d, should be 0, 1 or 3" %
59+
sqlite.threadsafety)
6860

6961
def test_param_style(self):
7062
self.assertEqual(sqlite.paramstyle, "qmark",

Modules/_sqlite/module.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,28 @@ add_integer_constants(PyObject *module) {
415415
return 0;
416416
}
417417

418+
/* Convert SQLite default threading mode (as set by the compile-time constant
419+
* SQLITE_THREADSAFE) to the corresponding DB-API 2.0 (PEP 249) threadsafety
420+
* level. */
421+
static int
422+
get_threadsafety(pysqlite_state *state)
423+
{
424+
int mode = sqlite3_threadsafe();
425+
switch (mode) {
426+
case 0: // SQLite single-thread mode; threads may not share the
427+
return 0; // module.
428+
case 1: // SQLite serialized mode; threads may share the module,
429+
return 3; // connections and cursors.
430+
case 2: // SQLite multi-thread mode; threads may share the module,
431+
return 1; // but not connections.
432+
default:
433+
PyErr_Format(state->InterfaceError,
434+
"Unable to interpret SQLite threadsafety mode. Got %d, "
435+
"expected 0, 1, or 2", mode);
436+
return -1;
437+
}
438+
}
439+
418440
static int
419441
module_traverse(PyObject *module, visitproc visit, void *arg)
420442
{
@@ -564,6 +586,11 @@ module_exec(PyObject *module)
564586
goto error;
565587
}
566588

589+
int threadsafety = get_threadsafety(state);
590+
if (PyModule_AddIntConstant(module, "threadsafety", threadsafety) < 0) {
591+
goto error;
592+
}
593+
567594
/* initialize microprotocols layer */
568595
if (pysqlite_microprotocols_init(module) < 0) {
569596
goto error;

0 commit comments

Comments
 (0)