Commit f9cee224 authored by Gerhard Häring's avatar Gerhard Häring

Merged new pysqlite version 2.6.0 from trunk.

parent 06dbff3b
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
...@@ -365,6 +365,25 @@ Connection Objects ...@@ -365,6 +365,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
...@@ -434,7 +453,7 @@ Connection Objects ...@@ -434,7 +453,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.
# #
...@@ -653,13 +653,13 @@ class ExtensionTests(unittest.TestCase): ...@@ -653,13 +653,13 @@ class ExtensionTests(unittest.TestCase):
res = cur.fetchone()[0] res = cur.fetchone()[0]
self.assertEqual(res, 5) self.assertEqual(res, 5)
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")
...@@ -692,7 +692,7 @@ class ExtensionTests(unittest.TestCase): ...@@ -692,7 +692,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
...@@ -744,6 +744,102 @@ class ClosedTests(unittest.TestCase): ...@@ -744,6 +744,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")
...@@ -751,8 +847,9 @@ def suite(): ...@@ -751,8 +847,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()
......
#-*- coding: ISO-8859-1 -*- #-*- coding: ISO-8859-1 -*-
# pysqlite2/test/regression.py: pysqlite regression tests # pysqlite2/test/regression.py: pysqlite regression tests
# #
# Copyright (C) 2006 Gerhard Hring <gh@ghaering.de> # Copyright (C) 2006-2010 Gerhard Hring <gh@ghaering.de>
# #
# This file is part of pysqlite. # This file is part of pysqlite.
# #
...@@ -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
...@@ -169,6 +159,25 @@ class RegressionTests(unittest.TestCase): ...@@ -169,6 +159,25 @@ class RegressionTests(unittest.TestCase):
con = sqlite.connect(":memory:") con = sqlite.connect(":memory:")
setattr(con, "isolation_level", "\xe9") setattr(con, "isolation_level", "\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 CheckStrSubclass(self): def CheckStrSubclass(self):
""" """
The Python 3.0 port of the module didn't cope with values of subclasses of str. The Python 3.0 port of the module didn't cope with values of subclasses of str.
...@@ -176,6 +185,90 @@ class RegressionTests(unittest.TestCase): ...@@ -176,6 +185,90 @@ class RegressionTests(unittest.TestCase):
class MyStr(str): pass class MyStr(str): pass
self.con.execute("select ?", (MyStr("abc"),)) self.con.execute("select ?", (MyStr("abc"),))
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")
return unittest.TestSuite((regression_suite,)) return unittest.TestSuite((regression_suite,))
......
...@@ -147,6 +147,26 @@ class TransactionTests(unittest.TestCase): ...@@ -147,6 +147,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 as 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:")
......
...@@ -268,6 +268,9 @@ C-API ...@@ -268,6 +268,9 @@ C-API
Library Library
------- -------
- The sqlite3 module was updated to pysqlite 2.6.0. This fixes several obscure
bugs and allows loading SQLite extensions from shared libraries.
- Issue #1054943: Fix unicodedata.normalize('NFC', text) for the Public Review - Issue #1054943: Fix unicodedata.normalize('NFC', text) for the Public Review
Issue #29 Issue #29
......
/* 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;
...@@ -120,6 +124,7 @@ PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args ...@@ -120,6 +124,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 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.
* *
...@@ -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(const char* statement) static pysqlite_StatementKind detect_statement_type(const char* statement)
{ {
char buf[20]; char buf[20];
...@@ -74,7 +76,7 @@ static pysqlite_StatementKind detect_statement_type(const char* statement) ...@@ -74,7 +76,7 @@ static pysqlite_StatementKind detect_statement_type(const 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,6 +141,10 @@ void pysqlite_cursor_dealloc(pysqlite_Cursor* self) ...@@ -130,6 +141,10 @@ 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);
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*)self);
}
Py_TYPE(self)->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
} }
...@@ -281,6 +296,11 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) ...@@ -281,6 +296,11 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self)
PyObject* buf_bytes; PyObject* buf_bytes;
PyObject* error_obj; PyObject* error_obj;
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
...@@ -397,6 +417,26 @@ PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) ...@@ -397,6 +417,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;
...@@ -416,13 +456,15 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -416,13 +456,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;
...@@ -573,42 +615,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -573,42 +615,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
} }
} }
func_args = PyTuple_New(1);
if (!func_args) {
goto error;
}
Py_INCREF(operation);
if (PyTuple_SetItem(func_args, 0, operation) != 0) {
goto error;
}
if (self->statement) {
(void)pysqlite_statement_reset(self->statement);
Py_DECREF(self->statement);
}
self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args);
Py_DECREF(func_args);
if (!self->statement) {
goto error;
}
if (self->statement->in_use) {
Py_DECREF(self->statement);
self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
if (!self->statement) {
goto error;
}
rc = pysqlite_statement_create(self->statement, self->connection, operation);
if (rc != SQLITE_OK) {
Py_CLEAR(self->statement);
goto error;
}
}
pysqlite_statement_reset(self->statement);
pysqlite_statement_mark_dirty(self->statement);
while (1) { while (1) {
parameters = PyIter_Next(parameters_iter); parameters = PyIter_Next(parameters_iter);
...@@ -623,11 +629,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -623,11 +629,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
goto error; goto error;
} }
if (pysqlite_build_row_cast_map(self) != 0) {
PyErr_SetString(pysqlite_OperationalError, "Error while building row_cast_map");
goto error;
}
/* Keep trying the SQL statement until the schema stops changing. */ /* Keep trying the SQL statement until the schema stops changing. */
while (1) { while (1) {
/* Actually execute the SQL statement. */ /* Actually execute the SQL statement. */
...@@ -671,10 +672,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* ...@@ -671,10 +672,6 @@ PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject*
} }
if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) { if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) {
Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_column_count(self->statement->st);
Py_END_ALLOW_THREADS
if (self->description == Py_None) { if (self->description == Py_None) {
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
numcols = sqlite3_column_count(self->statement->st); numcols = sqlite3_column_count(self->statement->st);
...@@ -782,16 +779,17 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) ...@@ -782,16 +779,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 (PyUnicode_Check(script_obj)) { if (PyUnicode_Check(script_obj)) {
script_cstr = _PyUnicode_AsString(script_obj); script_cstr = _PyUnicode_AsString(script_obj);
if (!script_cstr) { if (!script_cstr) {
...@@ -810,11 +808,6 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) ...@@ -810,11 +808,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,
...@@ -845,15 +838,15 @@ PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) ...@@ -845,15 +838,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 {
...@@ -874,7 +867,12 @@ PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) ...@@ -874,7 +867,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;
} }
...@@ -1017,6 +1015,8 @@ PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) ...@@ -1017,6 +1015,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;
} }
...@@ -1077,12 +1077,12 @@ PyTypeObject pysqlite_CursorType = { ...@@ -1077,12 +1077,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_BASETYPE, /* tp_flags */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* 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.
* *
...@@ -172,17 +172,17 @@ static long pysqlite_row_hash(pysqlite_Row *self) ...@@ -172,17 +172,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.
* *
......
...@@ -876,6 +876,8 @@ class PyBuildExt(build_ext): ...@@ -876,6 +876,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