blob: b8a13de55bc7209baadf2786ec10375e9e6e2b3f [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
Berker Peksagab994ed2016-09-11 12:57:15 +030055 def CheckDMLDoesNotAutoCommitBefore(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
63 def CheckInsertStartsTransaction(self):
64 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
70 def CheckUpdateStartsTransaction(self):
71 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
79 def CheckDeleteStartsTransaction(self):
80 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
88 def CheckReplaceStartsTransaction(self):
89 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
98 def CheckToggleAutoCommit(self):
99 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
Berker Peksagf85bce72016-06-14 14:19:02 +0300114 @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2),
115 'test hangs on sqlite versions older than 3.2.2')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000116 def CheckRaiseTimeout(self):
117 self.cur1.execute("create table test(i)")
118 self.cur1.execute("insert into test(i) values (5)")
Berker Peksag1003b342016-06-12 22:34:49 +0300119 with self.assertRaises(sqlite.OperationalError):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000120 self.cur2.execute("insert into test(i) values (5)")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000121
Berker Peksagf85bce72016-06-14 14:19:02 +0300122 @unittest.skipIf(sqlite.sqlite_version_info < (3, 2, 2),
123 'test hangs on sqlite versions older than 3.2.2')
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000124 def CheckLocking(self):
125 """
126 This tests the improved concurrency with pysqlite 2.3.4. You needed
127 to roll back con2 before you could commit con1.
128 """
129 self.cur1.execute("create table test(i)")
130 self.cur1.execute("insert into test(i) values (5)")
Berker Peksag1003b342016-06-12 22:34:49 +0300131 with self.assertRaises(sqlite.OperationalError):
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000132 self.cur2.execute("insert into test(i) values (5)")
Gerhard Häringe7ea7452008-03-29 00:45:29 +0000133 # NO self.con2.rollback() HERE!!!
134 self.con1.commit()
135
Gerhard Häringf9cee222010-03-05 15:20:03 +0000136 def CheckRollbackCursorConsistency(self):
137 """
138 Checks if cursors on the connection are set into a "reset" state
139 when a rollback is done on the connection.
140 """
141 con = sqlite.connect(":memory:")
142 cur = con.cursor()
143 cur.execute("create table test(x)")
144 cur.execute("insert into test(x) values (5)")
145 cur.execute("select 1 union select 2 union select 3")
146
147 con.rollback()
Berker Peksag1003b342016-06-12 22:34:49 +0300148 with self.assertRaises(sqlite.InterfaceError):
Gerhard Häringf9cee222010-03-05 15:20:03 +0000149 cur.fetchall()
Gerhard Häringf9cee222010-03-05 15:20:03 +0000150
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000151class SpecialCommandTests(unittest.TestCase):
152 def setUp(self):
153 self.con = sqlite.connect(":memory:")
154 self.cur = self.con.cursor()
155
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156 def CheckDropTable(self):
157 self.cur.execute("create table test(i)")
158 self.cur.execute("insert into test(i) values (5)")
159 self.cur.execute("drop table test")
160
161 def CheckPragma(self):
162 self.cur.execute("create table test(i)")
163 self.cur.execute("insert into test(i) values (5)")
164 self.cur.execute("pragma count_changes=1")
165
166 def tearDown(self):
167 self.cur.close()
168 self.con.close()
169
Berker Peksagab994ed2016-09-11 12:57:15 +0300170class TransactionalDDL(unittest.TestCase):
171 def setUp(self):
172 self.con = sqlite.connect(":memory:")
173
174 def CheckDdlDoesNotAutostartTransaction(self):
175 # For backwards compatibility reasons, DDL statements should not
176 # implicitly start a transaction.
177 self.con.execute("create table test(i)")
178 self.con.rollback()
179 result = self.con.execute("select * from test").fetchall()
180 self.assertEqual(result, [])
181
Berker Peksag4a926ca2017-02-26 18:22:38 +0300182 def CheckImmediateTransactionalDDL(self):
183 # You can achieve transactional DDL by issuing a BEGIN
184 # statement manually.
185 self.con.execute("begin immediate")
186 self.con.execute("create table test(i)")
187 self.con.rollback()
188 with self.assertRaises(sqlite.OperationalError):
189 self.con.execute("select * from test")
190
Berker Peksagab994ed2016-09-11 12:57:15 +0300191 def CheckTransactionalDDL(self):
192 # You can achieve transactional DDL by issuing a BEGIN
193 # statement manually.
194 self.con.execute("begin")
195 self.con.execute("create table test(i)")
196 self.con.rollback()
197 with self.assertRaises(sqlite.OperationalError):
198 self.con.execute("select * from test")
199
200 def tearDown(self):
201 self.con.close()
202
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000203def suite():
204 default_suite = unittest.makeSuite(TransactionTests, "Check")
205 special_command_suite = unittest.makeSuite(SpecialCommandTests, "Check")
Berker Peksagab994ed2016-09-11 12:57:15 +0300206 ddl_suite = unittest.makeSuite(TransactionalDDL, "Check")
207 return unittest.TestSuite((default_suite, special_command_suite, ddl_suite))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000208
209def test():
210 runner = unittest.TextTestRunner()
211 runner.run(suite())
212
213if __name__ == "__main__":
214 test()