blob: d4f7d622ed84821c39c6af0dea4fce88bc36ab34 [file] [log] [blame]
Anthony Baxterc51ee692006-04-01 00:57:31 +00001#-*- coding: ISO-8859-1 -*-
2# pysqlite2/test/transactions.py: tests transactions
3#
Gerhard Häring1cc60ed2008-02-29 22:08:41 +00004# Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de>
Anthony Baxterc51ee692006-04-01 00:57:31 +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
Gerhard Häring1cc60ed2008-02-29 22:08:41 +000024import sys
Anthony Baxterc51ee692006-04-01 00:57:31 +000025import os, unittest
26import sqlite3 as sqlite
27
28def get_db_path():
Anthony Baxter72289a62006-04-04 06:29:05 +000029 return "sqlite_testdb"
Anthony Baxterc51ee692006-04-01 00:57:31 +000030
31class TransactionTests(unittest.TestCase):
32 def setUp(self):
33 try:
34 os.remove(get_db_path())
Neal Norwitzce527882008-03-05 05:20:44 +000035 except OSError:
Anthony Baxterc51ee692006-04-01 00:57:31 +000036 pass
37
38 self.con1 = sqlite.connect(get_db_path(), timeout=0.1)
39 self.cur1 = self.con1.cursor()
40
41 self.con2 = sqlite.connect(get_db_path(), timeout=0.1)
42 self.cur2 = self.con2.cursor()
43
44 def tearDown(self):
45 self.cur1.close()
46 self.con1.close()
47
48 self.cur2.close()
49 self.con2.close()
50
Neal Norwitzce527882008-03-05 05:20:44 +000051 try:
52 os.unlink(get_db_path())
53 except OSError:
54 pass
Anthony Baxter72289a62006-04-04 06:29:05 +000055
Anthony Baxterc51ee692006-04-01 00:57:31 +000056 def CheckDMLdoesAutoCommitBefore(self):
57 self.cur1.execute("create table test(i)")
58 self.cur1.execute("insert into test(i) values (5)")
59 self.cur1.execute("create table test2(j)")
60 self.cur2.execute("select i from test")
61 res = self.cur2.fetchall()
62 self.failUnlessEqual(len(res), 1)
63
64 def CheckInsertStartsTransaction(self):
65 self.cur1.execute("create table test(i)")
66 self.cur1.execute("insert into test(i) values (5)")
67 self.cur2.execute("select i from test")
68 res = self.cur2.fetchall()
69 self.failUnlessEqual(len(res), 0)
70
71 def CheckUpdateStartsTransaction(self):
72 self.cur1.execute("create table test(i)")
73 self.cur1.execute("insert into test(i) values (5)")
74 self.con1.commit()
75 self.cur1.execute("update test set i=6")
76 self.cur2.execute("select i from test")
77 res = self.cur2.fetchone()[0]
78 self.failUnlessEqual(res, 5)
79
80 def CheckDeleteStartsTransaction(self):
81 self.cur1.execute("create table test(i)")
82 self.cur1.execute("insert into test(i) values (5)")
83 self.con1.commit()
84 self.cur1.execute("delete from test")
85 self.cur2.execute("select i from test")
86 res = self.cur2.fetchall()
87 self.failUnlessEqual(len(res), 1)
88
89 def CheckReplaceStartsTransaction(self):
90 self.cur1.execute("create table test(i)")
91 self.cur1.execute("insert into test(i) values (5)")
92 self.con1.commit()
93 self.cur1.execute("replace into test(i) values (6)")
94 self.cur2.execute("select i from test")
95 res = self.cur2.fetchall()
96 self.failUnlessEqual(len(res), 1)
97 self.failUnlessEqual(res[0][0], 5)
98
99 def CheckToggleAutoCommit(self):
100 self.cur1.execute("create table test(i)")
101 self.cur1.execute("insert into test(i) values (5)")
102 self.con1.isolation_level = None
103 self.failUnlessEqual(self.con1.isolation_level, None)
104 self.cur2.execute("select i from test")
105 res = self.cur2.fetchall()
106 self.failUnlessEqual(len(res), 1)
107
108 self.con1.isolation_level = "DEFERRED"
109 self.failUnlessEqual(self.con1.isolation_level , "DEFERRED")
110 self.cur1.execute("insert into test(i) values (5)")
111 self.cur2.execute("select i from test")
112 res = self.cur2.fetchall()
113 self.failUnlessEqual(len(res), 1)
114
115 def CheckRaiseTimeout(self):
116 self.cur1.execute("create table test(i)")
117 self.cur1.execute("insert into test(i) values (5)")
118 try:
119 self.cur2.execute("insert into test(i) values (5)")
120 self.fail("should have raised an OperationalError")
121 except sqlite.OperationalError:
122 pass
123 except:
124 self.fail("should have raised an OperationalError")
125
Gerhard Häring1cc60ed2008-02-29 22:08:41 +0000126 def CheckLocking(self):
127 """
128 This tests the improved concurrency with pysqlite 2.3.4. You needed
129 to roll back con2 before you could commit con1.
130 """
131 self.cur1.execute("create table test(i)")
132 self.cur1.execute("insert into test(i) values (5)")
133 try:
134 self.cur2.execute("insert into test(i) values (5)")
135 self.fail("should have raised an OperationalError")
136 except sqlite.OperationalError:
137 pass
138 except:
139 self.fail("should have raised an OperationalError")
140 # NO self.con2.rollback() HERE!!!
141 self.con1.commit()
142
Anthony Baxterc51ee692006-04-01 00:57:31 +0000143class SpecialCommandTests(unittest.TestCase):
144 def setUp(self):
145 self.con = sqlite.connect(":memory:")
146 self.cur = self.con.cursor()
147
148 def CheckVacuum(self):
149 self.cur.execute("create table test(i)")
150 self.cur.execute("insert into test(i) values (5)")
151 self.cur.execute("vacuum")
152
153 def CheckDropTable(self):
154 self.cur.execute("create table test(i)")
155 self.cur.execute("insert into test(i) values (5)")
156 self.cur.execute("drop table test")
157
158 def CheckPragma(self):
159 self.cur.execute("create table test(i)")
160 self.cur.execute("insert into test(i) values (5)")
161 self.cur.execute("pragma count_changes=1")
162
163 def tearDown(self):
164 self.cur.close()
165 self.con.close()
166
167def suite():
168 default_suite = unittest.makeSuite(TransactionTests, "Check")
169 special_command_suite = unittest.makeSuite(SpecialCommandTests, "Check")
170 return unittest.TestSuite((default_suite, special_command_suite))
171
172def test():
173 runner = unittest.TextTestRunner()
174 runner.run(suite())
175
176if __name__ == "__main__":
177 test()