Skip to content

Commit e7ea745

Browse files
committed
Bring sqlite3 module up-to-date with what's now in 2.6. Almost. I intentionally
left out the stuff about creating a connection object from a APSW connection.
1 parent b1b9382 commit e7ea745

22 files changed

+582
-196
lines changed

Lib/sqlite3/test/dbapi.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#-*- coding: ISO-8859-1 -*-
22
# pysqlite2/test/dbapi.py: tests for DB-API compliance
33
#
4-
# Copyright (C) 2004-2005 Gerhard Häring <[email protected]>
4+
# Copyright (C) 2004-2007 Gerhard Häring <[email protected]>
55
#
66
# This file is part of pysqlite.
77
#
@@ -223,12 +223,41 @@ def CheckExecuteWrongNoOfArgs3(self):
223223
except sqlite.ProgrammingError:
224224
pass
225225

226+
def CheckExecuteParamList(self):
227+
self.cu.execute("insert into test(name) values ('foo')")
228+
self.cu.execute("select name from test where name=?", ["foo"])
229+
row = self.cu.fetchone()
230+
self.failUnlessEqual(row[0], "foo")
231+
232+
def CheckExecuteParamSequence(self):
233+
class L(object):
234+
def __len__(self):
235+
return 1
236+
def __getitem__(self, x):
237+
assert x == 0
238+
return "foo"
239+
240+
self.cu.execute("insert into test(name) values ('foo')")
241+
self.cu.execute("select name from test where name=?", L())
242+
row = self.cu.fetchone()
243+
self.failUnlessEqual(row[0], "foo")
244+
226245
def CheckExecuteDictMapping(self):
227246
self.cu.execute("insert into test(name) values ('foo')")
228247
self.cu.execute("select name from test where name=:name", {"name": "foo"})
229248
row = self.cu.fetchone()
230249
self.failUnlessEqual(row[0], "foo")
231250

251+
def CheckExecuteDictMapping_Mapping(self):
252+
class D(dict):
253+
def __missing__(self, key):
254+
return "foo"
255+
256+
self.cu.execute("insert into test(name) values ('foo')")
257+
self.cu.execute("select name from test where name=:name", D())
258+
row = self.cu.fetchone()
259+
self.failUnlessEqual(row[0], "foo")
260+
232261
def CheckExecuteDictMappingTooLittleArgs(self):
233262
self.cu.execute("insert into test(name) values ('foo')")
234263
try:
@@ -378,6 +407,12 @@ def CheckFetchmany(self):
378407
res = self.cu.fetchmany(100)
379408
self.failUnlessEqual(res, [])
380409

410+
def CheckFetchmanyKwArg(self):
411+
"""Checks if fetchmany works with keyword arguments"""
412+
self.cu.execute("select name from test")
413+
res = self.cu.fetchmany(size=100)
414+
self.failUnlessEqual(len(res), 1)
415+
381416
def CheckFetchall(self):
382417
self.cu.execute("select name from test")
383418
res = self.cu.fetchall()
@@ -609,20 +644,6 @@ def CheckScriptStringSql(self):
609644
res = cur.fetchone()[0]
610645
self.failUnlessEqual(res, 5)
611646

612-
def CheckScriptStringUnicode(self):
613-
con = sqlite.connect(":memory:")
614-
cur = con.cursor()
615-
cur.executescript("""
616-
create table a(i);
617-
insert into a(i) values (5);
618-
select i from a;
619-
delete from a;
620-
insert into a(i) values (6);
621-
""")
622-
cur.execute("select i from a")
623-
res = cur.fetchone()[0]
624-
self.failUnlessEqual(res, 6)
625-
626647
def CheckScriptErrorIncomplete(self):
627648
con = sqlite.connect(":memory:")
628649
cur = con.cursor()

Lib/sqlite3/test/factory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#-*- coding: ISO-8859-1 -*-
22
# pysqlite2/test/factory.py: tests for the various factories in pysqlite
33
#
4-
# Copyright (C) 2005 Gerhard Häring <[email protected]>
4+
# Copyright (C) 2005-2007 Gerhard Häring <[email protected]>
55
#
66
# This file is part of pysqlite.
77
#

Lib/sqlite3/test/hooks.py

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#-*- coding: ISO-8859-1 -*-
22
# pysqlite2/test/hooks.py: tests for various SQLite-specific hooks
33
#
4-
# Copyright (C) 2006 Gerhard Häring <[email protected]>
4+
# Copyright (C) 2006-2007 Gerhard Häring <[email protected]>
55
#
66
# This file is part of pysqlite.
77
#
@@ -105,9 +105,80 @@ def CheckDeregisterCollation(self):
105105
if not e.args[0].startswith("no such collation sequence"):
106106
self.fail("wrong OperationalError raised")
107107

108+
class ProgressTests(unittest.TestCase):
109+
def CheckProgressHandlerUsed(self):
110+
"""
111+
Test that the progress handler is invoked once it is set.
112+
"""
113+
con = sqlite.connect(":memory:")
114+
progress_calls = []
115+
def progress():
116+
progress_calls.append(None)
117+
return 0
118+
con.set_progress_handler(progress, 1)
119+
con.execute("""
120+
create table foo(a, b)
121+
""")
122+
self.failUnless(progress_calls)
123+
124+
125+
def CheckOpcodeCount(self):
126+
"""
127+
Test that the opcode argument is respected.
128+
"""
129+
con = sqlite.connect(":memory:")
130+
progress_calls = []
131+
def progress():
132+
progress_calls.append(None)
133+
return 0
134+
con.set_progress_handler(progress, 1)
135+
curs = con.cursor()
136+
curs.execute("""
137+
create table foo (a, b)
138+
""")
139+
first_count = len(progress_calls)
140+
progress_calls = []
141+
con.set_progress_handler(progress, 2)
142+
curs.execute("""
143+
create table bar (a, b)
144+
""")
145+
second_count = len(progress_calls)
146+
self.failUnless(first_count > second_count)
147+
148+
def CheckCancelOperation(self):
149+
"""
150+
Test that returning a non-zero value stops the operation in progress.
151+
"""
152+
con = sqlite.connect(":memory:")
153+
progress_calls = []
154+
def progress():
155+
progress_calls.append(None)
156+
return 1
157+
con.set_progress_handler(progress, 1)
158+
curs = con.cursor()
159+
self.assertRaises(
160+
sqlite.OperationalError,
161+
curs.execute,
162+
"create table bar (a, b)")
163+
164+
def CheckClearHandler(self):
165+
"""
166+
Test that setting the progress handler to None clears the previously set handler.
167+
"""
168+
con = sqlite.connect(":memory:")
169+
action = 0
170+
def progress():
171+
action = 1
172+
return 0
173+
con.set_progress_handler(progress, 1)
174+
con.set_progress_handler(None, 1)
175+
con.execute("select 1 union select 2 union select 3").fetchall()
176+
self.failUnlessEqual(action, 0, "progress handler was not cleared")
177+
108178
def suite():
109179
collation_suite = unittest.makeSuite(CollationTests, "Check")
110-
return unittest.TestSuite((collation_suite,))
180+
progress_suite = unittest.makeSuite(ProgressTests, "Check")
181+
return unittest.TestSuite((collation_suite, progress_suite))
111182

112183
def test():
113184
runner = unittest.TextTestRunner()

Lib/sqlite3/test/regression.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
# misrepresented as being the original software.
2222
# 3. This notice may not be removed or altered from any source distribution.
2323

24+
import datetime
2425
import unittest
2526
import sqlite3 as sqlite
2627

@@ -79,6 +80,67 @@ def CheckStatementAvailable(self):
7980
cur.fetchone()
8081
cur.fetchone()
8182

83+
def CheckStatementFinalizationOnCloseDb(self):
84+
# pysqlite versions <= 2.3.3 only finalized statements in the statement
85+
# cache when closing the database. statements that were still
86+
# referenced in cursors weren't closed an could provoke "
87+
# "OperationalError: Unable to close due to unfinalised statements".
88+
con = sqlite.connect(":memory:")
89+
cursors = []
90+
# default statement cache size is 100
91+
for i in range(105):
92+
cur = con.cursor()
93+
cursors.append(cur)
94+
cur.execute("select 1 x union select " + str(i))
95+
con.close()
96+
97+
def CheckOnConflictRollback(self):
98+
if sqlite.sqlite_version_info < (3, 2, 2):
99+
return
100+
con = sqlite.connect(":memory:")
101+
con.execute("create table foo(x, unique(x) on conflict rollback)")
102+
con.execute("insert into foo(x) values (1)")
103+
try:
104+
con.execute("insert into foo(x) values (1)")
105+
except sqlite.DatabaseError:
106+
pass
107+
con.execute("insert into foo(x) values (2)")
108+
try:
109+
con.commit()
110+
except sqlite.OperationalError:
111+
self.fail("pysqlite knew nothing about the implicit ROLLBACK")
112+
113+
def CheckWorkaroundForBuggySqliteTransferBindings(self):
114+
"""
115+
pysqlite would crash with older SQLite versions unless
116+
a workaround is implemented.
117+
"""
118+
self.con.execute("create table foo(bar)")
119+
self.con.execute("drop table foo")
120+
self.con.execute("create table foo(bar)")
121+
122+
def CheckEmptyStatement(self):
123+
"""
124+
pysqlite used to segfault with SQLite versions 3.5.x. These return NULL
125+
for "no-operation" statements
126+
"""
127+
self.con.execute("")
128+
129+
def CheckTypeMapUsage(self):
130+
"""
131+
pysqlite until 2.4.1 did not rebuild the row_cast_map when recompiling
132+
a statement. This test exhibits the problem.
133+
"""
134+
SELECT = "select * from foo"
135+
con = sqlite.connect(":memory:",detect_types=sqlite.PARSE_DECLTYPES)
136+
con.execute("create table foo(bar timestamp)")
137+
con.execute("insert into foo(bar) values (?)", (datetime.datetime.now(),))
138+
con.execute(SELECT)
139+
con.execute("drop table foo")
140+
con.execute("create table foo(bar integer)")
141+
con.execute("insert into foo(bar) values (5)")
142+
con.execute(SELECT)
143+
82144
def CheckErrorMsgDecodeError(self):
83145
# When porting the module to Python 3.0, the error message about
84146
# decoding errors disappeared. This verifies they're back again.

Lib/sqlite3/test/transactions.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#-*- coding: ISO-8859-1 -*-
22
# pysqlite2/test/transactions.py: tests transactions
33
#
4-
# Copyright (C) 2005 Gerhard Häring <[email protected]>
4+
# Copyright (C) 2005-2007 Gerhard Häring <[email protected]>
55
#
66
# This file is part of pysqlite.
77
#
@@ -122,6 +122,23 @@ def CheckRaiseTimeout(self):
122122
except:
123123
self.fail("should have raised an OperationalError")
124124

125+
def CheckLocking(self):
126+
"""
127+
This tests the improved concurrency with pysqlite 2.3.4. You needed
128+
to roll back con2 before you could commit con1.
129+
"""
130+
self.cur1.execute("create table test(i)")
131+
self.cur1.execute("insert into test(i) values (5)")
132+
try:
133+
self.cur2.execute("insert into test(i) values (5)")
134+
self.fail("should have raised an OperationalError")
135+
except sqlite.OperationalError:
136+
pass
137+
except:
138+
self.fail("should have raised an OperationalError")
139+
# NO self.con2.rollback() HERE!!!
140+
self.con1.commit()
141+
125142
class SpecialCommandTests(unittest.TestCase):
126143
def setUp(self):
127144
self.con = sqlite.connect(":memory:")

Lib/sqlite3/test/types.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# misrepresented as being the original software.
2222
# 3. This notice may not be removed or altered from any source distribution.
2323

24-
import bz2, datetime
24+
import zlib, datetime
2525
import unittest
2626
import sqlite3 as sqlite
2727

@@ -221,11 +221,13 @@ def setUp(self):
221221
self.cur = self.con.cursor()
222222
self.cur.execute("create table test(x foo)")
223223

224-
sqlite.converters["BAR"] = lambda x: b"<" + x + b">"
224+
sqlite.converters["FOO"] = lambda x: "[%s]" % x.decode("ascii")
225+
sqlite.converters["BAR"] = lambda x: "<%s>" % x.decode("ascii")
225226
sqlite.converters["EXC"] = lambda x: 5/0
226227
sqlite.converters["B1B1"] = lambda x: "MARKER"
227228

228229
def tearDown(self):
230+
del sqlite.converters["FOO"]
229231
del sqlite.converters["BAR"]
230232
del sqlite.converters["EXC"]
231233
del sqlite.converters["B1B1"]
@@ -252,7 +254,7 @@ def CheckColName(self):
252254
self.cur.execute("insert into test(x) values (?)", ("xxx",))
253255
self.cur.execute('select x as "x [bar]" from test')
254256
val = self.cur.fetchone()[0]
255-
self.failUnlessEqual(val, b"<xxx>")
257+
self.failUnlessEqual(val, "<xxx>")
256258

257259
# Check if the stripping of colnames works. Everything after the first
258260
# whitespace should be stripped.
@@ -297,7 +299,7 @@ def CheckCasterIsUsed(self):
297299

298300
class BinaryConverterTests(unittest.TestCase):
299301
def convert(s):
300-
return bz2.decompress(s)
302+
return zlib.decompress(s)
301303
convert = staticmethod(convert)
302304

303305
def setUp(self):
@@ -309,7 +311,7 @@ def tearDown(self):
309311

310312
def CheckBinaryInputForConverter(self):
311313
testdata = b"abcdefg" * 10
312-
result = self.con.execute('select ? as "x [bin]"', (memoryview(bz2.compress(testdata)),)).fetchone()[0]
314+
result = self.con.execute('select ? as "x [bin]"', (memoryview(zlib.compress(testdata)),)).fetchone()[0]
313315
self.failUnlessEqual(testdata, result)
314316

315317
class DateTimeTests(unittest.TestCase):
@@ -341,7 +343,8 @@ def CheckSqlTimestamp(self):
341343
if sqlite.sqlite_version_info < (3, 1):
342344
return
343345

344-
now = datetime.datetime.utcnow()
346+
# SQLite's current_timestamp uses UTC time, while datetime.datetime.now() uses local time.
347+
now = datetime.datetime.now()
345348
self.cur.execute("insert into test(ts) values (current_timestamp)")
346349
self.cur.execute("select ts from test")
347350
ts = self.cur.fetchone()[0]

Modules/_sqlite/cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* cache .c - a LRU cache
22
*
3-
* Copyright (C) 2004-2006 Gerhard Häring <[email protected]>
3+
* Copyright (C) 2004-2007 Gerhard Häring <[email protected]>
44
*
55
* This file is part of pysqlite.
66
*

Modules/_sqlite/cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* cache.h - definitions for the LRU cache
22
*
3-
* Copyright (C) 2004-2006 Gerhard Häring <[email protected]>
3+
* Copyright (C) 2004-2007 Gerhard Häring <[email protected]>
44
*
55
* This file is part of pysqlite.
66
*

0 commit comments

Comments
 (0)