[Python-checkins] gh-105875: Require SQLite 3.15.2 or newer (#105876)

erlend-aasland webhook-mailer at python.org
Sun Jun 18 18:29:11 EDT 2023


https://github.com/python/cpython/commit/6849acb3feacda63ee43f1dc9be28fac1075ca7d
commit: 6849acb3feacda63ee43f1dc9be28fac1075ca7d
branch: main
author: Erlend E. Aasland <erlend.aasland at protonmail.com>
committer: erlend-aasland <erlend.aasland at protonmail.com>
date: 2023-06-19T00:29:08+02:00
summary:

gh-105875: Require SQLite 3.15.2 or newer (#105876)

SQLite 3.15.2 was released 2016-11-28.

files:
A Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst
M Doc/library/sqlite3.rst
M Doc/whatsnew/3.13.rst
M Lib/test/test_sqlite3/test_backup.py
M Lib/test/test_sqlite3/test_dbapi.py
M Lib/test/test_sqlite3/test_hooks.py
M Lib/test/test_sqlite3/test_types.py
M Lib/test/test_sqlite3/test_userfunctions.py
M Modules/_sqlite/blob.c
M Modules/_sqlite/connection.c
M Modules/_sqlite/module.c
M configure
M configure.ac

diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
index e7129fb3e4de6..7544b88216e73 100644
--- a/Doc/library/sqlite3.rst
+++ b/Doc/library/sqlite3.rst
@@ -29,7 +29,7 @@ PostgreSQL or Oracle.
 
 The :mod:`!sqlite3` module was written by Gerhard Häring.  It provides an SQL interface
 compliant with the DB-API 2.0 specification described by :pep:`249`, and
-requires SQLite 3.7.15 or newer.
+requires SQLite 3.15.2 or newer.
 
 This document includes four main sections:
 
@@ -734,9 +734,6 @@ Connection objects
           `deterministic <https://sqlite.org/deterministic.html>`_,
           which allows SQLite to perform additional optimizations.
 
-      :raises NotSupportedError:
-          If *deterministic* is used with SQLite versions older than 3.8.3.
-
       .. versionadded:: 3.8
          The *deterministic* parameter.
 
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index 7f61ade808cce..735715f015289 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -410,6 +410,9 @@ Build Changes
   :file:`!configure`.
   (Contributed by Christian Heimes in :gh:`89886`.)
 
+* SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension module.
+  (Contributed by Erlend Aasland in :gh:`105875`.)
+
 
 C API Changes
 =============
diff --git a/Lib/test/test_sqlite3/test_backup.py b/Lib/test/test_sqlite3/test_backup.py
index 384dd9229ab34..87ab29c54d65e 100644
--- a/Lib/test/test_sqlite3/test_backup.py
+++ b/Lib/test/test_sqlite3/test_backup.py
@@ -50,8 +50,6 @@ def test_bad_target_in_transaction(self):
         bck.executemany('INSERT INTO bar (key) VALUES (?)', [(3,), (4,)])
         with self.assertRaises(sqlite.OperationalError) as cm:
             self.cx.backup(bck)
-        if sqlite.sqlite_version_info < (3, 8, 8):
-            self.assertEqual(str(cm.exception), 'target is in transaction')
 
     def test_keyword_only_args(self):
         with self.assertRaises(TypeError):
diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py
index 328b0467e7fa3..3f9bd0248a8b9 100644
--- a/Lib/test/test_sqlite3/test_dbapi.py
+++ b/Lib/test/test_sqlite3/test_dbapi.py
@@ -165,6 +165,7 @@ def test_module_constants(self):
             "SQLITE_INTERNAL",
             "SQLITE_INTERRUPT",
             "SQLITE_IOERR",
+            "SQLITE_LIMIT_WORKER_THREADS",
             "SQLITE_LOCKED",
             "SQLITE_MISMATCH",
             "SQLITE_MISUSE",
@@ -172,6 +173,7 @@ def test_module_constants(self):
             "SQLITE_NOMEM",
             "SQLITE_NOTADB",
             "SQLITE_NOTFOUND",
+            "SQLITE_NOTICE",
             "SQLITE_OK",
             "SQLITE_PERM",
             "SQLITE_PRAGMA",
@@ -179,6 +181,7 @@ def test_module_constants(self):
             "SQLITE_RANGE",
             "SQLITE_READ",
             "SQLITE_READONLY",
+            "SQLITE_RECURSIVE",
             "SQLITE_REINDEX",
             "SQLITE_ROW",
             "SQLITE_SAVEPOINT",
@@ -187,6 +190,7 @@ def test_module_constants(self):
             "SQLITE_TOOBIG",
             "SQLITE_TRANSACTION",
             "SQLITE_UPDATE",
+            "SQLITE_WARNING",
             # Run-time limit categories
             "SQLITE_LIMIT_LENGTH",
             "SQLITE_LIMIT_SQL_LENGTH",
@@ -200,32 +204,43 @@ def test_module_constants(self):
             "SQLITE_LIMIT_VARIABLE_NUMBER",
             "SQLITE_LIMIT_TRIGGER_DEPTH",
         ]
-        if sqlite.sqlite_version_info >= (3, 7, 17):
-            consts += ["SQLITE_NOTICE", "SQLITE_WARNING"]
-        if sqlite.sqlite_version_info >= (3, 8, 3):
-            consts.append("SQLITE_RECURSIVE")
-        if sqlite.sqlite_version_info >= (3, 8, 7):
-            consts.append("SQLITE_LIMIT_WORKER_THREADS")
         consts += ["PARSE_DECLTYPES", "PARSE_COLNAMES"]
         # Extended result codes
         consts += [
             "SQLITE_ABORT_ROLLBACK",
+            "SQLITE_AUTH_USER",
             "SQLITE_BUSY_RECOVERY",
+            "SQLITE_BUSY_SNAPSHOT",
+            "SQLITE_CANTOPEN_CONVPATH",
             "SQLITE_CANTOPEN_FULLPATH",
             "SQLITE_CANTOPEN_ISDIR",
             "SQLITE_CANTOPEN_NOTEMPDIR",
+            "SQLITE_CONSTRAINT_CHECK",
+            "SQLITE_CONSTRAINT_COMMITHOOK",
+            "SQLITE_CONSTRAINT_FOREIGNKEY",
+            "SQLITE_CONSTRAINT_FUNCTION",
+            "SQLITE_CONSTRAINT_NOTNULL",
+            "SQLITE_CONSTRAINT_PRIMARYKEY",
+            "SQLITE_CONSTRAINT_ROWID",
+            "SQLITE_CONSTRAINT_TRIGGER",
+            "SQLITE_CONSTRAINT_UNIQUE",
+            "SQLITE_CONSTRAINT_VTAB",
             "SQLITE_CORRUPT_VTAB",
             "SQLITE_IOERR_ACCESS",
+            "SQLITE_IOERR_AUTH",
             "SQLITE_IOERR_BLOCKED",
             "SQLITE_IOERR_CHECKRESERVEDLOCK",
             "SQLITE_IOERR_CLOSE",
+            "SQLITE_IOERR_CONVPATH",
             "SQLITE_IOERR_DELETE",
             "SQLITE_IOERR_DELETE_NOENT",
             "SQLITE_IOERR_DIR_CLOSE",
             "SQLITE_IOERR_DIR_FSYNC",
             "SQLITE_IOERR_FSTAT",
             "SQLITE_IOERR_FSYNC",
+            "SQLITE_IOERR_GETTEMPPATH",
             "SQLITE_IOERR_LOCK",
+            "SQLITE_IOERR_MMAP",
             "SQLITE_IOERR_NOMEM",
             "SQLITE_IOERR_RDLOCK",
             "SQLITE_IOERR_READ",
@@ -237,50 +252,18 @@ def test_module_constants(self):
             "SQLITE_IOERR_SHORT_READ",
             "SQLITE_IOERR_TRUNCATE",
             "SQLITE_IOERR_UNLOCK",
+            "SQLITE_IOERR_VNODE",
             "SQLITE_IOERR_WRITE",
             "SQLITE_LOCKED_SHAREDCACHE",
+            "SQLITE_NOTICE_RECOVER_ROLLBACK",
+            "SQLITE_NOTICE_RECOVER_WAL",
+            "SQLITE_OK_LOAD_PERMANENTLY",
             "SQLITE_READONLY_CANTLOCK",
+            "SQLITE_READONLY_DBMOVED",
             "SQLITE_READONLY_RECOVERY",
+            "SQLITE_READONLY_ROLLBACK",
+            "SQLITE_WARNING_AUTOINDEX",
         ]
-        if sqlite.sqlite_version_info >= (3, 7, 16):
-            consts += [
-                "SQLITE_CONSTRAINT_CHECK",
-                "SQLITE_CONSTRAINT_COMMITHOOK",
-                "SQLITE_CONSTRAINT_FOREIGNKEY",
-                "SQLITE_CONSTRAINT_FUNCTION",
-                "SQLITE_CONSTRAINT_NOTNULL",
-                "SQLITE_CONSTRAINT_PRIMARYKEY",
-                "SQLITE_CONSTRAINT_TRIGGER",
-                "SQLITE_CONSTRAINT_UNIQUE",
-                "SQLITE_CONSTRAINT_VTAB",
-                "SQLITE_READONLY_ROLLBACK",
-            ]
-        if sqlite.sqlite_version_info >= (3, 7, 17):
-            consts += [
-                "SQLITE_IOERR_MMAP",
-                "SQLITE_NOTICE_RECOVER_ROLLBACK",
-                "SQLITE_NOTICE_RECOVER_WAL",
-            ]
-        if sqlite.sqlite_version_info >= (3, 8, 0):
-            consts += [
-                "SQLITE_BUSY_SNAPSHOT",
-                "SQLITE_IOERR_GETTEMPPATH",
-                "SQLITE_WARNING_AUTOINDEX",
-            ]
-        if sqlite.sqlite_version_info >= (3, 8, 1):
-            consts += ["SQLITE_CANTOPEN_CONVPATH", "SQLITE_IOERR_CONVPATH"]
-        if sqlite.sqlite_version_info >= (3, 8, 2):
-            consts.append("SQLITE_CONSTRAINT_ROWID")
-        if sqlite.sqlite_version_info >= (3, 8, 3):
-            consts.append("SQLITE_READONLY_DBMOVED")
-        if sqlite.sqlite_version_info >= (3, 8, 7):
-            consts.append("SQLITE_AUTH_USER")
-        if sqlite.sqlite_version_info >= (3, 9, 0):
-            consts.append("SQLITE_IOERR_VNODE")
-        if sqlite.sqlite_version_info >= (3, 10, 0):
-            consts.append("SQLITE_IOERR_AUTH")
-        if sqlite.sqlite_version_info >= (3, 14, 1):
-            consts.append("SQLITE_OK_LOAD_PERMANENTLY")
         if sqlite.sqlite_version_info >= (3, 21, 0):
             consts += [
                 "SQLITE_IOERR_BEGIN_ATOMIC",
@@ -330,8 +313,6 @@ def test_error_code_on_exception(self):
             self.assertEqual(e.sqlite_errorcode, err_code)
             self.assertTrue(e.sqlite_errorname.startswith("SQLITE_CANTOPEN"))
 
-    @unittest.skipIf(sqlite.sqlite_version_info <= (3, 7, 16),
-                     "Requires SQLite 3.7.16 or newer")
     def test_extended_error_code_on_exception(self):
         with memory_database() as con:
             with con:
diff --git a/Lib/test/test_sqlite3/test_hooks.py b/Lib/test/test_sqlite3/test_hooks.py
index 21042b9bf106f..89230c08cc914 100644
--- a/Lib/test/test_sqlite3/test_hooks.py
+++ b/Lib/test/test_sqlite3/test_hooks.py
@@ -323,7 +323,7 @@ def test_trace_expanded_sql(self):
     )
     def test_trace_too_much_expanded_sql(self):
         # If the expanded string is too large, we'll fall back to the
-        # unexpanded SQL statement (for SQLite 3.14.0 and newer).
+        # unexpanded SQL statement.
         # The resulting string length is limited by the runtime limit
         # SQLITE_LIMIT_LENGTH.
         template = "select 1 as a where a="
@@ -334,8 +334,6 @@ def test_trace_too_much_expanded_sql(self):
 
             unexpanded_query = template + "?"
             expected = [unexpanded_query]
-            if sqlite.sqlite_version_info < (3, 14, 0):
-                expected = []
             with self.check_stmt_trace(cx, expected):
                 cx.execute(unexpanded_query, (bad_param,))
 
diff --git a/Lib/test/test_sqlite3/test_types.py b/Lib/test/test_sqlite3/test_types.py
index fde5f888e6400..66d27d21b8dc1 100644
--- a/Lib/test/test_sqlite3/test_types.py
+++ b/Lib/test/test_sqlite3/test_types.py
@@ -371,7 +371,6 @@ def test_cursor_description_insert(self):
         self.assertIsNone(self.cur.description)
 
 
- at unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "CTEs not supported")
 class CommonTableExpressionTests(unittest.TestCase):
 
     def setUp(self):
diff --git a/Lib/test/test_sqlite3/test_userfunctions.py b/Lib/test/test_sqlite3/test_userfunctions.py
index 03d27531666c8..05c2fb3aa6f8f 100644
--- a/Lib/test/test_sqlite3/test_userfunctions.py
+++ b/Lib/test/test_sqlite3/test_userfunctions.py
@@ -381,38 +381,22 @@ def append_result(arg):
     # Regarding deterministic functions:
     #
     # Between 3.8.3 and 3.15.0, deterministic functions were only used to
-    # optimize inner loops, so for those versions we can only test if the
-    # sqlite machinery has factored out a call or not. From 3.15.0 and onward,
-    # deterministic functions were permitted in WHERE clauses of partial
-    # indices, which allows testing based on syntax, iso. the query optimizer.
-    @unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "Requires SQLite 3.8.3 or higher")
+    # optimize inner loops. From 3.15.0 and onward, deterministic functions
+    # were permitted in WHERE clauses of partial indices, which allows testing
+    # based on syntax, iso. the query optimizer.
     def test_func_non_deterministic(self):
         mock = Mock(return_value=None)
         self.con.create_function("nondeterministic", 0, mock, deterministic=False)
-        if sqlite.sqlite_version_info < (3, 15, 0):
-            self.con.execute("select nondeterministic() = nondeterministic()")
-            self.assertEqual(mock.call_count, 2)
-        else:
-            with self.assertRaises(sqlite.OperationalError):
-                self.con.execute("create index t on test(t) where nondeterministic() is not null")
+        with self.assertRaises(sqlite.OperationalError):
+            self.con.execute("create index t on test(t) where nondeterministic() is not null")
 
-    @unittest.skipIf(sqlite.sqlite_version_info < (3, 8, 3), "Requires SQLite 3.8.3 or higher")
     def test_func_deterministic(self):
         mock = Mock(return_value=None)
         self.con.create_function("deterministic", 0, mock, deterministic=True)
-        if sqlite.sqlite_version_info < (3, 15, 0):
-            self.con.execute("select deterministic() = deterministic()")
-            self.assertEqual(mock.call_count, 1)
-        else:
-            try:
-                self.con.execute("create index t on test(t) where deterministic() is not null")
-            except sqlite.OperationalError:
-                self.fail("Unexpected failure while creating partial index")
-
-    @unittest.skipIf(sqlite.sqlite_version_info >= (3, 8, 3), "SQLite < 3.8.3 needed")
-    def test_func_deterministic_not_supported(self):
-        with self.assertRaises(sqlite.NotSupportedError):
-            self.con.create_function("deterministic", 0, int, deterministic=True)
+        try:
+            self.con.execute("create index t on test(t) where deterministic() is not null")
+        except sqlite.OperationalError:
+            self.fail("Unexpected failure while creating partial index")
 
     def test_func_deterministic_keyword_only(self):
         with self.assertRaises(TypeError):
diff --git a/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst b/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst
new file mode 100644
index 0000000000000..5f60e65a2f6ae
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2023-06-16-23-40-49.gh-issue-105875.naj8v5.rst
@@ -0,0 +1,2 @@
+SQLite 3.15.2 or newer is required to build the :mod:`sqlite3` extension
+module. Patch by Erlend Aasland.
diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c
index 76d261baf00f3..3096fb0c2135e 100644
--- a/Modules/_sqlite/blob.c
+++ b/Modules/_sqlite/blob.c
@@ -108,14 +108,6 @@ static void
 blob_seterror(pysqlite_Blob *self, int rc)
 {
     assert(self->connection != NULL);
-#if SQLITE_VERSION_NUMBER < 3008008
-    // SQLite pre 3.8.8 does not set this blob error on the connection
-    if (rc == SQLITE_ABORT) {
-        PyErr_SetString(self->connection->OperationalError,
-                        "Cannot operate on an expired blob handle");
-        return;
-    }
-#endif
     _pysqlite_seterror(self->connection->state, self->connection->db);
 }
 
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 82d23c2c30b79..d12d65500c654 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -32,10 +32,6 @@
 
 #include <stdbool.h>
 
-#if SQLITE_VERSION_NUMBER >= 3014000
-#define HAVE_TRACE_V2
-#endif
-
 #if SQLITE_VERSION_NUMBER >= 3025000
 #define HAVE_WINDOW_FUNCTIONS
 #endif
@@ -401,11 +397,7 @@ free_callback_contexts(pysqlite_Connection *self)
 static void
 remove_callbacks(sqlite3 *db)
 {
-#ifdef HAVE_TRACE_V2
     sqlite3_trace_v2(db, SQLITE_TRACE_STMT, 0, 0);
-#else
-    sqlite3_trace(db, 0, (void*)0);
-#endif
     sqlite3_progress_handler(db, 0, 0, (void *)0);
     (void)sqlite3_set_authorizer(db, NULL, NULL);
 }
@@ -1086,18 +1078,7 @@ pysqlite_connection_create_function_impl(pysqlite_Connection *self,
     }
 
     if (deterministic) {
-#if SQLITE_VERSION_NUMBER < 3008003
-        PyErr_SetString(self->NotSupportedError,
-                        "deterministic=True requires SQLite 3.8.3 or higher");
-        return NULL;
-#else
-        if (sqlite3_libversion_number() < 3008003) {
-            PyErr_SetString(self->NotSupportedError,
-                            "deterministic=True requires SQLite 3.8.3 or higher");
-            return NULL;
-        }
         flags |= SQLITE_DETERMINISTIC;
-#endif
     }
     callback_context *ctx = create_callback_context(cls, func);
     if (ctx == NULL) {
@@ -1376,7 +1357,6 @@ progress_callback(void *ctx)
     return rc;
 }
 
-#ifdef HAVE_TRACE_V2
 /*
  * From https://sqlite.org/c3ref/trace_v2.html:
  * The integer return value from the callback is currently ignored, though this
@@ -1385,16 +1365,10 @@ progress_callback(void *ctx)
  */
 static int
 trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
-#else
-static void
-trace_callback(void *ctx, const char *sql)
-#endif
 {
-#ifdef HAVE_TRACE_V2
     if (type != SQLITE_TRACE_STMT) {
         return 0;
     }
-#endif
 
     PyGILState_STATE gilstate = PyGILState_Ensure();
 
@@ -1403,7 +1377,6 @@ trace_callback(void *ctx, const char *sql)
     assert(state != NULL);
 
     PyObject *py_statement = NULL;
-#ifdef HAVE_TRACE_V2
     const char *expanded_sql = sqlite3_expanded_sql((sqlite3_stmt *)stmt);
     if (expanded_sql == NULL) {
         sqlite3 *db = sqlite3_db_handle((sqlite3_stmt *)stmt);
@@ -1423,15 +1396,6 @@ trace_callback(void *ctx, const char *sql)
         py_statement = PyUnicode_FromString(expanded_sql);
         sqlite3_free((void *)expanded_sql);
     }
-#else
-    if (sql == NULL) {
-        PyErr_SetString(state->DataError,
-                "Expanded SQL string exceeds the maximum string length");
-        print_or_clear_traceback((callback_context *)ctx);
-        goto exit;
-    }
-    py_statement = PyUnicode_FromString(sql);
-#endif
     if (py_statement) {
         PyObject *callable = ((callback_context *)ctx)->callable;
         PyObject *ret = PyObject_CallOneArg(callable, py_statement);
@@ -1444,9 +1408,7 @@ trace_callback(void *ctx, const char *sql)
 
 exit:
     PyGILState_Release(gilstate);
-#ifdef HAVE_TRACE_V2
     return 0;
-#endif
 }
 
 /*[clinic input]
@@ -1556,11 +1518,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
          * - https://sqlite.org/c3ref/c_trace.html
          * - https://sqlite.org/c3ref/trace_v2.html
          */
-#ifdef HAVE_TRACE_V2
         sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, 0, 0);
-#else
-        sqlite3_trace(self->db, 0, (void*)0);
-#endif
         set_callback_context(&self->trace_ctx, NULL);
     }
     else {
@@ -1568,11 +1526,7 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
         if (ctx == NULL) {
             return NULL;
         }
-#ifdef HAVE_TRACE_V2
         sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, trace_callback, ctx);
-#else
-        sqlite3_trace(self->db, trace_callback, ctx);
-#endif
         set_callback_context(&self->trace_ctx, ctx);
     }
 
@@ -2000,15 +1954,6 @@ pysqlite_connection_backup_impl(pysqlite_Connection *self,
         return NULL;
     }
 
-#if SQLITE_VERSION_NUMBER < 3008008
-    /* Since 3.8.8 this is already done, per commit
-       https://www.sqlite.org/src/info/169b5505498c0a7e */
-    if (!sqlite3_get_autocommit(target->db)) {
-        PyErr_SetString(self->OperationalError, "target is in transaction");
-        return NULL;
-    }
-#endif
-
     if (progress != Py_None && !PyCallable_Check(progress)) {
         PyErr_SetString(PyExc_TypeError, "progress argument must be a callable");
         return NULL;
@@ -2371,12 +2316,8 @@ is_int_config(const int op)
     switch (op) {
         case SQLITE_DBCONFIG_ENABLE_FKEY:
         case SQLITE_DBCONFIG_ENABLE_TRIGGER:
-#if SQLITE_VERSION_NUMBER >= 3012002
         case SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER:
-#endif
-#if SQLITE_VERSION_NUMBER >= 3013000
         case SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION:
-#endif
 #if SQLITE_VERSION_NUMBER >= 3016000
         case SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE:
 #endif
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index 27bd42f4595e1..ea4d8c58b7ee0 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -29,8 +29,8 @@
 #include "row.h"
 #include "blob.h"
 
-#if SQLITE_VERSION_NUMBER < 3007015
-#error "SQLite 3.7.15 or higher required"
+#if SQLITE_VERSION_NUMBER < 3015002
+#error "SQLite 3.15.2 or higher required"
 #endif
 
 #define clinic_state() (pysqlite_get_state(module))
@@ -245,12 +245,6 @@ static PyMethodDef module_methods[] = {
 
 /* SQLite C API result codes. See also:
  * - https://www.sqlite.org/c3ref/c_abort_rollback.html
- * - https://sqlite.org/changes.html#version_3_3_8
- * - https://sqlite.org/changes.html#version_3_7_16
- * - https://sqlite.org/changes.html#version_3_7_17
- * - https://sqlite.org/changes.html#version_3_8_0
- * - https://sqlite.org/changes.html#version_3_8_3
- * - https://sqlite.org/changes.html#version_3_14
  *
  * Note: the SQLite changelogs rarely mention new result codes, so in order to
  * keep the 'error_codes' table in sync with SQLite, we must manually inspect
@@ -294,10 +288,8 @@ static const struct {
     DECLARE_ERROR_CODE(SQLITE_ROW),
     DECLARE_ERROR_CODE(SQLITE_SCHEMA),
     DECLARE_ERROR_CODE(SQLITE_TOOBIG),
-#if SQLITE_VERSION_NUMBER >= 3007017
     DECLARE_ERROR_CODE(SQLITE_NOTICE),
     DECLARE_ERROR_CODE(SQLITE_WARNING),
-#endif
     // Extended result code list
     DECLARE_ERROR_CODE(SQLITE_ABORT_ROLLBACK),
     DECLARE_ERROR_CODE(SQLITE_BUSY_RECOVERY),
@@ -331,7 +323,6 @@ static const struct {
     DECLARE_ERROR_CODE(SQLITE_LOCKED_SHAREDCACHE),
     DECLARE_ERROR_CODE(SQLITE_READONLY_CANTLOCK),
     DECLARE_ERROR_CODE(SQLITE_READONLY_RECOVERY),
-#if SQLITE_VERSION_NUMBER >= 3007016
     DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_CHECK),
     DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_COMMITHOOK),
     DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_FOREIGNKEY),
@@ -342,39 +333,20 @@ static const struct {
     DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_UNIQUE),
     DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_VTAB),
     DECLARE_ERROR_CODE(SQLITE_READONLY_ROLLBACK),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3007017
     DECLARE_ERROR_CODE(SQLITE_IOERR_MMAP),
     DECLARE_ERROR_CODE(SQLITE_NOTICE_RECOVER_ROLLBACK),
     DECLARE_ERROR_CODE(SQLITE_NOTICE_RECOVER_WAL),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008000
     DECLARE_ERROR_CODE(SQLITE_BUSY_SNAPSHOT),
     DECLARE_ERROR_CODE(SQLITE_IOERR_GETTEMPPATH),
     DECLARE_ERROR_CODE(SQLITE_WARNING_AUTOINDEX),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008001
     DECLARE_ERROR_CODE(SQLITE_CANTOPEN_CONVPATH),
     DECLARE_ERROR_CODE(SQLITE_IOERR_CONVPATH),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008002
     DECLARE_ERROR_CODE(SQLITE_CONSTRAINT_ROWID),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008003
     DECLARE_ERROR_CODE(SQLITE_READONLY_DBMOVED),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3008007
     DECLARE_ERROR_CODE(SQLITE_AUTH_USER),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3009000
     DECLARE_ERROR_CODE(SQLITE_IOERR_VNODE),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3010000
     DECLARE_ERROR_CODE(SQLITE_IOERR_AUTH),
-#endif
-#if SQLITE_VERSION_NUMBER >= 3014001
     DECLARE_ERROR_CODE(SQLITE_OK_LOAD_PERMANENTLY),
-#endif
 #if SQLITE_VERSION_NUMBER >= 3021000
     DECLARE_ERROR_CODE(SQLITE_IOERR_BEGIN_ATOMIC),
     DECLARE_ERROR_CODE(SQLITE_IOERR_COMMIT_ATOMIC),
@@ -481,9 +453,7 @@ add_integer_constants(PyObject *module) {
     ADD_INT(SQLITE_DROP_VTABLE);
     ADD_INT(SQLITE_FUNCTION);
     ADD_INT(SQLITE_SAVEPOINT);
-#if SQLITE_VERSION_NUMBER >= 3008003
     ADD_INT(SQLITE_RECURSIVE);
-#endif
     // Run-time limit categories
     ADD_INT(SQLITE_LIMIT_LENGTH);
     ADD_INT(SQLITE_LIMIT_SQL_LENGTH);
@@ -496,9 +466,7 @@ add_integer_constants(PyObject *module) {
     ADD_INT(SQLITE_LIMIT_LIKE_PATTERN_LENGTH);
     ADD_INT(SQLITE_LIMIT_VARIABLE_NUMBER);
     ADD_INT(SQLITE_LIMIT_TRIGGER_DEPTH);
-#if SQLITE_VERSION_NUMBER >= 3008007
     ADD_INT(SQLITE_LIMIT_WORKER_THREADS);
-#endif
 
     /*
      * Database connection configuration options.
@@ -506,12 +474,8 @@ add_integer_constants(PyObject *module) {
      */
     ADD_INT(SQLITE_DBCONFIG_ENABLE_FKEY);
     ADD_INT(SQLITE_DBCONFIG_ENABLE_TRIGGER);
-#if SQLITE_VERSION_NUMBER >= 3012002
     ADD_INT(SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER);
-#endif
-#if SQLITE_VERSION_NUMBER >= 3013000
     ADD_INT(SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION);
-#endif
 #if SQLITE_VERSION_NUMBER >= 3016000
     ADD_INT(SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE);
 #endif
@@ -678,8 +642,8 @@ do {                                                     \
 static int
 module_exec(PyObject *module)
 {
-    if (sqlite3_libversion_number() < 3007015) {
-        PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.7.15 or higher required");
+    if (sqlite3_libversion_number() < 3015002) {
+        PyErr_SetString(PyExc_ImportError, MODULE_NAME ": SQLite 3.15.2 or higher required");
         return -1;
     }
 
diff --git a/configure b/configure
index 7f17fe42120a2..fdc7c22531785 100755
--- a/configure
+++ b/configure
@@ -14552,12 +14552,12 @@ if test -n "$LIBSQLITE3_CFLAGS"; then
     pkg_cv_LIBSQLITE3_CFLAGS="$LIBSQLITE3_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.15\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.15") 2>&5
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.15.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.15.2") 2>&5
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIBSQLITE3_CFLAGS=`$PKG_CONFIG --cflags "sqlite3 >= 3.7.15" 2>/dev/null`
+  pkg_cv_LIBSQLITE3_CFLAGS=`$PKG_CONFIG --cflags "sqlite3 >= 3.15.2" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -14569,12 +14569,12 @@ if test -n "$LIBSQLITE3_LIBS"; then
     pkg_cv_LIBSQLITE3_LIBS="$LIBSQLITE3_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.7.15\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.7.15") 2>&5
+    { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3 >= 3.15.2\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "sqlite3 >= 3.15.2") 2>&5
   ac_status=$?
   printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_LIBSQLITE3_LIBS=`$PKG_CONFIG --libs "sqlite3 >= 3.7.15" 2>/dev/null`
+  pkg_cv_LIBSQLITE3_LIBS=`$PKG_CONFIG --libs "sqlite3 >= 3.15.2" 2>/dev/null`
 		      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -14595,9 +14595,9 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-	        LIBSQLITE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3 >= 3.7.15" 2>&1`
+	        LIBSQLITE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3 >= 3.15.2" 2>&1`
         else
-	        LIBSQLITE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3 >= 3.7.15" 2>&1`
+	        LIBSQLITE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3 >= 3.15.2" 2>&1`
         fi
 	# Put the nasty error message in config.log where it belongs
 	echo "$LIBSQLITE3_PKG_ERRORS" >&5
@@ -14646,8 +14646,8 @@ then :
 
 
         #include <sqlite3.h>
-        #if SQLITE_VERSION_NUMBER < 3007015
-        #  error "SQLite 3.7.15 or higher required"
+        #if SQLITE_VERSION_NUMBER < 3015002
+        #  error "SQLite 3.15.2 or higher required"
         #endif
 
 int
diff --git a/configure.ac b/configure.ac
index ce4e4d4b061f0..a24cd689730d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3952,7 +3952,7 @@ PY_CHECK_EMSCRIPTEN_PORT([LIBSQLITE3], [-sUSE_SQLITE3])
 
 dnl Check for SQLite library. Use pkg-config if available.
 PKG_CHECK_MODULES(
-  [LIBSQLITE3], [sqlite3 >= 3.7.15], [], [
+  [LIBSQLITE3], [sqlite3 >= 3.15.2], [], [
     LIBSQLITE3_CFLAGS=${LIBSQLITE3_CFLAGS-""}
     LIBSQLITE3_LIBS=${LIBSQLITE3_LIBS-"-lsqlite3"}
   ]
@@ -3978,8 +3978,8 @@ dnl hence CPPFLAGS instead of CFLAGS.
     AC_COMPILE_IFELSE([
       AC_LANG_PROGRAM([
         #include <sqlite3.h>
-        #if SQLITE_VERSION_NUMBER < 3007015
-        #  error "SQLite 3.7.15 or higher required"
+        #if SQLITE_VERSION_NUMBER < 3015002
+        #  error "SQLite 3.15.2 or higher required"
         #endif
       ], [])
     ], [



More information about the Python-checkins mailing list