blob: 80284902a1a6e95ea02a51a9e2c650750f0f1a31 [file] [log] [blame]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001# pysqlite2/test/transactions.py: tests transactions
2#
Erlend Egeberg Aaslanddeab1e52021-01-07 01:36:35 +01003# Copyright (C) 2005-2007 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
23import os, unittest
24import sqlite3 as sqlite
25
26def get_db_path():
27 return "sqlite_testdb"
28
29class TransactionTests(unittest.TestCase):
30 def setUp(self):
31 try:
32 os.remove(get_db_path())
Christian Heimesdd15f6c2008-03-16 00:07:10 +000033 except OSError:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000034 pass
35
36 self.con1 = sqlite.connect(get_db_path(), timeout=0.1)
37 self.cur1 = self.con1.cursor()
38
39 self.con2 = sqlite.connect(get_db_path(), timeout=0.1)
40 self.cur2 = self.con2.cursor()
41
42 def tearDown(self):
43 self.cur1.close()
44 self.con1.close()
45
46 self.cur2.close()
47 self.con2.close()
48
Christian Heimesdd15f6c2008-03-16 00:07:10 +000049 try:
50 os.unlink(get_db_path())
51 except OSError:
52 pass
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000053
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010054 def test_dml_does_not_auto_commit_before(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000055 self.cur1.execute("create table test(i)")
56 self.cur1.execute("insert into test(i) values (5)")
57 self.cur1.execute("create table test2(j)")
58 self.cur2.execute("select i from test")
59 res = self.cur2.fetchall()
Berker Peksagab994ed2016-09-11 12:57:15 +030060 self.assertEqual(len(res), 0)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000061
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010062 def test_insert_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000063 self.cur1.execute("create table test(i)")
64 self.cur1.execute("insert into test(i) values (5)")
65 self.cur2.execute("select i from test")
66 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000067 self.assertEqual(len(res), 0)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000068
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010069 def test_update_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000070 self.cur1.execute("create table test(i)")
71 self.cur1.execute("insert into test(i) values (5)")
72 self.con1.commit()
73 self.cur1.execute("update test set i=6")
74 self.cur2.execute("select i from test")
75 res = self.cur2.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000076 self.assertEqual(res, 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000077
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010078 def test_delete_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000079 self.cur1.execute("create table test(i)")
80 self.cur1.execute("insert into test(i) values (5)")
81 self.con1.commit()
82 self.cur1.execute("delete from test")
83 self.cur2.execute("select i from test")
84 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000085 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000086
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010087 def test_replace_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000088 self.cur1.execute("create table test(i)")
89 self.cur1.execute("insert into test(i) values (5)")
90 self.con1.commit()
91 self.cur1.execute("replace into test(i) values (6)")
92 self.cur2.execute("select i from test")
93 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000094 self.assertEqual(len(res), 1)
95 self.assertEqual(res[0][0], 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000096
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010097 def test_toggle_auto_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000098 self.cur1.execute("create table test(i)")
99 self.cur1.execute("insert into test(i) values (5)")
100 self.con1.isolation_level = None
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000101 self.assertEqual(self.con1.isolation_level, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000102 self.cur2.execute("select i from test")
103 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000104 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000105
106 self.con1.isolation_level = "DEFERRED"
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000107 self.assertEqual(self.con1.isolation_level , "DEFERRED")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000108 self.cur1.execute("insert into test(i) values (5)")
109 self.cur2.execute("select i from test")
110 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000111 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000112
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100113 def test_raise_timeout(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000114 self.cur1.execute("create table test(i)")
115 self.cur1.execute("insert into test(i) values (5)")
Berker Peksag1003b342016-06-12 22:34:49 +0300116 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000117 self.cur2.execute("insert into test(i) values (5)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000118
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100119 def test_locking(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000120 """
121 This tests the improved concurrency with pysqlite 2.3.4. You needed
122 to roll back con2 before you could commit con1.
123 """
124 self.cur1.execute("create table test(i)")
125 self.cur1.execute("insert into test(i) values (5)")
Berker Peksag1003b342016-06-12 22:34:49 +0300126 with self.assertRaises(sqlite.OperationalError):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000127 self.cur2.execute("insert into test(i) values (5)")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000128 # NO self.con2.rollback() HERE!!!
129 self.con1.commit()
130
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100131 def test_rollback_cursor_consistency(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000132 """
133 Checks if cursors on the connection are set into a "reset" state
134 when a rollback is done on the connection.
135 """
136 con = sqlite.connect(":memory:")
137 cur = con.cursor()
138 cur.execute("create table test(x)")
139 cur.execute("insert into test(x) values (5)")
140 cur.execute("select 1 union select 2 union select 3")
141
142 con.rollback()
Berker Peksag1003b342016-06-12 22:34:49 +0300143 with self.assertRaises(sqlite.InterfaceError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000144 cur.fetchall()
Gerhard Häringf9cee222010-03-05 15:20:03 +0000145
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000146class SpecialCommandTests(unittest.TestCase):
147 def setUp(self):
148 self.con = sqlite.connect(":memory:")
149 self.cur = self.con.cursor()
150
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100151 def test_drop_table(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000152 self.cur.execute("create table test(i)")
153 self.cur.execute("insert into test(i) values (5)")
154 self.cur.execute("drop table test")
155
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100156 def test_pragma(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000157 self.cur.execute("create table test(i)")
158 self.cur.execute("insert into test(i) values (5)")
159 self.cur.execute("pragma count_changes=1")
160
161 def tearDown(self):
162 self.cur.close()
163 self.con.close()
164
Berker Peksagab994ed2016-09-11 12:57:15 +0300165class TransactionalDDL(unittest.TestCase):
166 def setUp(self):
167 self.con = sqlite.connect(":memory:")
168
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100169 def test_ddl_does_not_autostart_transaction(self):
Berker Peksagab994ed2016-09-11 12:57:15 +0300170 # For backwards compatibility reasons, DDL statements should not
171 # implicitly start a transaction.
172 self.con.execute("create table test(i)")
173 self.con.rollback()
174 result = self.con.execute("select * from test").fetchall()
175 self.assertEqual(result, [])
176
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100177 def test_immediate_transactional_ddl(self):
Berker Peksag4a926ca2017-02-26 18:22:38 +0300178 # You can achieve transactional DDL by issuing a BEGIN
179 # statement manually.
180 self.con.execute("begin immediate")
181 self.con.execute("create table test(i)")
182 self.con.rollback()
183 with self.assertRaises(sqlite.OperationalError):
184 self.con.execute("select * from test")
185
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100186 def test_transactional_ddl(self):
Berker Peksagab994ed2016-09-11 12:57:15 +0300187 # You can achieve transactional DDL by issuing a BEGIN
188 # statement manually.
189 self.con.execute("begin")
190 self.con.execute("create table test(i)")
191 self.con.rollback()
192 with self.assertRaises(sqlite.OperationalError):
193 self.con.execute("select * from test")
194
195 def tearDown(self):
196 self.con.close()
197
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000198def suite():
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100199 tests = [
200 SpecialCommandTests,
201 TransactionTests,
202 TransactionalDDL,
203 ]
204 return unittest.TestSuite(
205 [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
206 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000207
208def test():
209 runner = unittest.TextTestRunner()
210 runner.run(suite())
211
212if __name__ == "__main__":
213 test()