blob: 45f1b04c69648f9d118b35f17c2038bc4051df0b [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
182 def CheckTransactionalDDL(self):
183 # You can achieve transactional DDL by issuing a BEGIN
184 # statement manually.
185 self.con.execute("begin")
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
191 def tearDown(self):
192 self.con.close()
193
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000194def suite():
195 default_suite = unittest.makeSuite(TransactionTests, "Check")
196 special_command_suite = unittest.makeSuite(SpecialCommandTests, "Check")
Berker Peksagab994ed2016-09-11 12:57:15 +0300197 ddl_suite = unittest.makeSuite(TransactionalDDL, "Check")
198 return unittest.TestSuite((default_suite, special_command_suite, ddl_suite))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000199
200def test():
201 runner = unittest.TextTestRunner()
202 runner.run(suite())
203
204if __name__ == "__main__":
205 test()