blob: 3b47ff174a0ad63e8e170e02c99978bf7ef28a39 [file] [log] [blame]
Petri Lehtinenf8547992012-02-02 17:17:36 +02001#-*- coding: iso-8859-1 -*-
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002# pysqlite2/test/transactions.py: tests transactions
3#
Gerhard Häringe7ea7452008-03-29 00:45:29 +00004# Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de>
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005#
6# This file is part of pysqlite.
7#
8# This software is provided 'as-is', without any express or implied
9# warranty. In no event will the authors be held liable for any damages
10# arising from the use of this software.
11#
12# Permission is granted to anyone to use this software for any purpose,
13# including commercial applications, and to alter it and redistribute it
14# freely, subject to the following restrictions:
15#
16# 1. The origin of this software must not be misrepresented; you must not
17# claim that you wrote the original software. If you use this software
18# in a product, an acknowledgment in the product documentation would be
19# appreciated but is not required.
20# 2. Altered source versions must be plainly marked as such, and must not be
21# misrepresented as being the original software.
22# 3. This notice may not be removed or altered from any source distribution.
23
24import os, unittest
25import sqlite3 as sqlite
26
27def get_db_path():
28 return "sqlite_testdb"
29
30class TransactionTests(unittest.TestCase):
31 def setUp(self):
32 try:
33 os.remove(get_db_path())
Christian Heimesdd15f6c2008-03-16 00:07:10 +000034 except OSError:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000035 pass
36
37 self.con1 = sqlite.connect(get_db_path(), timeout=0.1)
38 self.cur1 = self.con1.cursor()
39
40 self.con2 = sqlite.connect(get_db_path(), timeout=0.1)
41 self.cur2 = self.con2.cursor()
42
43 def tearDown(self):
44 self.cur1.close()
45 self.con1.close()
46
47 self.cur2.close()
48 self.con2.close()
49
Christian Heimesdd15f6c2008-03-16 00:07:10 +000050 try:
51 os.unlink(get_db_path())
52 except OSError:
53 pass
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000054
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010055 def test_dml_does_not_auto_commit_before(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000056 self.cur1.execute("create table test(i)")
57 self.cur1.execute("insert into test(i) values (5)")
58 self.cur1.execute("create table test2(j)")
59 self.cur2.execute("select i from test")
60 res = self.cur2.fetchall()
Berker Peksagab994ed2016-09-11 12:57:15 +030061 self.assertEqual(len(res), 0)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000062
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010063 def test_insert_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000064 self.cur1.execute("create table test(i)")
65 self.cur1.execute("insert into test(i) values (5)")
66 self.cur2.execute("select i from test")
67 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000068 self.assertEqual(len(res), 0)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000069
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010070 def test_update_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000071 self.cur1.execute("create table test(i)")
72 self.cur1.execute("insert into test(i) values (5)")
73 self.con1.commit()
74 self.cur1.execute("update test set i=6")
75 self.cur2.execute("select i from test")
76 res = self.cur2.fetchone()[0]
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000077 self.assertEqual(res, 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000078
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010079 def test_delete_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000080 self.cur1.execute("create table test(i)")
81 self.cur1.execute("insert into test(i) values (5)")
82 self.con1.commit()
83 self.cur1.execute("delete from test")
84 self.cur2.execute("select i from test")
85 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000086 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000087
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010088 def test_replace_starts_transaction(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000089 self.cur1.execute("create table test(i)")
90 self.cur1.execute("insert into test(i) values (5)")
91 self.con1.commit()
92 self.cur1.execute("replace into test(i) values (6)")
93 self.cur2.execute("select i from test")
94 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +000095 self.assertEqual(len(res), 1)
96 self.assertEqual(res[0][0], 5)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000097
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +010098 def test_toggle_auto_commit(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000099 self.cur1.execute("create table test(i)")
100 self.cur1.execute("insert into test(i) values (5)")
101 self.con1.isolation_level = None
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000102 self.assertEqual(self.con1.isolation_level, None)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000103 self.cur2.execute("select i from test")
104 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000105 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000106
107 self.con1.isolation_level = "DEFERRED"
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000108 self.assertEqual(self.con1.isolation_level , "DEFERRED")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000109 self.cur1.execute("insert into test(i) values (5)")
110 self.cur2.execute("select i from test")
111 res = self.cur2.fetchall()
Gregory P. Smith04cecaf2009-07-04 08:32:15 +0000112 self.assertEqual(len(res), 1)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000113
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100114 def test_raise_timeout(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000115 self.cur1.execute("create table test(i)")
116 self.cur1.execute("insert into test(i) values (5)")
Berker Peksag1003b342016-06-12 22:34:49 +0300117 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000118 self.cur2.execute("insert into test(i) values (5)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000119
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100120 def test_locking(self):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000121 """
122 This tests the improved concurrency with pysqlite 2.3.4. You needed
123 to roll back con2 before you could commit con1.
124 """
125 self.cur1.execute("create table test(i)")
126 self.cur1.execute("insert into test(i) values (5)")
Berker Peksag1003b342016-06-12 22:34:49 +0300127 with self.assertRaises(sqlite.OperationalError):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000128 self.cur2.execute("insert into test(i) values (5)")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000129 # NO self.con2.rollback() HERE!!!
130 self.con1.commit()
131
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100132 def test_rollback_cursor_consistency(self):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000133 """
134 Checks if cursors on the connection are set into a "reset" state
135 when a rollback is done on the connection.
136 """
137 con = sqlite.connect(":memory:")
138 cur = con.cursor()
139 cur.execute("create table test(x)")
140 cur.execute("insert into test(x) values (5)")
141 cur.execute("select 1 union select 2 union select 3")
142
143 con.rollback()
Berker Peksag1003b342016-06-12 22:34:49 +0300144 with self.assertRaises(sqlite.InterfaceError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000145 cur.fetchall()
Gerhard Häringf9cee222010-03-05 15:20:03 +0000146
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000147class SpecialCommandTests(unittest.TestCase):
148 def setUp(self):
149 self.con = sqlite.connect(":memory:")
150 self.cur = self.con.cursor()
151
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100152 def test_drop_table(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000153 self.cur.execute("create table test(i)")
154 self.cur.execute("insert into test(i) values (5)")
155 self.cur.execute("drop table test")
156
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100157 def test_pragma(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000158 self.cur.execute("create table test(i)")
159 self.cur.execute("insert into test(i) values (5)")
160 self.cur.execute("pragma count_changes=1")
161
162 def tearDown(self):
163 self.cur.close()
164 self.con.close()
165
Berker Peksagab994ed2016-09-11 12:57:15 +0300166class TransactionalDDL(unittest.TestCase):
167 def setUp(self):
168 self.con = sqlite.connect(":memory:")
169
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100170 def test_ddl_does_not_autostart_transaction(self):
Berker Peksagab994ed2016-09-11 12:57:15 +0300171 # For backwards compatibility reasons, DDL statements should not
172 # implicitly start a transaction.
173 self.con.execute("create table test(i)")
174 self.con.rollback()
175 result = self.con.execute("select * from test").fetchall()
176 self.assertEqual(result, [])
177
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100178 def test_immediate_transactional_ddl(self):
Berker Peksag4a926ca2017-02-26 18:22:38 +0300179 # You can achieve transactional DDL by issuing a BEGIN
180 # statement manually.
181 self.con.execute("begin immediate")
182 self.con.execute("create table test(i)")
183 self.con.rollback()
184 with self.assertRaises(sqlite.OperationalError):
185 self.con.execute("select * from test")
186
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100187 def test_transactional_ddl(self):
Berker Peksagab994ed2016-09-11 12:57:15 +0300188 # You can achieve transactional DDL by issuing a BEGIN
189 # statement manually.
190 self.con.execute("begin")
191 self.con.execute("create table test(i)")
192 self.con.rollback()
193 with self.assertRaises(sqlite.OperationalError):
194 self.con.execute("select * from test")
195
196 def tearDown(self):
197 self.con.close()
198
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000199def suite():
Erlend Egeberg Aasland849e3392021-01-07 01:05:07 +0100200 tests = [
201 SpecialCommandTests,
202 TransactionTests,
203 TransactionalDDL,
204 ]
205 return unittest.TestSuite(
206 [unittest.TestLoader().loadTestsFromTestCase(t) for t in tests]
207 )
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000208
209def test():
210 runner = unittest.TextTestRunner()
211 runner.run(suite())
212
213if __name__ == "__main__":
214 test()