Kaydet (Commit) 3bbb6727 authored tarafından Gerhard Häring's avatar Gerhard Häring

Merged code from pysqlite 2.6.0.

üst 2bb66e03
import sqlite3
con = sqlite3.connect(":memory:")
# enable extension loading
con.enable_load_extension(True)
# Load the fulltext search extension
con.execute("select load_extension('./fts3.so')")
# alternatively you can load the extension using an API call:
# con.load_extension("./fts3.so")
# disable extension laoding again
con.enable_load_extension(False)
# example from SQLite wiki
con.execute("create virtual table recipe using fts3(name, ingredients)")
con.executescript("""
insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes');
insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery');
insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour');
insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter');
""")
for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"):
print row
...@@ -368,6 +368,25 @@ Connection Objects ...@@ -368,6 +368,25 @@ Connection Objects
method with :const:`None` for *handler*. method with :const:`None` for *handler*.
.. method:: Connection.enable_load_extension(enabled)
.. versionadded:: 2.7
This routine allows/disallows the SQLite engine to load SQLite extensions
from shared libraries. SQLite extensions can define new functions,
aggregates or whole new virtual table implementations. One well-known
extension is the fulltext-search extension distributed with SQLite.
.. literalinclude:: ../includes/sqlite3/load_extension.py
.. method:: Connection.load_extension(path)
.. versionadded:: 2.7
This routine loads a SQLite extension from a shared library. You have to
enable extension loading with ``enable_load_extension`` before you can use
this routine.
.. attribute:: Connection.row_factory .. attribute:: Connection.row_factory
You can change this attribute to a callable that accepts the cursor and the You can change this attribute to a callable that accepts the cursor and the
...@@ -439,7 +458,7 @@ Connection Objects ...@@ -439,7 +458,7 @@ Connection Objects
Cursor Objects Cursor Objects
-------------- --------------
.. class:: Cursor A :class:`Cursor` instance has the following attributes and methods:
A SQLite database cursor has the following attributes and methods: A SQLite database cursor has the following attributes and methods:
......
#-*- coding: ISO-8859-1 -*- #-*- coding: ISO-8859-1 -*-
# pysqlite2/test/dbapi.py: tests for DB-API compliance # pysqlite2/test/dbapi.py: tests for DB-API compliance
# #
# Copyright (C) 2004-2007 Gerhard Hring <gh@ghaering.de> # Copyright (C) 2004-2010 Gerhard Hring <gh@ghaering.de>
# #
# This file is part of pysqlite. # This file is part of pysqlite.
# #
...@@ -672,13 +672,13 @@ class ExtensionTests(unittest.TestCase): ...@@ -672,13 +672,13 @@ class ExtensionTests(unittest.TestCase):
res = cur.fetchone()[0] res = cur.fetchone()[0]
self.assertEqual(res, 6) self.assertEqual(res, 6)
def CheckScriptErrorIncomplete(self): def CheckScriptSyntaxError(self):
con = sqlite.connect(":memory:") con = sqlite.connect(":memory:")
cur = con.cursor() cur = con.cursor()
raised = False raised = False
try: try:
cur.executescript("create table test(sadfsadfdsa") cur.executescript("create table test(x); asdf; create table test2(x)")
except sqlite.ProgrammingError: except sqlite.OperationalError:
raised = True raised = True
self.assertEqual(raised, True, "should have raised an exception") self.assertEqual(raised, True, "should have raised an exception")
...@@ -711,7 +711,7 @@ class ExtensionTests(unittest.TestCase): ...@@ -711,7 +711,7 @@ class ExtensionTests(unittest.TestCase):
result = con.execute("select foo from test").fetchone()[0] result = con.execute("select foo from test").fetchone()[0]
self.assertEqual(result, 5, "Basic test of Connection.executescript") self.assertEqual(result, 5, "Basic test of Connection.executescript")
class ClosedTests(unittest.TestCase): class ClosedConTests(unittest.TestCase):
def setUp(self): def setUp(self):
pass pass
...@@ -763,6 +763,102 @@ class ClosedTests(unittest.TestCase): ...@@ -763,6 +763,102 @@ class ClosedTests(unittest.TestCase):
except: except:
self.fail("Should have raised a ProgrammingError") self.fail("Should have raised a ProgrammingError")
def CheckClosedCreateFunction(self):
con = sqlite.connect(":memory:")
con.close()
def f(x): return 17
try:
con.create_function("foo", 1, f)
self.fail("Should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("Should have raised a ProgrammingError")
def CheckClosedCreateAggregate(self):
con = sqlite.connect(":memory:")
con.close()
class Agg:
def __init__(self):
pass
def step(self, x):
pass
def finalize(self):
return 17
try:
con.create_aggregate("foo", 1, Agg)
self.fail("Should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("Should have raised a ProgrammingError")
def CheckClosedSetAuthorizer(self):
con = sqlite.connect(":memory:")
con.close()
def authorizer(*args):
return sqlite.DENY
try:
con.set_authorizer(authorizer)
self.fail("Should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("Should have raised a ProgrammingError")
def CheckClosedSetProgressCallback(self):
con = sqlite.connect(":memory:")
con.close()
def progress(): pass
try:
con.set_progress_handler(progress, 100)
self.fail("Should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("Should have raised a ProgrammingError")
def CheckClosedCall(self):
con = sqlite.connect(":memory:")
con.close()
try:
con()
self.fail("Should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("Should have raised a ProgrammingError")
class ClosedCurTests(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def CheckClosed(self):
con = sqlite.connect(":memory:")
cur = con.cursor()
cur.close()
for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"):
if method_name in ("execute", "executescript"):
params = ("select 4 union select 5",)
elif method_name == "executemany":
params = ("insert into foo(bar) values (?)", [(3,), (4,)])
else:
params = []
try:
method = getattr(cur, method_name)
method(*params)
self.fail("Should have raised a ProgrammingError: method " + method_name)
except sqlite.ProgrammingError:
pass
except:
self.fail("Should have raised a ProgrammingError: " + method_name)
def suite(): def suite():
module_suite = unittest.makeSuite(ModuleTests, "Check") module_suite = unittest.makeSuite(ModuleTests, "Check")
connection_suite = unittest.makeSuite(ConnectionTests, "Check") connection_suite = unittest.makeSuite(ConnectionTests, "Check")
...@@ -770,8 +866,9 @@ def suite(): ...@@ -770,8 +866,9 @@ def suite():
thread_suite = unittest.makeSuite(ThreadTests, "Check") thread_suite = unittest.makeSuite(ThreadTests, "Check")
constructor_suite = unittest.makeSuite(ConstructorTests, "Check") constructor_suite = unittest.makeSuite(ConstructorTests, "Check")
ext_suite = unittest.makeSuite(ExtensionTests, "Check") ext_suite = unittest.makeSuite(ExtensionTests, "Check")
closed_suite = unittest.makeSuite(ClosedTests, "Check") closed_con_suite = unittest.makeSuite(ClosedConTests, "Check")
return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_suite)) closed_cur_suite = unittest.makeSuite(ClosedCurTests, "Check")
return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_con_suite, closed_cur_suite))
def test(): def test():
runner = unittest.TextTestRunner() runner = unittest.TextTestRunner()
......
...@@ -70,16 +70,6 @@ class RegressionTests(unittest.TestCase): ...@@ -70,16 +70,6 @@ class RegressionTests(unittest.TestCase):
cur.execute('select 1 as "foo baz"') cur.execute('select 1 as "foo baz"')
self.assertEqual(cur.description[0][0], "foo baz") self.assertEqual(cur.description[0][0], "foo baz")
def CheckStatementAvailable(self):
# pysqlite up to 2.3.2 crashed on this, because the active statement handle was not checked
# before trying to fetch data from it. close() destroys the active statement ...
con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
cur = con.cursor()
cur.execute("select 4 union select 5")
cur.close()
cur.fetchone()
cur.fetchone()
def CheckStatementFinalizationOnCloseDb(self): def CheckStatementFinalizationOnCloseDb(self):
# pysqlite versions <= 2.3.3 only finalized statements in the statement # pysqlite versions <= 2.3.3 only finalized statements in the statement
# cache when closing the database. statements that were still # cache when closing the database. statements that were still
...@@ -167,6 +157,107 @@ class RegressionTests(unittest.TestCase): ...@@ -167,6 +157,107 @@ class RegressionTests(unittest.TestCase):
self.assertRaises(UnicodeEncodeError, setattr, con, self.assertRaises(UnicodeEncodeError, setattr, con,
"isolation_level", u"\xe9") "isolation_level", u"\xe9")
def CheckCursorConstructorCallCheck(self):
"""
Verifies that cursor methods check wether base class __init__ was called.
"""
class Cursor(sqlite.Cursor):
def __init__(self, con):
pass
con = sqlite.connect(":memory:")
cur = Cursor(con)
try:
cur.execute("select 4+5").fetchall()
self.fail("should have raised ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("should have raised ProgrammingError")
def CheckConnectionConstructorCallCheck(self):
"""
Verifies that connection methods check wether base class __init__ was called.
"""
class Connection(sqlite.Connection):
def __init__(self, name):
pass
con = Connection(":memory:")
try:
cur = con.cursor()
self.fail("should have raised ProgrammingError")
except sqlite.ProgrammingError:
pass
except:
self.fail("should have raised ProgrammingError")
def CheckCursorRegistration(self):
"""
Verifies that subclassed cursor classes are correctly registered with
the connection object, too. (fetch-across-rollback problem)
"""
class Connection(sqlite.Connection):
def cursor(self):
return Cursor(self)
class Cursor(sqlite.Cursor):
def __init__(self, con):
sqlite.Cursor.__init__(self, con)
con = Connection(":memory:")
cur = con.cursor()
cur.execute("create table foo(x)")
cur.executemany("insert into foo(x) values (?)", [(3,), (4,), (5,)])
cur.execute("select x from foo")
con.rollback()
try:
cur.fetchall()
self.fail("should have raised InterfaceError")
except sqlite.InterfaceError:
pass
except:
self.fail("should have raised InterfaceError")
def CheckAutoCommit(self):
"""
Verifies that creating a connection in autocommit mode works.
2.5.3 introduced a regression so that these could no longer
be created.
"""
con = sqlite.connect(":memory:", isolation_level=None)
def CheckPragmaAutocommit(self):
"""
Verifies that running a PRAGMA statement that does an autocommit does
work. This did not work in 2.5.3/2.5.4.
"""
con = sqlite.connect(":memory:")
cur = con.cursor()
cur.execute("create table foo(bar)")
cur.execute("insert into foo(bar) values (5)")
cur.execute("pragma page_size")
row = cur.fetchone()
def CheckSetDict(self):
"""
See http://bugs.python.org/issue7478
It was possible to successfully register callbacks that could not be
hashed. Return codes of PyDict_SetItem were not checked properly.
"""
class NotHashable:
def __call__(self, *args, **kw):
pass
def __hash__(self):
raise TypeError()
var = NotHashable()
con = sqlite.connect(":memory:")
self.assertRaises(TypeError, con.create_function, var)
self.assertRaises(TypeError, con.create_aggregate, var)
self.assertRaises(TypeError, con.set_authorizer, var)
self.assertRaises(TypeError, con.set_progress_handler, var)
def suite(): def suite():
regression_suite = unittest.makeSuite(RegressionTests, "Check") regression_suite = unittest.makeSuite(RegressionTests, "Check")
......
...@@ -148,6 +148,26 @@ class TransactionTests(unittest.TestCase): ...@@ -148,6 +148,26 @@ class TransactionTests(unittest.TestCase):
# NO self.con2.rollback() HERE!!! # NO self.con2.rollback() HERE!!!
self.con1.commit() self.con1.commit()
def CheckRollbackCursorConsistency(self):
"""
Checks if cursors on the connection are set into a "reset" state
when a rollback is done on the connection.
"""
con = sqlite.connect(":memory:")
cur = con.cursor()
cur.execute("create table test(x)")
cur.execute("insert into test(x) values (5)")
cur.execute("select 1 union select 2 union select 3")
con.rollback()
try:
cur.fetchall()
self.fail("InterfaceError should have been raised")
except sqlite.InterfaceError, e:
pass
except:
self.fail("InterfaceError should have been raised")
class SpecialCommandTests(unittest.TestCase): class SpecialCommandTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.con = sqlite.connect(":memory:") self.con = sqlite.connect(":memory:")
......
...@@ -78,6 +78,33 @@ class SqliteTypeTests(unittest.TestCase): ...@@ -78,6 +78,33 @@ class SqliteTypeTests(unittest.TestCase):
row = self.cur.fetchone() row = self.cur.fetchone()
self.assertEqual(row[0], u"sterreich") self.assertEqual(row[0], u"sterreich")
def CheckNonUtf8_Default(self):
try:
self.cur.execute("select ?", (chr(150),))
self.fail("should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
def CheckNonUtf8_TextFactoryString(self):
orig_text_factory = self.con.text_factory
try:
self.con.text_factory = str
self.cur.execute("select ?", (chr(150),))
finally:
self.con.text_factory = orig_text_factory
def CheckNonUtf8_TextFactoryOptimizedUnicode(self):
orig_text_factory = self.con.text_factory
try:
try:
self.con.text_factory = sqlite.OptimizedUnicode
self.cur.execute("select ?", (chr(150),))
self.fail("should have raised a ProgrammingError")
except sqlite.ProgrammingError:
pass
finally:
self.con.text_factory = orig_text_factory
class DeclTypesTests(unittest.TestCase): class DeclTypesTests(unittest.TestCase):
class Foo: class Foo:
def __init__(self, _val): def __init__(self, _val):
......
...@@ -103,6 +103,9 @@ Library ...@@ -103,6 +103,9 @@ Library
Extension Modules Extension Modules
----------------- -----------------
- The sqlite3 module was updated to pysqlite 2.6.0. This fixes several obscure
bugs and allows loading SQLite extensions from shared libraries.
- Issue #7808: Fix reference leaks in _bsddb and related tests. - Issue #7808: Fix reference leaks in _bsddb and related tests.
- Issue #6544: fix a reference leak in the kqueue implementation's error - Issue #6544: fix a reference leak in the kqueue implementation's error
......
/* cache .c - a LRU cache /* cache .c - a LRU cache
* *
* Copyright (C) 2004-2007 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*/ */
#include "sqlitecompat.h"
#include "cache.h" #include "cache.h"
#include <limits.h> #include <limits.h>
......
/* cache.h - definitions for the LRU cache /* cache.h - definitions for the LRU cache
* *
* Copyright (C) 2004-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
This diff is collapsed.
/* connection.h - definitions for the connection type /* connection.h - definitions for the connection type
* *
* Copyright (C) 2004-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -63,17 +63,21 @@ typedef struct ...@@ -63,17 +63,21 @@ typedef struct
* used from the same thread it was created in */ * used from the same thread it was created in */
int check_same_thread; int check_same_thread;
int initialized;
/* thread identification of the thread the connection was created in */ /* thread identification of the thread the connection was created in */
long thread_ident; long thread_ident;
pysqlite_Cache* statement_cache; pysqlite_Cache* statement_cache;
/* A list of weak references to statements used within this connection */ /* Lists of weak references to statements and cursors used within this connection */
PyObject* statements; PyObject* statements;
PyObject* cursors;
/* a counter for how many statements were created in the connection. May be /* Counters for how many statements/cursors were created in the connection. May be
* reset to 0 at certain intervals */ * reset to 0 at certain intervals */
int created_statements; int created_statements;
int created_cursors;
PyObject* row_factory; PyObject* row_factory;
...@@ -125,6 +129,7 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args ...@@ -125,6 +129,7 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args
PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw);
int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs);
int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor);
int pysqlite_check_thread(pysqlite_Connection* self); int pysqlite_check_thread(pysqlite_Connection* self);
int pysqlite_check_connection(pysqlite_Connection* con); int pysqlite_check_connection(pysqlite_Connection* con);
......
/* cursor.c - the cursor type /* cursor.c - the cursor type
* *
* Copyright (C) 2004-2007 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self);
static char* errmsg_fetch_across_rollback = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from.";
static pysqlite_StatementKind detect_statement_type(char* statement) static pysqlite_StatementKind detect_statement_type(char* statement)
{ {
char buf[20]; char buf[20];
...@@ -74,7 +76,7 @@ static pysqlite_StatementKind detect_statement_type(char* statement) ...@@ -74,7 +76,7 @@ static pysqlite_StatementKind detect_statement_type(char* statement)
} }
} }
int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs)
{ {
pysqlite_Connection* connection; pysqlite_Connection* connection;
...@@ -87,6 +89,7 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs ...@@ -87,6 +89,7 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs
self->connection = connection; self->connection = connection;
self->statement = NULL; self->statement = NULL;
self->next_row = NULL; self->next_row = NULL;
self->in_weakreflist = NULL;
self->row_cast_map = PyList_New(0); self->row_cast_map = PyList_New(0);
if (!self->row_cast_map) { if (!self->row_cast_map) {
...@@ -100,6 +103,8 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs ...@@ -100,6 +103,8 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs
self->lastrowid= Py_None; self->lastrowid= Py_None;
self->arraysize = 1; self->arraysize = 1;
self->closed = 0;
self->reset = 0;
self->rowcount = -1L; self->rowcount = -1L;
...@@ -110,10 +115,16 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs ...@@ -110,10 +115,16 @@ int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs
return -1; return -1;
} }
if (!pysqlite_connection_register_cursor(connection, (PyObject*)self)) {
return -1;
}
self->initialized = 1;
return 0; return 0;
} }
void pysqlite_cursor_dealloc(pysqlite_Cursor* self) static void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
{ {
int rc; int rc;
...@@ -130,7 +141,11 @@ void pysqlite_cursor_dealloc(pysqlite_Cursor* self) ...@@ -130,7 +141,11 @@ void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
Py_XDECREF(self->row_factory); Py_XDECREF(self->row_factory);
Py_XDECREF(self->next_row); Py_XDECREF(self->next_row);
Py_TYPE(self)->tp_free((PyObject*)self); if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*)self);
}
self->ob_type->tp_free((PyObject*)self);
} }
PyObject* _pysqlite_get_converter(PyObject* key) PyObject* _pysqlite_get_converter(PyObject* key)
...@@ -301,6 +316,11 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) ...@@ -301,6 +316,11 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
char buf[200]; char buf[200];
const char* colname; const char* colname;
if (self->reset) {
PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback);
return NULL;
}
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_data_count(self->statement->st); numcols = sqlite3_data_count(self->statement->st);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
...@@ -406,6 +426,26 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) ...@@ -406,6 +426,26 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
return row; return row;
} }
/*
* Checks if a cursor object is usable.
*
* 0 => error; 1 => ok
*/
static int check_cursor(pysqlite_Cursor* cur)
{
if (!cur->initialized) {
PyErr_SetString(pysqlite_ProgrammingError, "Base Cursor.__init__ not called.");
return 0;
}
if (cur->closed) {
PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor.");
return 0;
} else {
return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection);
}
}
PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
{ {
PyObject* operation; PyObject* operation;
...@@ -425,13 +465,15 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -425,13 +465,15 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
PyObject* second_argument = NULL; PyObject* second_argument = NULL;
int allow_8bit_chars; int allow_8bit_chars;
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) { if (!check_cursor(self)) {
return NULL; return NULL;
} }
self->reset = 0;
/* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */ /* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) && allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) &&
(self->connection->text_factory != (PyObject*)&PyUnicode_Type && pysqlite_OptimizedUnicode)); (self->connection->text_factory != pysqlite_OptimizedUnicode));
Py_XDECREF(self->next_row); Py_XDECREF(self->next_row);
self->next_row = NULL; self->next_row = NULL;
...@@ -753,16 +795,17 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) ...@@ -753,16 +795,17 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
sqlite3_stmt* statement; sqlite3_stmt* statement;
int rc; int rc;
PyObject* result; PyObject* result;
int statement_completed = 0;
if (!PyArg_ParseTuple(args, "O", &script_obj)) { if (!PyArg_ParseTuple(args, "O", &script_obj)) {
return NULL; return NULL;
} }
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) { if (!check_cursor(self)) {
return NULL; return NULL;
} }
self->reset = 0;
if (PyString_Check(script_obj)) { if (PyString_Check(script_obj)) {
script_cstr = PyString_AsString(script_obj); script_cstr = PyString_AsString(script_obj);
} else if (PyUnicode_Check(script_obj)) { } else if (PyUnicode_Check(script_obj)) {
...@@ -785,11 +828,6 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) ...@@ -785,11 +828,6 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
Py_DECREF(result); Py_DECREF(result);
while (1) { while (1) {
if (!sqlite3_complete(script_cstr)) {
break;
}
statement_completed = 1;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->connection->db, rc = sqlite3_prepare(self->connection->db,
script_cstr, script_cstr,
...@@ -820,15 +858,15 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) ...@@ -820,15 +858,15 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args)
_pysqlite_seterror(self->connection->db, NULL); _pysqlite_seterror(self->connection->db, NULL);
goto error; goto error;
} }
if (*script_cstr == (char)0) {
break;
}
} }
error: error:
Py_XDECREF(script_str); Py_XDECREF(script_str);
if (!statement_completed) {
PyErr_SetString(pysqlite_ProgrammingError, "you did not provide a complete SQL statement");
}
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} else { } else {
...@@ -849,7 +887,12 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) ...@@ -849,7 +887,12 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self)
PyObject* next_row; PyObject* next_row;
int rc; int rc;
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) { if (!check_cursor(self)) {
return NULL;
}
if (self->reset) {
PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback);
return NULL; return NULL;
} }
...@@ -992,6 +1035,8 @@ PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) ...@@ -992,6 +1035,8 @@ PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args)
Py_CLEAR(self->statement); Py_CLEAR(self->statement);
} }
self->closed = 1;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -1052,12 +1097,12 @@ PyTypeObject pysqlite_CursorType = { ...@@ -1052,12 +1097,12 @@ PyTypeObject pysqlite_CursorType = {
0, /* tp_getattro */ 0, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER|Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
cursor_doc, /* tp_doc */ cursor_doc, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
0, /* tp_clear */ 0, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ offsetof(pysqlite_Cursor, in_weakreflist), /* tp_weaklistoffset */
(getiterfunc)pysqlite_cursor_getiter, /* tp_iter */ (getiterfunc)pysqlite_cursor_getiter, /* tp_iter */
(iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */ (iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */
cursor_methods, /* tp_methods */ cursor_methods, /* tp_methods */
......
/* cursor.h - definitions for the cursor type /* cursor.h - definitions for the cursor type
* *
* Copyright (C) 2004-2007 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -40,9 +40,14 @@ typedef struct ...@@ -40,9 +40,14 @@ typedef struct
long rowcount; long rowcount;
PyObject* row_factory; PyObject* row_factory;
pysqlite_Statement* statement; pysqlite_Statement* statement;
int closed;
int reset;
int initialized;
/* the next row to be returned, NULL if no next row available */ /* the next row to be returned, NULL if no next row available */
PyObject* next_row; PyObject* next_row;
PyObject* in_weakreflist; /* List of weak references */
} pysqlite_Cursor; } pysqlite_Cursor;
typedef enum { typedef enum {
...@@ -53,8 +58,6 @@ typedef enum { ...@@ -53,8 +58,6 @@ typedef enum {
extern PyTypeObject pysqlite_CursorType; extern PyTypeObject pysqlite_CursorType;
int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs);
void pysqlite_cursor_dealloc(pysqlite_Cursor* self);
PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args);
PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args); PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args);
PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self); PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self);
......
/* module.c - the module itself /* module.c - the module itself
* *
* Copyright (C) 2004-2007 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
/* module.h - definitions for the module /* module.h - definitions for the module
* *
* Copyright (C) 2004-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2004-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define PYSQLITE_MODULE_H #define PYSQLITE_MODULE_H
#include "Python.h" #include "Python.h"
#define PYSQLITE_VERSION "2.4.1" #define PYSQLITE_VERSION "2.6.0"
extern PyObject* pysqlite_Error; extern PyObject* pysqlite_Error;
extern PyObject* pysqlite_Warning; extern PyObject* pysqlite_Warning;
......
/* prepare_protocol.c - the protocol for preparing values for SQLite /* prepare_protocol.c - the protocol for preparing values for SQLite
* *
* Copyright (C) 2005-2006 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*/ */
#include "sqlitecompat.h"
#include "prepare_protocol.h" #include "prepare_protocol.h"
int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs) int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs)
......
/* prepare_protocol.h - the protocol for preparing values for SQLite /* prepare_protocol.h - the protocol for preparing values for SQLite
* *
* Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
/* row.c - an enhanced tuple for database rows /* row.c - an enhanced tuple for database rows
* *
* Copyright (C) 2005-2006 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -177,17 +177,17 @@ static long pysqlite_row_hash(pysqlite_Row *self) ...@@ -177,17 +177,17 @@ static long pysqlite_row_hash(pysqlite_Row *self)
static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid) static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
{ {
if (opid != Py_EQ && opid != Py_NE) { if (opid != Py_EQ && opid != Py_NE) {
Py_INCREF(Py_NotImplemented); Py_INCREF(Py_NotImplemented);
return Py_NotImplemented; return Py_NotImplemented;
} }
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) { if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other; pysqlite_Row *other = (pysqlite_Row *)_other;
PyObject *res = PyObject_RichCompare(self->description, other->description, opid); PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
if ((opid == Py_EQ && res == Py_True) if ((opid == Py_EQ && res == Py_True)
|| (opid == Py_NE && res == Py_False)) { || (opid == Py_NE && res == Py_False)) {
Py_DECREF(res); Py_DECREF(res);
return PyObject_RichCompare(self->data, other->data, opid); return PyObject_RichCompare(self->data, other->data, opid);
} }
} }
Py_INCREF(Py_NotImplemented); Py_INCREF(Py_NotImplemented);
return Py_NotImplemented; return Py_NotImplemented;
......
/* row.h - an enhanced tuple for database rows /* row.h - an enhanced tuple for database rows
* *
* Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
/* sqlitecompat.h - compatibility macros /* sqlitecompat.h - compatibility macros
* *
* Copyright (C) 2006 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2006-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
* 3. This notice may not be removed or altered from any source distribution. * 3. This notice may not be removed or altered from any source distribution.
*/ */
#include "Python.h"
#ifndef PYSQLITE_COMPAT_H #ifndef PYSQLITE_COMPAT_H
#define PYSQLITE_COMPAT_H #define PYSQLITE_COMPAT_H
...@@ -31,4 +33,31 @@ typedef int Py_ssize_t; ...@@ -31,4 +33,31 @@ typedef int Py_ssize_t;
typedef int (*lenfunc)(PyObject*); typedef int (*lenfunc)(PyObject*);
#endif #endif
/* define PyDict_CheckExact for pre-2.4 versions of Python */
#ifndef PyDict_CheckExact
#define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type)
#endif
/* define Py_CLEAR for pre-2.4 versions of Python */
#ifndef Py_CLEAR
#define Py_CLEAR(op) \
do { \
if (op) { \
PyObject *tmp = (PyObject *)(op); \
(op) = NULL; \
Py_DECREF(tmp); \
} \
} while (0)
#endif
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
#endif
#ifndef Py_TYPE
#define Py_TYPE(ob) ((ob)->ob_type)
#endif
#endif #endif
/* statement.c - the statement type /* statement.c - the statement type
* *
* Copyright (C) 2005-2007 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
/* statement.h - definitions for the statement type /* statement.h - definitions for the statement type
* *
* Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
/* util.c - various utility functions /* util.c - various utility functions
* *
* Copyright (C) 2005-2007 Gerhard Hring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Hring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
/* util.h - various utility functions /* util.h - various utility functions
* *
* Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de> * Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
* *
* This file is part of pysqlite. * This file is part of pysqlite.
* *
......
...@@ -955,6 +955,8 @@ class PyBuildExt(build_ext): ...@@ -955,6 +955,8 @@ class PyBuildExt(build_ext):
else: else:
sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"')) sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
# Comment this out if you want the sqlite3 module to be able to load extensions.
sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
if sys.platform == 'darwin': if sys.platform == 'darwin':
# In every directory on the search path search for a dynamic # In every directory on the search path search for a dynamic
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment