Skip to content

Commit f9cee22

Browse files
committed
Merged new pysqlite version 2.6.0 from trunk.
1 parent 06dbff3 commit f9cee22

File tree

24 files changed

+601
-128
lines changed

24 files changed

+601
-128
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import sqlite3
2+
3+
con = sqlite3.connect(":memory:")
4+
5+
# enable extension loading
6+
con.enable_load_extension(True)
7+
8+
# Load the fulltext search extension
9+
con.execute("select load_extension('./fts3.so')")
10+
11+
# alternatively you can load the extension using an API call:
12+
# con.load_extension("./fts3.so")
13+
14+
# disable extension laoding again
15+
con.enable_load_extension(False)
16+
17+
# example from SQLite wiki
18+
con.execute("create virtual table recipe using fts3(name, ingredients)")
19+
con.executescript("""
20+
insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes');
21+
insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery');
22+
insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour');
23+
insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter');
24+
""")
25+
for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"):
26+
print row

Doc/library/sqlite3.rst

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,25 @@ Connection Objects
365365
method with :const:`None` for *handler*.
366366

367367

368+
.. method:: Connection.enable_load_extension(enabled)
369+
370+
.. versionadded:: 2.7
371+
372+
This routine allows/disallows the SQLite engine to load SQLite extensions
373+
from shared libraries. SQLite extensions can define new functions,
374+
aggregates or whole new virtual table implementations. One well-known
375+
extension is the fulltext-search extension distributed with SQLite.
376+
377+
.. literalinclude:: ../includes/sqlite3/load_extension.py
378+
379+
.. method:: Connection.load_extension(path)
380+
381+
.. versionadded:: 2.7
382+
383+
This routine loads a SQLite extension from a shared library. You have to
384+
enable extension loading with ``enable_load_extension`` before you can use
385+
this routine.
386+
368387
.. attribute:: Connection.row_factory
369388

370389
You can change this attribute to a callable that accepts the cursor and the
@@ -434,7 +453,7 @@ Connection Objects
434453
Cursor Objects
435454
--------------
436455

437-
.. class:: Cursor
456+
A :class:`Cursor` instance has the following attributes and methods:
438457

439458
A SQLite database cursor has the following attributes and methods:
440459

Lib/sqlite3/test/dbapi.py

Lines changed: 104 additions & 7 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-2007 Gerhard Häring <gh@ghaering.de>
4+
# Copyright (C) 2004-2010 Gerhard Häring <gh@ghaering.de>
55
#
66
# This file is part of pysqlite.
77
#
@@ -653,13 +653,13 @@ def CheckScriptStringSql(self):
653653
res = cur.fetchone()[0]
654654
self.assertEqual(res, 5)
655655

656-
def CheckScriptErrorIncomplete(self):
656+
def CheckScriptSyntaxError(self):
657657
con = sqlite.connect(":memory:")
658658
cur = con.cursor()
659659
raised = False
660660
try:
661-
cur.executescript("create table test(sadfsadfdsa")
662-
except sqlite.ProgrammingError:
661+
cur.executescript("create table test(x); asdf; create table test2(x)")
662+
except sqlite.OperationalError:
663663
raised = True
664664
self.assertEqual(raised, True, "should have raised an exception")
665665

@@ -692,7 +692,7 @@ def CheckConnectionExecutescript(self):
692692
result = con.execute("select foo from test").fetchone()[0]
693693
self.assertEqual(result, 5, "Basic test of Connection.executescript")
694694

695-
class ClosedTests(unittest.TestCase):
695+
class ClosedConTests(unittest.TestCase):
696696
def setUp(self):
697697
pass
698698

@@ -744,15 +744,112 @@ def CheckClosedCurExecute(self):
744744
except:
745745
self.fail("Should have raised a ProgrammingError")
746746

747+
def CheckClosedCreateFunction(self):
748+
con = sqlite.connect(":memory:")
749+
con.close()
750+
def f(x): return 17
751+
try:
752+
con.create_function("foo", 1, f)
753+
self.fail("Should have raised a ProgrammingError")
754+
except sqlite.ProgrammingError:
755+
pass
756+
except:
757+
self.fail("Should have raised a ProgrammingError")
758+
759+
def CheckClosedCreateAggregate(self):
760+
con = sqlite.connect(":memory:")
761+
con.close()
762+
class Agg:
763+
def __init__(self):
764+
pass
765+
def step(self, x):
766+
pass
767+
def finalize(self):
768+
return 17
769+
try:
770+
con.create_aggregate("foo", 1, Agg)
771+
self.fail("Should have raised a ProgrammingError")
772+
except sqlite.ProgrammingError:
773+
pass
774+
except:
775+
self.fail("Should have raised a ProgrammingError")
776+
777+
def CheckClosedSetAuthorizer(self):
778+
con = sqlite.connect(":memory:")
779+
con.close()
780+
def authorizer(*args):
781+
return sqlite.DENY
782+
try:
783+
con.set_authorizer(authorizer)
784+
self.fail("Should have raised a ProgrammingError")
785+
except sqlite.ProgrammingError:
786+
pass
787+
except:
788+
self.fail("Should have raised a ProgrammingError")
789+
790+
def CheckClosedSetProgressCallback(self):
791+
con = sqlite.connect(":memory:")
792+
con.close()
793+
def progress(): pass
794+
try:
795+
con.set_progress_handler(progress, 100)
796+
self.fail("Should have raised a ProgrammingError")
797+
except sqlite.ProgrammingError:
798+
pass
799+
except:
800+
self.fail("Should have raised a ProgrammingError")
801+
802+
def CheckClosedCall(self):
803+
con = sqlite.connect(":memory:")
804+
con.close()
805+
try:
806+
con()
807+
self.fail("Should have raised a ProgrammingError")
808+
except sqlite.ProgrammingError:
809+
pass
810+
except:
811+
self.fail("Should have raised a ProgrammingError")
812+
813+
class ClosedCurTests(unittest.TestCase):
814+
def setUp(self):
815+
pass
816+
817+
def tearDown(self):
818+
pass
819+
820+
def CheckClosed(self):
821+
con = sqlite.connect(":memory:")
822+
cur = con.cursor()
823+
cur.close()
824+
825+
for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"):
826+
if method_name in ("execute", "executescript"):
827+
params = ("select 4 union select 5",)
828+
elif method_name == "executemany":
829+
params = ("insert into foo(bar) values (?)", [(3,), (4,)])
830+
else:
831+
params = []
832+
833+
try:
834+
method = getattr(cur, method_name)
835+
836+
method(*params)
837+
self.fail("Should have raised a ProgrammingError: method " + method_name)
838+
except sqlite.ProgrammingError:
839+
pass
840+
except:
841+
self.fail("Should have raised a ProgrammingError: " + method_name)
842+
747843
def suite():
748844
module_suite = unittest.makeSuite(ModuleTests, "Check")
749845
connection_suite = unittest.makeSuite(ConnectionTests, "Check")
750846
cursor_suite = unittest.makeSuite(CursorTests, "Check")
751847
thread_suite = unittest.makeSuite(ThreadTests, "Check")
752848
constructor_suite = unittest.makeSuite(ConstructorTests, "Check")
753849
ext_suite = unittest.makeSuite(ExtensionTests, "Check")
754-
closed_suite = unittest.makeSuite(ClosedTests, "Check")
755-
return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_suite))
850+
closed_con_suite = unittest.makeSuite(ClosedConTests, "Check")
851+
closed_cur_suite = unittest.makeSuite(ClosedCurTests, "Check")
852+
return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_con_suite, closed_cur_suite))
756853

757854
def test():
758855
runner = unittest.TextTestRunner()

Lib/sqlite3/test/regression.py

Lines changed: 104 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#-*- coding: ISO-8859-1 -*-
22
# pysqlite2/test/regression.py: pysqlite regression tests
33
#
4-
# Copyright (C) 2006 Gerhard Häring <gh@ghaering.de>
4+
# Copyright (C) 2006-2010 Gerhard Häring <gh@ghaering.de>
55
#
66
# This file is part of pysqlite.
77
#
@@ -70,16 +70,6 @@ def CheckColumnNameWithSpaces(self):
7070
cur.execute('select 1 as "foo baz"')
7171
self.assertEqual(cur.description[0][0], "foo baz")
7272

73-
def CheckStatementAvailable(self):
74-
# pysqlite up to 2.3.2 crashed on this, because the active statement handle was not checked
75-
# before trying to fetch data from it. close() destroys the active statement ...
76-
con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
77-
cur = con.cursor()
78-
cur.execute("select 4 union select 5")
79-
cur.close()
80-
cur.fetchone()
81-
cur.fetchone()
82-
8373
def CheckStatementFinalizationOnCloseDb(self):
8474
# pysqlite versions <= 2.3.3 only finalized statements in the statement
8575
# cache when closing the database. statements that were still
@@ -169,13 +159,116 @@ def CheckSetIsolationLevel(self):
169159
con = sqlite.connect(":memory:")
170160
setattr(con, "isolation_level", "\xe9")
171161

162+
def CheckCursorConstructorCallCheck(self):
163+
"""
164+
Verifies that cursor methods check wether base class __init__ was called.
165+
"""
166+
class Cursor(sqlite.Cursor):
167+
def __init__(self, con):
168+
pass
169+
170+
con = sqlite.connect(":memory:")
171+
cur = Cursor(con)
172+
try:
173+
cur.execute("select 4+5").fetchall()
174+
self.fail("should have raised ProgrammingError")
175+
except sqlite.ProgrammingError:
176+
pass
177+
except:
178+
self.fail("should have raised ProgrammingError")
179+
180+
172181
def CheckStrSubclass(self):
173182
"""
174183
The Python 3.0 port of the module didn't cope with values of subclasses of str.
175184
"""
176185
class MyStr(str): pass
177186
self.con.execute("select ?", (MyStr("abc"),))
178187

188+
def CheckConnectionConstructorCallCheck(self):
189+
"""
190+
Verifies that connection methods check wether base class __init__ was called.
191+
"""
192+
class Connection(sqlite.Connection):
193+
def __init__(self, name):
194+
pass
195+
196+
con = Connection(":memory:")
197+
try:
198+
cur = con.cursor()
199+
self.fail("should have raised ProgrammingError")
200+
except sqlite.ProgrammingError:
201+
pass
202+
except:
203+
self.fail("should have raised ProgrammingError")
204+
205+
def CheckCursorRegistration(self):
206+
"""
207+
Verifies that subclassed cursor classes are correctly registered with
208+
the connection object, too. (fetch-across-rollback problem)
209+
"""
210+
class Connection(sqlite.Connection):
211+
def cursor(self):
212+
return Cursor(self)
213+
214+
class Cursor(sqlite.Cursor):
215+
def __init__(self, con):
216+
sqlite.Cursor.__init__(self, con)
217+
218+
con = Connection(":memory:")
219+
cur = con.cursor()
220+
cur.execute("create table foo(x)")
221+
cur.executemany("insert into foo(x) values (?)", [(3,), (4,), (5,)])
222+
cur.execute("select x from foo")
223+
con.rollback()
224+
try:
225+
cur.fetchall()
226+
self.fail("should have raised InterfaceError")
227+
except sqlite.InterfaceError:
228+
pass
229+
except:
230+
self.fail("should have raised InterfaceError")
231+
232+
def CheckAutoCommit(self):
233+
"""
234+
Verifies that creating a connection in autocommit mode works.
235+
2.5.3 introduced a regression so that these could no longer
236+
be created.
237+
"""
238+
con = sqlite.connect(":memory:", isolation_level=None)
239+
240+
def CheckPragmaAutocommit(self):
241+
"""
242+
Verifies that running a PRAGMA statement that does an autocommit does
243+
work. This did not work in 2.5.3/2.5.4.
244+
"""
245+
con = sqlite.connect(":memory:")
246+
cur = con.cursor()
247+
cur.execute("create table foo(bar)")
248+
cur.execute("insert into foo(bar) values (5)")
249+
250+
cur.execute("pragma page_size")
251+
row = cur.fetchone()
252+
253+
def CheckSetDict(self):
254+
"""
255+
See http://bugs.python.org/issue7478
256+
257+
It was possible to successfully register callbacks that could not be
258+
hashed. Return codes of PyDict_SetItem were not checked properly.
259+
"""
260+
class NotHashable:
261+
def __call__(self, *args, **kw):
262+
pass
263+
def __hash__(self):
264+
raise TypeError()
265+
var = NotHashable()
266+
con = sqlite.connect(":memory:")
267+
self.assertRaises(TypeError, con.create_function, var)
268+
self.assertRaises(TypeError, con.create_aggregate, var)
269+
self.assertRaises(TypeError, con.set_authorizer, var)
270+
self.assertRaises(TypeError, con.set_progress_handler, var)
271+
179272
def suite():
180273
regression_suite = unittest.makeSuite(RegressionTests, "Check")
181274
return unittest.TestSuite((regression_suite,))

Lib/sqlite3/test/transactions.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,26 @@ def CheckLocking(self):
147147
# NO self.con2.rollback() HERE!!!
148148
self.con1.commit()
149149

150+
def CheckRollbackCursorConsistency(self):
151+
"""
152+
Checks if cursors on the connection are set into a "reset" state
153+
when a rollback is done on the connection.
154+
"""
155+
con = sqlite.connect(":memory:")
156+
cur = con.cursor()
157+
cur.execute("create table test(x)")
158+
cur.execute("insert into test(x) values (5)")
159+
cur.execute("select 1 union select 2 union select 3")
160+
161+
con.rollback()
162+
try:
163+
cur.fetchall()
164+
self.fail("InterfaceError should have been raised")
165+
except sqlite.InterfaceError as e:
166+
pass
167+
except:
168+
self.fail("InterfaceError should have been raised")
169+
150170
class SpecialCommandTests(unittest.TestCase):
151171
def setUp(self):
152172
self.con = sqlite.connect(":memory:")

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ C-API
268268
Library
269269
-------
270270

271+
- The sqlite3 module was updated to pysqlite 2.6.0. This fixes several obscure
272+
bugs and allows loading SQLite extensions from shared libraries.
273+
271274
- Issue #1054943: Fix unicodedata.normalize('NFC', text) for the Public Review
272275
Issue #29
273276

0 commit comments

Comments
 (0)