blob: 2d02045b72e8d66bed9b450e851c4349f7134bb5 [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
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020023import threading
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000024import unittest
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000025import sqlite3 as sqlite
Erlend Egeberg Aaslandd16f6172021-01-09 12:25:55 +010026import sys
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000027
Erlend Egeberg Aasland0a3452e2021-06-24 01:46:25 +020028from test.support import check_disallow_instantiation
Hai Shifcce8c62020-08-08 05:55:35 +080029from test.support.os_helper import TESTFN, unlink
Antoine Pitrou902fc8b2013-02-10 00:02:44 +010030
31
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000032class ModuleTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010033 def test_api_level(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000034 self.assertEqual(sqlite.apilevel, "2.0",
35 "apilevel is %s, should be 2.0" % sqlite.apilevel)
36
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010037 def test_thread_safety(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000038 self.assertEqual(sqlite.threadsafety, 1,
39 "threadsafety is %d, should be 1" % sqlite.threadsafety)
40
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010041 def test_param_style(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000042 self.assertEqual(sqlite.paramstyle, "qmark",
43 "paramstyle is '%s', should be 'qmark'" %
44 sqlite.paramstyle)
45
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010046 def test_warning(self):
Ezio Melottib3aedd42010-11-20 19:04:17 +000047 self.assertTrue(issubclass(sqlite.Warning, Exception),
Guido van Rossumcd16bf62007-06-13 18:07:49 +000048 "Warning is not a subclass of Exception")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000049
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010050 def test_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000051 self.assertTrue(issubclass(sqlite.Error, Exception),
Guido van Rossumcd16bf62007-06-13 18:07:49 +000052 "Error is not a subclass of Exception")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000053
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010054 def test_interface_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000055 self.assertTrue(issubclass(sqlite.InterfaceError, sqlite.Error),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000056 "InterfaceError is not a subclass of Error")
57
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010058 def test_database_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000059 self.assertTrue(issubclass(sqlite.DatabaseError, sqlite.Error),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000060 "DatabaseError is not a subclass of Error")
61
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010062 def test_data_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000063 self.assertTrue(issubclass(sqlite.DataError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000064 "DataError is not a subclass of DatabaseError")
65
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010066 def test_operational_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000067 self.assertTrue(issubclass(sqlite.OperationalError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000068 "OperationalError is not a subclass of DatabaseError")
69
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010070 def test_integrity_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000071 self.assertTrue(issubclass(sqlite.IntegrityError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000072 "IntegrityError is not a subclass of DatabaseError")
73
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010074 def test_internal_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000075 self.assertTrue(issubclass(sqlite.InternalError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000076 "InternalError is not a subclass of DatabaseError")
77
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010078 def test_programming_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000079 self.assertTrue(issubclass(sqlite.ProgrammingError, sqlite.DatabaseError),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000080 "ProgrammingError is not a subclass of DatabaseError")
81
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010082 def test_not_supported_error(self):
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000083 self.assertTrue(issubclass(sqlite.NotSupportedError,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000084 sqlite.DatabaseError),
85 "NotSupportedError is not a subclass of DatabaseError")
86
Erlend Egeberg Aaslandd16f6172021-01-09 12:25:55 +010087 # sqlite3_enable_shared_cache() is deprecated on macOS and calling it may raise
88 # OperationalError on some buildbots.
89 @unittest.skipIf(sys.platform == "darwin", "shared cache is deprecated on macOS")
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010090 def test_shared_cache_deprecated(self):
Erlend Egeberg Aaslandddb5e112021-01-06 01:36:04 +010091 for enable in (True, False):
92 with self.assertWarns(DeprecationWarning) as cm:
93 sqlite.enable_shared_cache(enable)
94 self.assertIn("dbapi.py", cm.filename)
95
Erlend Egeberg Aaslandccc95c72021-06-20 23:07:31 +020096 def test_disallow_instantiation(self):
97 cx = sqlite.connect(":memory:")
Erlend Egeberg Aasland0a3452e2021-06-24 01:46:25 +020098 check_disallow_instantiation(self, type(cx("select 1")))
Erlend Egeberg Aaslandccc95c72021-06-20 23:07:31 +020099
Erlend Egeberg Aaslandddb5e112021-01-06 01:36:04 +0100100
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000101class ConnectionTests(unittest.TestCase):
R. David Murrayd35251d2010-06-01 01:32:12 +0000102
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000103 def setUp(self):
104 self.cx = sqlite.connect(":memory:")
105 cu = self.cx.cursor()
106 cu.execute("create table test(id integer primary key, name text)")
107 cu.execute("insert into test(name) values (?)", ("foo",))
108
109 def tearDown(self):
110 self.cx.close()
111
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100112 def test_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000113 self.cx.commit()
114
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100115 def test_commit_after_no_changes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000116 """
117 A commit should also work when no changes were made to the database.
118 """
119 self.cx.commit()
120 self.cx.commit()
121
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100122 def test_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000123 self.cx.rollback()
124
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100125 def test_rollback_after_no_changes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000126 """
127 A rollback should also work when no changes were made to the database.
128 """
129 self.cx.rollback()
130 self.cx.rollback()
131
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100132 def test_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000133 cu = self.cx.cursor()
134
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100135 def test_failed_open(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000136 YOU_CANNOT_OPEN_THIS = "/foo/bar/bla/23534/mydb.db"
Berker Peksag1003b342016-06-12 22:34:49 +0300137 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000138 con = sqlite.connect(YOU_CANNOT_OPEN_THIS)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000139
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100140 def test_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000141 self.cx.close()
142
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100143 def test_exceptions(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000144 # Optional DB-API extension.
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000145 self.assertEqual(self.cx.Warning, sqlite.Warning)
146 self.assertEqual(self.cx.Error, sqlite.Error)
147 self.assertEqual(self.cx.InterfaceError, sqlite.InterfaceError)
148 self.assertEqual(self.cx.DatabaseError, sqlite.DatabaseError)
149 self.assertEqual(self.cx.DataError, sqlite.DataError)
150 self.assertEqual(self.cx.OperationalError, sqlite.OperationalError)
151 self.assertEqual(self.cx.IntegrityError, sqlite.IntegrityError)
152 self.assertEqual(self.cx.InternalError, sqlite.InternalError)
153 self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError)
154 self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000155
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100156 def test_in_transaction(self):
R. David Murrayd35251d2010-06-01 01:32:12 +0000157 # Can't use db from setUp because we want to test initial state.
158 cx = sqlite.connect(":memory:")
159 cu = cx.cursor()
160 self.assertEqual(cx.in_transaction, False)
161 cu.execute("create table transactiontest(id integer primary key, name text)")
162 self.assertEqual(cx.in_transaction, False)
163 cu.execute("insert into transactiontest(name) values (?)", ("foo",))
164 self.assertEqual(cx.in_transaction, True)
165 cu.execute("select name from transactiontest where name=?", ["foo"])
166 row = cu.fetchone()
167 self.assertEqual(cx.in_transaction, True)
168 cx.commit()
169 self.assertEqual(cx.in_transaction, False)
170 cu.execute("select name from transactiontest where name=?", ["foo"])
171 row = cu.fetchone()
172 self.assertEqual(cx.in_transaction, False)
173
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100174 def test_in_transaction_ro(self):
R. David Murrayd35251d2010-06-01 01:32:12 +0000175 with self.assertRaises(AttributeError):
176 self.cx.in_transaction = True
177
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100178 def test_open_with_path_like_object(self):
Ville Skyttä61f82e02018-04-20 23:08:45 +0300179 """ Checks that we can successfully connect to a database using an object that
Anders Lorentsena22a1272017-11-07 01:47:43 +0100180 is PathLike, i.e. has __fspath__(). """
181 self.addCleanup(unlink, TESTFN)
182 class Path:
183 def __fspath__(self):
184 return TESTFN
185 path = Path()
186 with sqlite.connect(path) as cx:
187 cx.execute('create table test(id integer)')
188
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100189 def test_open_uri(self):
Antoine Pitrou902fc8b2013-02-10 00:02:44 +0100190 self.addCleanup(unlink, TESTFN)
191 with sqlite.connect(TESTFN) as cx:
192 cx.execute('create table test(id integer)')
193 with sqlite.connect('file:' + TESTFN, uri=True) as cx:
194 cx.execute('insert into test(id) values(0)')
195 with sqlite.connect('file:' + TESTFN + '?mode=ro', uri=True) as cx:
196 with self.assertRaises(sqlite.OperationalError):
197 cx.execute('insert into test(id) values(1)')
198
199
Erlend Egeberg Aasland0cb470e2021-07-30 14:01:22 +0200200class UninitialisedConnectionTests(unittest.TestCase):
201 def setUp(self):
202 self.cx = sqlite.Connection.__new__(sqlite.Connection)
203
204 def test_uninit_operations(self):
205 funcs = (
206 lambda: self.cx.isolation_level,
207 lambda: self.cx.total_changes,
208 lambda: self.cx.in_transaction,
209 lambda: self.cx.iterdump(),
210 lambda: self.cx.cursor(),
211 lambda: self.cx.close(),
212 )
213 for func in funcs:
214 with self.subTest(func=func):
215 self.assertRaisesRegex(sqlite.ProgrammingError,
216 "Base Connection.__init__ not called",
217 func)
218
219
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000220class CursorTests(unittest.TestCase):
221 def setUp(self):
222 self.cx = sqlite.connect(":memory:")
223 self.cu = self.cx.cursor()
Berker Peksage0b70cd2016-06-14 15:25:36 +0300224 self.cu.execute(
225 "create table test(id integer primary key, name text, "
226 "income number, unique_test text unique)"
227 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000228 self.cu.execute("insert into test(name) values (?)", ("foo",))
229
230 def tearDown(self):
231 self.cu.close()
232 self.cx.close()
233
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100234 def test_execute_no_args(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000235 self.cu.execute("delete from test")
236
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100237 def test_execute_illegal_sql(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300238 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000239 self.cu.execute("select asdf")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000240
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100241 def test_execute_too_much_sql(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300242 with self.assertRaises(sqlite.Warning):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000243 self.cu.execute("select 5+4; select 4+5")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000244
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100245 def test_execute_too_much_sql2(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000246 self.cu.execute("select 5+4; -- foo bar")
247
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100248 def test_execute_too_much_sql3(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000249 self.cu.execute("""
250 select 5+4;
251
252 /*
253 foo
254 */
255 """)
256
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100257 def test_execute_wrong_sql_arg(self):
Victor Stinnerc6a23202019-06-26 03:16:24 +0200258 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000259 self.cu.execute(42)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000260
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100261 def test_execute_arg_int(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000262 self.cu.execute("insert into test(id) values (?)", (42,))
263
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100264 def test_execute_arg_float(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000265 self.cu.execute("insert into test(income) values (?)", (2500.32,))
266
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100267 def test_execute_arg_string(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000268 self.cu.execute("insert into test(name) values (?)", ("Hugo",))
269
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100270 def test_execute_arg_string_with_zero_byte(self):
Petri Lehtinen023fe332012-02-01 22:18:19 +0200271 self.cu.execute("insert into test(name) values (?)", ("Hu\x00go",))
272
273 self.cu.execute("select name from test where id=?", (self.cu.lastrowid,))
274 row = self.cu.fetchone()
275 self.assertEqual(row[0], "Hu\x00go")
276
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100277 def test_execute_non_iterable(self):
Berker Peksagc4154402016-06-12 13:41:47 +0300278 with self.assertRaises(ValueError) as cm:
279 self.cu.execute("insert into test(id) values (?)", 42)
280 self.assertEqual(str(cm.exception), 'parameters are of unsupported type')
281
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100282 def test_execute_wrong_no_of_args1(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000283 # too many parameters
Berker Peksag1003b342016-06-12 22:34:49 +0300284 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000285 self.cu.execute("insert into test(id) values (?)", (17, "Egon"))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000286
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100287 def test_execute_wrong_no_of_args2(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000288 # too little parameters
Berker Peksag1003b342016-06-12 22:34:49 +0300289 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000290 self.cu.execute("insert into test(id) values (?)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000291
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100292 def test_execute_wrong_no_of_args3(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000293 # no parameters, parameters are needed
Berker Peksag1003b342016-06-12 22:34:49 +0300294 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000295 self.cu.execute("insert into test(id) values (?)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000296
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100297 def test_execute_param_list(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000298 self.cu.execute("insert into test(name) values ('foo')")
299 self.cu.execute("select name from test where name=?", ["foo"])
300 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000301 self.assertEqual(row[0], "foo")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000302
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100303 def test_execute_param_sequence(self):
Serhiy Storchaka0b419b72020-09-17 10:35:44 +0300304 class L:
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000305 def __len__(self):
306 return 1
307 def __getitem__(self, x):
308 assert x == 0
309 return "foo"
310
311 self.cu.execute("insert into test(name) values ('foo')")
312 self.cu.execute("select name from test where name=?", L())
313 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000314 self.assertEqual(row[0], "foo")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000315
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100316 def test_execute_param_sequence_bad_len(self):
Serhiy Storchaka0b419b72020-09-17 10:35:44 +0300317 # Issue41662: Error in __len__() was overridden with ProgrammingError.
318 class L:
319 def __len__(self):
320 1/0
321 def __getitem__(slf, x):
322 raise AssertionError
323
324 self.cu.execute("insert into test(name) values ('foo')")
325 with self.assertRaises(ZeroDivisionError):
326 self.cu.execute("select name from test where name=?", L())
327
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100328 def test_execute_dict_mapping(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000329 self.cu.execute("insert into test(name) values ('foo')")
330 self.cu.execute("select name from test where name=:name", {"name": "foo"})
331 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000332 self.assertEqual(row[0], "foo")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000333
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100334 def test_execute_dict_mapping_mapping(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000335 class D(dict):
336 def __missing__(self, key):
337 return "foo"
338
339 self.cu.execute("insert into test(name) values ('foo')")
340 self.cu.execute("select name from test where name=:name", D())
341 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000342 self.assertEqual(row[0], "foo")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000343
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100344 def test_execute_dict_mapping_too_little_args(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000345 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag1003b342016-06-12 22:34:49 +0300346 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000347 self.cu.execute("select name from test where name=:name and id=:id", {"name": "foo"})
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000348
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100349 def test_execute_dict_mapping_no_args(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000350 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag1003b342016-06-12 22:34:49 +0300351 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000352 self.cu.execute("select name from test where name=:name")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000353
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100354 def test_execute_dict_mapping_unnamed(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000355 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag1003b342016-06-12 22:34:49 +0300356 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000357 self.cu.execute("select name from test where name=?", {"name": "foo"})
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000358
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100359 def test_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000360 self.cu.close()
361
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100362 def test_rowcount_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000363 self.cu.execute("delete from test")
364 self.cu.execute("insert into test(name) values ('foo')")
365 self.cu.execute("insert into test(name) values ('foo')")
366 self.cu.execute("update test set name='bar'")
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000367 self.assertEqual(self.cu.rowcount, 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000368
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100369 def test_rowcount_select(self):
Georg Brandlf78e02b2008-06-10 17:40:04 +0000370 """
371 pysqlite does not know the rowcount of SELECT statements, because we
372 don't fetch all rows after executing the select statement. The rowcount
373 has thus to be -1.
374 """
375 self.cu.execute("select 5 union select 6")
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000376 self.assertEqual(self.cu.rowcount, -1)
Georg Brandlf78e02b2008-06-10 17:40:04 +0000377
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100378 def test_rowcount_executemany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000379 self.cu.execute("delete from test")
380 self.cu.executemany("insert into test(name) values (?)", [(1,), (2,), (3,)])
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000381 self.assertEqual(self.cu.rowcount, 3)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000382
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100383 def test_total_changes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000384 self.cu.execute("insert into test(name) values ('foo')")
385 self.cu.execute("insert into test(name) values ('foo')")
Berker Peksag48b5c982016-06-14 00:42:50 +0300386 self.assertLess(2, self.cx.total_changes, msg='total changes reported wrong value')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000387
388 # Checks for executemany:
389 # Sequences are required by the DB-API, iterators
390 # enhancements in pysqlite.
391
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100392 def test_execute_many_sequence(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000393 self.cu.executemany("insert into test(income) values (?)", [(x,) for x in range(100, 110)])
394
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100395 def test_execute_many_iterator(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000396 class MyIter:
397 def __init__(self):
398 self.value = 5
399
Georg Brandla18af4e2007-04-21 15:47:16 +0000400 def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000401 if self.value == 10:
402 raise StopIteration
403 else:
404 self.value += 1
405 return (self.value,)
406
407 self.cu.executemany("insert into test(income) values (?)", MyIter())
408
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100409 def test_execute_many_generator(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000410 def mygen():
411 for i in range(5):
412 yield (i,)
413
414 self.cu.executemany("insert into test(income) values (?)", mygen())
415
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100416 def test_execute_many_wrong_sql_arg(self):
Victor Stinnerc6a23202019-06-26 03:16:24 +0200417 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000418 self.cu.executemany(42, [(3,)])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000419
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100420 def test_execute_many_select(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300421 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000422 self.cu.executemany("select ?", [(3,)])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000423
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100424 def test_execute_many_not_iterable(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300425 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000426 self.cu.executemany("insert into test(income) values (?)", 42)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000427
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100428 def test_fetch_iter(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000429 # Optional DB-API extension.
430 self.cu.execute("delete from test")
431 self.cu.execute("insert into test(id) values (?)", (5,))
432 self.cu.execute("insert into test(id) values (?)", (6,))
433 self.cu.execute("select id from test order by id")
434 lst = []
435 for row in self.cu:
436 lst.append(row[0])
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000437 self.assertEqual(lst[0], 5)
438 self.assertEqual(lst[1], 6)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000439
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100440 def test_fetchone(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000441 self.cu.execute("select name from test")
442 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000443 self.assertEqual(row[0], "foo")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000444 row = self.cu.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000445 self.assertEqual(row, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000446
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100447 def test_fetchone_no_statement(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000448 cur = self.cx.cursor()
449 row = cur.fetchone()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000450 self.assertEqual(row, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000451
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100452 def test_array_size(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000453 # must default ot 1
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000454 self.assertEqual(self.cu.arraysize, 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000455
456 # now set to 2
457 self.cu.arraysize = 2
458
459 # now make the query return 3 rows
460 self.cu.execute("delete from test")
461 self.cu.execute("insert into test(name) values ('A')")
462 self.cu.execute("insert into test(name) values ('B')")
463 self.cu.execute("insert into test(name) values ('C')")
464 self.cu.execute("select name from test")
465 res = self.cu.fetchmany()
466
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000467 self.assertEqual(len(res), 2)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000468
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100469 def test_fetchmany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000470 self.cu.execute("select name from test")
471 res = self.cu.fetchmany(100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000472 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000473 res = self.cu.fetchmany(100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000474 self.assertEqual(res, [])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000475
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100476 def test_fetchmany_kw_arg(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000477 """Checks if fetchmany works with keyword arguments"""
478 self.cu.execute("select name from test")
479 res = self.cu.fetchmany(size=100)
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000480 self.assertEqual(len(res), 1)
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000481
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100482 def test_fetchall(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000483 self.cu.execute("select name from test")
484 res = self.cu.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000485 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000486 res = self.cu.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000487 self.assertEqual(res, [])
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000488
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100489 def test_setinputsizes(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000490 self.cu.setinputsizes([3, 4, 5])
491
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100492 def test_setoutputsize(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000493 self.cu.setoutputsize(5, 0)
494
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100495 def test_setoutputsize_no_column(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000496 self.cu.setoutputsize(42)
497
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100498 def test_cursor_connection(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000499 # Optional DB-API extension.
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000500 self.assertEqual(self.cu.connection, self.cx)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000501
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100502 def test_wrong_cursor_callable(self):
Berker Peksag1003b342016-06-12 22:34:49 +0300503 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000504 def f(): pass
505 cur = self.cx.cursor(f)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000506
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100507 def test_cursor_wrong_class(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000508 class Foo: pass
509 foo = Foo()
Berker Peksag1003b342016-06-12 22:34:49 +0300510 with self.assertRaises(TypeError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000511 cur = sqlite.Cursor(foo)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000512
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100513 def test_last_row_id_on_replace(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300514 """
515 INSERT OR REPLACE and REPLACE INTO should produce the same behavior.
516 """
517 sql = '{} INTO test(id, unique_test) VALUES (?, ?)'
518 for statement in ('INSERT OR REPLACE', 'REPLACE'):
519 with self.subTest(statement=statement):
520 self.cu.execute(sql.format(statement), (1, 'foo'))
521 self.assertEqual(self.cu.lastrowid, 1)
522
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100523 def test_last_row_id_on_ignore(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300524 self.cu.execute(
525 "insert or ignore into test(unique_test) values (?)",
526 ('test',))
527 self.assertEqual(self.cu.lastrowid, 2)
528 self.cu.execute(
529 "insert or ignore into test(unique_test) values (?)",
530 ('test',))
531 self.assertEqual(self.cu.lastrowid, 2)
532
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100533 def test_last_row_id_insert_o_r(self):
Berker Peksage0b70cd2016-06-14 15:25:36 +0300534 results = []
535 for statement in ('FAIL', 'ABORT', 'ROLLBACK'):
536 sql = 'INSERT OR {} INTO test(unique_test) VALUES (?)'
537 with self.subTest(statement='INSERT OR {}'.format(statement)):
538 self.cu.execute(sql.format(statement), (statement,))
539 results.append((statement, self.cu.lastrowid))
540 with self.assertRaises(sqlite.IntegrityError):
541 self.cu.execute(sql.format(statement), (statement,))
542 results.append((statement, self.cu.lastrowid))
543 expected = [
544 ('FAIL', 2), ('FAIL', 2),
545 ('ABORT', 3), ('ABORT', 3),
546 ('ROLLBACK', 4), ('ROLLBACK', 4),
547 ]
548 self.assertEqual(results, expected)
549
550
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000551class ThreadTests(unittest.TestCase):
552 def setUp(self):
553 self.con = sqlite.connect(":memory:")
554 self.cur = self.con.cursor()
555 self.cur.execute("create table test(id integer primary key, name text, bin binary, ratio number, ts timestamp)")
556
557 def tearDown(self):
558 self.cur.close()
559 self.con.close()
560
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100561 def test_con_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000562 def run(con, errors):
563 try:
564 cur = con.cursor()
565 errors.append("did not raise ProgrammingError")
566 return
567 except sqlite.ProgrammingError:
568 return
569 except:
570 errors.append("raised wrong exception")
571
572 errors = []
573 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
574 t.start()
575 t.join()
576 if len(errors) > 0:
577 self.fail("\n".join(errors))
578
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100579 def test_con_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000580 def run(con, errors):
581 try:
582 con.commit()
583 errors.append("did not raise ProgrammingError")
584 return
585 except sqlite.ProgrammingError:
586 return
587 except:
588 errors.append("raised wrong exception")
589
590 errors = []
591 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
592 t.start()
593 t.join()
594 if len(errors) > 0:
595 self.fail("\n".join(errors))
596
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100597 def test_con_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000598 def run(con, errors):
599 try:
600 con.rollback()
601 errors.append("did not raise ProgrammingError")
602 return
603 except sqlite.ProgrammingError:
604 return
605 except:
606 errors.append("raised wrong exception")
607
608 errors = []
609 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
610 t.start()
611 t.join()
612 if len(errors) > 0:
613 self.fail("\n".join(errors))
614
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100615 def test_con_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000616 def run(con, errors):
617 try:
618 con.close()
619 errors.append("did not raise ProgrammingError")
620 return
621 except sqlite.ProgrammingError:
622 return
623 except:
624 errors.append("raised wrong exception")
625
626 errors = []
627 t = threading.Thread(target=run, kwargs={"con": self.con, "errors": errors})
628 t.start()
629 t.join()
630 if len(errors) > 0:
631 self.fail("\n".join(errors))
632
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100633 def test_cur_implicit_begin(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000634 def run(cur, errors):
635 try:
636 cur.execute("insert into test(name) values ('a')")
637 errors.append("did not raise ProgrammingError")
638 return
639 except sqlite.ProgrammingError:
640 return
641 except:
642 errors.append("raised wrong exception")
643
644 errors = []
645 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
646 t.start()
647 t.join()
648 if len(errors) > 0:
649 self.fail("\n".join(errors))
650
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100651 def test_cur_close(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000652 def run(cur, errors):
653 try:
654 cur.close()
655 errors.append("did not raise ProgrammingError")
656 return
657 except sqlite.ProgrammingError:
658 return
659 except:
660 errors.append("raised wrong exception")
661
662 errors = []
663 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
664 t.start()
665 t.join()
666 if len(errors) > 0:
667 self.fail("\n".join(errors))
668
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100669 def test_cur_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000670 def run(cur, errors):
671 try:
672 cur.execute("select name from test")
673 errors.append("did not raise ProgrammingError")
674 return
675 except sqlite.ProgrammingError:
676 return
677 except:
678 errors.append("raised wrong exception")
679
680 errors = []
681 self.cur.execute("insert into test(name) values ('a')")
682 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
683 t.start()
684 t.join()
685 if len(errors) > 0:
686 self.fail("\n".join(errors))
687
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100688 def test_cur_iter_next(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000689 def run(cur, errors):
690 try:
691 row = cur.fetchone()
692 errors.append("did not raise ProgrammingError")
693 return
694 except sqlite.ProgrammingError:
695 return
696 except:
697 errors.append("raised wrong exception")
698
699 errors = []
700 self.cur.execute("insert into test(name) values ('a')")
701 self.cur.execute("select name from test")
702 t = threading.Thread(target=run, kwargs={"cur": self.cur, "errors": errors})
703 t.start()
704 t.join()
705 if len(errors) > 0:
706 self.fail("\n".join(errors))
707
708class ConstructorTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100709 def test_date(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000710 d = sqlite.Date(2004, 10, 28)
711
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100712 def test_time(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000713 t = sqlite.Time(12, 39, 35)
714
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100715 def test_timestamp(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000716 ts = sqlite.Timestamp(2004, 10, 28, 12, 39, 35)
717
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100718 def test_date_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000719 d = sqlite.DateFromTicks(42)
720
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100721 def test_time_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000722 t = sqlite.TimeFromTicks(42)
723
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100724 def test_timestamp_from_ticks(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000725 ts = sqlite.TimestampFromTicks(42)
726
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100727 def test_binary(self):
Guido van Rossumbae07c92007-10-08 02:46:15 +0000728 b = sqlite.Binary(b"\0'")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000729
730class ExtensionTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100731 def test_script_string_sql(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000732 con = sqlite.connect(":memory:")
733 cur = con.cursor()
734 cur.executescript("""
735 -- bla bla
736 /* a stupid comment */
737 create table a(i);
738 insert into a(i) values (5);
739 """)
740 cur.execute("select i from a")
741 res = cur.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000742 self.assertEqual(res, 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000743
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100744 def test_script_syntax_error(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000745 con = sqlite.connect(":memory:")
746 cur = con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300747 with self.assertRaises(sqlite.OperationalError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000748 cur.executescript("create table test(x); asdf; create table test2(x)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000749
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100750 def test_script_error_normal(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000751 con = sqlite.connect(":memory:")
752 cur = con.cursor()
Berker Peksag1003b342016-06-12 22:34:49 +0300753 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000754 cur.executescript("create table test(sadfsadfdsa); select foo from hurz;")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000755
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100756 def test_cursor_executescript_as_bytes(self):
Berker Peksagc4154402016-06-12 13:41:47 +0300757 con = sqlite.connect(":memory:")
758 cur = con.cursor()
759 with self.assertRaises(ValueError) as cm:
760 cur.executescript(b"create table test(foo); insert into test(foo) values (5);")
761 self.assertEqual(str(cm.exception), 'script argument must be unicode.')
762
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100763 def test_connection_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000764 con = sqlite.connect(":memory:")
765 result = con.execute("select 5").fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000766 self.assertEqual(result, 5, "Basic test of Connection.execute")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000767
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100768 def test_connection_executemany(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000769 con = sqlite.connect(":memory:")
770 con.execute("create table test(foo)")
771 con.executemany("insert into test(foo) values (?)", [(3,), (4,)])
772 result = con.execute("select foo from test order by foo").fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000773 self.assertEqual(result[0][0], 3, "Basic test of Connection.executemany")
774 self.assertEqual(result[1][0], 4, "Basic test of Connection.executemany")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000775
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100776 def test_connection_executescript(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000777 con = sqlite.connect(":memory:")
778 con.executescript("create table test(foo); insert into test(foo) values (5);")
779 result = con.execute("select foo from test").fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000780 self.assertEqual(result, 5, "Basic test of Connection.executescript")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000781
Gerhard Häringf9cee222010-03-05 15:20:03 +0000782class ClosedConTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100783 def test_closed_con_cursor(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000784 con = sqlite.connect(":memory:")
785 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300786 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000787 cur = con.cursor()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000788
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100789 def test_closed_con_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000790 con = sqlite.connect(":memory:")
791 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300792 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000793 con.commit()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000794
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100795 def test_closed_con_rollback(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000796 con = sqlite.connect(":memory:")
797 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300798 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000799 con.rollback()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000800
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100801 def test_closed_cur_execute(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000802 con = sqlite.connect(":memory:")
803 cur = con.cursor()
804 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300805 with self.assertRaises(sqlite.ProgrammingError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000806 cur.execute("select 4")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000807
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100808 def test_closed_create_function(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000809 con = sqlite.connect(":memory:")
810 con.close()
811 def f(x): return 17
Berker Peksag1003b342016-06-12 22:34:49 +0300812 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000813 con.create_function("foo", 1, f)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000814
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100815 def test_closed_create_aggregate(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000816 con = sqlite.connect(":memory:")
817 con.close()
818 class Agg:
819 def __init__(self):
820 pass
821 def step(self, x):
822 pass
823 def finalize(self):
824 return 17
Berker Peksag1003b342016-06-12 22:34:49 +0300825 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000826 con.create_aggregate("foo", 1, Agg)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000827
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100828 def test_closed_set_authorizer(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000829 con = sqlite.connect(":memory:")
830 con.close()
831 def authorizer(*args):
832 return sqlite.DENY
Berker Peksag1003b342016-06-12 22:34:49 +0300833 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000834 con.set_authorizer(authorizer)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000835
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100836 def test_closed_set_progress_callback(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000837 con = sqlite.connect(":memory:")
838 con.close()
839 def progress(): pass
Berker Peksag1003b342016-06-12 22:34:49 +0300840 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000841 con.set_progress_handler(progress, 100)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000842
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100843 def test_closed_call(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000844 con = sqlite.connect(":memory:")
845 con.close()
Berker Peksag1003b342016-06-12 22:34:49 +0300846 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000847 con()
Gerhard Häringf9cee222010-03-05 15:20:03 +0000848
849class ClosedCurTests(unittest.TestCase):
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100850 def test_closed(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000851 con = sqlite.connect(":memory:")
852 cur = con.cursor()
853 cur.close()
854
855 for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"):
856 if method_name in ("execute", "executescript"):
857 params = ("select 4 union select 5",)
858 elif method_name == "executemany":
859 params = ("insert into foo(bar) values (?)", [(3,), (4,)])
860 else:
861 params = []
862
Berker Peksag1003b342016-06-12 22:34:49 +0300863 with self.assertRaises(sqlite.ProgrammingError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000864 method = getattr(cur, method_name)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000865 method(*params)
Gerhard Häringf9cee222010-03-05 15:20:03 +0000866
Berker Peksag4bf580d2016-09-07 02:04:34 +0300867
868class SqliteOnConflictTests(unittest.TestCase):
869 """
870 Tests for SQLite's "insert on conflict" feature.
871
872 See https://www.sqlite.org/lang_conflict.html for details.
873 """
874
875 def setUp(self):
876 self.cx = sqlite.connect(":memory:")
877 self.cu = self.cx.cursor()
878 self.cu.execute("""
879 CREATE TABLE test(
880 id INTEGER PRIMARY KEY, name TEXT, unique_name TEXT UNIQUE
881 );
882 """)
883
884 def tearDown(self):
885 self.cu.close()
886 self.cx.close()
887
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100888 def test_on_conflict_rollback_with_explicit_transaction(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300889 self.cx.isolation_level = None # autocommit mode
890 self.cu = self.cx.cursor()
891 # Start an explicit transaction.
892 self.cu.execute("BEGIN")
893 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
894 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
895 with self.assertRaises(sqlite.IntegrityError):
896 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
897 # Use connection to commit.
898 self.cx.commit()
899 self.cu.execute("SELECT name, unique_name from test")
900 # Transaction should have rolled back and nothing should be in table.
901 self.assertEqual(self.cu.fetchall(), [])
902
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100903 def test_on_conflict_abort_raises_with_explicit_transactions(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300904 # Abort cancels the current sql statement but doesn't change anything
905 # about the current transaction.
906 self.cx.isolation_level = None # autocommit mode
907 self.cu = self.cx.cursor()
908 # Start an explicit transaction.
909 self.cu.execute("BEGIN")
910 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
911 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
912 with self.assertRaises(sqlite.IntegrityError):
913 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
914 self.cx.commit()
915 self.cu.execute("SELECT name, unique_name FROM test")
916 # Expect the first two inserts to work, third to do nothing.
917 self.assertEqual(self.cu.fetchall(), [('abort_test', None), (None, 'foo',)])
918
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100919 def test_on_conflict_rollback_without_transaction(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300920 # Start of implicit transaction
921 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
922 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
923 with self.assertRaises(sqlite.IntegrityError):
924 self.cu.execute("INSERT OR ROLLBACK INTO test(unique_name) VALUES ('foo')")
925 self.cu.execute("SELECT name, unique_name FROM test")
926 # Implicit transaction is rolled back on error.
927 self.assertEqual(self.cu.fetchall(), [])
928
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100929 def test_on_conflict_abort_raises_without_transactions(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300930 # Abort cancels the current sql statement but doesn't change anything
931 # about the current transaction.
932 self.cu.execute("INSERT INTO test(name) VALUES ('abort_test')")
933 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
934 with self.assertRaises(sqlite.IntegrityError):
935 self.cu.execute("INSERT OR ABORT INTO test(unique_name) VALUES ('foo')")
936 # Make sure all other values were inserted.
937 self.cu.execute("SELECT name, unique_name FROM test")
938 self.assertEqual(self.cu.fetchall(), [('abort_test', None), (None, 'foo',)])
939
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100940 def test_on_conflict_fail(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300941 self.cu.execute("INSERT OR FAIL INTO test(unique_name) VALUES ('foo')")
942 with self.assertRaises(sqlite.IntegrityError):
943 self.cu.execute("INSERT OR FAIL INTO test(unique_name) VALUES ('foo')")
944 self.assertEqual(self.cu.fetchall(), [])
945
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100946 def test_on_conflict_ignore(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300947 self.cu.execute("INSERT OR IGNORE INTO test(unique_name) VALUES ('foo')")
948 # Nothing should happen.
949 self.cu.execute("INSERT OR IGNORE INTO test(unique_name) VALUES ('foo')")
950 self.cu.execute("SELECT unique_name FROM test")
951 self.assertEqual(self.cu.fetchall(), [('foo',)])
952
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100953 def test_on_conflict_replace(self):
Berker Peksag4bf580d2016-09-07 02:04:34 +0300954 self.cu.execute("INSERT OR REPLACE INTO test(name, unique_name) VALUES ('Data!', 'foo')")
955 # There shouldn't be an IntegrityError exception.
956 self.cu.execute("INSERT OR REPLACE INTO test(name, unique_name) VALUES ('Very different data!', 'foo')")
957 self.cu.execute("SELECT name, unique_name FROM test")
958 self.assertEqual(self.cu.fetchall(), [('Very different data!', 'foo')])
959
960
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000961def suite():
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100962 tests = [
963 ClosedConTests,
964 ClosedCurTests,
965 ConnectionTests,
966 ConstructorTests,
967 CursorTests,
968 ExtensionTests,
969 ModuleTests,
970 SqliteOnConflictTests,
971 ThreadTests,
Erlend Egeberg Aasland0cb470e2021-07-30 14:01:22 +0200972 UninitialisedConnectionTests,
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100973 ]
974 return unittest.TestSuite(
975 [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
976 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000977
978def test():
979 runner = unittest.TextTestRunner()
980 runner.run(suite())
981
982if __name__ == "__main__":
983 test()