blob: a8dcd7e8bfeddbc0a1cdfbe676bf2bad8793920c [file] [log] [blame]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001# pysqlite2/test/dbapi.py: tests for DB-API compliance
2#
Erlend Egeberg Aaslanddeab1e52021-01-07 01:36:35 +01003# Copyright (C) 2004-2010 Gerhard Häring <gh@ghaering.de>
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00004#
5# This file is part of pysqlite.
6#
7# This software is provided 'as-is', without any express or implied
8# warranty. In no event will the authors be held liable for any damages
9# arising from the use of this software.
10#
11# Permission is granted to anyone to use this software for any purpose,
12# including commercial applications, and to alter it and redistribute it
13# freely, subject to the following restrictions:
14#
15# 1. The origin of this software must not be misrepresented; you must not
16# claim that you wrote the original software. If you use this software
17# in a product, an acknowledgment in the product documentation would be
18# appreciated but is not required.
19# 2. Altered source versions must be plainly marked as such, and must not be
20# misrepresented as being the original software.
21# 3. This notice may not be removed or altered from any source distribution.
22
Erlend Egeberg Aasland2a808932021-08-28 20:26:00 +020023import subprocess
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020024import threading
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000025import unittest
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000026import sqlite3 as sqlite
Erlend Egeberg Aaslandd16f6172021-01-09 12:25:55 +010027import sys
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000028
Erlend Egeberg Aasland2a808932021-08-28 20:26:00 +020029from test.support import check_disallow_instantiation, SHORT_TIMEOUT
Hai Shifcce8c62020-08-08 05:55:35 +080030from test.support.os_helper import TESTFN, unlink
Antoine Pitrou902fc8b2013-02-10 00:02:44 +010031
32
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000033class ModuleTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010034 def test_api_level(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000035 self.assertEqual(sqlite.apilevel, "2.0",
36 "apilevel is %s, should be 2.0" % sqlite.apilevel)
37
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010038 def test_thread_safety(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000039 self.assertEqual(sqlite.threadsafety, 1,
40 "threadsafety is %d, should be 1" % sqlite.threadsafety)
41
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010042 def test_param_style(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000043 self.assertEqual(sqlite.paramstyle, "qmark",
44 "paramstyle is '%s', should be 'qmark'" %
45 sqlite.paramstyle)
46
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010047 def test_warning(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +000048 self.assertTrue(issubclass(sqlite.Warning, Exception),
Guido van Rossumcd16bf62007-06-13 18:07:49 +000049 "Warning is not a subclass of Exception")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000050
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010051 def test_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000052 self.assertTrue(issubclass(sqlite.Error, Exception),
Guido van Rossumcd16bf62007-06-13 18:07:49 +000053 "Error is not a subclass of Exception")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000054
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010055 def test_interface_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000056 self.assertTrue(issubclass(sqlite.InterfaceError, sqlite.Error),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000057 "InterfaceError is not a subclass of Error")
58
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010059 def test_database_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000060 self.assertTrue(issubclass(sqlite.DatabaseError, sqlite.Error),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000061 "DatabaseError is not a subclass of Error")
62
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010063 def test_data_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000064 self.assertTrue(issubclass(sqlite.DataError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000065 "DataError is not a subclass of DatabaseError")
66
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010067 def test_operational_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000068 self.assertTrue(issubclass(sqlite.OperationalError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000069 "OperationalError is not a subclass of DatabaseError")
70
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010071 def test_integrity_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000072 self.assertTrue(issubclass(sqlite.IntegrityError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000073 "IntegrityError is not a subclass of DatabaseError")
74
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010075 def test_internal_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000076 self.assertTrue(issubclass(sqlite.InternalError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000077 "InternalError is not a subclass of DatabaseError")
78
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010079 def test_programming_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000080 self.assertTrue(issubclass(sqlite.ProgrammingError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000081 "ProgrammingError is not a subclass of DatabaseError")
82
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010083 def test_not_supported_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000084 self.assertTrue(issubclass(sqlite.NotSupportedError,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000085 sqlite.DatabaseError),
86 "NotSupportedError is not a subclass of DatabaseError")
87
Erlend Egeberg Aaslandd16f6172021-01-09 12:25:55 +010088 # sqlite3_enable_shared_cache() is deprecated on macOS and calling it may raise
89 # OperationalError on some buildbots.
90 @unittest.skipIf(sys.platform == "darwin", "shared cache is deprecated on macOS")
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010091 def test_shared_cache_deprecated(self):
Erlend Egeberg Aaslandddb5e112021-01-06 01:36:04 +010092 for enable in (True, False):
93 with self.assertWarns(DeprecationWarning) as cm:
94 sqlite.enable_shared_cache(enable)
95 self.assertIn("dbapi.py", cm.filename)
96
Erlend Egeberg Aaslandccc95c72021-06-20 23:07:31 +020097 def test_disallow_instantiation(self):
98 cx = sqlite.connect(":memory:")
Erlend Egeberg Aasland0a3452e2021-06-24 01:46:25 +020099 check_disallow_instantiation(self, type(cx("select 1")))
Erlend Egeberg Aaslandccc95c72021-06-20 23:07:31 +0200100
Erlend Egeberg Aaslandddb5e112021-01-06 01:36:04 +0100101
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102class ConnectionTests(unittest.TestCase):
R. David Murrayd35251d2010-06-01 01:32:12 +0000103
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000104 def setUp(self):
105 self.cx = sqlite.connect(":memory:")
106 cu = self.cx.cursor()
107 cu.execute("create table test(id integer primary key, name text)")
108 cu.execute("insert into test(name) values (?)", ("foo",))
109
110 def tearDown(self):
111 self.cx.close()
112
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100113 def test_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000114 self.cx.commit()
115
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100116 def test_commit_after_no_changes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000117 """
118 A commit should also work when no changes were made to the database.
119 """
120 self.cx.commit()
121 self.cx.commit()
122
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100123 def test_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000124 self.cx.rollback()
125
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100126 def test_rollback_after_no_changes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000127 """
128 A rollback should also work when no changes were made to the database.
129 """
130 self.cx.rollback()
131 self.cx.rollback()
132
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100133 def test_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000134 cu = self.cx.cursor()
135
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100136 def test_failed_open(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000137 YOU_CANNOT_OPEN_THIS = "/foo/bar/bla/23534/mydb.db"
Berker Peksag1003b342016-06-12 22:34:49 +0300138 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000139 con = sqlite.connect(YOU_CANNOT_OPEN_THIS)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000140
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100141 def test_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000142 self.cx.close()
143
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100144 def test_exceptions(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000145 # Optional DB-API extension.
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000146 self.assertEqual(self.cx.Warning, sqlite.Warning)
147 self.assertEqual(self.cx.Error, sqlite.Error)
148 self.assertEqual(self.cx.InterfaceError, sqlite.InterfaceError)
149 self.assertEqual(self.cx.DatabaseError, sqlite.DatabaseError)
150 self.assertEqual(self.cx.DataError, sqlite.DataError)
151 self.assertEqual(self.cx.OperationalError, sqlite.OperationalError)
152 self.assertEqual(self.cx.IntegrityError, sqlite.IntegrityError)
153 self.assertEqual(self.cx.InternalError, sqlite.InternalError)
154 self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError)
155 self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100157 def test_in_transaction(self):
R. David Murrayd35251d2010-06-01 01:32:12 +0000158 # Can't use db from setUp because we want to test initial state.
159 cx = sqlite.connect(":memory:")
160 cu = cx.cursor()
161 self.assertEqual(cx.in_transaction, False)
162 cu.execute("create table transactiontest(id integer primary key, name text)")
163 self.assertEqual(cx.in_transaction, False)
164 cu.execute("insert into transactiontest(name) values (?)", ("foo",))
165 self.assertEqual(cx.in_transaction, True)
166 cu.execute("select name from transactiontest where name=?", ["foo"])
167 row = cu.fetchone()
168 self.assertEqual(cx.in_transaction, True)
169 cx.commit()
170 self.assertEqual(cx.in_transaction, False)
171 cu.execute("select name from transactiontest where name=?", ["foo"])
172 row = cu.fetchone()
173 self.assertEqual(cx.in_transaction, False)
174
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100175 def test_in_transaction_ro(self):
R. David Murrayd35251d2010-06-01 01:32:12 +0000176 with self.assertRaises(AttributeError):
177 self.cx.in_transaction = True
178
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100179 def test_open_with_path_like_object(self):
Ville Skyttä61f82e02018-04-20 23:08:45 +0300180 """ Checks that we can successfully connect to a database using an object that
Anders Lorentsena22a1272017-11-07 01:47:43 +0100181 is PathLike, i.e. has __fspath__(). """
182 self.addCleanup(unlink, TESTFN)
183 class Path:
184 def __fspath__(self):
185 return TESTFN
186 path = Path()
187 with sqlite.connect(path) as cx:
188 cx.execute('create table test(id integer)')
189
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100190 def test_open_uri(self):
Antoine Pitrou902fc8b2013-02-10 00:02:44 +0100191 self.addCleanup(unlink, TESTFN)
192 with sqlite.connect(TESTFN) as cx:
193 cx.execute('create table test(id integer)')
194 with sqlite.connect('file:' + TESTFN, uri=True) as cx:
195 cx.execute('insert into test(id) values(0)')
196 with sqlite.connect('file:' + TESTFN + '?mode=ro', uri=True) as cx:
197 with self.assertRaises(sqlite.OperationalError):
198 cx.execute('insert into test(id) values(1)')
199
200
Erlend Egeberg Aasland0cb470e2021-07-30 14:01:22 +0200201class UninitialisedConnectionTests(unittest.TestCase):
202 def setUp(self):
203 self.cx = sqlite.Connection.__new__(sqlite.Connection)
204
205 def test_uninit_operations(self):
206 funcs = (
207 lambda: self.cx.isolation_level,
208 lambda: self.cx.total_changes,
209 lambda: self.cx.in_transaction,
210 lambda: self.cx.iterdump(),
211 lambda: self.cx.cursor(),
212 lambda: self.cx.close(),
213 )
214 for func in funcs:
215 with self.subTest(func=func):
216 self.assertRaisesRegex(sqlite.ProgrammingError,
217 "Base Connection.__init__ not called",
218 func)
219
220
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000221class CursorTests(unittest.TestCase):
222 def setUp(self):
223 self.cx = sqlite.connect(":memory:")
224 self.cu = self.cx.cursor()
Berker Peksage0b70cd2016-06-14 15:25:36 +0300225 self.cu.execute(
226 "create table test(id integer primary key, name text, "
227 "income number, unique_test text unique)"
228 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000229 self.cu.execute("insert into test(name) values (?)", ("foo",))
230
231 def tearDown(self):
232 self.cu.close()
233 self.cx.close()
234
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100235 def test_execute_no_args(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000236 self.cu.execute("delete from test")
237
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100238 def test_execute_illegal_sql(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300239 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000240 self.cu.execute("select asdf")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000241
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100242 def test_execute_too_much_sql(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300243 with self.assertRaises(sqlite.Warning):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000244 self.cu.execute("select 5+4; select 4+5")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000245
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100246 def test_execute_too_much_sql2(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000247 self.cu.execute("select 5+4; -- foo bar")
248
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100249 def test_execute_too_much_sql3(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000250 self.cu.execute("""
251 select 5+4;
252
253 /*
254 foo
255 */
256 """)
257
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100258 def test_execute_wrong_sql_arg(self):
Victor Stinnerc6a23202019-06-26 03:16:24 +0200259 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000260 self.cu.execute(42)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000261
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100262 def test_execute_arg_int(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000263 self.cu.execute("insert into test(id) values (?)", (42,))
264
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100265 def test_execute_arg_float(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000266 self.cu.execute("insert into test(income) values (?)", (2500.32,))
267
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100268 def test_execute_arg_string(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000269 self.cu.execute("insert into test(name) values (?)", ("Hugo",))
270
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100271 def test_execute_arg_string_with_zero_byte(self):
Petri Lehtinen023fe332012-02-01 22:18:19 +0200272 self.cu.execute("insert into test(name) values (?)", ("Hu\x00go",))
273
274 self.cu.execute("select name from test where id=?", (self.cu.lastrowid,))
275 row = self.cu.fetchone()
276 self.assertEqual(row[0], "Hu\x00go")
277
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100278 def test_execute_non_iterable(self):
Berker Peksagc4154402016-06-12 13:41:47 +0300279 with self.assertRaises(ValueError) as cm:
280 self.cu.execute("insert into test(id) values (?)", 42)
281 self.assertEqual(str(cm.exception), 'parameters are of unsupported type')
282
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100283 def test_execute_wrong_no_of_args1(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000284 # too many parameters
Berker Peksag1003b342016-06-12 22:34:49 +0300285 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000286 self.cu.execute("insert into test(id) values (?)", (17, "Egon"))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000287
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100288 def test_execute_wrong_no_of_args2(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000289 # too little parameters
Berker Peksag1003b342016-06-12 22:34:49 +0300290 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000291 self.cu.execute("insert into test(id) values (?)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000292
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100293 def test_execute_wrong_no_of_args3(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000294 # no parameters, parameters are needed
Berker Peksag1003b342016-06-12 22:34:49 +0300295 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000296 self.cu.execute("insert into test(id) values (?)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000297
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100298 def test_execute_param_list(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000299 self.cu.execute("insert into test(name) values ('foo')")
300 self.cu.execute("select name from test where name=?", ["foo"])
301 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000302 self.assertEqual(row[0], "foo")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000303
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100304 def test_execute_param_sequence(self):
Serhiy Storchaka0b419b72020-09-17 10:35:44 +0300305 class L:
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000306 def __len__(self):
307 return 1
308 def __getitem__(self, x):
309 assert x == 0
310 return "foo"
311
312 self.cu.execute("insert into test(name) values ('foo')")
313 self.cu.execute("select name from test where name=?", L())
314 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000315 self.assertEqual(row[0], "foo")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000316
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100317 def test_execute_param_sequence_bad_len(self):
Serhiy Storchaka0b419b72020-09-17 10:35:44 +0300318 # Issue41662: Error in __len__() was overridden with ProgrammingError.
319 class L:
320 def __len__(self):
321 1/0
322 def __getitem__(slf, x):
323 raise AssertionError
324
325 self.cu.execute("insert into test(name) values ('foo')")
326 with self.assertRaises(ZeroDivisionError):
327 self.cu.execute("select name from test where name=?", L())
328
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100329 def test_execute_dict_mapping(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000330 self.cu.execute("insert into test(name) values ('foo')")
331 self.cu.execute("select name from test where name=:name", {"name": "foo"})
332 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000333 self.assertEqual(row[0], "foo")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000334
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100335 def test_execute_dict_mapping_mapping(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000336 class D(dict):
337 def __missing__(self, key):
338 return "foo"
339
340 self.cu.execute("insert into test(name) values ('foo')")
341 self.cu.execute("select name from test where name=:name", D())
342 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000343 self.assertEqual(row[0], "foo")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000344
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100345 def test_execute_dict_mapping_too_little_args(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000346 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag1003b342016-06-12 22:34:49 +0300347 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000348 self.cu.execute("select name from test where name=:name and id=:id", {"name": "foo"})
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000349
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100350 def test_execute_dict_mapping_no_args(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000351 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag1003b342016-06-12 22:34:49 +0300352 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000353 self.cu.execute("select name from test where name=:name")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000354
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100355 def test_execute_dict_mapping_unnamed(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000356 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag1003b342016-06-12 22:34:49 +0300357 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000358 self.cu.execute("select name from test where name=?", {"name": "foo"})
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000359
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100360 def test_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000361 self.cu.close()
362
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100363 def test_rowcount_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000364 self.cu.execute("delete from test")
365 self.cu.execute("insert into test(name) values ('foo')")
366 self.cu.execute("insert into test(name) values ('foo')")
367 self.cu.execute("update test set name='bar'")
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000368 self.assertEqual(self.cu.rowcount, 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000369
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100370 def test_rowcount_select(self):
Georg Brandlf78e02b2008-06-10 17:40:04 +0000371 """
372 pysqlite does not know the rowcount of SELECT statements, because we
373 don't fetch all rows after executing the select statement. The rowcount
374 has thus to be -1.
375 """
376 self.cu.execute("select 5 union select 6")
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000377 self.assertEqual(self.cu.rowcount, -1)
Georg Brandlf78e02b2008-06-10 17:40:04 +0000378
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100379 def test_rowcount_executemany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000380 self.cu.execute("delete from test")
381 self.cu.executemany("insert into test(name) values (?)", [(1,), (2,), (3,)])
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000382 self.assertEqual(self.cu.rowcount, 3)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000383
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100384 def test_total_changes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000385 self.cu.execute("insert into test(name) values ('foo')")
386 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag48b5c982016-06-14 00:42:50 +0300387 self.assertLess(2, self.cx.total_changes, msg='total changes reported wrong value')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000388
389 # Checks for executemany:
390 # Sequences are required by the DB-API, iterators
391 # enhancements in pysqlite.
392
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100393 def test_execute_many_sequence(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000394 self.cu.executemany("insert into test(income) values (?)", [(x,) for x in range(100, 110)])
395
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100396 def test_execute_many_iterator(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000397 class MyIter:
398 def __init__(self):
399 self.value = 5
400
Miss Islington (bot)a49398b2021-08-29 03:43:48 -0700401 def __iter__(self):
402 return self
403
Georg Brandla18af4e2007-04-21 15:47:16 +0000404 def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000405 if self.value == 10:
406 raise StopIteration
407 else:
408 self.value += 1
409 return (self.value,)
410
411 self.cu.executemany("insert into test(income) values (?)", MyIter())
412
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100413 def test_execute_many_generator(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000414 def mygen():
415 for i in range(5):
416 yield (i,)
417
418 self.cu.executemany("insert into test(income) values (?)", mygen())
419
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100420 def test_execute_many_wrong_sql_arg(self):
Victor Stinnerc6a23202019-06-26 03:16:24 +0200421 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000422 self.cu.executemany(42, [(3,)])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000423
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100424 def test_execute_many_select(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300425 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000426 self.cu.executemany("select ?", [(3,)])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000427
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100428 def test_execute_many_not_iterable(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300429 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000430 self.cu.executemany("insert into test(income) values (?)", 42)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000431
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100432 def test_fetch_iter(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000433 # Optional DB-API extension.
434 self.cu.execute("delete from test")
435 self.cu.execute("insert into test(id) values (?)", (5,))
436 self.cu.execute("insert into test(id) values (?)", (6,))
437 self.cu.execute("select id from test order by id")
438 lst = []
439 for row in self.cu:
440 lst.append(row[0])
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000441 self.assertEqual(lst[0], 5)
442 self.assertEqual(lst[1], 6)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000443
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100444 def test_fetchone(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000445 self.cu.execute("select name from test")
446 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000447 self.assertEqual(row[0], "foo")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000448 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000449 self.assertEqual(row, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000450
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100451 def test_fetchone_no_statement(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000452 cur = self.cx.cursor()
453 row = cur.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000454 self.assertEqual(row, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000455
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100456 def test_array_size(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000457 # must default ot 1
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000458 self.assertEqual(self.cu.arraysize, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000459
460 # now set to 2
461 self.cu.arraysize = 2
462
463 # now make the query return 3 rows
464 self.cu.execute("delete from test")
465 self.cu.execute("insert into test(name) values ('A')")
466 self.cu.execute("insert into test(name) values ('B')")
467 self.cu.execute("insert into test(name) values ('C')")
468 self.cu.execute("select name from test")
469 res = self.cu.fetchmany()
470
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000471 self.assertEqual(len(res), 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000472
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100473 def test_fetchmany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000474 self.cu.execute("select name from test")
475 res = self.cu.fetchmany(100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000476 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000477 res = self.cu.fetchmany(100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000478 self.assertEqual(res, [])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000479
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100480 def test_fetchmany_kw_arg(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000481 """Checks if fetchmany works with keyword arguments"""
482 self.cu.execute("select name from test")
483 res = self.cu.fetchmany(size=100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000484 self.assertEqual(len(res), 1)
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000485
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100486 def test_fetchall(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000487 self.cu.execute("select name from test")
488 res = self.cu.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000489 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000490 res = self.cu.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000491 self.assertEqual(res, [])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000492
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100493 def test_setinputsizes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000494 self.cu.setinputsizes([3, 4, 5])
495
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100496 def test_setoutputsize(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000497 self.cu.setoutputsize(5, 0)
498
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100499 def test_setoutputsize_no_column(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000500 self.cu.setoutputsize(42)
501
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100502 def test_cursor_connection(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000503 # Optional DB-API extension.
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000504 self.assertEqual(self.cu.connection, self.cx)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000505
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100506 def test_wrong_cursor_callable(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300507 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000508 def f(): pass
509 cur = self.cx.cursor(f)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000510
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100511 def test_cursor_wrong_class(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000512 class Foo: pass
513 foo = Foo()
Berker Peksag1003b342016-06-12 22:34:49 +0300514 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000515 cur = sqlite.Cursor(foo)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000516
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100517 def test_last_row_id_on_replace(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300518 """
519 INSERT OR REPLACE and REPLACE INTO should produce the same behavior.
520 """
521 sql = '{} INTO test(id, unique_test) VALUES (?, ?)'
522 for statement in ('INSERT OR REPLACE', 'REPLACE'):
523 with self.subTest(statement=statement):
524 self.cu.execute(sql.format(statement), (1, 'foo'))
525 self.assertEqual(self.cu.lastrowid, 1)
526
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100527 def test_last_row_id_on_ignore(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300528 self.cu.execute(
529 "insert or ignore into test(unique_test) values (?)",
530 ('test',))
531 self.assertEqual(self.cu.lastrowid, 2)
532 self.cu.execute(
533 "insert or ignore into test(unique_test) values (?)",
534 ('test',))
535 self.assertEqual(self.cu.lastrowid, 2)
536
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100537 def test_last_row_id_insert_o_r(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300538 results = []
539 for statement in ('FAIL', 'ABORT', 'ROLLBACK'):
540 sql = 'INSERT OR {} INTO test(unique_test) VALUES (?)'
541 with self.subTest(statement='INSERT OR {}'.format(statement)):
542 self.cu.execute(sql.format(statement), (statement,))
543 results.append((statement, self.cu.lastrowid))
544 with self.assertRaises(sqlite.IntegrityError):
545 self.cu.execute(sql.format(statement), (statement,))
546 results.append((statement, self.cu.lastrowid))
547 expected = [
548 ('FAIL', 2), ('FAIL', 2),
549 ('ABORT', 3), ('ABORT', 3),
550 ('ROLLBACK', 4), ('ROLLBACK', 4),
551 ]
552 self.assertEqual(results, expected)
553
554
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000555class ThreadTests(unittest.TestCase):
556 def setUp(self):
557 self.con = sqlite.connect(":memory:")
558 self.cur = self.con.cursor()
559 self.cur.execute("create table test(id integer primary key, name text, bin binary, ratio number, ts timestamp)")
560
561 def tearDown(self):
562 self.cur.close()
563 self.con.close()
564
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100565 def test_con_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000566 def run(con, errors):
567 try:
568 cur = con.cursor()
569 errors.append("did not raise ProgrammingError")
570 return
571 except sqlite.ProgrammingError:
572 return
573 except:
574 errors.append("raised wrong exception")
575
576 errors = []
577 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
578 t.start()
579 t.join()
580 if len(errors) > 0:
581 self.fail("\n".join(errors))
582
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100583 def test_con_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000584 def run(con, errors):
585 try:
586 con.commit()
587 errors.append("did not raise ProgrammingError")
588 return
589 except sqlite.ProgrammingError:
590 return
591 except:
592 errors.append("raised wrong exception")
593
594 errors = []
595 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
596 t.start()
597 t.join()
598 if len(errors) > 0:
599 self.fail("\n".join(errors))
600
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100601 def test_con_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000602 def run(con, errors):
603 try:
604 con.rollback()
605 errors.append("did not raise ProgrammingError")
606 return
607 except sqlite.ProgrammingError:
608 return
609 except:
610 errors.append("raised wrong exception")
611
612 errors = []
613 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
614 t.start()
615 t.join()
616 if len(errors) > 0:
617 self.fail("\n".join(errors))
618
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100619 def test_con_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000620 def run(con, errors):
621 try:
622 con.close()
623 errors.append("did not raise ProgrammingError")
624 return
625 except sqlite.ProgrammingError:
626 return
627 except:
628 errors.append("raised wrong exception")
629
630 errors = []
631 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
632 t.start()
633 t.join()
634 if len(errors) > 0:
635 self.fail("\n".join(errors))
636
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100637 def test_cur_implicit_begin(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000638 def run(cur, errors):
639 try:
640 cur.execute("insert into test(name) values ('a')")
641 errors.append("did not raise ProgrammingError")
642 return
643 except sqlite.ProgrammingError:
644 return
645 except:
646 errors.append("raised wrong exception")
647
648 errors = []
649 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
650 t.start()
651 t.join()
652 if len(errors) > 0:
653 self.fail("\n".join(errors))
654
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100655 def test_cur_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000656 def run(cur, errors):
657 try:
658 cur.close()
659 errors.append("did not raise ProgrammingError")
660 return
661 except sqlite.ProgrammingError:
662 return
663 except:
664 errors.append("raised wrong exception")
665
666 errors = []
667 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
668 t.start()
669 t.join()
670 if len(errors) > 0:
671 self.fail("\n".join(errors))
672
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100673 def test_cur_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000674 def run(cur, errors):
675 try:
676 cur.execute("select name from test")
677 errors.append("did not raise ProgrammingError")
678 return
679 except sqlite.ProgrammingError:
680 return
681 except:
682 errors.append("raised wrong exception")
683
684 errors = []
685 self.cur.execute("insert into test(name) values ('a')")
686 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
687 t.start()
688 t.join()
689 if len(errors) > 0:
690 self.fail("\n".join(errors))
691
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100692 def test_cur_iter_next(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000693 def run(cur, errors):
694 try:
695 row = cur.fetchone()
696 errors.append("did not raise ProgrammingError")
697 return
698 except sqlite.ProgrammingError:
699 return
700 except:
701 errors.append("raised wrong exception")
702
703 errors = []
704 self.cur.execute("insert into test(name) values ('a')")
705 self.cur.execute("select name from test")
706 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
707 t.start()
708 t.join()
709 if len(errors) > 0:
710 self.fail("\n".join(errors))
711
712class ConstructorTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100713 def test_date(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000714 d = sqlite.Date(2004, 10, 28)
715
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100716 def test_time(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000717 t = sqlite.Time(12, 39, 35)
718
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100719 def test_timestamp(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000720 ts = sqlite.Timestamp(2004, 10, 28, 12, 39, 35)
721
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100722 def test_date_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000723 d = sqlite.DateFromTicks(42)
724
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100725 def test_time_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000726 t = sqlite.TimeFromTicks(42)
727
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100728 def test_timestamp_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000729 ts = sqlite.TimestampFromTicks(42)
730
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100731 def test_binary(self):
Guido van Rossumbae07c92007-10-08 02:46:15 +0000732 b = sqlite.Binary(b"\0'")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000733
734class ExtensionTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100735 def test_script_string_sql(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000736 con = sqlite.connect(":memory:")
737 cur = con.cursor()
738 cur.executescript("""
739 -- bla bla
740 /* a stupid comment */
741 create table a(i);
742 insert into a(i) values (5);
743 """)
744 cur.execute("select i from a")
745 res = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000746 self.assertEqual(res, 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000747
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100748 def test_script_syntax_error(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000749 con = sqlite.connect(":memory:")
750 cur = con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300751 with self.assertRaises(sqlite.OperationalError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000752 cur.executescript("create table test(x); asdf; create table test2(x)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000753
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100754 def test_script_error_normal(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000755 con = sqlite.connect(":memory:")
756 cur = con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300757 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000758 cur.executescript("create table test(sadfsadfdsa); select foo from hurz;")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000759
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100760 def test_cursor_executescript_as_bytes(self):
Berker Peksagc4154402016-06-12 13:41:47 +0300761 con = sqlite.connect(":memory:")
762 cur = con.cursor()
763 with self.assertRaises(ValueError) as cm:
764 cur.executescript(b"create table test(foo); insert into test(foo) values (5);")
765 self.assertEqual(str(cm.exception), 'script argument must be unicode.')
766
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100767 def test_connection_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000768 con = sqlite.connect(":memory:")
769 result = con.execute("select 5").fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000770 self.assertEqual(result, 5, "Basic test of Connection.execute")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000771
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100772 def test_connection_executemany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000773 con = sqlite.connect(":memory:")
774 con.execute("create table test(foo)")
775 con.executemany("insert into test(foo) values (?)", [(3,), (4,)])
776 result = con.execute("select foo from test order by foo").fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000777 self.assertEqual(result[0][0], 3, "Basic test of Connection.executemany")
778 self.assertEqual(result[1][0], 4, "Basic test of Connection.executemany")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000779
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100780 def test_connection_executescript(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000781 con = sqlite.connect(":memory:")
782 con.executescript("create table test(foo); insert into test(foo) values (5);")
783 result = con.execute("select foo from test").fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000784 self.assertEqual(result, 5, "Basic test of Connection.executescript")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000785
Gerhard Häringf9cee222010-03-05 15:20:03 +0000786class ClosedConTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100787 def test_closed_con_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000788 con = sqlite.connect(":memory:")
789 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300790 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000791 cur = con.cursor()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000792
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100793 def test_closed_con_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000794 con = sqlite.connect(":memory:")
795 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300796 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000797 con.commit()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000798
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100799 def test_closed_con_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000800 con = sqlite.connect(":memory:")
801 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300802 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000803 con.rollback()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000804
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100805 def test_closed_cur_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000806 con = sqlite.connect(":memory:")
807 cur = con.cursor()
808 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300809 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000810 cur.execute("select 4")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000811
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100812 def test_closed_create_function(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000813 con = sqlite.connect(":memory:")
814 con.close()
815 def f(x): return 17
Berker Peksag1003b342016-06-12 22:34:49 +0300816 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000817 con.create_function("foo", 1, f)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000818
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100819 def test_closed_create_aggregate(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000820 con = sqlite.connect(":memory:")
821 con.close()
822 class Agg:
823 def __init__(self):
824 pass
825 def step(self, x):
826 pass
827 def finalize(self):
828 return 17
Berker Peksag1003b342016-06-12 22:34:49 +0300829 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000830 con.create_aggregate("foo", 1, Agg)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000831
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100832 def test_closed_set_authorizer(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000833 con = sqlite.connect(":memory:")
834 con.close()
835 def authorizer(*args):
836 return sqlite.DENY
Berker Peksag1003b342016-06-12 22:34:49 +0300837 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000838 con.set_authorizer(authorizer)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000839
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100840 def test_closed_set_progress_callback(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000841 con = sqlite.connect(":memory:")
842 con.close()
843 def progress(): pass
Berker Peksag1003b342016-06-12 22:34:49 +0300844 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000845 con.set_progress_handler(progress, 100)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000846
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100847 def test_closed_call(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000848 con = sqlite.connect(":memory:")
849 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300850 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000851 con()
Gerhard Häringf9cee222010-03-05 15:20:03 +0000852
853class ClosedCurTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100854 def test_closed(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000855 con = sqlite.connect(":memory:")
856 cur = con.cursor()
857 cur.close()
858
859 for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"):
860 if method_name in ("execute", "executescript"):
861 params = ("select 4 union select 5",)
862 elif method_name == "executemany":
863 params = ("insert into foo(bar) values (?)", [(3,), (4,)])
864 else:
865 params = []
866
Berker Peksag1003b342016-06-12 22:34:49 +0300867 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000868 method = getattr(cur, method_name)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000869 method(*params)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000870
Berker Peksag4bf580d2016-09-07 02:04:34 +0300871
872class SqliteOnConflictTests(unittest.TestCase):
873 """
874 Tests for SQLite's "insert on conflict" feature.
875
876 See https://www.sqlite.org/lang_conflict.html for details.
877 """
878
879 def setUp(self):
880 self.cx = sqlite.connect(":memory:")
881 self.cu = self.cx.cursor()
882 self.cu.execute("""
883 CREATE TABLE test(
884 id INTEGER PRIMARY KEY, name TEXT, unique_name TEXT UNIQUE
885 );
886 """)
887
888 def tearDown(self):
889 self.cu.close()
890 self.cx.close()
891
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100892 def test_on_conflict_rollback_with_explicit_transaction(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300893 self.cx.isolation_level = None # autocommit mode
894 self.cu = self.cx.cursor()
895 # Start an explicit transaction.
896 self.cu.execute("BEGIN")
897 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
898 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
899 with self.assertRaises(sqlite.IntegrityError):
900 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
901 # Use connection to commit.
902 self.cx.commit()
903 self.cu.execute("SELECT name, unique_name from test")
904 # Transaction should have rolled back and nothing should be in table.
905 self.assertEqual(self.cu.fetchall(), [])
906
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100907 def test_on_conflict_abort_raises_with_explicit_transactions(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300908 # Abort cancels the current sql statement but doesn't change anything
909 # about the current transaction.
910 self.cx.isolation_level = None # autocommit mode
911 self.cu = self.cx.cursor()
912 # Start an explicit transaction.
913 self.cu.execute("BEGIN")
914 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
915 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
916 with self.assertRaises(sqlite.IntegrityError):
917 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
918 self.cx.commit()
919 self.cu.execute("SELECT name, unique_name FROM test")
920 # Expect the first two inserts to work, third to do nothing.
921 self.assertEqual(self.cu.fetchall(), [('abort_test', None), (None, 'foo',)])
922
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100923 def test_on_conflict_rollback_without_transaction(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300924 # Start of implicit transaction
925 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
926 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
927 with self.assertRaises(sqlite.IntegrityError):
928 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
929 self.cu.execute("SELECT name, unique_name FROM test")
930 # Implicit transaction is rolled back on error.
931 self.assertEqual(self.cu.fetchall(), [])
932
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100933 def test_on_conflict_abort_raises_without_transactions(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300934 # Abort cancels the current sql statement but doesn't change anything
935 # about the current transaction.
936 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
937 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
938 with self.assertRaises(sqlite.IntegrityError):
939 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
940 # Make sure all other values were inserted.
941 self.cu.execute("SELECT name, unique_name FROM test")
942 self.assertEqual(self.cu.fetchall(), [('abort_test', None), (None, 'foo',)])
943
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100944 def test_on_conflict_fail(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300945 self.cu.execute("INSERT OR FAIL INTO test(unique_name) VALUES ('foo')")
946 with self.assertRaises(sqlite.IntegrityError):
947 self.cu.execute("INSERT OR FAIL INTO test(unique_name) VALUES ('foo')")
948 self.assertEqual(self.cu.fetchall(), [])
949
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100950 def test_on_conflict_ignore(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300951 self.cu.execute("INSERT OR IGNORE INTO test(unique_name) VALUES ('foo')")
952 # Nothing should happen.
953 self.cu.execute("INSERT OR IGNORE INTO test(unique_name) VALUES ('foo')")
954 self.cu.execute("SELECT unique_name FROM test")
955 self.assertEqual(self.cu.fetchall(), [('foo',)])
956
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100957 def test_on_conflict_replace(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300958 self.cu.execute("INSERT OR REPLACE INTO test(name, unique_name) VALUES ('Data!', 'foo')")
959 # There shouldn't be an IntegrityError exception.
960 self.cu.execute("INSERT OR REPLACE INTO test(name, unique_name) VALUES ('Very different data!', 'foo')")
961 self.cu.execute("SELECT name, unique_name FROM test")
962 self.assertEqual(self.cu.fetchall(), [('Very different data!', 'foo')])
963
964
Erlend Egeberg Aasland2a808932021-08-28 20:26:00 +0200965class MultiprocessTests(unittest.TestCase):
966 CONNECTION_TIMEOUT = SHORT_TIMEOUT / 1000. # Defaults to 30 ms
967
968 def tearDown(self):
969 unlink(TESTFN)
970
971 def test_ctx_mgr_rollback_if_commit_failed(self):
972 # bpo-27334: ctx manager does not rollback if commit fails
973 SCRIPT = f"""if 1:
974 import sqlite3
975 def wait():
976 print("started")
977 assert "database is locked" in input()
978
979 cx = sqlite3.connect("{TESTFN}", timeout={self.CONNECTION_TIMEOUT})
980 cx.create_function("wait", 0, wait)
981 with cx:
982 cx.execute("create table t(t)")
983 try:
984 # execute two transactions; both will try to lock the db
985 cx.executescript('''
986 -- start a transaction and wait for parent
987 begin transaction;
988 select * from t;
989 select wait();
990 rollback;
991
992 -- start a new transaction; would fail if parent holds lock
993 begin transaction;
994 select * from t;
995 rollback;
996 ''')
997 finally:
998 cx.close()
999 """
1000
1001 # spawn child process
1002 proc = subprocess.Popen(
1003 [sys.executable, "-c", SCRIPT],
1004 encoding="utf-8",
1005 bufsize=0,
1006 stdin=subprocess.PIPE,
1007 stdout=subprocess.PIPE,
1008 )
1009 self.addCleanup(proc.communicate)
1010
1011 # wait for child process to start
1012 self.assertEqual("started", proc.stdout.readline().strip())
1013
1014 cx = sqlite.connect(TESTFN, timeout=self.CONNECTION_TIMEOUT)
1015 try: # context manager should correctly release the db lock
1016 with cx:
1017 cx.execute("insert into t values('test')")
1018 except sqlite.OperationalError as exc:
1019 proc.stdin.write(str(exc))
1020 else:
1021 proc.stdin.write("no error")
1022 finally:
1023 cx.close()
1024
1025 # terminate child process
1026 self.assertIsNone(proc.returncode)
1027 try:
1028 proc.communicate(input="end", timeout=SHORT_TIMEOUT)
1029 except subprocess.TimeoutExpired:
1030 proc.kill()
1031 proc.communicate()
1032 raise
1033 self.assertEqual(proc.returncode, 0)
1034
1035
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001036def suite():
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +01001037 tests = [
1038 ClosedConTests,
1039 ClosedCurTests,
1040 ConnectionTests,
1041 ConstructorTests,
1042 CursorTests,
1043 ExtensionTests,
1044 ModuleTests,
Erlend Egeberg Aasland2a808932021-08-28 20:26:00 +02001045 MultiprocessTests,
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +01001046 SqliteOnConflictTests,
1047 ThreadTests,
Erlend Egeberg Aasland0cb470e2021-07-30 14:01:22 +02001048 UninitialisedConnectionTests,
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +01001049 ]
1050 return unittest.TestSuite(
1051 [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
1052 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001053
1054def test():
1055 runner = unittest.TextTestRunner()
1056 runner.run(suite())
1057
1058if __name__ == "__main__":
1059 test()