diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 67ea2b1d776638..c318cd4827596f 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -6,6 +6,10 @@ .. sectionauthor:: Gerhard Häring +.. note:: + + This module requires SQLite 3.7.3+. + **Source code:** :source:`Lib/sqlite3/` -------------- @@ -590,8 +594,6 @@ Connection Objects dest = sqlite3.connect(':memory:') source.backup(dest) - Availability: SQLite 3.6.11 or higher - .. versionadded:: 3.7 @@ -700,9 +702,6 @@ Cursor Objects statements because we cannot determine the number of rows a query produced until all rows were fetched. - With SQLite versions before 3.6.5, :attr:`rowcount` is set to 0 if - you make a ``DELETE FROM table`` without any condition. - .. attribute:: lastrowid This read-only attribute provides the rowid of the last modified row. It is diff --git a/Lib/sqlite3/test/backup.py b/Lib/sqlite3/test/backup.py index 903bacf490301c..2752a4db337ddd 100644 --- a/Lib/sqlite3/test/backup.py +++ b/Lib/sqlite3/test/backup.py @@ -2,7 +2,6 @@ import unittest -@unittest.skipIf(sqlite.sqlite_version_info < (3, 6, 11), "Backup API not supported") class BackupTests(unittest.TestCase): def setUp(self): cx = self.cx = sqlite.connect(":memory:") diff --git a/Lib/sqlite3/test/dbapi.py b/Lib/sqlite3/test/dbapi.py index be11337154bdd2..73f7ccf33a32b6 100644 --- a/Lib/sqlite3/test/dbapi.py +++ b/Lib/sqlite3/test/dbapi.py @@ -185,12 +185,6 @@ def CheckOpenUri(self): with self.assertRaises(sqlite.OperationalError): cx.execute('insert into test(id) values(1)') - @unittest.skipIf(sqlite.sqlite_version_info >= (3, 3, 1), - 'needs sqlite versions older than 3.3.1') - def CheckSameThreadErrorOnOldVersion(self): - with self.assertRaises(sqlite.NotSupportedError) as cm: - sqlite.connect(':memory:', check_same_thread=False) - self.assertEqual(str(cm.exception), 'shared connections not available') class CursorTests(unittest.TestCase): def setUp(self): diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py index d74e74bf272275..c8a9e5ee8f9c5d 100644 --- a/Lib/sqlite3/test/hooks.py +++ b/Lib/sqlite3/test/hooks.py @@ -60,8 +60,6 @@ def upper(self): self.assertEqual(result[0][0], 'b') self.assertEqual(result[1][0], 'a') - @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 1), - 'old SQLite versions crash on this test') def CheckCollationIsUsed(self): def mycoll(x, y): # reverse order @@ -239,16 +237,12 @@ def trace(statement): traced_statements.append(statement) con.set_trace_callback(trace) con.execute("create table foo(x)") - # Can't execute bound parameters as their values don't appear - # in traced statements before SQLite 3.6.21 - # (cf. http://www.sqlite.org/draft/releaselog/3_6_21.html) - con.execute('insert into foo(x) values ("%s")' % unicode_value) + con.execute("insert into foo(x) values (?)", (unicode_value,)) con.commit() self.assertTrue(any(unicode_value in stmt for stmt in traced_statements), "Unicode data %s garbled in trace callback: %s" % (ascii(unicode_value), ', '.join(map(ascii, traced_statements)))) - @unittest.skipIf(sqlite.sqlite_version_info < (3, 3, 9), "sqlite3_prepare_v2 is not available") def CheckTraceCallbackContent(self): # set_trace_callback() shouldn't produce duplicate content (bpo-26187) traced_statements = [] diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py index c714116ac49208..79d23017b6bee8 100644 --- a/Lib/sqlite3/test/regression.py +++ b/Lib/sqlite3/test/regression.py @@ -87,7 +87,6 @@ def CheckStatementFinalizationOnCloseDb(self): cur.execute("select 1 x union select " + str(i)) con.close() - @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2), 'needs sqlite 3.2.2 or newer') def CheckOnConflictRollback(self): con = sqlite.connect(":memory:") con.execute("create table foo(x, unique(x) on conflict rollback)") diff --git a/Lib/sqlite3/test/transactions.py b/Lib/sqlite3/test/transactions.py index b8a13de55bc720..c463f7490da573 100644 --- a/Lib/sqlite3/test/transactions.py +++ b/Lib/sqlite3/test/transactions.py @@ -111,16 +111,12 @@ def CheckToggleAutoCommit(self): res = self.cur2.fetchall() self.assertEqual(len(res), 1) - @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2), - 'test hangs on sqlite versions older than 3.2.2') def CheckRaiseTimeout(self): self.cur1.execute("create table test(i)") self.cur1.execute("insert into test(i) values (5)") with self.assertRaises(sqlite.OperationalError): self.cur2.execute("insert into test(i) values (5)") - @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2), - 'test hangs on sqlite versions older than 3.2.2') def CheckLocking(self): """ This tests the improved concurrency with pysqlite 2.3.4. You needed diff --git a/Lib/sqlite3/test/types.py b/Lib/sqlite3/test/types.py index 19ecd07500fec5..483e9f909eaf4f 100644 --- a/Lib/sqlite3/test/types.py +++ b/Lib/sqlite3/test/types.py @@ -401,8 +401,6 @@ def CheckSqliteTimestamp(self): ts2 = self.cur.fetchone()[0] self.assertEqual(ts, ts2) - @unittest.skipIf(sqlite.sqlite_version_info < (3, 1), - 'the date functions are available on 3.1 or later') def CheckSqlTimestamp(self): now = datetime.datetime.utcnow() self.cur.execute("insert into test(ts) values (current_timestamp)") diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 64051669185ba6..e3127bb7879ca8 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -35,15 +35,9 @@ #define ACTION_FINALIZE 1 #define ACTION_RESET 2 -#if SQLITE_VERSION_NUMBER >= 3003008 #ifndef SQLITE_OMIT_LOAD_EXTENSION #define HAVE_LOAD_EXTENSION #endif -#endif - -#if SQLITE_VERSION_NUMBER >= 3006011 -#define HAVE_BACKUP_API -#endif _Py_IDENTIFIER(cursor); @@ -59,18 +53,6 @@ static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, Py static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self); -static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int len) -{ - /* in older SQLite versions, calling sqlite3_result_error in callbacks - * triggers a bug in SQLite that leads either to irritating results or - * segfaults, depending on the SQLite version */ -#if SQLITE_VERSION_NUMBER >= 3003003 - sqlite3_result_error(ctx, errmsg, len); -#else - PyErr_SetString(pysqlite_OperationalError, errmsg); -#endif -} - int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) { static char *kwlist[] = { @@ -180,10 +162,6 @@ int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject self->timeout = timeout; (void)sqlite3_busy_timeout(self->db, (int)(timeout*1000)); self->thread_ident = PyThread_get_thread_ident(); - if (!check_same_thread && sqlite3_libversion_number() < 3003001) { - PyErr_SetString(pysqlite_NotSupportedError, "shared connections not available"); - return -1; - } self->check_same_thread = check_same_thread; self->function_pinboard_trace_callback = NULL; @@ -618,7 +596,7 @@ void _pysqlite_func_callback(sqlite3_context* context, int argc, sqlite3_value** } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined function raised exception", -1); + sqlite3_result_error(context, "user-defined function raised exception", -1); } PyGILState_Release(threadstate); @@ -650,7 +628,7 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); + sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); goto error; } } @@ -674,7 +652,7 @@ static void _pysqlite_step_callback(sqlite3_context *context, int argc, sqlite3_ } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); + sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); } error: @@ -724,12 +702,7 @@ void _pysqlite_final_callback(sqlite3_context* context) } else { PyErr_Clear(); } - _sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); -#if SQLITE_VERSION_NUMBER < 3003003 - /* with old SQLite versions, _sqlite3_result_error() sets a new Python - exception, so don't restore the previous exception */ - restore = 0; -#endif + sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); } if (restore) { @@ -1479,7 +1452,6 @@ pysqlite_connection_iterdump(pysqlite_Connection* self, PyObject* args) return retval; } -#ifdef HAVE_BACKUP_API static PyObject * pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *kwds) { @@ -1630,7 +1602,6 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject * return NULL; } } -#endif static PyObject * pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args) @@ -1804,10 +1775,8 @@ static PyMethodDef connection_methods[] = { PyDoc_STR("Abort any pending database operation. Non-standard.")}, {"iterdump", (PyCFunction)pysqlite_connection_iterdump, METH_NOARGS, PyDoc_STR("Returns iterator to the dump of the database in an SQL text format. Non-standard.")}, - #ifdef HAVE_BACKUP_API {"backup", (PyCFunction)(void(*)(void))pysqlite_connection_backup, METH_VARARGS | METH_KEYWORDS, PyDoc_STR("Makes a backup of the database. Non-standard.")}, - #endif {"__enter__", (PyCFunction)pysqlite_connection_enter, METH_NOARGS, PyDoc_STR("For context manager. Non-standard.")}, {"__exit__", (PyCFunction)pysqlite_connection_exit, METH_VARARGS, diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c index d5c353ea7bee83..277965246145c0 100644 --- a/Modules/_sqlite/module.c +++ b/Modules/_sqlite/module.c @@ -29,10 +29,6 @@ #include "microprotocols.h" #include "row.h" -#if SQLITE_VERSION_NUMBER >= 3003003 -#define HAVE_SHARED_CACHE -#endif - /* static objects at module-level */ PyObject *pysqlite_Error = NULL; @@ -131,7 +127,6 @@ PyDoc_STRVAR(module_complete_doc, \n\ Checks if a string contains a complete SQL statement. Non-standard."); -#ifdef HAVE_SHARED_CACHE static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* kwargs) { @@ -159,7 +154,6 @@ PyDoc_STRVAR(module_enable_shared_cache_doc, \n\ Enable or disable shared cache mode for the calling thread.\n\ Experimental/Non-standard."); -#endif /* HAVE_SHARED_CACHE */ static PyObject* module_register_adapter(PyObject* self, PyObject* args) { @@ -253,10 +247,8 @@ static PyMethodDef module_methods[] = { METH_VARARGS | METH_KEYWORDS, module_connect_doc}, {"complete_statement", (PyCFunction)(void(*)(void))module_complete, METH_VARARGS | METH_KEYWORDS, module_complete_doc}, -#ifdef HAVE_SHARED_CACHE {"enable_shared_cache", (PyCFunction)(void(*)(void))module_enable_shared_cache, METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, -#endif {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, module_register_adapter_doc}, {"register_converter", (PyCFunction)module_register_converter, @@ -307,29 +299,17 @@ static const IntConstantPair _int_constants[] = { {"SQLITE_UPDATE", SQLITE_UPDATE}, {"SQLITE_ATTACH", SQLITE_ATTACH}, {"SQLITE_DETACH", SQLITE_DETACH}, -#if SQLITE_VERSION_NUMBER >= 3002001 {"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE}, {"SQLITE_REINDEX", SQLITE_REINDEX}, -#endif -#if SQLITE_VERSION_NUMBER >= 3003000 {"SQLITE_ANALYZE", SQLITE_ANALYZE}, -#endif -#if SQLITE_VERSION_NUMBER >= 3003007 {"SQLITE_CREATE_VTABLE", SQLITE_CREATE_VTABLE}, {"SQLITE_DROP_VTABLE", SQLITE_DROP_VTABLE}, -#endif -#if SQLITE_VERSION_NUMBER >= 3003008 {"SQLITE_FUNCTION", SQLITE_FUNCTION}, -#endif -#if SQLITE_VERSION_NUMBER >= 3006008 {"SQLITE_SAVEPOINT", SQLITE_SAVEPOINT}, -#endif #if SQLITE_VERSION_NUMBER >= 3008003 {"SQLITE_RECURSIVE", SQLITE_RECURSIVE}, #endif -#if SQLITE_VERSION_NUMBER >= 3006011 {"SQLITE_DONE", SQLITE_DONE}, -#endif {(char*)NULL, 0} }; diff --git a/setup.py b/setup.py index 02f523c42d355f..bc8449c6d2bef5 100644 --- a/setup.py +++ b/setup.py @@ -1348,7 +1348,6 @@ def detect_sqlite(self): sqlite_setup_debug = False # verbose debug prints from this script? # We hunt for #define SQLITE_VERSION "n.n.n" - # We need to find >= sqlite version 3.3.9, for sqlite3_prepare_v2 sqlite_incdir = sqlite_libdir = None sqlite_inc_paths = [ '/usr/include', '/usr/include/sqlite', @@ -1359,7 +1358,8 @@ def detect_sqlite(self): ] if CROSS_COMPILING: sqlite_inc_paths = [] - MIN_SQLITE_VERSION_NUMBER = (3, 7, 2) + # We need to find >= sqlite version 3.7.3, for sqlite3_create_function_v2() + MIN_SQLITE_VERSION_NUMBER = (3, 7, 3) MIN_SQLITE_VERSION = ".".join([str(x) for x in MIN_SQLITE_VERSION_NUMBER])