Skip to content

Commit e002e20

Browse files
committed
Add sqlite3_setlk_timeout
1 parent a73a728 commit e002e20

7 files changed

Lines changed: 83 additions & 1 deletion

File tree

apsw/tests/__main__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,16 @@ def testFormatSQLValue(self):
14261426
self.assertRaises(TypeError, apsw.format_sql_value, apsw)
14271427
self.assertRaises(TypeError, apsw.format_sql_value)
14281428

1429+
def testSetlkTimeout(self):
1430+
"sqlite3_setlk_timeout"
1431+
self.assertRaises(OverflowError, self.db.setlk_timeout, sys.maxsize * 64, apsw.SQLITE_SETLK_BLOCK_ON_CONNECT)
1432+
# it current gives range for values less than -1
1433+
self.assertRaises(apsw.RangeError, self.db.setlk_timeout, -2, apsw.SQLITE_SETLK_BLOCK_ON_CONNECT)
1434+
1435+
# no error is given for unknown flags so we don't test them
1436+
self.db.setlk_timeout(1000, apsw.SQLITE_SETLK_BLOCK_ON_CONNECT)
1437+
1438+
14291439
def testVTableStuff(self):
14301440
"Test new stuff added for Virtual tables"
14311441

doc/changes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ APSW changes by version
1515

1616
Full support for the :doc:`session`
1717

18+
Added :meth:`Connection.setlk_timeout`,
19+
:attr:`apsw.mapping_setlk_timeout_flags`, and enabled the timeout for
20+
amalgamation builds such as PyPI.
21+
1822
Shell :ref:`open command <shell-cmd-open>` allows specifying flags to
1923
open a connection, and :ref:`connection command
2024
<shell-cmd-connection>` shows flags used for each open. (:issue:`557`)

src/apsw.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ API Reference
8181
#define SQLITE_MAX_MMAP_SIZE 0x1000000000000LL
8282
#endif
8383

84+
#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
85+
#define SQLITE_ENABLE_SETLK_TIMEOUT 1
86+
#endif
87+
8488
#ifndef SQLITE_DEBUG
8589
#define SQLITE_API static
8690
#define SQLITE_EXTERN static

src/apsw.docstrings

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2476,6 +2476,20 @@
24762476
#define Connection_set_wal_hook_OLDNAME "setwalhook"
24772477
#define Connection_set_wal_hook_OLDDOC Connection_set_wal_hook_USAGE "\n(Old less clear name setwalhook)"
24782478

2479+
#define Connection_setlk_timeout_DOC "Connection.setlk_timeout(ms: int, flags: int) -> None\n\n" \
2480+
"Sets a VFS level timeout.\n" \
2481+
"\n" \
2482+
"Calls: `sqlite3_setlk_timeout <https://sqlite.org/c3ref/setlk_timeout.html>`__\n"
2483+
2484+
#define Connection_setlk_timeout_KWNAMES "ms", "flags"
2485+
#define Connection_setlk_timeout_USAGE "Connection.setlk_timeout(ms: int, flags: int) -> None"
2486+
2487+
#define Connection_setlk_timeout_CHECK do { \
2488+
assert(__builtin_types_compatible_p(typeof(ms), int)); \
2489+
assert(__builtin_types_compatible_p(typeof(flags), int)); \
2490+
} while(0)
2491+
2492+
24792493
#define Connection_sqlite3_pointer_DOC "Connection.sqlite3_pointer() -> int\n\n" \
24802494
"Returns the underlying `sqlite3 *\n" \
24812495
"<https://sqlite.org/c3ref/sqlite3.html>`_ for the connection. This\n" \

src/connection.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5545,6 +5545,35 @@ Connection_data_version(PyObject *self_, PyObject *const *fast_args, Py_ssize_t
55455545
return PyErr_Occurred() ? NULL : PyLong_FromLong(data_version);
55465546
}
55475547

5548+
/** .. method:: setlk_timeout(ms: int, flags: int) -> None
5549+
5550+
Sets a VFS level timeout.
5551+
5552+
-* sqlite3_setlk_timeout
5553+
5554+
*/
5555+
static PyObject *
5556+
Connection_setlk_timeout(PyObject *self_, PyObject *const *fast_args, Py_ssize_t fast_nargs, PyObject *fast_kwnames)
5557+
{
5558+
Connection *self = (Connection *)self_;
5559+
CHECK_CLOSED(self, NULL);
5560+
5561+
int ms, flags;
5562+
{
5563+
Connection_setlk_timeout_CHECK;
5564+
ARG_PROLOG(2, Connection_setlk_timeout_KWNAMES);
5565+
ARG_MANDATORY ARG_int(ms);
5566+
ARG_MANDATORY ARG_int(flags);
5567+
ARG_EPILOG(NULL, Connection_setlk_timeout_USAGE, );
5568+
}
5569+
5570+
int res = sqlite3_setlk_timeout(self->db, ms, flags);
5571+
SET_EXC(res, NULL);
5572+
if(PyErr_Occurred())
5573+
return NULL;
5574+
Py_RETURN_NONE;
5575+
}
5576+
55485577
/* done this way here to keep doc generation simple */
55495578
#include "fts.c"
55505579

@@ -6014,6 +6043,7 @@ static PyMethodDef Connection_methods[] = {
60146043
{ "register_fts5_function", (PyCFunction)Connection_register_fts5_function, METH_FASTCALL | METH_KEYWORDS,
60156044
Connection_register_fts5_function_DOC },
60166045
{ "data_version", (PyCFunction)Connection_data_version, METH_FASTCALL | METH_KEYWORDS, Connection_data_version_DOC },
6046+
{ "setlk_timeout", (PyCFunction)Connection_setlk_timeout, METH_FASTCALL | METH_KEYWORDS, Connection_setlk_timeout_DOC },
60176047
#ifndef APSW_OMIT_OLD_NAMES
60186048
{ Connection_set_busy_timeout_OLDNAME, (PyCFunction)Connection_set_busy_timeout, METH_FASTCALL | METH_KEYWORDS,
60196049
Connection_set_busy_timeout_OLDDOC },

src/constants.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,22 @@ add_apsw_constants(PyObject *module)
476476
return -1;
477477
}
478478

479+
/* Flags for sqlite3_setlk_timeout() */
480+
the_dict = Py_BuildValue(
481+
"{siis}",
482+
"SQLITE_SETLK_BLOCK_ON_CONNECT", SQLITE_SETLK_BLOCK_ON_CONNECT, SQLITE_SETLK_BLOCK_ON_CONNECT, "SQLITE_SETLK_BLOCK_ON_CONNECT");
483+
if (!the_dict)
484+
{
485+
assert(PyErr_Occurred());
486+
return -1;
487+
}
488+
if (PyModule_AddObject(module, "mapping_setlk_timeout_flags", the_dict))
489+
{
490+
assert(PyErr_Occurred());
491+
Py_DECREF(the_dict);
492+
return -1;
493+
}
494+
479495
#ifdef SQLITE_ENABLE_SESSION
480496
/* Flags for sqlite3changeset_apply_v2 */
481497
the_dict = Py_BuildValue(
@@ -705,8 +721,9 @@ add_apsw_constants(PyObject *module)
705721

706722
/* Standard File Control Opcodes */
707723
the_dict = Py_BuildValue(
708-
"{siissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiis}",
724+
"{siissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiissiis}",
709725
"SQLITE_FCNTL_BEGIN_ATOMIC_WRITE", SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, "SQLITE_FCNTL_BEGIN_ATOMIC_WRITE",
726+
"SQLITE_FCNTL_BLOCK_ON_CONNECT", SQLITE_FCNTL_BLOCK_ON_CONNECT, SQLITE_FCNTL_BLOCK_ON_CONNECT, "SQLITE_FCNTL_BLOCK_ON_CONNECT",
710727
"SQLITE_FCNTL_BUSYHANDLER", SQLITE_FCNTL_BUSYHANDLER, SQLITE_FCNTL_BUSYHANDLER, "SQLITE_FCNTL_BUSYHANDLER",
711728
"SQLITE_FCNTL_CHUNK_SIZE", SQLITE_FCNTL_CHUNK_SIZE, SQLITE_FCNTL_CHUNK_SIZE, "SQLITE_FCNTL_CHUNK_SIZE",
712729
"SQLITE_FCNTL_CKPT_DONE", SQLITE_FCNTL_CKPT_DONE, SQLITE_FCNTL_CKPT_DONE, "SQLITE_FCNTL_CKPT_DONE",
@@ -1088,6 +1105,7 @@ add_apsw_constants(PyObject *module)
10881105
|| PyModule_AddIntConstant(module, "SQLITE_ERROR_SNAPSHOT", SQLITE_ERROR_SNAPSHOT)
10891106
|| PyModule_AddIntConstant(module, "SQLITE_FAIL", SQLITE_FAIL)
10901107
|| PyModule_AddIntConstant(module, "SQLITE_FCNTL_BEGIN_ATOMIC_WRITE", SQLITE_FCNTL_BEGIN_ATOMIC_WRITE)
1108+
|| PyModule_AddIntConstant(module, "SQLITE_FCNTL_BLOCK_ON_CONNECT", SQLITE_FCNTL_BLOCK_ON_CONNECT)
10911109
|| PyModule_AddIntConstant(module, "SQLITE_FCNTL_BUSYHANDLER", SQLITE_FCNTL_BUSYHANDLER)
10921110
|| PyModule_AddIntConstant(module, "SQLITE_FCNTL_CHUNK_SIZE", SQLITE_FCNTL_CHUNK_SIZE)
10931111
|| PyModule_AddIntConstant(module, "SQLITE_FCNTL_CKPT_DONE", SQLITE_FCNTL_CKPT_DONE)
@@ -1288,6 +1306,7 @@ add_apsw_constants(PyObject *module)
12881306
|| PyModule_AddIntConstant(module, "SQLITE_SCHEMA", SQLITE_SCHEMA)
12891307
|| PyModule_AddIntConstant(module, "SQLITE_SELECT", SQLITE_SELECT)
12901308
|| PyModule_AddIntConstant(module, "SQLITE_SELFORDER1", SQLITE_SELFORDER1)
1309+
|| PyModule_AddIntConstant(module, "SQLITE_SETLK_BLOCK_ON_CONNECT", SQLITE_SETLK_BLOCK_ON_CONNECT)
12911310
|| PyModule_AddIntConstant(module, "SQLITE_SHM_EXCLUSIVE", SQLITE_SHM_EXCLUSIVE)
12921311
|| PyModule_AddIntConstant(module, "SQLITE_SHM_LOCK", SQLITE_SHM_LOCK)
12931312
|| PyModule_AddIntConstant(module, "SQLITE_SHM_SHARED", SQLITE_SHM_SHARED)

tools/genconstants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"Flags For File Open Operations": "open_flags",
2828
"Flags for sqlite3_deserialize()": None,
2929
"Flags for sqlite3_serialize": None,
30+
"Flags for sqlite3_setlk_timeout()": "setlk_timeout_flags",
3031
"Flags for the xAccess VFS method": "access",
3132
"Flags for the xShmLock VFS method": "xshmlock_flags",
3233
"Function Flags": "function_flags",

0 commit comments

Comments
 (0)