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

- Added version checks in C code to make sure we don't trigger bugs in older

  SQLite versions.
- Added version checks in test suite so that we don't execute tests that we
  know will fail with older (buggy) SQLite versions.

Now, all tests should run against all SQLite versions from 3.0.8 until 3.3.6
(latest one now). The sqlite3 module can be built against all these SQLite
versions and the sqlite3 module does its best to not trigger bugs in SQLite,
but using SQLite 3.3.3 or later is recommended.
parent 69f6168b
...@@ -48,6 +48,8 @@ class CollationTests(unittest.TestCase): ...@@ -48,6 +48,8 @@ class CollationTests(unittest.TestCase):
pass pass
def CheckCollationIsUsed(self): def CheckCollationIsUsed(self):
if sqlite.version_info < (3, 2, 1): # old SQLite versions crash on this test
return
def mycoll(x, y): def mycoll(x, y):
# reverse order # reverse order
return -cmp(x, y) return -cmp(x, y)
......
...@@ -200,6 +200,8 @@ class FunctionTests(unittest.TestCase): ...@@ -200,6 +200,8 @@ class FunctionTests(unittest.TestCase):
self.failUnlessEqual(val, buffer("blob")) self.failUnlessEqual(val, buffer("blob"))
def CheckFuncException(self): def CheckFuncException(self):
if sqlite.version_info < (3, 3, 3): # don't raise bug in earlier SQLite versions
return
cur = self.con.cursor() cur = self.con.cursor()
try: try:
cur.execute("select raiseexception()") cur.execute("select raiseexception()")
...@@ -283,6 +285,8 @@ class AggregateTests(unittest.TestCase): ...@@ -283,6 +285,8 @@ class AggregateTests(unittest.TestCase):
self.failUnlessEqual(e.args[0], "AggrNoStep instance has no attribute 'step'") self.failUnlessEqual(e.args[0], "AggrNoStep instance has no attribute 'step'")
def CheckAggrNoFinalize(self): def CheckAggrNoFinalize(self):
if sqlite.version_info < (3, 3, 3): # don't raise bug in earlier SQLite versions
return
cur = self.con.cursor() cur = self.con.cursor()
try: try:
cur.execute("select nofinalize(t) from test") cur.execute("select nofinalize(t) from test")
...@@ -292,6 +296,8 @@ class AggregateTests(unittest.TestCase): ...@@ -292,6 +296,8 @@ class AggregateTests(unittest.TestCase):
self.failUnlessEqual(e.args[0], "user-defined aggregate's 'finalize' method raised error") self.failUnlessEqual(e.args[0], "user-defined aggregate's 'finalize' method raised error")
def CheckAggrExceptionInInit(self): def CheckAggrExceptionInInit(self):
if sqlite.version_info < (3, 3, 3): # don't raise bug in earlier SQLite versions
return
cur = self.con.cursor() cur = self.con.cursor()
try: try:
cur.execute("select excInit(t) from test") cur.execute("select excInit(t) from test")
...@@ -301,6 +307,8 @@ class AggregateTests(unittest.TestCase): ...@@ -301,6 +307,8 @@ class AggregateTests(unittest.TestCase):
self.failUnlessEqual(e.args[0], "user-defined aggregate's '__init__' method raised error") self.failUnlessEqual(e.args[0], "user-defined aggregate's '__init__' method raised error")
def CheckAggrExceptionInStep(self): def CheckAggrExceptionInStep(self):
if sqlite.version_info < (3, 3, 3): # don't raise bug in earlier SQLite versions
return
cur = self.con.cursor() cur = self.con.cursor()
try: try:
cur.execute("select excStep(t) from test") cur.execute("select excStep(t) from test")
...@@ -310,6 +318,8 @@ class AggregateTests(unittest.TestCase): ...@@ -310,6 +318,8 @@ class AggregateTests(unittest.TestCase):
self.failUnlessEqual(e.args[0], "user-defined aggregate's 'step' method raised error") self.failUnlessEqual(e.args[0], "user-defined aggregate's 'step' method raised error")
def CheckAggrExceptionInFinalize(self): def CheckAggrExceptionInFinalize(self):
if sqlite.version_info < (3, 3, 3): # don't raise bug in earlier SQLite versions
return
cur = self.con.cursor() cur = self.con.cursor()
try: try:
cur.execute("select excFinalize(t) from test") cur.execute("select excFinalize(t) from test")
......
...@@ -34,6 +34,17 @@ ...@@ -34,6 +34,17 @@
static int connection_set_isolation_level(Connection* self, PyObject* isolation_level); static int connection_set_isolation_level(Connection* self, PyObject* isolation_level);
void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int len)
{
/* in older SQLite versions, calling sqlite3_result_error in callbacks
* triggers a bug in SQLite that leads either to irritating results or
* segfaults, depending on the SQLite version */
#if SQLITE_VERSION_NUMBER >= 3003003
sqlite3_result_error(ctx, errmsg, len);
#endif
}
int connection_init(Connection* self, PyObject* args, PyObject* kwargs) int connection_init(Connection* self, PyObject* args, PyObject* kwargs)
{ {
static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL}; static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL};
...@@ -526,7 +537,7 @@ void _func_callback(sqlite3_context* context, int argc, sqlite3_value** argv) ...@@ -526,7 +537,7 @@ void _func_callback(sqlite3_context* context, int argc, sqlite3_value** argv)
} else { } else {
PyErr_Clear(); PyErr_Clear();
} }
sqlite3_result_error(context, "user-defined function raised exception", -1); _sqlite3_result_error(context, "user-defined function raised exception", -1);
} }
PyGILState_Release(threadstate); PyGILState_Release(threadstate);
...@@ -558,7 +569,7 @@ static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** p ...@@ -558,7 +569,7 @@ static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** p
} else { } else {
PyErr_Clear(); PyErr_Clear();
} }
sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1); _sqlite3_result_error(context, "user-defined aggregate's '__init__' method raised error", -1);
goto error; goto error;
} }
} }
...@@ -582,7 +593,7 @@ static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** p ...@@ -582,7 +593,7 @@ static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** p
} else { } else {
PyErr_Clear(); PyErr_Clear();
} }
sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1); _sqlite3_result_error(context, "user-defined aggregate's 'step' method raised error", -1);
} }
error: error:
...@@ -619,7 +630,7 @@ void _final_callback(sqlite3_context* context) ...@@ -619,7 +630,7 @@ void _final_callback(sqlite3_context* context)
} else { } else {
PyErr_Clear(); PyErr_Clear();
} }
sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1); _sqlite3_result_error(context, "user-defined aggregate's 'finalize' method raised error", -1);
} else { } else {
_set_result(context, function_result); _set_result(context, function_result);
} }
......
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