blob: 5d521d0cce5e1b62b3f02b0f7b25c67e4a955d82 [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
Georg Brandla18af4e2007-04-21 15:47:16 +0000401 def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000402 if self.value == 10:
403 raise StopIteration
404 else:
405 self.value += 1
406 return (self.value,)
407
408 self.cu.executemany("insert into test(income) values (?)", MyIter())
409
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100410 def test_execute_many_generator(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000411 def mygen():
412 for i in range(5):
413 yield (i,)
414
415 self.cu.executemany("insert into test(income) values (?)", mygen())
416
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100417 def test_execute_many_wrong_sql_arg(self):
Victor Stinnerc6a23202019-06-26 03:16:24 +0200418 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000419 self.cu.executemany(42, [(3,)])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000420
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100421 def test_execute_many_select(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300422 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000423 self.cu.executemany("select ?", [(3,)])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000424
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100425 def test_execute_many_not_iterable(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300426 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000427 self.cu.executemany("insert into test(income) values (?)", 42)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000428
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100429 def test_fetch_iter(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000430 # Optional DB-API extension.
431 self.cu.execute("delete from test")
432 self.cu.execute("insert into test(id) values (?)", (5,))
433 self.cu.execute("insert into test(id) values (?)", (6,))
434 self.cu.execute("select id from test order by id")
435 lst = []
436 for row in self.cu:
437 lst.append(row[0])
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000438 self.assertEqual(lst[0], 5)
439 self.assertEqual(lst[1], 6)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000440
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100441 def test_fetchone(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000442 self.cu.execute("select name from test")
443 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000444 self.assertEqual(row[0], "foo")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000445 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000446 self.assertEqual(row, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000447
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100448 def test_fetchone_no_statement(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000449 cur = self.cx.cursor()
450 row = cur.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000451 self.assertEqual(row, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000452
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100453 def test_array_size(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000454 # must default ot 1
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000455 self.assertEqual(self.cu.arraysize, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000456
457 # now set to 2
458 self.cu.arraysize = 2
459
460 # now make the query return 3 rows
461 self.cu.execute("delete from test")
462 self.cu.execute("insert into test(name) values ('A')")
463 self.cu.execute("insert into test(name) values ('B')")
464 self.cu.execute("insert into test(name) values ('C')")
465 self.cu.execute("select name from test")
466 res = self.cu.fetchmany()
467
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000468 self.assertEqual(len(res), 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000469
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100470 def test_fetchmany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000471 self.cu.execute("select name from test")
472 res = self.cu.fetchmany(100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000473 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000474 res = self.cu.fetchmany(100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000475 self.assertEqual(res, [])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000476
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100477 def test_fetchmany_kw_arg(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000478 """Checks if fetchmany works with keyword arguments"""
479 self.cu.execute("select name from test")
480 res = self.cu.fetchmany(size=100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000481 self.assertEqual(len(res), 1)
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000482
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100483 def test_fetchall(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000484 self.cu.execute("select name from test")
485 res = self.cu.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000486 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000487 res = self.cu.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000488 self.assertEqual(res, [])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000489
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100490 def test_setinputsizes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000491 self.cu.setinputsizes([3, 4, 5])
492
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100493 def test_setoutputsize(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000494 self.cu.setoutputsize(5, 0)
495
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100496 def test_setoutputsize_no_column(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000497 self.cu.setoutputsize(42)
498
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100499 def test_cursor_connection(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000500 # Optional DB-API extension.
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000501 self.assertEqual(self.cu.connection, self.cx)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000502
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100503 def test_wrong_cursor_callable(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300504 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000505 def f(): pass
506 cur = self.cx.cursor(f)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000507
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100508 def test_cursor_wrong_class(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000509 class Foo: pass
510 foo = Foo()
Berker Peksag1003b342016-06-12 22:34:49 +0300511 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000512 cur = sqlite.Cursor(foo)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000513
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100514 def test_last_row_id_on_replace(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300515 """
516 INSERT OR REPLACE and REPLACE INTO should produce the same behavior.
517 """
518 sql = '{} INTO test(id, unique_test) VALUES (?, ?)'
519 for statement in ('INSERT OR REPLACE', 'REPLACE'):
520 with self.subTest(statement=statement):
521 self.cu.execute(sql.format(statement), (1, 'foo'))
522 self.assertEqual(self.cu.lastrowid, 1)
523
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100524 def test_last_row_id_on_ignore(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300525 self.cu.execute(
526 "insert or ignore into test(unique_test) values (?)",
527 ('test',))
528 self.assertEqual(self.cu.lastrowid, 2)
529 self.cu.execute(
530 "insert or ignore into test(unique_test) values (?)",
531 ('test',))
532 self.assertEqual(self.cu.lastrowid, 2)
533
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100534 def test_last_row_id_insert_o_r(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300535 results = []
536 for statement in ('FAIL', 'ABORT', 'ROLLBACK'):
537 sql = 'INSERT OR {} INTO test(unique_test) VALUES (?)'
538 with self.subTest(statement='INSERT OR {}'.format(statement)):
539 self.cu.execute(sql.format(statement), (statement,))
540 results.append((statement, self.cu.lastrowid))
541 with self.assertRaises(sqlite.IntegrityError):
542 self.cu.execute(sql.format(statement), (statement,))
543 results.append((statement, self.cu.lastrowid))
544 expected = [
545 ('FAIL', 2), ('FAIL', 2),
546 ('ABORT', 3), ('ABORT', 3),
547 ('ROLLBACK', 4), ('ROLLBACK', 4),
548 ]
549 self.assertEqual(results, expected)
550
551
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000552class ThreadTests(unittest.TestCase):
553 def setUp(self):
554 self.con = sqlite.connect(":memory:")
555 self.cur = self.con.cursor()
556 self.cur.execute("create table test(id integer primary key, name text, bin binary, ratio number, ts timestamp)")
557
558 def tearDown(self):
559 self.cur.close()
560 self.con.close()
561
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100562 def test_con_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000563 def run(con, errors):
564 try:
565 cur = con.cursor()
566 errors.append("did not raise ProgrammingError")
567 return
568 except sqlite.ProgrammingError:
569 return
570 except:
571 errors.append("raised wrong exception")
572
573 errors = []
574 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
575 t.start()
576 t.join()
577 if len(errors) > 0:
578 self.fail("\n".join(errors))
579
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100580 def test_con_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000581 def run(con, errors):
582 try:
583 con.commit()
584 errors.append("did not raise ProgrammingError")
585 return
586 except sqlite.ProgrammingError:
587 return
588 except:
589 errors.append("raised wrong exception")
590
591 errors = []
592 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
593 t.start()
594 t.join()
595 if len(errors) > 0:
596 self.fail("\n".join(errors))
597
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100598 def test_con_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000599 def run(con, errors):
600 try:
601 con.rollback()
602 errors.append("did not raise ProgrammingError")
603 return
604 except sqlite.ProgrammingError:
605 return
606 except:
607 errors.append("raised wrong exception")
608
609 errors = []
610 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
611 t.start()
612 t.join()
613 if len(errors) > 0:
614 self.fail("\n".join(errors))
615
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100616 def test_con_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000617 def run(con, errors):
618 try:
619 con.close()
620 errors.append("did not raise ProgrammingError")
621 return
622 except sqlite.ProgrammingError:
623 return
624 except:
625 errors.append("raised wrong exception")
626
627 errors = []
628 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
629 t.start()
630 t.join()
631 if len(errors) > 0:
632 self.fail("\n".join(errors))
633
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100634 def test_cur_implicit_begin(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000635 def run(cur, errors):
636 try:
637 cur.execute("insert into test(name) values ('a')")
638 errors.append("did not raise ProgrammingError")
639 return
640 except sqlite.ProgrammingError:
641 return
642 except:
643 errors.append("raised wrong exception")
644
645 errors = []
646 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
647 t.start()
648 t.join()
649 if len(errors) > 0:
650 self.fail("\n".join(errors))
651
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100652 def test_cur_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000653 def run(cur, errors):
654 try:
655 cur.close()
656 errors.append("did not raise ProgrammingError")
657 return
658 except sqlite.ProgrammingError:
659 return
660 except:
661 errors.append("raised wrong exception")
662
663 errors = []
664 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
665 t.start()
666 t.join()
667 if len(errors) > 0:
668 self.fail("\n".join(errors))
669
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100670 def test_cur_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000671 def run(cur, errors):
672 try:
673 cur.execute("select name from test")
674 errors.append("did not raise ProgrammingError")
675 return
676 except sqlite.ProgrammingError:
677 return
678 except:
679 errors.append("raised wrong exception")
680
681 errors = []
682 self.cur.execute("insert into test(name) values ('a')")
683 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
684 t.start()
685 t.join()
686 if len(errors) > 0:
687 self.fail("\n".join(errors))
688
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100689 def test_cur_iter_next(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000690 def run(cur, errors):
691 try:
692 row = cur.fetchone()
693 errors.append("did not raise ProgrammingError")
694 return
695 except sqlite.ProgrammingError:
696 return
697 except:
698 errors.append("raised wrong exception")
699
700 errors = []
701 self.cur.execute("insert into test(name) values ('a')")
702 self.cur.execute("select name from test")
703 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
704 t.start()
705 t.join()
706 if len(errors) > 0:
707 self.fail("\n".join(errors))
708
709class ConstructorTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100710 def test_date(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000711 d = sqlite.Date(2004, 10, 28)
712
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100713 def test_time(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000714 t = sqlite.Time(12, 39, 35)
715
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100716 def test_timestamp(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000717 ts = sqlite.Timestamp(2004, 10, 28, 12, 39, 35)
718
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100719 def test_date_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000720 d = sqlite.DateFromTicks(42)
721
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100722 def test_time_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000723 t = sqlite.TimeFromTicks(42)
724
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100725 def test_timestamp_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000726 ts = sqlite.TimestampFromTicks(42)
727
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100728 def test_binary(self):
Guido van Rossumbae07c92007-10-08 02:46:15 +0000729 b = sqlite.Binary(b"\0'")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000730
731class ExtensionTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100732 def test_script_string_sql(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000733 con = sqlite.connect(":memory:")
734 cur = con.cursor()
735 cur.executescript("""
736 -- bla bla
737 /* a stupid comment */
738 create table a(i);
739 insert into a(i) values (5);
740 """)
741 cur.execute("select i from a")
742 res = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000743 self.assertEqual(res, 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000744
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100745 def test_script_syntax_error(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000746 con = sqlite.connect(":memory:")
747 cur = con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300748 with self.assertRaises(sqlite.OperationalError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000749 cur.executescript("create table test(x); asdf; create table test2(x)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000750
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100751 def test_script_error_normal(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000752 con = sqlite.connect(":memory:")
753 cur = con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300754 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000755 cur.executescript("create table test(sadfsadfdsa); select foo from hurz;")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000756
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100757 def test_cursor_executescript_as_bytes(self):
Berker Peksagc4154402016-06-12 13:41:47 +0300758 con = sqlite.connect(":memory:")
759 cur = con.cursor()
760 with self.assertRaises(ValueError) as cm:
761 cur.executescript(b"create table test(foo); insert into test(foo) values (5);")
762 self.assertEqual(str(cm.exception), 'script argument must be unicode.')
763
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100764 def test_connection_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000765 con = sqlite.connect(":memory:")
766 result = con.execute("select 5").fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000767 self.assertEqual(result, 5, "Basic test of Connection.execute")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000768
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100769 def test_connection_executemany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000770 con = sqlite.connect(":memory:")
771 con.execute("create table test(foo)")
772 con.executemany("insert into test(foo) values (?)", [(3,), (4,)])
773 result = con.execute("select foo from test order by foo").fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000774 self.assertEqual(result[0][0], 3, "Basic test of Connection.executemany")
775 self.assertEqual(result[1][0], 4, "Basic test of Connection.executemany")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000776
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100777 def test_connection_executescript(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000778 con = sqlite.connect(":memory:")
779 con.executescript("create table test(foo); insert into test(foo) values (5);")
780 result = con.execute("select foo from test").fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000781 self.assertEqual(result, 5, "Basic test of Connection.executescript")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000782
Gerhard Häringf9cee222010-03-05 15:20:03 +0000783class ClosedConTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100784 def test_closed_con_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000785 con = sqlite.connect(":memory:")
786 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300787 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000788 cur = con.cursor()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000789
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100790 def test_closed_con_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000791 con = sqlite.connect(":memory:")
792 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300793 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000794 con.commit()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000795
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100796 def test_closed_con_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000797 con = sqlite.connect(":memory:")
798 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300799 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000800 con.rollback()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000801
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100802 def test_closed_cur_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000803 con = sqlite.connect(":memory:")
804 cur = con.cursor()
805 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300806 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000807 cur.execute("select 4")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000808
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100809 def test_closed_create_function(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000810 con = sqlite.connect(":memory:")
811 con.close()
812 def f(x): return 17
Berker Peksag1003b342016-06-12 22:34:49 +0300813 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000814 con.create_function("foo", 1, f)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000815
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100816 def test_closed_create_aggregate(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000817 con = sqlite.connect(":memory:")
818 con.close()
819 class Agg:
820 def __init__(self):
821 pass
822 def step(self, x):
823 pass
824 def finalize(self):
825 return 17
Berker Peksag1003b342016-06-12 22:34:49 +0300826 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000827 con.create_aggregate("foo", 1, Agg)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000828
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100829 def test_closed_set_authorizer(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000830 con = sqlite.connect(":memory:")
831 con.close()
832 def authorizer(*args):
833 return sqlite.DENY
Berker Peksag1003b342016-06-12 22:34:49 +0300834 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000835 con.set_authorizer(authorizer)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000836
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100837 def test_closed_set_progress_callback(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000838 con = sqlite.connect(":memory:")
839 con.close()
840 def progress(): pass
Berker Peksag1003b342016-06-12 22:34:49 +0300841 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000842 con.set_progress_handler(progress, 100)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000843
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100844 def test_closed_call(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000845 con = sqlite.connect(":memory:")
846 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300847 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000848 con()
Gerhard Häringf9cee222010-03-05 15:20:03 +0000849
850class ClosedCurTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100851 def test_closed(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000852 con = sqlite.connect(":memory:")
853 cur = con.cursor()
854 cur.close()
855
856 for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"):
857 if method_name in ("execute", "executescript"):
858 params = ("select 4 union select 5",)
859 elif method_name == "executemany":
860 params = ("insert into foo(bar) values (?)", [(3,), (4,)])
861 else:
862 params = []
863
Berker Peksag1003b342016-06-12 22:34:49 +0300864 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000865 method = getattr(cur, method_name)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000866 method(*params)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000867
Berker Peksag4bf580d2016-09-07 02:04:34 +0300868
869class SqliteOnConflictTests(unittest.TestCase):
870 """
871 Tests for SQLite's "insert on conflict" feature.
872
873 See https://www.sqlite.org/lang_conflict.html for details.
874 """
875
876 def setUp(self):
877 self.cx = sqlite.connect(":memory:")
878 self.cu = self.cx.cursor()
879 self.cu.execute("""
880 CREATE TABLE test(
881 id INTEGER PRIMARY KEY, name TEXT, unique_name TEXT UNIQUE
882 );
883 """)
884
885 def tearDown(self):
886 self.cu.close()
887 self.cx.close()
888
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100889 def test_on_conflict_rollback_with_explicit_transaction(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300890 self.cx.isolation_level = None # autocommit mode
891 self.cu = self.cx.cursor()
892 # Start an explicit transaction.
893 self.cu.execute("BEGIN")
894 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
895 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
896 with self.assertRaises(sqlite.IntegrityError):
897 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
898 # Use connection to commit.
899 self.cx.commit()
900 self.cu.execute("SELECT name, unique_name from test")
901 # Transaction should have rolled back and nothing should be in table.
902 self.assertEqual(self.cu.fetchall(), [])
903
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100904 def test_on_conflict_abort_raises_with_explicit_transactions(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300905 # Abort cancels the current sql statement but doesn't change anything
906 # about the current transaction.
907 self.cx.isolation_level = None # autocommit mode
908 self.cu = self.cx.cursor()
909 # Start an explicit transaction.
910 self.cu.execute("BEGIN")
911 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
912 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
913 with self.assertRaises(sqlite.IntegrityError):
914 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
915 self.cx.commit()
916 self.cu.execute("SELECT name, unique_name FROM test")
917 # Expect the first two inserts to work, third to do nothing.
918 self.assertEqual(self.cu.fetchall(), [('abort_test', None), (None, 'foo',)])
919
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100920 def test_on_conflict_rollback_without_transaction(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300921 # Start of implicit transaction
922 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
923 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
924 with self.assertRaises(sqlite.IntegrityError):
925 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
926 self.cu.execute("SELECT name, unique_name FROM test")
927 # Implicit transaction is rolled back on error.
928 self.assertEqual(self.cu.fetchall(), [])
929
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100930 def test_on_conflict_abort_raises_without_transactions(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300931 # Abort cancels the current sql statement but doesn't change anything
932 # about the current transaction.
933 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
934 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
935 with self.assertRaises(sqlite.IntegrityError):
936 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
937 # Make sure all other values were inserted.
938 self.cu.execute("SELECT name, unique_name FROM test")
939 self.assertEqual(self.cu.fetchall(), [('abort_test', None), (None, 'foo',)])
940
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100941 def test_on_conflict_fail(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300942 self.cu.execute("INSERT OR FAIL INTO test(unique_name) VALUES ('foo')")
943 with self.assertRaises(sqlite.IntegrityError):
944 self.cu.execute("INSERT OR FAIL INTO test(unique_name) VALUES ('foo')")
945 self.assertEqual(self.cu.fetchall(), [])
946
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100947 def test_on_conflict_ignore(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300948 self.cu.execute("INSERT OR IGNORE INTO test(unique_name) VALUES ('foo')")
949 # Nothing should happen.
950 self.cu.execute("INSERT OR IGNORE INTO test(unique_name) VALUES ('foo')")
951 self.cu.execute("SELECT unique_name FROM test")
952 self.assertEqual(self.cu.fetchall(), [('foo',)])
953
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100954 def test_on_conflict_replace(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300955 self.cu.execute("INSERT OR REPLACE INTO test(name, unique_name) VALUES ('Data!', 'foo')")
956 # There shouldn't be an IntegrityError exception.
957 self.cu.execute("INSERT OR REPLACE INTO test(name, unique_name) VALUES ('Very different data!', 'foo')")
958 self.cu.execute("SELECT name, unique_name FROM test")
959 self.assertEqual(self.cu.fetchall(), [('Very different data!', 'foo')])
960
961
Erlend Egeberg Aasland2a808932021-08-28 20:26:00 +0200962class MultiprocessTests(unittest.TestCase):
963 CONNECTION_TIMEOUT = SHORT_TIMEOUT / 1000. # Defaults to 30 ms
964
965 def tearDown(self):
966 unlink(TESTFN)
967
968 def test_ctx_mgr_rollback_if_commit_failed(self):
969 # bpo-27334: ctx manager does not rollback if commit fails
970 SCRIPT = f"""if 1:
971 import sqlite3
972 def wait():
973 print("started")
974 assert "database is locked" in input()
975
976 cx = sqlite3.connect("{TESTFN}", timeout={self.CONNECTION_TIMEOUT})
977 cx.create_function("wait", 0, wait)
978 with cx:
979 cx.execute("create table t(t)")
980 try:
981 # execute two transactions; both will try to lock the db
982 cx.executescript('''
983 -- start a transaction and wait for parent
984 begin transaction;
985 select * from t;
986 select wait();
987 rollback;
988
989 -- start a new transaction; would fail if parent holds lock
990 begin transaction;
991 select * from t;
992 rollback;
993 ''')
994 finally:
995 cx.close()
996 """
997
998 # spawn child process
999 proc = subprocess.Popen(
1000 [sys.executable, "-c", SCRIPT],
1001 encoding="utf-8",
1002 bufsize=0,
1003 stdin=subprocess.PIPE,
1004 stdout=subprocess.PIPE,
1005 )
1006 self.addCleanup(proc.communicate)
1007
1008 # wait for child process to start
1009 self.assertEqual("started", proc.stdout.readline().strip())
1010
1011 cx = sqlite.connect(TESTFN, timeout=self.CONNECTION_TIMEOUT)
1012 try: # context manager should correctly release the db lock
1013 with cx:
1014 cx.execute("insert into t values('test')")
1015 except sqlite.OperationalError as exc:
1016 proc.stdin.write(str(exc))
1017 else:
1018 proc.stdin.write("no error")
1019 finally:
1020 cx.close()
1021
1022 # terminate child process
1023 self.assertIsNone(proc.returncode)
1024 try:
1025 proc.communicate(input="end", timeout=SHORT_TIMEOUT)
1026 except subprocess.TimeoutExpired:
1027 proc.kill()
1028 proc.communicate()
1029 raise
1030 self.assertEqual(proc.returncode, 0)
1031
1032
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001033def suite():
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +01001034 tests = [
1035 ClosedConTests,
1036 ClosedCurTests,
1037 ConnectionTests,
1038 ConstructorTests,
1039 CursorTests,
1040 ExtensionTests,
1041 ModuleTests,
Erlend Egeberg Aasland2a808932021-08-28 20:26:00 +02001042 MultiprocessTests,
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +01001043 SqliteOnConflictTests,
1044 ThreadTests,
Erlend Egeberg Aasland0cb470e2021-07-30 14:01:22 +02001045 UninitialisedConnectionTests,
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +01001046 ]
1047 return unittest.TestSuite(
1048 [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
1049 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001050
1051def test():
1052 runner = unittest.TextTestRunner()
1053 runner.run(suite())
1054
1055if __name__ == "__main__":
1056 test()