Updated the sqlite3 module to the external pysqlite 2.2.2 version.
diff --git a/Lib/sqlite3/dbapi2.py b/Lib/sqlite3/dbapi2.py
index e0c8a84..665dbb2 100644
--- a/Lib/sqlite3/dbapi2.py
+++ b/Lib/sqlite3/dbapi2.py
@@ -22,6 +22,9 @@
 # 3. This notice may not be removed or altered from any source distribution.
 
 import datetime
+import time
+
+from _sqlite3 import *
 
 paramstyle = "qmark"
 
@@ -29,10 +32,6 @@
 
 apilevel = "2.0"
 
-from _sqlite3 import *
-
-import datetime, time
-
 Date = datetime.date
 
 Time = datetime.time
@@ -40,45 +39,50 @@
 Timestamp = datetime.datetime
 
 def DateFromTicks(ticks):
-    return apply(Date,time.localtime(ticks)[:3])
+    return apply(Date, time.localtime(ticks)[:3])
 
 def TimeFromTicks(ticks):
-    return apply(Time,time.localtime(ticks)[3:6])
+    return apply(Time, time.localtime(ticks)[3:6])
 
 def TimestampFromTicks(ticks):
-    return apply(Timestamp,time.localtime(ticks)[:6])
+    return apply(Timestamp, time.localtime(ticks)[:6])
 
-_major, _minor, _micro = version.split(".")
-version_info = (int(_major), int(_minor), _micro)
-_major, _minor, _micro = sqlite_version.split(".")
-sqlite_version_info = (int(_major), int(_minor), _micro)
+version_info = tuple([int(x) for x in version.split(".")])
+sqlite_version_info = tuple([int(x) for x in sqlite_version.split(".")])
 
 Binary = buffer
 
-def adapt_date(val):
-    return val.isoformat()
+def register_adapters_and_converters():
+    def adapt_date(val):
+        return val.isoformat()
 
-def adapt_datetime(val):
-    return val.isoformat(" ")
+    def adapt_datetime(val):
+        return val.isoformat(" ")
 
-def convert_date(val):
-    return datetime.date(*map(int, val.split("-")))
+    def convert_date(val):
+        return datetime.date(*map(int, val.split("-")))
 
-def convert_timestamp(val):
-    datepart, timepart = val.split(" ")
-    year, month, day = map(int, datepart.split("-"))
-    timepart_full = timepart.split(".")
-    hours, minutes, seconds = map(int, timepart_full[0].split(":"))
-    if len(timepart_full) == 2:
-        microseconds = int(float("0." + timepart_full[1]) * 1000000)
-    else:
-        microseconds = 0
+    def convert_timestamp(val):
+        datepart, timepart = val.split(" ")
+        year, month, day = map(int, datepart.split("-"))
+        timepart_full = timepart.split(".")
+        hours, minutes, seconds = map(int, timepart_full[0].split(":"))
+        if len(timepart_full) == 2:
+            microseconds = int(float("0." + timepart_full[1]) * 1000000)
+        else:
+            microseconds = 0
 
-    val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds)
-    return val
+        val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds)
+        return val
 
 
-register_adapter(datetime.date, adapt_date)
-register_adapter(datetime.datetime, adapt_datetime)
-register_converter("date", convert_date)
-register_converter("timestamp", convert_timestamp)
+    register_adapter(datetime.date, adapt_date)
+    register_adapter(datetime.datetime, adapt_datetime)
+    register_converter("date", convert_date)
+    register_converter("timestamp", convert_timestamp)
+
+register_adapters_and_converters()
+
+# Clean up namespace
+
+del(register_adapters_and_converters)
diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py
index 21f7b88..b10b3ef 100644
--- a/Lib/sqlite3/test/hooks.py
+++ b/Lib/sqlite3/test/hooks.py
@@ -22,7 +22,7 @@
 # 3. This notice may not be removed or altered from any source distribution.
 
 import os, unittest
-import pysqlite2.dbapi2 as sqlite
+import sqlite3 as sqlite
 
 class CollationTests(unittest.TestCase):
     def setUp(self):
@@ -72,7 +72,7 @@
             result = con.execute(sql).fetchall()
             self.fail("should have raised an OperationalError")
         except sqlite.OperationalError, e:
-            self.failUnlessEqual(e.args[0], "no such collation sequence: mycoll")
+            self.failUnlessEqual(e.args[0].lower(), "no such collation sequence: mycoll")
 
     def CheckCollationRegisterTwice(self):
         """
diff --git a/Lib/sqlite3/test/regression.py b/Lib/sqlite3/test/regression.py
index 648ada5..25e4b63 100644
--- a/Lib/sqlite3/test/regression.py
+++ b/Lib/sqlite3/test/regression.py
@@ -22,7 +22,7 @@
 # 3. This notice may not be removed or altered from any source distribution.
 
 import unittest
-import pysqlite2.dbapi2 as sqlite
+import sqlite3 as sqlite
 
 class RegressionTests(unittest.TestCase):
     def setUp(self):
@@ -36,6 +36,31 @@
         cur = self.con.cursor()
         cur.execute("pragma user_version")
 
+    def CheckPragmaSchemaVersion(self):
+        # This still crashed pysqlite <= 2.2.1
+        con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
+        try:
+            cur = self.con.cursor()
+            cur.execute("pragma schema_version")
+        finally:
+            cur.close()
+            con.close()
+
+    def CheckStatementReset(self):
+        # pysqlite 2.1.0 to 2.2.0 have the problem that not all statements are
+        # reset before a rollback, but only those that are still in the
+        # statement cache. The others are not accessible from the connection object.
+        con = sqlite.connect(":memory:", cached_statements=5)
+        cursors = [con.cursor() for x in xrange(5)]
+        cursors[0].execute("create table test(x)")
+        for i in range(10):
+            cursors[0].executemany("insert into test(x) values (?)", [(x,) for x in xrange(10)])
+
+        for i in range(5):
+            cursors[i].execute(" " * i + "select x from test")
+
+        con.rollback()
+
 def suite():
     regression_suite = unittest.makeSuite(RegressionTests, "Check")
     return unittest.TestSuite((regression_suite,))
diff --git a/Lib/sqlite3/test/userfunctions.py b/Lib/sqlite3/test/userfunctions.py
index ff7db9c..78656e7 100644
--- a/Lib/sqlite3/test/userfunctions.py
+++ b/Lib/sqlite3/test/userfunctions.py
@@ -134,6 +134,13 @@
     def tearDown(self):
         self.con.close()
 
+    def CheckFuncErrorOnCreate(self):
+        try:
+            self.con.create_function("bla", -100, lambda x: 2*x)
+            self.fail("should have raised an OperationalError")
+        except sqlite.OperationalError:
+            pass
+
     def CheckFuncRefCount(self):
         def getfunc():
             def f():
@@ -251,6 +258,13 @@
         #self.con.close()
         pass
 
+    def CheckAggrErrorOnCreate(self):
+        try:
+            self.con.create_function("bla", -100, AggrSum)
+            self.fail("should have raised an OperationalError")
+        except sqlite.OperationalError:
+            pass
+
     def CheckAggrNoStep(self):
         cur = self.con.cursor()
         cur.execute("select nostep(t) from test")
diff --git a/Lib/test/test_sqlite.py b/Lib/test/test_sqlite.py
index 1b1d0e5..f033772 100644
--- a/Lib/test/test_sqlite.py
+++ b/Lib/test/test_sqlite.py
@@ -6,11 +6,12 @@
 except ImportError:
     raise TestSkipped('no sqlite available')
 from sqlite3.test import (dbapi, types, userfunctions,
-                                factory, transactions)
+                                factory, transactions, hooks, regression)
 
 def test_main():
     run_unittest(dbapi.suite(), types.suite(), userfunctions.suite(),
-                 factory.suite(), transactions.suite())
+                 factory.suite(), transactions.suite(), hooks.suite(),
+                 regression.suite())
 
 if __name__ == "__main__":
     test_main()
diff --git a/Modules/_sqlite/adapters.c b/Modules/_sqlite/adapters.c
deleted file mode 100644
index e6fde03..0000000
--- a/Modules/_sqlite/adapters.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* adapters.c - default adapters
- *
- * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
- *
- * This file is part of pysqlite.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "util.h"
-#include "module.h"
-#include "adapters.h"
-
-/* dummy, will be implemented in a later version */
-
-PyObject* adapt_date(PyObject* self, PyObject* args, PyObject* kwargs)
-{
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-PyObject* adapt_datetime(PyObject* self, PyObject* args, PyObject* kwargs)
-{
-    Py_INCREF(Py_None);
-    return Py_None;
-}
diff --git a/Modules/_sqlite/adapters.h b/Modules/_sqlite/adapters.h
deleted file mode 100644
index d2e8479..0000000
--- a/Modules/_sqlite/adapters.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* adapters.h - default adapters
- *
- * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
- *
- * This file is part of pysqlite.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef PYSQLITE_ADAPTERS_H
-#define PYSQLITE_ADAPTERS_H
-#include "Python.h"
-#include "pythread.h"
-#include "sqlite3.h"
-
-PyObject* adapt_date(PyObject* self, PyObject* args, PyObject* kwargs);
-PyObject* adapt_datetime(PyObject* self, PyObject* args, PyObject* kwargs);
-
-#endif
diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c
index d102e97..6962695 100644
--- a/Modules/_sqlite/cache.c
+++ b/Modules/_sqlite/cache.c
@@ -22,6 +22,7 @@
  */
 
 #include "cache.h"
+#include <limits.h>
 
 /* only used internally */
 Node* new_node(PyObject* key, PyObject* data)
@@ -60,11 +61,11 @@
 
     self->factory = NULL;
 
-    if (!PyArg_ParseTuple(args, "O|i", &factory, &size))
-    {
-        return -1; 
+    if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) {
+        return -1;
     }
 
+    /* minimum cache size is 5 entries */
     if (size < 5) {
         size = 5;
     }
@@ -95,6 +96,7 @@
         return;
     }
 
+    /* iterate over all nodes and deallocate them */
     node = self->first;
     while (node) {
         delete_node = node;
@@ -119,7 +121,14 @@
 
     node = (Node*)PyDict_GetItem(self->mapping, key);
     if (node) {
-        node->count++;
+        /* an entry for this key already exists in the cache */
+
+        /* increase usage counter of the node found */
+        if (node->count < LONG_MAX) {
+            node->count++;
+        }
+
+        /* if necessary, reorder entries in the cache by swapping positions */
         if (node->prev && node->count > node->prev->count) {
             ptr = node->prev;
 
@@ -149,6 +158,10 @@
             ptr->prev = node;
         }
     } else {
+        /* There is no entry for this key in the cache, yet. We'll insert a new
+         * entry in the cache, and make space if necessary by throwing the
+         * least used item out of the cache. */
+
         if (PyDict_Size(self->mapping) == self->size) {
             if (self->last) {
                 node = self->last;
@@ -253,7 +266,7 @@
 
 static PyMethodDef cache_methods[] = {
     {"get", (PyCFunction)cache_get, METH_O,
-        PyDoc_STR("Gets an entry from the cache.")},
+        PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")},
     {"display", (PyCFunction)cache_display, METH_NOARGS,
         PyDoc_STR("For debugging only.")},
     {NULL, NULL}
diff --git a/Modules/_sqlite/cache.h b/Modules/_sqlite/cache.h
index 5cc16f3..1f13907 100644
--- a/Modules/_sqlite/cache.h
+++ b/Modules/_sqlite/cache.h
@@ -1,6 +1,6 @@
 /* cache.h - definitions for the LRU cache
  *
- * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -25,6 +25,10 @@
 #define PYSQLITE_CACHE_H
 #include "Python.h"
 
+/* The LRU cache is implemented as a combination of a doubly-linked with a
+ * dictionary. The list items are of type 'Node' and the dictionary has the
+ * nodes as values. */
+
 typedef struct _Node
 {
     PyObject_HEAD
@@ -39,10 +43,18 @@
 {
     PyObject_HEAD
     int size;
+
+    /* a dictionary mapping keys to Node entries */
     PyObject* mapping;
+
+    /* the factory callable */
     PyObject* factory;
+
     Node* first;
     Node* last;
+
+    /* if set, decrement the factory function when the Cache is deallocated.
+     * this is almost always desirable, but not in the pysqlite context */
     int decref_factory;
 } Cache;
 
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 78aad37..64e43eb 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -56,6 +56,7 @@
     self->begin_statement = NULL;
 
     self->statement_cache = NULL;
+    self->statements = NULL;
 
     Py_INCREF(Py_None);
     self->row_factory = Py_None;
@@ -74,6 +75,9 @@
 
     if (!isolation_level) {
         isolation_level = PyString_FromString("");
+        if (!isolation_level) {
+            return -1;
+        }
     } else {
         Py_INCREF(isolation_level);
     }
@@ -86,6 +90,12 @@
         return -1;
     }
 
+    self->statements = PyList_New(0);
+    if (!self->statements) {
+        return -1;
+    }
+    self->created_statements = 0;
+
     /* By default, the Cache class INCREFs the factory in its initializer, and
      * decrefs it in its deallocator method. Since this would create a circular
      * reference here, we're breaking it by decrementing self, and telling the
@@ -126,6 +136,7 @@
     return 0;
 }
 
+/* Empty the entire statement cache of this connection */
 void flush_statement_cache(Connection* self)
 {
     Node* node;
@@ -147,15 +158,16 @@
 
 void reset_all_statements(Connection* self)
 {
-    Node* node;
-    Statement* statement;
+    int i;
+    PyObject* weakref;
+    PyObject* statement;
 
-    node = self->statement_cache->first;
-
-    while (node) {
-        statement = (Statement*)(node->data);
-        (void)statement_reset(statement);
-        node = node->next;
+    for (i = 0; i < PyList_Size(self->statements); i++) {
+        weakref = PyList_GetItem(self->statements, i);
+        statement = PyWeakref_GetObject(weakref);
+        if (statement != Py_None) {
+            (void)statement_reset((Statement*)statement);
+        }
     }
 }
 
@@ -178,6 +190,7 @@
     Py_XDECREF(self->row_factory);
     Py_XDECREF(self->text_factory);
     Py_XDECREF(self->collations);
+    Py_XDECREF(self->statements);
 
     self->ob_type->tp_free((PyObject*)self);
 }
@@ -391,7 +404,7 @@
     Py_ssize_t buflen;
     PyObject* stringval;
 
-    if (PyErr_Occurred()) {
+    if ((!py_val) || PyErr_Occurred()) {
         /* Errors in callbacks are ignored, and we return NULL */
         PyErr_Clear();
         sqlite3_result_null(context);
@@ -399,21 +412,23 @@
         sqlite3_result_null(context);
     } else if (PyInt_Check(py_val)) {
         longval = PyInt_AsLong(py_val);
-        /* TODO: investigate what to do with range overflows - long vs. long long */
         sqlite3_result_int64(context, (PY_LONG_LONG)longval);
     } else if (PyFloat_Check(py_val)) {
         sqlite3_result_double(context, PyFloat_AsDouble(py_val));
     } else if (PyBuffer_Check(py_val)) {
         if (PyObject_AsCharBuffer(py_val, &buffer, &buflen) != 0) {
             PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
+        } else {
+            sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT);
         }
-        sqlite3_result_blob(context, buffer, buflen, SQLITE_TRANSIENT);
     } else if (PyString_Check(py_val)) {
         sqlite3_result_text(context, PyString_AsString(py_val), -1, SQLITE_TRANSIENT);
     } else if (PyUnicode_Check(py_val)) {
         stringval = PyUnicode_AsUTF8String(py_val);
-        sqlite3_result_text(context, PyString_AsString(stringval), -1, SQLITE_TRANSIENT);
-        Py_DECREF(stringval);
+        if (stringval) {
+            sqlite3_result_text(context, PyString_AsString(stringval), -1, SQLITE_TRANSIENT);
+            Py_DECREF(stringval);
+        }
     } else {
         /* TODO: raise error */
     }
@@ -450,6 +465,7 @@
                 cur_py_value = PyUnicode_DecodeUTF8(val_str, strlen(val_str), NULL);
                 /* TODO: have a way to show errors here */
                 if (!cur_py_value) {
+                    PyErr_Clear();
                     Py_INCREF(Py_None);
                     cur_py_value = Py_None;
                 }
@@ -458,10 +474,12 @@
                 buflen = sqlite3_value_bytes(cur_value);
                 cur_py_value = PyBuffer_New(buflen);
                 if (!cur_py_value) {
-                    /* TODO: error */
+                    break;
                 }
                 if (PyObject_AsWriteBuffer(cur_py_value, &raw_buffer, &buflen)) {
-                    /* TODO: error */
+                    Py_DECREF(cur_py_value);
+                    cur_py_value = NULL;
+                    break;
                 }
                 memcpy(raw_buffer, sqlite3_value_blob(cur_value), buflen);
                 break;
@@ -470,6 +488,12 @@
                 Py_INCREF(Py_None);
                 cur_py_value = Py_None;
         }
+
+        if (!cur_py_value) {
+            Py_DECREF(args);
+            return NULL;
+        }
+
         PyTuple_SetItem(args, i, cur_py_value);
 
     }
@@ -481,8 +505,7 @@
 {
     PyObject* args;
     PyObject* py_func;
-    PyObject* py_retval;
-
+    PyObject* py_retval = NULL;
 
     PyGILState_STATE threadstate;
 
@@ -491,9 +514,10 @@
     py_func = (PyObject*)sqlite3_user_data(context);
 
     args = _build_py_params(context, argc, argv);
-
-    py_retval = PyObject_CallObject(py_func, args);
-    Py_DECREF(args);
+    if (args) {
+        py_retval = PyObject_CallObject(py_func, args);
+        Py_DECREF(args);
+    }
 
     _set_result(context, py_retval);
     Py_XDECREF(py_retval);
@@ -504,10 +528,10 @@
 static void _step_callback(sqlite3_context *context, int argc, sqlite3_value** params)
 {
     PyObject* args;
-    PyObject* function_result;
+    PyObject* function_result = NULL;
     PyObject* aggregate_class;
     PyObject** aggregate_instance;
-    PyObject* stepmethod;
+    PyObject* stepmethod = NULL;
 
     PyGILState_STATE threadstate;
 
@@ -520,44 +544,42 @@
     if (*aggregate_instance == 0) {
         *aggregate_instance = PyObject_CallFunction(aggregate_class, "");
 
-        if (PyErr_Occurred())
-        {
+        if (PyErr_Occurred()) {
             PyErr_Clear();
             *aggregate_instance = 0;
-            PyGILState_Release(threadstate);
-            return;
+            goto error;
         }
     }
 
     stepmethod = PyObject_GetAttrString(*aggregate_instance, "step");
-    if (!stepmethod)
-    {
-        PyGILState_Release(threadstate);
-        return;
+    if (!stepmethod) {
+        goto error;
     }
 
     args = _build_py_params(context, argc, params);
+    if (!args) {
+        goto error;
+    }
 
     function_result = PyObject_CallObject(stepmethod, args);
     Py_DECREF(args);
-    Py_DECREF(stepmethod);
 
-    if (function_result == NULL) {
+    if (!function_result) {
         PyErr_Clear();
-    } else {
-        Py_DECREF(function_result);
     }
 
+error:
+    Py_XDECREF(stepmethod);
+    Py_XDECREF(function_result);
+
     PyGILState_Release(threadstate);
 }
 
 void _final_callback(sqlite3_context* context)
 {
-    PyObject* args;
-    PyObject* function_result;
+    PyObject* function_result = NULL;
     PyObject** aggregate_instance;
     PyObject* aggregate_class;
-    PyObject* finalizemethod;
 
     PyGILState_STATE threadstate;
 
@@ -570,35 +592,56 @@
         /* this branch is executed if there was an exception in the aggregate's
          * __init__ */
 
-        PyGILState_Release(threadstate);
-        return;
+        goto error;
     }
 
-    finalizemethod = PyObject_GetAttrString(*aggregate_instance, "finalize");
-
-    if (!finalizemethod) {
-        /*
-        PyErr_SetString(ProgrammingError, "finalize method missing");
-        goto error;
-        */
+    function_result = PyObject_CallMethod(*aggregate_instance, "finalize", "");
+    if (!function_result) {
+        PyErr_Clear();
         Py_INCREF(Py_None);
         function_result = Py_None;
-    } else {
-        args = PyTuple_New(0);
-        if (!args)
-                return;
-        function_result = PyObject_CallObject(finalizemethod, args);
-        Py_DECREF(args);
-        Py_DECREF(finalizemethod);
     }
 
     _set_result(context, function_result);
+
+error:
     Py_XDECREF(*aggregate_instance);
     Py_XDECREF(function_result);
 
     PyGILState_Release(threadstate);
 }
 
+void _drop_unused_statement_references(Connection* self)
+{
+    PyObject* new_list;
+    PyObject* weakref;
+    int i;
+
+    /* we only need to do this once in a while */
+    if (self->created_statements++ < 200) {
+        return;
+    }
+
+    self->created_statements = 0;
+
+    new_list = PyList_New(0);
+    if (!new_list) {
+        return;
+    }
+
+    for (i = 0; i < PyList_Size(self->statements); i++) {
+        weakref = PyList_GetItem(self->statements, i);
+        if (weakref != Py_None) {
+            if (PyList_Append(new_list, weakref) != 0) {
+                Py_DECREF(new_list);
+                return;
+            }
+        }
+    }
+
+    Py_DECREF(self->statements);
+    self->statements = new_list;
+}
 
 PyObject* connection_create_function(Connection* self, PyObject* args, PyObject* kwargs)
 {
@@ -617,10 +660,16 @@
 
     rc = sqlite3_create_function(self->db, name, narg, SQLITE_UTF8, (void*)func, _func_callback, NULL, NULL);
 
-    PyDict_SetItem(self->function_pinboard, func, Py_None);
+    if (rc != SQLITE_OK) {
+        /* Workaround for SQLite bug: no error code or string is available here */
+        PyErr_SetString(OperationalError, "Error creating function");
+        return NULL;
+    } else {
+        PyDict_SetItem(self->function_pinboard, func, Py_None);
 
-    Py_INCREF(Py_None);
-    return Py_None;
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
 }
 
 PyObject* connection_create_aggregate(Connection* self, PyObject* args, PyObject* kwargs)
@@ -639,7 +688,8 @@
 
     rc = sqlite3_create_function(self->db, name, n_arg, SQLITE_UTF8, (void*)aggregate_class, 0, &_step_callback, &_final_callback);
     if (rc != SQLITE_OK) {
-        _seterror(self->db);
+        /* Workaround for SQLite bug: no error code or string is available here */
+        PyErr_SetString(OperationalError, "Error creating aggregate");
         return NULL;
     } else {
         PyDict_SetItem(self->function_pinboard, aggregate_class, Py_None);
@@ -682,7 +732,6 @@
 
 static int connection_set_isolation_level(Connection* self, PyObject* isolation_level)
 {
-    PyObject* empty;
     PyObject* res;
     PyObject* begin_statement;
 
@@ -697,15 +746,10 @@
         Py_INCREF(Py_None);
         self->isolation_level = Py_None;
 
-        empty = PyTuple_New(0);
-        if (!empty) {
-            return -1;
-        }
-        res = connection_commit(self, empty);
+        res = connection_commit(self, NULL);
         if (!res) {
             return -1;
         }
-        Py_DECREF(empty);
         Py_DECREF(res);
 
         self->inTransaction = 0;
@@ -738,12 +782,15 @@
 {
     PyObject* sql;
     Statement* statement;
+    PyObject* weakref;
     int rc;
 
     if (!PyArg_ParseTuple(args, "O", &sql)) {
         return NULL;
     }
 
+    _drop_unused_statement_references(self);
+
     statement = PyObject_New(Statement, &StatementType);
     if (!statement) {
         return NULL;
@@ -762,8 +809,24 @@
 
         Py_DECREF(statement);
         statement = 0;
+    } else {
+        weakref = PyWeakref_NewRef((PyObject*)statement, NULL);
+        if (!weakref) {
+            Py_DECREF(statement);
+            statement = 0;
+            goto error;
+        }
+
+        if (PyList_Append(self->statements, weakref) != 0) {
+            Py_DECREF(weakref);
+            statement = 0;
+            goto error;
+        }
+
+        Py_DECREF(weakref);
     }
 
+error:
     return (PyObject*)statement;
 }
 
@@ -983,7 +1046,7 @@
 }
 
 static char connection_doc[] =
-PyDoc_STR("<missing docstring>");
+PyDoc_STR("SQLite database connection object.");
 
 static PyGetSetDef connection_getset[] = {
     {"isolation_level",  (getter)connection_get_isolation_level, (setter)connection_set_isolation_level},
@@ -1011,7 +1074,7 @@
     {"executescript", (PyCFunction)connection_executescript, METH_VARARGS,
         PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")},
     {"create_collation", (PyCFunction)connection_create_collation, METH_VARARGS,
-        PyDoc_STR("Creates a collation function.")},
+        PyDoc_STR("Creates a collation function. Non-standard.")},
     {NULL, NULL}
 };
 
diff --git a/Modules/_sqlite/connection.h b/Modules/_sqlite/connection.h
index faae6e4..8f4d36e 100644
--- a/Modules/_sqlite/connection.h
+++ b/Modules/_sqlite/connection.h
@@ -1,6 +1,6 @@
 /* connection.h - definitions for the connection type
  *
- * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -37,7 +37,12 @@
     PyObject_HEAD
     sqlite3* db;
 
+    /* 1 if we are currently within a transaction, i. e. if a BEGIN has been
+     * issued */
     int inTransaction;
+
+    /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a
+     * bitwise combination thereof makes sense */
     int detect_types;
 
     /* the timeout value in seconds for database locks */
@@ -54,13 +59,31 @@
      * freed in connection destructor */
     char* begin_statement;
 
+    /* 1 if a check should be performed for each API call if the connection is
+     * used from the same thread it was created in */
     int check_same_thread;
+
+    /* thread identification of the thread the connection was created in */
     long thread_ident;
 
     Cache* statement_cache;
 
+    /* A list of weak references to statements used within this connection */
+    PyObject* statements;
+
+    /* a counter for how many statements were created in the connection. May be
+     * reset to 0 at certain intervals */
+    int created_statements;
+
     PyObject* row_factory;
 
+    /* Determines how bytestrings from SQLite are converted to Python objects:
+     * - PyUnicode_Type:        Python Unicode objects are constructed from UTF-8 bytestrings
+     * - OptimizedUnicode:      Like before, but for ASCII data, only PyStrings are created.
+     * - PyString_Type:         PyStrings are created as-is.
+     * - Any custom callable:   Any object returned from the callable called with the bytestring
+     *                          as single parameter.
+     */
     PyObject* text_factory;
 
     /* remember references to functions/classes used in
diff --git a/Modules/_sqlite/converters.c b/Modules/_sqlite/converters.c
deleted file mode 100644
index 018063a..0000000
--- a/Modules/_sqlite/converters.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* converters.c - default converters
- *
- * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
- *
- * This file is part of pysqlite.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "util.h"
-#include "module.h"
-#include "adapters.h"
-
-/* dummy, will be implemented in a later version */
-
-PyObject* convert_date(PyObject* self, PyObject* args, PyObject* kwargs)
-{
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-PyObject* convert_timestamp(PyObject* self, PyObject* args, PyObject* kwargs)
-{
-    Py_INCREF(Py_None);
-    return Py_None;
-}
diff --git a/Modules/_sqlite/converters.h b/Modules/_sqlite/converters.h
deleted file mode 100644
index df3768a..0000000
--- a/Modules/_sqlite/converters.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* converters.h - default converters
- *
- * Copyright (C) 2005 Gerhard Häring <gh@ghaering.de>
- *
- * This file is part of pysqlite.
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef PYSQLITE_CONVERTERS_H
-#define PYSQLITE_CONVERTERS_H
-#include "Python.h"
-#include "pythread.h"
-#include "sqlite3.h"
-
-PyObject* convert_date(PyObject* self, PyObject* args, PyObject* kwargs);
-PyObject* convert_timestamp(PyObject* self, PyObject* args, PyObject* kwargs);
-
-#endif
diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
index c6b8c77..8c72412 100644
--- a/Modules/_sqlite/cursor.c
+++ b/Modules/_sqlite/cursor.c
@@ -157,24 +157,24 @@
 
         if (self->connection->detect_types | PARSE_COLNAMES) {
             colname = sqlite3_column_name(self->statement->st, i);
+            if (colname) {
+                for (pos = colname; *pos != 0; pos++) {
+                    if (*pos == '[') {
+                        type_start = pos + 1;
+                    } else if (*pos == ']' && type_start != (const char*)-1) {
+                        key = PyString_FromStringAndSize(type_start, pos - type_start);
+                        if (!key) {
+                            /* creating a string failed, but it is too complicated
+                             * to propagate the error here, we just assume there is
+                             * no converter and proceed */
+                            break;
+                        }
 
-            for (pos = colname; *pos != 0; pos++) {
-                if (*pos == '[') {
-                    type_start = pos + 1;
-                } else if (*pos == ']' && type_start != (const char*)-1) {
-                    key = PyString_FromStringAndSize(type_start, pos - type_start);
-                    if (!key) {
-                        /* creating a string failed, but it is too complicated
-                         * to propagate the error here, we just assume there is
-                         * no converter and proceed */
+                        converter = PyDict_GetItem(converters, key);
+                        Py_DECREF(key);
                         break;
                     }
-
-                    converter = PyDict_GetItem(converters, key);
-                    Py_DECREF(key);
-                    break;
                 }
-
             }
         }
 
@@ -276,6 +276,7 @@
     void* raw_buffer;
     const char* val_str;
     char buf[200];
+    const char* colname;
 
     Py_BEGIN_ALLOW_THREADS
     numcols = sqlite3_data_count(self->statement->st);
@@ -340,8 +341,12 @@
                         self->connection->text_factory == OptimizedUnicode ? 1 : 0);
 
                     if (!converted) {
+                        colname = sqlite3_column_name(self->statement->st, i);
+                        if (colname) {
+                            colname = "<unknown column name>";
+                        }
                         PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column %s with text %s",
-                                    sqlite3_column_name(self->statement->st, i), val_str);
+                                     colname , val_str);
                         PyErr_SetString(OperationalError, buf);
                     }
                 } else if (self->connection->text_factory == (PyObject*)&PyString_Type) {
@@ -419,8 +424,7 @@
         } else {
             /* sequence */
             parameters_iter = PyObject_GetIter(second_argument);
-            if (!parameters_iter)
-            {
+            if (!parameters_iter) {
                 return NULL;
             }
         }
@@ -506,12 +510,7 @@
                 /* it's a DDL statement or something similar
                    - we better COMMIT first so it works for all cases */
                 if (self->connection->inTransaction) {
-                    func_args = PyTuple_New(0);
-                    if (!func_args) {
-                        goto error;
-                    }
-                    result = connection_commit(self->connection, func_args);
-                    Py_DECREF(func_args);
+                    result = connection_commit(self->connection, NULL);
                     if (!result) {
                         goto error;
                     }
@@ -701,7 +700,6 @@
     const char* script_cstr;
     sqlite3_stmt* statement;
     int rc;
-    PyObject* func_args;
     PyObject* result;
     int statement_completed = 0;
 
@@ -728,12 +726,7 @@
     }
 
     /* commit first */
-    func_args = PyTuple_New(0);
-    if (!func_args) {
-        goto error;
-    }
-    result = connection_commit(self->connection, func_args);
-    Py_DECREF(func_args);
+    result = connection_commit(self->connection, NULL);
     if (!result) {
         goto error;
     }
@@ -977,6 +970,9 @@
     {NULL}
 };
 
+static char cursor_doc[] =
+PyDoc_STR("SQLite database cursor class.");
+
 PyTypeObject CursorType = {
         PyObject_HEAD_INIT(NULL)
         0,                                              /* ob_size */
@@ -999,7 +995,7 @@
         0,                                              /* tp_setattro */
         0,                                              /* tp_as_buffer */
         Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER|Py_TPFLAGS_BASETYPE, /* tp_flags */
-        0,                                              /* tp_doc */
+        cursor_doc,                                     /* tp_doc */
         0,                                              /* tp_traverse */
         0,                                              /* tp_clear */
         0,                                              /* tp_richcompare */
diff --git a/Modules/_sqlite/cursor.h b/Modules/_sqlite/cursor.h
index 7f56799..831ff81 100644
--- a/Modules/_sqlite/cursor.h
+++ b/Modules/_sqlite/cursor.h
@@ -1,6 +1,6 @@
 /* cursor.h - definitions for the cursor type
  *
- * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
  *
  * This file is part of pysqlite.
  *
diff --git a/Modules/_sqlite/microprotocols.h b/Modules/_sqlite/microprotocols.h
index d2d9b65..f601bb3 100644
--- a/Modules/_sqlite/microprotocols.h
+++ b/Modules/_sqlite/microprotocols.h
@@ -54,6 +54,6 @@
 extern PyObject *
     psyco_microprotocols_adapt(Cursor* self, PyObject *args);   
 #define psyco_microprotocols_adapt_doc \
-    "adapt(obj, protocol, alternate) -> adapt obj to given protocol"
-    
+    "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard."
+
 #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index 1537e79..fb6eb06 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -167,12 +167,12 @@
 
 static PyMethodDef module_methods[] = {
     {"connect",  (PyCFunction)module_connect,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Creates a connection.")},
-    {"complete_statement",  (PyCFunction)module_complete,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Checks if a string contains a complete SQL statement.")},
+    {"complete_statement",  (PyCFunction)module_complete,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Checks if a string contains a complete SQL statement. Non-standard.")},
 #ifdef HAVE_SHARED_CACHE
-    {"enable_shared_cache",  (PyCFunction)module_enable_shared_cache,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Enable or disable shared cache mode for the calling thread.")},
+    {"enable_shared_cache",  (PyCFunction)module_enable_shared_cache,  METH_VARARGS|METH_KEYWORDS, PyDoc_STR("Enable or disable shared cache mode for the calling thread. Experimental/Non-standard.")},
 #endif
-    {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, PyDoc_STR("Registers an adapter with sqlite's adapter registry.")},
-    {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, PyDoc_STR("Registers a converter with sqlite.")},
+    {"register_adapter", (PyCFunction)module_register_adapter, METH_VARARGS, PyDoc_STR("Registers an adapter with pysqlite's adapter registry. Non-standard.")},
+    {"register_converter", (PyCFunction)module_register_converter, METH_VARARGS, PyDoc_STR("Registers a converter with pysqlite. Non-standard.")},
     {"adapt",  (PyCFunction)psyco_microprotocols_adapt, METH_VARARGS, psyco_microprotocols_adapt_doc},
     {NULL, NULL}
 };
diff --git a/Modules/_sqlite/module.h b/Modules/_sqlite/module.h
index 6694735..f3e2aa1 100644
--- a/Modules/_sqlite/module.h
+++ b/Modules/_sqlite/module.h
@@ -1,6 +1,6 @@
 /* module.h - definitions for the module
  *
- * Copyright (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+ * Copyright (C) 2004-2006 Gerhard Häring <gh@ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -25,7 +25,7 @@
 #define PYSQLITE_MODULE_H
 #include "Python.h"
 
-#define PYSQLITE_VERSION "2.2.0"
+#define PYSQLITE_VERSION "2.2.2"
 
 extern PyObject* Error;
 extern PyObject* Warning;
diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c
index 0c93651..55923e7 100644
--- a/Modules/_sqlite/statement.c
+++ b/Modules/_sqlite/statement.c
@@ -64,6 +64,7 @@
         return rc;
     }
 
+    self->in_weakreflist = NULL;
     self->sql = sql_str;
 
     sql_cstr = PyString_AsString(sql_str);
@@ -304,6 +305,10 @@
 
     Py_XDECREF(self->sql);
 
+    if (self->in_weakreflist != NULL) {
+        PyObject_ClearWeakRefs((PyObject*)self);
+    }
+
     self->ob_type->tp_free((PyObject*)self);
 }
 
@@ -398,12 +403,12 @@
         0,                                              /* tp_getattro */
         0,                                              /* tp_setattro */
         0,                                              /* tp_as_buffer */
-        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
+        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,  /* tp_flags */
         0,                                              /* tp_doc */
         0,                                              /* tp_traverse */
         0,                                              /* tp_clear */
         0,                                              /* tp_richcompare */
-        0,                                              /* tp_weaklistoffset */
+        offsetof(Statement, in_weakreflist),            /* tp_weaklistoffset */
         0,                                              /* tp_iter */
         0,                                              /* tp_iternext */
         0,                                              /* tp_methods */
diff --git a/Modules/_sqlite/statement.h b/Modules/_sqlite/statement.h
index e45a0fc..57ee36f 100644
--- a/Modules/_sqlite/statement.h
+++ b/Modules/_sqlite/statement.h
@@ -38,6 +38,7 @@
     sqlite3_stmt* st;
     PyObject* sql;
     int in_use;
+    PyObject* in_weakreflist; /* List of weak references */
 } Statement;
 
 extern PyTypeObject StatementType;
diff --git a/PCbuild/_sqlite3.vcproj b/PCbuild/_sqlite3.vcproj
index e81d3a0..a0408a6 100644
--- a/PCbuild/_sqlite3.vcproj
+++ b/PCbuild/_sqlite3.vcproj
@@ -251,18 +251,12 @@
 	</References>
 	<Files>
 		<File
-			RelativePath="..\Modules\_sqlite\adapters.c">
-		</File>
-		<File
 			RelativePath="..\Modules\_sqlite\cache.c">
 		</File>
 		<File
 			RelativePath="..\Modules\_sqlite\connection.c">
 		</File>
 		<File
-			RelativePath="..\Modules\_sqlite\converters.c">
-		</File>
-		<File
 			RelativePath="..\Modules\_sqlite\cursor.c">
 		</File>
 		<File
diff --git a/setup.py b/setup.py
index 61c1fec..750f47c 100644
--- a/setup.py
+++ b/setup.py
@@ -743,10 +743,8 @@
             sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))]
 
         if sqlite_incdir and sqlite_libdir:
-            sqlite_srcs = ['_sqlite/adapters.c',
-                '_sqlite/cache.c',
+            sqlite_srcs = ['_sqlite/cache.c',
                 '_sqlite/connection.c',
-                '_sqlite/converters.c',
                 '_sqlite/cursor.c',
                 '_sqlite/microprotocols.c',
                 '_sqlite/module.c',
@@ -755,18 +753,12 @@
                 '_sqlite/statement.c',
                 '_sqlite/util.c', ]
 
-            PYSQLITE_VERSION = "2.2.0"
             sqlite_defines = []
             if sys.platform != "win32":
                 sqlite_defines.append(('MODULE_NAME', '"sqlite3"'))
             else:
                 sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
 
-            sqlite_defines.append(('PY_MAJOR_VERSION',
-                                        str(sys.version_info[0])))
-            sqlite_defines.append(('PY_MINOR_VERSION',
-                                        str(sys.version_info[1])))
-
             exts.append(Extension('_sqlite3', sqlite_srcs,
                                   define_macros=sqlite_defines,
                                   include_dirs=["Modules/_sqlite",