blob: 85eb3b4fd78a91349324de7d61b565ba926fb2d9 [file] [log] [blame]
Anthony Baxter72289a62006-04-04 06:29:05 +00001#-*- coding: ISO-8859-1 -*-
2# pysqlite2/test/regression.py: pysqlite regression tests
3#
Gerhard Häring1cc60ed2008-02-29 22:08:41 +00004# Copyright (C) 2006-2007 Gerhard Häring <gh@ghaering.de>
Anthony Baxter72289a62006-04-04 06:29:05 +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 datetime
Anthony Baxter72289a62006-04-04 06:29:05 +000025import unittest
Gerhard Häring3e99c0a2006-04-23 15:24:26 +000026import sqlite3 as sqlite
Anthony Baxter72289a62006-04-04 06:29:05 +000027
28class RegressionTests(unittest.TestCase):
29 def setUp(self):
30 self.con = sqlite.connect(":memory:")
31
32 def tearDown(self):
33 self.con.close()
34
35 def CheckPragmaUserVersion(self):
36 # This used to crash pysqlite because this pragma command returns NULL for the column name
37 cur = self.con.cursor()
38 cur.execute("pragma user_version")
39
Gerhard Häring3e99c0a2006-04-23 15:24:26 +000040 def CheckPragmaSchemaVersion(self):
41 # This still crashed pysqlite <= 2.2.1
42 con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
43 try:
44 cur = self.con.cursor()
45 cur.execute("pragma schema_version")
46 finally:
47 cur.close()
48 con.close()
49
50 def CheckStatementReset(self):
51 # pysqlite 2.1.0 to 2.2.0 have the problem that not all statements are
52 # reset before a rollback, but only those that are still in the
53 # statement cache. The others are not accessible from the connection object.
54 con = sqlite.connect(":memory:", cached_statements=5)
55 cursors = [con.cursor() for x in xrange(5)]
56 cursors[0].execute("create table test(x)")
57 for i in range(10):
58 cursors[0].executemany("insert into test(x) values (?)", [(x,) for x in xrange(10)])
59
60 for i in range(5):
61 cursors[i].execute(" " * i + "select x from test")
62
63 con.rollback()
64
Gerhard Häring1541ef02006-06-13 22:24:47 +000065 def CheckColumnNameWithSpaces(self):
66 cur = self.con.cursor()
67 cur.execute('select 1 as "foo bar [datetime]"')
Gregory P. Smith1844b0d2009-07-04 08:42:10 +000068 self.assertEqual(cur.description[0][0], "foo bar")
Gerhard Häring1541ef02006-06-13 22:24:47 +000069
70 cur.execute('select 1 as "foo baz"')
Gregory P. Smith1844b0d2009-07-04 08:42:10 +000071 self.assertEqual(cur.description[0][0], "foo baz")
Gerhard Häring1541ef02006-06-13 22:24:47 +000072
Gerhard Häring1cc60ed2008-02-29 22:08:41 +000073 def CheckStatementFinalizationOnCloseDb(self):
74 # pysqlite versions <= 2.3.3 only finalized statements in the statement
75 # cache when closing the database. statements that were still
76 # referenced in cursors weren't closed an could provoke "
77 # "OperationalError: Unable to close due to unfinalised statements".
78 con = sqlite.connect(":memory:")
79 cursors = []
80 # default statement cache size is 100
81 for i in range(105):
82 cur = con.cursor()
83 cursors.append(cur)
84 cur.execute("select 1 x union select " + str(i))
85 con.close()
86
87 def CheckOnConflictRollback(self):
88 if sqlite.sqlite_version_info < (3, 2, 2):
89 return
90 con = sqlite.connect(":memory:")
91 con.execute("create table foo(x, unique(x) on conflict rollback)")
92 con.execute("insert into foo(x) values (1)")
93 try:
94 con.execute("insert into foo(x) values (1)")
95 except sqlite.DatabaseError:
96 pass
97 con.execute("insert into foo(x) values (2)")
98 try:
99 con.commit()
100 except sqlite.OperationalError:
101 self.fail("pysqlite knew nothing about the implicit ROLLBACK")
102
103 def CheckWorkaroundForBuggySqliteTransferBindings(self):
104 """
105 pysqlite would crash with older SQLite versions unless
106 a workaround is implemented.
107 """
Gerhard Häringf40f6842008-03-02 13:08:03 +0000108 self.con.execute("create table foo(bar)")
109 self.con.execute("drop table foo")
110 self.con.execute("create table foo(bar)")
Gerhard Häring1cc60ed2008-02-29 22:08:41 +0000111
112 def CheckEmptyStatement(self):
113 """
114 pysqlite used to segfault with SQLite versions 3.5.x. These return NULL
115 for "no-operation" statements
116 """
117 self.con.execute("")
118
119 def CheckUnicodeConnect(self):
120 """
121 With pysqlite 2.4.0 you needed to use a string or a APSW connection
122 object for opening database connections.
123
124 Formerly, both bytestrings and unicode strings used to work.
125
126 Let's make sure unicode strings work in the future.
127 """
128 con = sqlite.connect(u":memory:")
129 con.close()
130
131 def CheckTypeMapUsage(self):
132 """
133 pysqlite until 2.4.1 did not rebuild the row_cast_map when recompiling
134 a statement. This test exhibits the problem.
135 """
136 SELECT = "select * from foo"
137 con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES)
138 con.execute("create table foo(bar timestamp)")
139 con.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),))
140 con.execute(SELECT)
141 con.execute("drop table foo")
142 con.execute("create table foo(bar integer)")
143 con.execute("insert into foo(bar) values (5)")
144 con.execute(SELECT)
145
Georg Brandla24869a2008-07-16 22:33:18 +0000146 def CheckRegisterAdapter(self):
147 """
148 See issue 3312.
149 """
150 self.assertRaises(TypeError, sqlite.register_adapter, {}, None)
151
152 def CheckSetIsolationLevel(self):
153 """
154 See issue 3312.
155 """
156 con = sqlite.connect(":memory:")
157 self.assertRaises(UnicodeEncodeError, setattr, con,
158 "isolation_level", u"\xe9")
159
Gerhard Häring3bbb6722010-03-05 09:12:37 +0000160 def CheckCursorConstructorCallCheck(self):
161 """
162 Verifies that cursor methods check wether base class __init__ was called.
163 """
164 class Cursor(sqlite.Cursor):
165 def __init__(self, con):
166 pass
167
168 con = sqlite.connect(":memory:")
169 cur = Cursor(con)
170 try:
171 cur.execute("select 4+5").fetchall()
172 self.fail("should have raised ProgrammingError")
173 except sqlite.ProgrammingError:
174 pass
175 except:
176 self.fail("should have raised ProgrammingError")
177
178 def CheckConnectionConstructorCallCheck(self):
179 """
180 Verifies that connection methods check wether base class __init__ was called.
181 """
182 class Connection(sqlite.Connection):
183 def __init__(self, name):
184 pass
185
186 con = Connection(":memory:")
187 try:
188 cur = con.cursor()
189 self.fail("should have raised ProgrammingError")
190 except sqlite.ProgrammingError:
191 pass
192 except:
193 self.fail("should have raised ProgrammingError")
194
195 def CheckCursorRegistration(self):
196 """
197 Verifies that subclassed cursor classes are correctly registered with
198 the connection object, too. (fetch-across-rollback problem)
199 """
200 class Connection(sqlite.Connection):
201 def cursor(self):
202 return Cursor(self)
203
204 class Cursor(sqlite.Cursor):
205 def __init__(self, con):
206 sqlite.Cursor.__init__(self, con)
207
208 con = Connection(":memory:")
209 cur = con.cursor()
210 cur.execute("create table foo(x)")
211 cur.executemany("insert into foo(x) values (?)", [(3,), (4,), (5,)])
212 cur.execute("select x from foo")
213 con.rollback()
214 try:
215 cur.fetchall()
216 self.fail("should have raised InterfaceError")
217 except sqlite.InterfaceError:
218 pass
219 except:
220 self.fail("should have raised InterfaceError")
221
222 def CheckAutoCommit(self):
223 """
224 Verifies that creating a connection in autocommit mode works.
225 2.5.3 introduced a regression so that these could no longer
226 be created.
227 """
228 con = sqlite.connect(":memory:", isolation_level=None)
229
230 def CheckPragmaAutocommit(self):
231 """
232 Verifies that running a PRAGMA statement that does an autocommit does
233 work. This did not work in 2.5.3/2.5.4.
234 """
235 con = sqlite.connect(":memory:")
236 cur = con.cursor()
237 cur.execute("create table foo(bar)")
238 cur.execute("insert into foo(bar) values (5)")
239
240 cur.execute("pragma page_size")
241 row = cur.fetchone()
242
243 def CheckSetDict(self):
244 """
245 See http://bugs.python.org/issue7478
246
247 It was possible to successfully register callbacks that could not be
248 hashed. Return codes of PyDict_SetItem were not checked properly.
249 """
250 class NotHashable:
251 def __call__(self, *args, **kw):
252 pass
253 def __hash__(self):
254 raise TypeError()
255 var = NotHashable()
256 con = sqlite.connect(":memory:")
257 self.assertRaises(TypeError, con.create_function, var)
258 self.assertRaises(TypeError, con.create_aggregate, var)
259 self.assertRaises(TypeError, con.set_authorizer, var)
260 self.assertRaises(TypeError, con.set_progress_handler, var)
Gerhard Häring1cc60ed2008-02-29 22:08:41 +0000261
Anthony Baxter72289a62006-04-04 06:29:05 +0000262def suite():
263 regression_suite = unittest.makeSuite(RegressionTests, "Check")
264 return unittest.TestSuite((regression_suite,))
265
266def test():
267 runner = unittest.TextTestRunner()
268 runner.run(suite())
269
270if __name__ == "__main__":
271 test()