--- a/System.Data.SQLite/SQLite3.cs
+++ b/System.Data.SQLite/SQLite3.cs
@@ -3,966 +3,990 @@
  * Written by Robert Simpson (robert@blackcastlesoft.com)
  * 
  * Released to the public domain, use at your own risk!
- ********************************************************/
-
-namespace System.Data.SQLite
-{
-  using System;
-  using System.Runtime.InteropServices;
-  using System.Collections.Generic;
-  using System.Globalization;
-
-  /// <summary>
-  /// This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET
-  /// </summary>
-  internal class SQLite3 : SQLiteBase
-  {
-    /// <summary>
-    /// The opaque pointer returned to us by the sqlite provider
-    /// </summary>
-    protected SQLiteConnectionHandle _sql;
-    protected string _fileName;
-    protected bool _usePool;
-    protected int _poolVersion;
-
-#if !PLATFORM_COMPACTFRAMEWORK
-    private bool _buildingSchema;
-#endif
-    /// <summary>
-    /// The user-defined functions registered on this connection
-    /// </summary>
-    protected SQLiteFunction[] _functionsArray;
-
-    internal SQLite3(SQLiteDateFormats fmt)
-      : base(fmt)
-    {
-    }
-
-    protected override void Dispose(bool bDisposing)
-    {
-      if (bDisposing)
-        Close();
-    }
-
-    // It isn't necessary to cleanup any functions we've registered.  If the connection
-    // goes to the pool and is resurrected later, re-registered functions will overwrite the
-    // previous functions.  The SQLiteFunctionCookieHandle will take care of freeing unmanaged
-    // resources belonging to the previously-registered functions.
-    internal override void Close()
-    {
-      if (_sql != null)
-      {
-        if (_usePool)
-        {
-          SQLiteBase.ResetConnection(_sql);
-          SQLiteConnectionPool.Add(_fileName, _sql, _poolVersion);
-        }
-        else
-          _sql.Dispose();
-      }
-
-      _sql = null;
-    }
-
-    internal override void Cancel()
-    {
-      UnsafeNativeMethods.sqlite3_interrupt(_sql);
-    }
-
-    internal override string Version
-    {
-      get
-      {
-        return SQLite3.SQLiteVersion;
-      }
-    }
-
-    internal static string SQLiteVersion
-    {
-      get
-      {
-        return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1);
-      }
-    }
-
-    internal override bool AutoCommit
-    {
-      get
-      {
-        return IsAutocommit(_sql);
-      }
-    }
-
-    internal override int Changes
-    {
-      get
-      {
-        return UnsafeNativeMethods.sqlite3_changes(_sql);
-      }
-    }
-
-    internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
-    {
-      if (_sql != null) return;
-
-      _usePool = usePool;
-      if (usePool)
-      {
-        _fileName = strFilename;
-        _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);
-      }
-
-      if (_sql == null)
-      {
-        IntPtr db;
-
-#if !SQLITE_STANDARD
-        int n = UnsafeNativeMethods.sqlite3_open_interop(ToUTF8(strFilename), (int)flags, out db);
-#else
-        int n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero);
-#endif
-        if (n > 0) throw new SQLiteException(n, null);
-
-        _sql = db;
-      }
-      // Bind functions to this connection.  If any previous functions of the same name
-      // were already bound, then the new bindings replace the old.
-      _functionsArray = SQLiteFunction.BindFunctions(this);
-      SetTimeout(0);
-    }
-
-    internal override void ClearPool()
-    {
-      SQLiteConnectionPool.ClearPool(_fileName);
-    }
-
-    internal override void SetTimeout(int nTimeoutMS)
-    {
-      int n = UnsafeNativeMethods.sqlite3_busy_timeout(_sql, nTimeoutMS);
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override bool Step(SQLiteStatement stmt)
-    {
-      int n;
-      Random rnd = null;
-      uint starttick = (uint)Environment.TickCount;
-      uint timeout = (uint)(stmt._command._commandTimeout * 1000);
-
-      while (true)
-      {
-        n = UnsafeNativeMethods.sqlite3_step(stmt._sqlite_stmt);
-
-        if (n == 100) return true;
-        if (n == 101) return false;
-
-        if (n > 0)
-        {
-          int r;
-
-          // An error occurred, attempt to reset the statement.  If the reset worked because the
-          // schema has changed, re-try the step again.  If it errored our because the database
-          // is locked, then keep retrying until the command timeout occurs.
-          r = Reset(stmt);
-
-          if (r == 0)
-            throw new SQLiteException(n, SQLiteLastError());
-
-          else if ((r == 6 || r == 5) && stmt._command != null) // SQLITE_LOCKED || SQLITE_BUSY
-          {
-            // Keep trying
-            if (rnd == null) // First time we've encountered the lock
-              rnd = new Random();
-
-            // If we've exceeded the command's timeout, give up and throw an error
-            if ((uint)Environment.TickCount - starttick > timeout)
-            {
-              throw new SQLiteException(r, SQLiteLastError());
-            }
-            else
-            {
-              // Otherwise sleep for a random amount of time up to 150ms
-              System.Threading.Thread.Sleep(rnd.Next(1, 150));
-            }
-          }
-        }
-      }
-    }
-
-    internal override int Reset(SQLiteStatement stmt)
-    {
-      int n;
-
-#if !SQLITE_STANDARD
-      n = UnsafeNativeMethods.sqlite3_reset_interop(stmt._sqlite_stmt);
-#else
-      n = UnsafeNativeMethods.sqlite3_reset(stmt._sqlite_stmt);
-#endif
-
-      // If the schema changed, try and re-prepare it
-      if (n == 17) // SQLITE_SCHEMA
-      {
-        // Recreate a dummy statement
-        string str;
-        using (SQLiteStatement tmp = Prepare(null, stmt._sqlStatement, null, (uint)(stmt._command._commandTimeout * 1000), out str))
-        {
-          // Finalize the existing statement
-          stmt._sqlite_stmt.Dispose();
-          // Reassign a new statement pointer to the old statement and clear the temporary one
-          stmt._sqlite_stmt = tmp._sqlite_stmt;
-          tmp._sqlite_stmt = null;
-
-          // Reapply parameters
-          stmt.BindParameters();
-        }
-        return -1; // Reset was OK, with schema change
-      }
-      else if (n == 6 || n == 5) // SQLITE_LOCKED || SQLITE_BUSY
-        return n;
-
-      if (n > 0)
-        throw new SQLiteException(n, SQLiteLastError());
-
-      return 0; // We reset OK, no schema changes
-    }
-
-    internal override string SQLiteLastError()
-    {
-      return SQLiteBase.SQLiteLastError(_sql);
-    }
-
-    internal override SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain)
-    {
-      IntPtr stmt = IntPtr.Zero;
-      IntPtr ptr = IntPtr.Zero;
-      int len = 0;
-      int n = 17;
-      int retries = 0;
-      byte[] b = ToUTF8(strSql);
-      string typedefs = null;
-      SQLiteStatement cmd = null;
-      Random rnd = null;
-      uint starttick = (uint)Environment.TickCount;
-
-      GCHandle handle = GCHandle.Alloc(b, GCHandleType.Pinned);
-      IntPtr psql = handle.AddrOfPinnedObject();
-      try
-      {
-        while ((n == 17 || n == 6 || n == 5) && retries < 3)
-        {
-#if !SQLITE_STANDARD
-          n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len);
+ ********************************************************/
+
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+
+namespace System.Data.SQLite
+{
+    /// <summary>
+    /// This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET
+    /// </summary>
+    internal class SQLite3 : SQLiteBase
+    {
+        /// <summary>
+        /// The opaque pointer returned to us by the sqlite provider
+        /// </summary>
+        protected SQLiteConnectionHandle _sql;
+
+        protected string _fileName;
+        protected bool _usePool;
+        protected int _poolVersion;
+
+#if !PLATFORM_COMPACTFRAMEWORK
+        private bool _buildingSchema;
+#endif
+
+        /// <summary>
+        /// The user-defined functions registered on this connection
+        /// </summary>
+        protected SQLiteFunction[] _functionsArray;
+
+        internal SQLite3(SQLiteDateFormats fmt)
+            : base(fmt)
+        {
+        }
+
+        protected override void Dispose(bool bDisposing)
+        {
+            if (bDisposing)
+                Close();
+        }
+
+        // It isn't necessary to cleanup any functions we've registered.  If the connection
+        // goes to the pool and is resurrected later, re-registered functions will overwrite the
+        // previous functions.  The SQLiteFunctionCookieHandle will take care of freeing unmanaged
+        // resources belonging to the previously-registered functions.
+        internal override void Close()
+        {
+            if (_sql != null)
+            {
+                if (_usePool)
+                {
+                    ResetConnection(_sql);
+                    SQLiteConnectionPool.Add(_fileName, _sql, _poolVersion);
+                }
+                else
+                    _sql.Dispose();
+            }
+
+            _sql = null;
+        }
+
+        internal override void Cancel()
+        {
+            UnsafeNativeMethods.sqlite3_interrupt(_sql);
+        }
+
+        internal override string Version
+        {
+            get { return SQLiteVersion; }
+        }
+
+        internal static string SQLiteVersion
+        {
+            get { return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1); }
+        }
+
+        internal override bool AutoCommit
+        {
+            get { return IsAutocommit(_sql); }
+        }
+
+        internal override int Changes
+        {
+            get { return UnsafeNativeMethods.sqlite3_changes(_sql); }
+        }
+
+        internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool)
+        {
+            if (_sql != null) return;
+
+            _usePool = usePool;
+            if (usePool)
+            {
+                _fileName = strFilename;
+                _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);
+            }
+
+            if (_sql == null)
+            {
+                IntPtr db;
+
+#if !SQLITE_STANDARD
+                int n = UnsafeNativeMethods.sqlite3_open_interop(ToUTF8(strFilename), (int) flags, out db);
+#else
+        int n = UnsafeNativeMethods.sqlite3_open_v2(ToUTF8(strFilename), out db, (int)flags, IntPtr.Zero);
+#endif
+                if (n > 0) throw new SQLiteException(n, null);
+
+                _sql = db;
+            }
+            // Bind functions to this connection.  If any previous functions of the same name
+            // were already bound, then the new bindings replace the old.
+            _functionsArray = SQLiteFunction.BindFunctions(this);
+            SetTimeout(0);
+        }
+
+        internal override void ClearPool()
+        {
+            SQLiteConnectionPool.ClearPool(_fileName);
+        }
+
+        internal override void SetTimeout(int nTimeoutMS)
+        {
+            int n = UnsafeNativeMethods.sqlite3_busy_timeout(_sql, nTimeoutMS);
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override bool Step(SQLiteStatement stmt)
+        {
+            int n;
+            Random rnd = null;
+            var starttick = (uint) Environment.TickCount;
+            var timeout = (uint) (stmt._command._commandTimeout*1000);
+
+            while (true)
+            {
+                n = UnsafeNativeMethods.sqlite3_step(stmt._sqlite_stmt);
+
+                if (n == 100) return true;
+                if (n == 101) return false;
+
+                if (n > 0)
+                {
+                    int r;
+
+                    // An error occurred, attempt to reset the statement.  If the reset worked because the
+                    // schema has changed, re-try the step again.  If it errored our because the database
+                    // is locked, then keep retrying until the command timeout occurs.
+                    r = Reset(stmt);
+
+                    if (r == 0)
+                        throw new SQLiteException(n, SQLiteLastError());
+
+                    else if ((r == 6 || r == 5) && stmt._command != null) // SQLITE_LOCKED || SQLITE_BUSY
+                    {
+                        // Keep trying
+                        if (rnd == null) // First time we've encountered the lock
+                            rnd = new Random();
+
+                        // If we've exceeded the command's timeout, give up and throw an error
+                        if ((uint) Environment.TickCount - starttick > timeout)
+                        {
+                            throw new SQLiteException(r, SQLiteLastError());
+                        }
+                        else
+                        {
+                            // Otherwise sleep for a random amount of time up to 150ms
+                            Thread.Sleep(rnd.Next(1, 150));
+                        }
+                    }
+                }
+            }
+        }
+
+        internal override int Reset(SQLiteStatement stmt)
+        {
+            int n;
+
+#if !SQLITE_STANDARD
+            n = UnsafeNativeMethods.sqlite3_reset_interop(stmt._sqlite_stmt);
+#else
+      n = UnsafeNativeMethods.sqlite3_reset(stmt._sqlite_stmt);
+#endif
+
+            // If the schema changed, try and re-prepare it
+            if (n == 17) // SQLITE_SCHEMA
+            {
+                // Recreate a dummy statement
+                string str;
+                using (
+                    SQLiteStatement tmp = Prepare(null, stmt._sqlStatement, null,
+                                                  (uint) (stmt._command._commandTimeout*1000), out str))
+                {
+                    // Finalize the existing statement
+                    stmt._sqlite_stmt.Dispose();
+                    // Reassign a new statement pointer to the old statement and clear the temporary one
+                    stmt._sqlite_stmt = tmp._sqlite_stmt;
+                    tmp._sqlite_stmt = null;
+
+                    // Reapply parameters
+                    stmt.BindParameters();
+                }
+                return -1; // Reset was OK, with schema change
+            }
+            else if (n == 6 || n == 5) // SQLITE_LOCKED || SQLITE_BUSY
+                return n;
+
+            if (n > 0)
+                throw new SQLiteException(n, SQLiteLastError());
+
+            return 0; // We reset OK, no schema changes
+        }
+
+        internal override string SQLiteLastError()
+        {
+            return SQLiteLastError(_sql);
+        }
+
+        internal override SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous,
+                                                  uint timeoutMS, out string strRemain)
+        {
+            IntPtr stmt = IntPtr.Zero;
+            IntPtr ptr = IntPtr.Zero;
+            int len = 0;
+            int n = 17;
+            int retries = 0;
+            byte[] b = ToUTF8(strSql);
+            string typedefs = null;
+            SQLiteStatement cmd = null;
+            Random rnd = null;
+            var starttick = (uint) Environment.TickCount;
+
+            GCHandle handle = GCHandle.Alloc(b, GCHandleType.Pinned);
+            IntPtr psql = handle.AddrOfPinnedObject();
+            try
+            {
+                while ((n == 17 || n == 6 || n == 5) && retries < 3)
+                {
+#if !SQLITE_STANDARD
+                    n = UnsafeNativeMethods.sqlite3_prepare_interop(_sql, psql, b.Length - 1, out stmt, out ptr, out len);
 #else
           n = UnsafeNativeMethods.sqlite3_prepare(_sql, psql, b.Length - 1, out stmt, out ptr);
-          len = -1;
-#endif
-
-          if (n == 17)
-            retries++;
-          else if (n == 1)
-          {
-            if (String.Compare(SQLiteLastError(), "near \"TYPES\": syntax error", StringComparison.OrdinalIgnoreCase) == 0)
-            {
-              int pos = strSql.IndexOf(';');
-              if (pos == -1) pos = strSql.Length - 1;
-
-              typedefs = strSql.Substring(0, pos + 1);
-              strSql = strSql.Substring(pos + 1);
-
-              strRemain = "";
-
-              while (cmd == null && strSql.Length > 0)
-              {
-                cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain);
-                strSql = strRemain;
-              }
-
-              if (cmd != null)
-                cmd.SetTypes(typedefs);
-
-              return cmd;
-            }
-#if !PLATFORM_COMPACTFRAMEWORK
-            else if (_buildingSchema == false && String.Compare(SQLiteLastError(), 0, "no such table: TEMP.SCHEMA", 0, 26, StringComparison.OrdinalIgnoreCase) == 0)
-            {
-              strRemain = "";
-              _buildingSchema = true;
-              try
-              {
-                ISQLiteSchemaExtensions ext = ((IServiceProvider)SQLiteFactory.Instance).GetService(typeof(ISQLiteSchemaExtensions)) as ISQLiteSchemaExtensions;
-
-                if (ext != null)
-                  ext.BuildTempSchema(cnn);
-
-                while (cmd == null && strSql.Length > 0)
-                {
-                  cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain);
-                  strSql = strRemain;
-                }
-
-                return cmd;
-              }
-              finally
-              {
-                _buildingSchema = false;
-              }
-            }
-#endif
-          }
-          else if (n == 6 || n == 5) // Locked -- delay a small amount before retrying
-          {
-            // Keep trying
-            if (rnd == null) // First time we've encountered the lock
-              rnd = new Random();
-
-            // If we've exceeded the command's timeout, give up and throw an error
-            if ((uint)Environment.TickCount - starttick > timeoutMS)
-            {
-              throw new SQLiteException(n, SQLiteLastError());
-            }
-            else
-            {
-              // Otherwise sleep for a random amount of time up to 150ms
-              System.Threading.Thread.Sleep(rnd.Next(1, 150));
-            }
-          }
-        }
-
-        if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-
-        strRemain = UTF8ToString(ptr, len);
-
-        if (stmt != IntPtr.Zero) cmd = new SQLiteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length), previous);
-
-        return cmd;
-      }
-      finally
-      {
-        handle.Free();
-      }
-    }
-
-    internal override void Bind_Double(SQLiteStatement stmt, int index, double value)
-    {
-#if !PLATFORM_COMPACTFRAMEWORK
-      int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
-#else
-      int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
-#endif
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void Bind_Int32(SQLiteStatement stmt, int index, int value)
-    {
-      int n = UnsafeNativeMethods.sqlite3_bind_int(stmt._sqlite_stmt, index, value);
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void Bind_Int64(SQLiteStatement stmt, int index, long value)
-    {
-#if !PLATFORM_COMPACTFRAMEWORK
-      int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
-#else
-      int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
-#endif
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
-    {
-      byte[] b = ToUTF8(value);
-      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
-    {
-      byte[] b = ToUTF8(dt);
-      int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr)(-1));
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
-    {
-      int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length, (IntPtr)(-1));
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void Bind_Null(SQLiteStatement stmt, int index)
-    {
-      int n = UnsafeNativeMethods.sqlite3_bind_null(stmt._sqlite_stmt, index);
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override int Bind_ParamCount(SQLiteStatement stmt)
-    {
-      return UnsafeNativeMethods.sqlite3_bind_parameter_count(stmt._sqlite_stmt);
-    }
-
-    internal override string Bind_ParamName(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override int Bind_ParamIndex(SQLiteStatement stmt, string paramName)
-    {
-      return UnsafeNativeMethods.sqlite3_bind_parameter_index(stmt._sqlite_stmt, ToUTF8(paramName));
-    }
-
-    internal override int ColumnCount(SQLiteStatement stmt)
-    {
-      return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt);
-    }
-
-    internal override string ColumnName(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_name_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_name(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override TypeAffinity ColumnAffinity(SQLiteStatement stmt, int index)
-    {
-      return UnsafeNativeMethods.sqlite3_column_type(stmt._sqlite_stmt, index);
-    }
-
-    internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity)
-    {
-      int len;
-#if !SQLITE_STANDARD
-      IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype_interop(stmt._sqlite_stmt, index, out len);
+          len = -1;
+#endif
+
+                    if (n == 17)
+                        retries++;
+                    else if (n == 1)
+                    {
+                        if (
+                            String.Compare(SQLiteLastError(), "near \"TYPES\": syntax error",
+                                           StringComparison.OrdinalIgnoreCase) == 0)
+                        {
+                            int pos = strSql.IndexOf(';');
+                            if (pos == -1) pos = strSql.Length - 1;
+
+                            typedefs = strSql.Substring(0, pos + 1);
+                            strSql = strSql.Substring(pos + 1);
+
+                            strRemain = "";
+
+                            while (cmd == null && strSql.Length > 0)
+                            {
+                                cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain);
+                                strSql = strRemain;
+                            }
+
+                            if (cmd != null)
+                                cmd.SetTypes(typedefs);
+
+                            return cmd;
+                        }
+#if !PLATFORM_COMPACTFRAMEWORK
+                        else if (_buildingSchema == false &&
+                                 String.Compare(SQLiteLastError(), 0, "no such table: TEMP.SCHEMA", 0, 26,
+                                                StringComparison.OrdinalIgnoreCase) == 0)
+                        {
+                            strRemain = "";
+                            _buildingSchema = true;
+                            try
+                            {
+                                var ext =
+                                    ((IServiceProvider) SQLiteFactory.Instance).GetService(
+                                        typeof (ISQLiteSchemaExtensions)) as ISQLiteSchemaExtensions;
+
+                                if (ext != null)
+                                    ext.BuildTempSchema(cnn);
+
+                                while (cmd == null && strSql.Length > 0)
+                                {
+                                    cmd = Prepare(cnn, strSql, previous, timeoutMS, out strRemain);
+                                    strSql = strRemain;
+                                }
+
+                                return cmd;
+                            }
+                            finally
+                            {
+                                _buildingSchema = false;
+                            }
+                        }
+#endif
+                    }
+                    else if (n == 6 || n == 5) // Locked -- delay a small amount before retrying
+                    {
+                        // Keep trying
+                        if (rnd == null) // First time we've encountered the lock
+                            rnd = new Random();
+
+                        // If we've exceeded the command's timeout, give up and throw an error
+                        if ((uint) Environment.TickCount - starttick > timeoutMS)
+                        {
+                            throw new SQLiteException(n, SQLiteLastError());
+                        }
+                        else
+                        {
+                            // Otherwise sleep for a random amount of time up to 150ms
+                            Thread.Sleep(rnd.Next(1, 150));
+                        }
+                    }
+                }
+
+                if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+
+                strRemain = UTF8ToString(ptr, len);
+
+                if (stmt != IntPtr.Zero)
+                    cmd = new SQLiteStatement(this, stmt, strSql.Substring(0, strSql.Length - strRemain.Length),
+                                              previous);
+
+                return cmd;
+            }
+            finally
+            {
+                handle.Free();
+            }
+        }
+
+        internal override void Bind_Double(SQLiteStatement stmt, int index, double value)
+        {
+#if !PLATFORM_COMPACTFRAMEWORK
+            int n = UnsafeNativeMethods.sqlite3_bind_double(stmt._sqlite_stmt, index, value);
+#else
+      int n = UnsafeNativeMethods.sqlite3_bind_double_interop(stmt._sqlite_stmt, index, ref value);
+#endif
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void Bind_Int32(SQLiteStatement stmt, int index, int value)
+        {
+            int n = UnsafeNativeMethods.sqlite3_bind_int(stmt._sqlite_stmt, index, value);
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void Bind_Int64(SQLiteStatement stmt, int index, long value)
+        {
+#if !PLATFORM_COMPACTFRAMEWORK
+            int n = UnsafeNativeMethods.sqlite3_bind_int64(stmt._sqlite_stmt, index, value);
+#else
+      int n = UnsafeNativeMethods.sqlite3_bind_int64_interop(stmt._sqlite_stmt, index, ref value);
+#endif
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void Bind_Text(SQLiteStatement stmt, int index, string value)
+        {
+            byte[] b = ToUTF8(value);
+            int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr) (-1));
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void Bind_DateTime(SQLiteStatement stmt, int index, DateTime dt)
+        {
+            byte[] b = ToUTF8(dt);
+            int n = UnsafeNativeMethods.sqlite3_bind_text(stmt._sqlite_stmt, index, b, b.Length - 1, (IntPtr) (-1));
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void Bind_Blob(SQLiteStatement stmt, int index, byte[] blobData)
+        {
+            int n = UnsafeNativeMethods.sqlite3_bind_blob(stmt._sqlite_stmt, index, blobData, blobData.Length,
+                                                          (IntPtr) (-1));
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void Bind_Null(SQLiteStatement stmt, int index)
+        {
+            int n = UnsafeNativeMethods.sqlite3_bind_null(stmt._sqlite_stmt, index);
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override int Bind_ParamCount(SQLiteStatement stmt)
+        {
+            return UnsafeNativeMethods.sqlite3_bind_parameter_count(stmt._sqlite_stmt);
+        }
+
+        internal override string Bind_ParamName(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return
+                UTF8ToString(
+                    UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override int Bind_ParamIndex(SQLiteStatement stmt, string paramName)
+        {
+            return UnsafeNativeMethods.sqlite3_bind_parameter_index(stmt._sqlite_stmt, ToUTF8(paramName));
+        }
+
+        internal override int ColumnCount(SQLiteStatement stmt)
+        {
+            return UnsafeNativeMethods.sqlite3_column_count(stmt._sqlite_stmt);
+        }
+
+        internal override string ColumnName(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return UTF8ToString(UnsafeNativeMethods.sqlite3_column_name_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_name(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override TypeAffinity ColumnAffinity(SQLiteStatement stmt, int index)
+        {
+            return UnsafeNativeMethods.sqlite3_column_type(stmt._sqlite_stmt, index);
+        }
+
+        internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity)
+        {
+            int len;
+#if !SQLITE_STANDARD
+            IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype_interop(stmt._sqlite_stmt, index, out len);
 #else
       len = -1;
-      IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype(stmt._sqlite_stmt, index);
-#endif
-      nAffinity = ColumnAffinity(stmt, index);
-
-      if (p != IntPtr.Zero) return UTF8ToString(p, len);
-      else
-      {
-        string[] ar = stmt.TypeDefinitions;
-        if (ar != null)
-        {
-          if (index < ar.Length && ar[index] != null)
-            return ar[index];
-        }
-        return String.Empty;
-
-        //switch (nAffinity)
-        //{
-        //  case TypeAffinity.Int64:
-        //    return "BIGINT";
-        //  case TypeAffinity.Double:
-        //    return "DOUBLE";
-        //  case TypeAffinity.Blob:
-        //    return "BLOB";
-        //  default:
-        //    return "TEXT";
-        //}
-      }
-    }
-
-    internal override int ColumnIndex(SQLiteStatement stmt, string columnName)
-    {
-      int x = ColumnCount(stmt);
-
-      for (int n = 0; n < x; n++)
-      {
-        if (String.Compare(columnName, ColumnName(stmt, n), StringComparison.OrdinalIgnoreCase) == 0)
-          return n;
-      }
-      return -1;
-    }
-
-    internal override string ColumnOriginalName(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_origin_name_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_origin_name(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override string ColumnDatabaseName(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_database_name_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_database_name(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override string ColumnTableName(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_table_name_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_table_name(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement)
-    {
-      IntPtr dataTypePtr;
-      IntPtr collSeqPtr;
-      int nnotNull;
-      int nprimaryKey;
-      int nautoInc;
-      int n;
-      int dtLen;
-      int csLen;
-
-#if !SQLITE_STANDARD
-      n = UnsafeNativeMethods.sqlite3_table_column_metadata_interop(_sql, ToUTF8(dataBase), ToUTF8(table), ToUTF8(column), out dataTypePtr, out collSeqPtr, out nnotNull, out nprimaryKey, out nautoInc, out dtLen, out csLen);
+      IntPtr p = UnsafeNativeMethods.sqlite3_column_decltype(stmt._sqlite_stmt, index);
+#endif
+            nAffinity = ColumnAffinity(stmt, index);
+
+            if (p != IntPtr.Zero) return UTF8ToString(p, len);
+            else
+            {
+                string[] ar = stmt.TypeDefinitions;
+                if (ar != null)
+                {
+                    if (index < ar.Length && ar[index] != null)
+                        return ar[index];
+                }
+                return String.Empty;
+
+                //switch (nAffinity)
+                //{
+                //  case TypeAffinity.Int64:
+                //    return "BIGINT";
+                //  case TypeAffinity.Double:
+                //    return "DOUBLE";
+                //  case TypeAffinity.Blob:
+                //    return "BLOB";
+                //  default:
+                //    return "TEXT";
+                //}
+            }
+        }
+
+        internal override int ColumnIndex(SQLiteStatement stmt, string columnName)
+        {
+            int x = ColumnCount(stmt);
+
+            for (int n = 0; n < x; n++)
+            {
+                if (String.Compare(columnName, ColumnName(stmt, n), StringComparison.OrdinalIgnoreCase) == 0)
+                    return n;
+            }
+            return -1;
+        }
+
+        internal override string ColumnOriginalName(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return
+                UTF8ToString(UnsafeNativeMethods.sqlite3_column_origin_name_interop(stmt._sqlite_stmt, index, out len),
+                             len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_origin_name(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override string ColumnDatabaseName(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return
+                UTF8ToString(
+                    UnsafeNativeMethods.sqlite3_column_database_name_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_database_name(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override string ColumnTableName(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return UTF8ToString(
+                UnsafeNativeMethods.sqlite3_column_table_name_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_table_name(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override void ColumnMetaData(string dataBase, string table, string column, out string dataType,
+                                              out string collateSequence, out bool notNull, out bool primaryKey,
+                                              out bool autoIncrement)
+        {
+            IntPtr dataTypePtr;
+            IntPtr collSeqPtr;
+            int nnotNull;
+            int nprimaryKey;
+            int nautoInc;
+            int n;
+            int dtLen;
+            int csLen;
+
+#if !SQLITE_STANDARD
+            n = UnsafeNativeMethods.sqlite3_table_column_metadata_interop(_sql, ToUTF8(dataBase), ToUTF8(table),
+                                                                          ToUTF8(column), out dataTypePtr,
+                                                                          out collSeqPtr, out nnotNull, out nprimaryKey,
+                                                                          out nautoInc, out dtLen, out csLen);
 #else
       dtLen = -1;
       csLen = -1;
 
-      n = UnsafeNativeMethods.sqlite3_table_column_metadata(_sql, ToUTF8(dataBase), ToUTF8(table), ToUTF8(column), out dataTypePtr, out collSeqPtr, out nnotNull, out nprimaryKey, out nautoInc);
-#endif
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-
-      dataType = UTF8ToString(dataTypePtr, dtLen);
-      collateSequence = UTF8ToString(collSeqPtr, csLen);
-
-      notNull = (nnotNull == 1);
-      primaryKey = (nprimaryKey == 1);
-      autoIncrement = (nautoInc == 1);
-    }
-
-    internal override double GetDouble(SQLiteStatement stmt, int index)
-    {
-      double value;
-#if !PLATFORM_COMPACTFRAMEWORK
-      value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index);
-#else
-      UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value);
-#endif
-      return value;
-    }
-
-    internal override int GetInt32(SQLiteStatement stmt, int index)
-    {
-      return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index);
-    }
-
-    internal override long GetInt64(SQLiteStatement stmt, int index)
-    {
-      long value;
-#if !PLATFORM_COMPACTFRAMEWORK
-      value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index);
-#else
-      UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value);
-#endif
-      return value;
-    }
-
-    internal override string GetText(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return ToDateTime(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
-#else
-      return ToDateTime(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1);
-#endif
-    }
-
-    internal override long GetBytes(SQLiteStatement stmt, int index, int nDataOffset, byte[] bDest, int nStart, int nLength)
-    {
-      IntPtr ptr;
-      int nlen;
-      int nCopied = nLength;
-
-      nlen = UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index);
-      ptr = UnsafeNativeMethods.sqlite3_column_blob(stmt._sqlite_stmt, index);
-
-      if (bDest == null) return nlen;
-
-      if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart;
-      if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset;
-
-      if (nCopied > 0)
-        Marshal.Copy((IntPtr)(ptr.ToInt64() + nDataOffset), bDest, nStart, nCopied);
-      else nCopied = 0;
-
-      return nCopied;
-    }
-
-    internal override long GetChars(SQLiteStatement stmt, int index, int nDataOffset, char[] bDest, int nStart, int nLength)
-    {
-      int nlen;
-      int nCopied = nLength;
-
-      string str = GetText(stmt, index);
-      nlen = str.Length;
-
-      if (bDest == null) return nlen;
-
-      if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart;
-      if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset;
-
-      if (nCopied > 0)
-        str.CopyTo(nDataOffset, bDest, nStart, nCopied);
-      else nCopied = 0;
-
-      return nCopied;
-    }
-
-    internal override bool IsNull(SQLiteStatement stmt, int index)
-    {
-      return (ColumnAffinity(stmt, index) == TypeAffinity.Null);
-    }
-
-    internal override int AggregateCount(IntPtr context)
-    {
-      return UnsafeNativeMethods.sqlite3_aggregate_count(context);
-    }
-
-    internal override void CreateFunction(string strFunction, int nArgs, bool needCollSeq, SQLiteCallback func, SQLiteCallback funcstep, SQLiteFinalCallback funcfinal)
-    {
-      int n;
-
-#if !SQLITE_STANDARD
-      n = UnsafeNativeMethods.sqlite3_create_function_interop(_sql, ToUTF8(strFunction), nArgs, 4, IntPtr.Zero, func, funcstep, funcfinal, (needCollSeq == true) ? 1 : 0);
-      if (n == 0) n = UnsafeNativeMethods.sqlite3_create_function_interop(_sql, ToUTF8(strFunction), nArgs, 1, IntPtr.Zero, func, funcstep, funcfinal, (needCollSeq == true) ? 1 : 0);
+      n = UnsafeNativeMethods.sqlite3_table_column_metadata(_sql, ToUTF8(dataBase), ToUTF8(table), ToUTF8(column), out dataTypePtr, out collSeqPtr, out nnotNull, out nprimaryKey, out nautoInc);
+#endif
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+
+            dataType = UTF8ToString(dataTypePtr, dtLen);
+            collateSequence = UTF8ToString(collSeqPtr, csLen);
+
+            notNull = (nnotNull == 1);
+            primaryKey = (nprimaryKey == 1);
+            autoIncrement = (nautoInc == 1);
+        }
+
+        internal override double GetDouble(SQLiteStatement stmt, int index)
+        {
+            double value;
+#if !PLATFORM_COMPACTFRAMEWORK
+            value = UnsafeNativeMethods.sqlite3_column_double(stmt._sqlite_stmt, index);
+#else
+      UnsafeNativeMethods.sqlite3_column_double_interop(stmt._sqlite_stmt, index, out value);
+#endif
+            return value;
+        }
+
+        internal override int GetInt32(SQLiteStatement stmt, int index)
+        {
+            return UnsafeNativeMethods.sqlite3_column_int(stmt._sqlite_stmt, index);
+        }
+
+        internal override long GetInt64(SQLiteStatement stmt, int index)
+        {
+            long value;
+#if !PLATFORM_COMPACTFRAMEWORK
+            value = UnsafeNativeMethods.sqlite3_column_int64(stmt._sqlite_stmt, index);
+#else
+      UnsafeNativeMethods.sqlite3_column_int64_interop(stmt._sqlite_stmt, index, out value);
+#endif
+            return value;
+        }
+
+        internal override string GetText(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override DateTime GetDateTime(SQLiteStatement stmt, int index)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return ToDateTime(UnsafeNativeMethods.sqlite3_column_text_interop(stmt._sqlite_stmt, index, out len), len);
+#else
+      return ToDateTime(UnsafeNativeMethods.sqlite3_column_text(stmt._sqlite_stmt, index), -1);
+#endif
+        }
+
+        internal override long GetBytes(SQLiteStatement stmt, int index, int nDataOffset, byte[] bDest, int nStart,
+                                        int nLength)
+        {
+            IntPtr ptr;
+            int nlen;
+            int nCopied = nLength;
+
+            nlen = UnsafeNativeMethods.sqlite3_column_bytes(stmt._sqlite_stmt, index);
+            ptr = UnsafeNativeMethods.sqlite3_column_blob(stmt._sqlite_stmt, index);
+
+            if (bDest == null) return nlen;
+
+            if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart;
+            if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset;
+
+            if (nCopied > 0)
+                Marshal.Copy((IntPtr) (ptr.ToInt64() + nDataOffset), bDest, nStart, nCopied);
+            else nCopied = 0;
+
+            return nCopied;
+        }
+
+        internal override long GetChars(SQLiteStatement stmt, int index, int nDataOffset, char[] bDest, int nStart,
+                                        int nLength)
+        {
+            int nlen;
+            int nCopied = nLength;
+
+            string str = GetText(stmt, index);
+            nlen = str.Length;
+
+            if (bDest == null) return nlen;
+
+            if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart;
+            if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset;
+
+            if (nCopied > 0)
+                str.CopyTo(nDataOffset, bDest, nStart, nCopied);
+            else nCopied = 0;
+
+            return nCopied;
+        }
+
+        internal override bool IsNull(SQLiteStatement stmt, int index)
+        {
+            return (ColumnAffinity(stmt, index) == TypeAffinity.Null);
+        }
+
+        internal override int AggregateCount(IntPtr context)
+        {
+            return UnsafeNativeMethods.sqlite3_aggregate_count(context);
+        }
+
+        internal override void CreateFunction(string strFunction, int nArgs, bool needCollSeq, SQLiteCallback func,
+                                              SQLiteCallback funcstep, SQLiteFinalCallback funcfinal)
+        {
+            int n;
+
+#if !SQLITE_STANDARD
+            n = UnsafeNativeMethods.sqlite3_create_function_interop(_sql, ToUTF8(strFunction), nArgs, 4, IntPtr.Zero,
+                                                                    func, funcstep, funcfinal, needCollSeq ? 1 : 0);
+            if (n == 0)
+                n = UnsafeNativeMethods.sqlite3_create_function_interop(_sql, ToUTF8(strFunction), nArgs, 1, IntPtr.Zero,
+                                                                        func, funcstep, funcfinal, needCollSeq ? 1 : 0);
 #else
       n = UnsafeNativeMethods.sqlite3_create_function(_sql, ToUTF8(strFunction), nArgs, 4, IntPtr.Zero, func, funcstep, funcfinal);
-      if (n == 0) n = UnsafeNativeMethods.sqlite3_create_function(_sql, ToUTF8(strFunction), nArgs, 1, IntPtr.Zero, func, funcstep, funcfinal);
-#endif
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16)
-    {
-      int n = UnsafeNativeMethods.sqlite3_create_collation(_sql, ToUTF8(strCollation), 2, IntPtr.Zero, func16);
-      if (n == 0) n = UnsafeNativeMethods.sqlite3_create_collation(_sql, ToUTF8(strCollation), 1, IntPtr.Zero, func);
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override int ContextCollateCompare(CollationEncodingEnum enc, IntPtr context, string s1, string s2)
-    {
-#if !SQLITE_STANDARD
-      byte[] b1;
-      byte[] b2;
-      System.Text.Encoding converter = null;
-
-      switch (enc)
-      {
-        case CollationEncodingEnum.UTF8:
-          converter = System.Text.Encoding.UTF8;
-          break;
-        case CollationEncodingEnum.UTF16LE:
-          converter = System.Text.Encoding.Unicode;
-          break;
-        case CollationEncodingEnum.UTF16BE:
-          converter = System.Text.Encoding.BigEndianUnicode;
-          break;
-      }
-
-      b1 = converter.GetBytes(s1);
-      b2 = converter.GetBytes(s2);
-
-      return UnsafeNativeMethods.sqlite3_context_collcompare(context, b1, b1.Length, b2, b2.Length);
-#else
-      throw new NotImplementedException();
-#endif
-    }
-
-    internal override int ContextCollateCompare(CollationEncodingEnum enc, IntPtr context, char[] c1, char[] c2)
-    {
-#if !SQLITE_STANDARD
-      byte[] b1;
-      byte[] b2;
-      System.Text.Encoding converter = null;
-
-      switch (enc)
-      {
-        case CollationEncodingEnum.UTF8:
-          converter = System.Text.Encoding.UTF8;
-          break;
-        case CollationEncodingEnum.UTF16LE:
-          converter = System.Text.Encoding.Unicode;
-          break;
-        case CollationEncodingEnum.UTF16BE:
-          converter = System.Text.Encoding.BigEndianUnicode;
-          break;
-      }
-
-      b1 = converter.GetBytes(c1);
-      b2 = converter.GetBytes(c2);
-
-      return UnsafeNativeMethods.sqlite3_context_collcompare(context, b1, b1.Length, b2, b2.Length);
-#else
-      throw new NotImplementedException();
-#endif
-    }
-
-    internal override CollationSequence GetCollationSequence(SQLiteFunction func, IntPtr context)
-    {
-#if !SQLITE_STANDARD
-      CollationSequence seq = new CollationSequence();
-      int len;
-      int type;
-      int enc;
-      IntPtr p = UnsafeNativeMethods.sqlite3_context_collseq(context, out type, out enc, out len);
-
-      if (p != null) seq.Name = UTF8ToString(p, len);
-      seq.Type = (CollationTypeEnum)type;
-      seq._func = func;
-      seq.Encoding = (CollationEncodingEnum)enc;
-
-      return seq;
-#else
-      throw new NotImplementedException();
-#endif
-    }
-
-    internal override long GetParamValueBytes(IntPtr p, int nDataOffset, byte[] bDest, int nStart, int nLength)
-    {
-      IntPtr ptr;
-      int nlen;
-      int nCopied = nLength;
-
-      nlen = UnsafeNativeMethods.sqlite3_value_bytes(p);
-      ptr = UnsafeNativeMethods.sqlite3_value_blob(p);
-
-      if (bDest == null) return nlen;
-
-      if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart;
-      if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset;
-
-      if (nCopied > 0)
-        Marshal.Copy((IntPtr)(ptr.ToInt32() + nDataOffset), bDest, nStart, nCopied);
-      else nCopied = 0;
-
-      return nCopied;
-    }
-
-    internal override double GetParamValueDouble(IntPtr ptr)
-    {
-      double value;
-#if !PLATFORM_COMPACTFRAMEWORK
-      value = UnsafeNativeMethods.sqlite3_value_double(ptr);
-#else
-      UnsafeNativeMethods.sqlite3_value_double_interop(ptr, out value);
-#endif
-      return value;
-    }
-
-    internal override int GetParamValueInt32(IntPtr ptr)
-    {
-      return UnsafeNativeMethods.sqlite3_value_int(ptr);
-    }
-
-    internal override long GetParamValueInt64(IntPtr ptr)
-    {
-      Int64 value;
-#if !PLATFORM_COMPACTFRAMEWORK
-      value = UnsafeNativeMethods.sqlite3_value_int64(ptr);
-#else
-      UnsafeNativeMethods.sqlite3_value_int64_interop(ptr, out value);
-#endif
-      return value;
-    }
-
-    internal override string GetParamValueText(IntPtr ptr)
-    {
-#if !SQLITE_STANDARD
-      int len;
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text_interop(ptr, out len), len);
-#else
-      return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text(ptr), -1);
-#endif
-    }
-
-    internal override TypeAffinity GetParamValueType(IntPtr ptr)
-    {
-      return UnsafeNativeMethods.sqlite3_value_type(ptr);
-    }
-
-    internal override void ReturnBlob(IntPtr context, byte[] value)
-    {
-      UnsafeNativeMethods.sqlite3_result_blob(context, value, value.Length, (IntPtr)(-1));
-    }
-
-    internal override void ReturnDouble(IntPtr context, double value)
-    {
-#if !PLATFORM_COMPACTFRAMEWORK
-      UnsafeNativeMethods.sqlite3_result_double(context, value);
-#else
-      UnsafeNativeMethods.sqlite3_result_double_interop(context, ref value);
-#endif
-    }
-
-    internal override void ReturnError(IntPtr context, string value)
-    {
-      UnsafeNativeMethods.sqlite3_result_error(context, ToUTF8(value), value.Length);
-    }
-
-    internal override void ReturnInt32(IntPtr context, int value)
-    {
-      UnsafeNativeMethods.sqlite3_result_int(context, value);
-    }
-
-    internal override void ReturnInt64(IntPtr context, long value)
-    {
-#if !PLATFORM_COMPACTFRAMEWORK
-      UnsafeNativeMethods.sqlite3_result_int64(context, value);
-#else
-      UnsafeNativeMethods.sqlite3_result_int64_interop(context, ref value);
-#endif
-    }
-
-    internal override void ReturnNull(IntPtr context)
-    {
-      UnsafeNativeMethods.sqlite3_result_null(context);
-    }
-
-    internal override void ReturnText(IntPtr context, string value)
-    {
-      byte[] b = ToUTF8(value);
-      UnsafeNativeMethods.sqlite3_result_text(context, ToUTF8(value), b.Length - 1, (IntPtr)(-1));
-    }
-
-    internal override IntPtr AggregateContext(IntPtr context)
-    {
-      return UnsafeNativeMethods.sqlite3_aggregate_context(context, 1);
-    }
-
-    internal override void SetPassword(byte[] passwordBytes)
-    {
-      int n = UnsafeNativeMethods.sqlite3_key(_sql, passwordBytes, passwordBytes.Length);
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void ChangePassword(byte[] newPasswordBytes)
-    {
-      int n = UnsafeNativeMethods.sqlite3_rekey(_sql, newPasswordBytes, (newPasswordBytes == null) ? 0 : newPasswordBytes.Length);
-      if (n > 0) throw new SQLiteException(n, SQLiteLastError());
-    }
-
-    internal override void SetUpdateHook(SQLiteUpdateCallback func)
-    {
-      UnsafeNativeMethods.sqlite3_update_hook(_sql, func, IntPtr.Zero);
-    }
-
-    internal override void SetCommitHook(SQLiteCommitCallback func)
-    {
-      UnsafeNativeMethods.sqlite3_commit_hook(_sql, func, IntPtr.Zero);
-    }
-
-    internal override void SetRollbackHook(SQLiteRollbackCallback func)
-    {
-      UnsafeNativeMethods.sqlite3_rollback_hook(_sql, func, IntPtr.Zero);
-    }
-
-    /// <summary>
-    /// Helper function to retrieve a column of data from an active statement.
-    /// </summary>
-    /// <param name="stmt">The statement being step()'d through</param>
-    /// <param name="index">The column index to retrieve</param>
-    /// <param name="typ">The type of data contained in the column.  If Uninitialized, this function will retrieve the datatype information.</param>
-    /// <returns>Returns the data in the column</returns>
-    internal override object GetValue(SQLiteStatement stmt, int index, SQLiteType typ)
-    {
-      if (IsNull(stmt, index)) return DBNull.Value;
-      TypeAffinity aff = typ.Affinity;
-      Type t = null;
-
-      if (typ.Type != DbType.Object)
-      {
-        t = SQLiteConvert.SQLiteTypeToType(typ);
-        aff = TypeToAffinity(t);
-      }
-
-      switch (aff)
-      {
-        case TypeAffinity.Blob:
-          if (typ.Type == DbType.Guid && typ.Affinity == TypeAffinity.Text)
-            return new Guid(GetText(stmt, index));
-
-          int n = (int)GetBytes(stmt, index, 0, null, 0, 0);
-          byte[] b = new byte[n];
-          GetBytes(stmt, index, 0, b, 0, n);
-
-          if (typ.Type == DbType.Guid && n == 16)
-            return new Guid(b);
-
-          return b;
-        case TypeAffinity.DateTime:
-          return GetDateTime(stmt, index);
-        case TypeAffinity.Double:
-          if (t == null) return GetDouble(stmt, index);
-          else
-            return Convert.ChangeType(GetDouble(stmt, index), t, null);
-        case TypeAffinity.Int64:
-          if (t == null) return GetInt64(stmt, index);
-          else
-            return Convert.ChangeType(GetInt64(stmt, index), t, null);
-        default:
-          return GetText(stmt, index);
-      }
-    }
-
-    internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage)
-    {
-#if !SQLITE_STANDARD
-      return UnsafeNativeMethods.sqlite3_table_cursor(stmt._sqlite_stmt, db, rootPage);
-#else
-      return -1;
-#endif
-    }
-
-    internal override long GetRowIdForCursor(SQLiteStatement stmt, int cursor)
-    {
-#if !SQLITE_STANDARD
-      long rowid;
-      int rc = UnsafeNativeMethods.sqlite3_cursor_rowid(stmt._sqlite_stmt, cursor, out rowid);
-      if (rc == 0) return rowid;
-
-      return 0;
-#else
-      return 0;
-#endif
-    }
-
-    internal override void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence)
-    {
-#if !SQLITE_STANDARD
-      IntPtr coll;
-      int colllen;
-      int rc;
-
-      rc = UnsafeNativeMethods.sqlite3_index_column_info_interop(_sql, ToUTF8(database), ToUTF8(index), ToUTF8(column), out sortMode, out onError, out coll, out colllen);
-      if (rc != 0) throw new SQLiteException(rc, "");
-
-      collationSequence = UTF8ToString(coll, colllen);
+      if (n == 0) n = UnsafeNativeMethods.sqlite3_create_function(_sql, ToUTF8(strFunction), nArgs, 1, IntPtr.Zero, func, funcstep, funcfinal);
+#endif
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16)
+        {
+            int n = UnsafeNativeMethods.sqlite3_create_collation(_sql, ToUTF8(strCollation), 2, IntPtr.Zero, func16);
+            if (n == 0)
+                n = UnsafeNativeMethods.sqlite3_create_collation(_sql, ToUTF8(strCollation), 1, IntPtr.Zero, func);
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override int ContextCollateCompare(CollationEncodingEnum enc, IntPtr context, string s1, string s2)
+        {
+#if !SQLITE_STANDARD
+            byte[] b1;
+            byte[] b2;
+            Encoding converter = null;
+
+            switch (enc)
+            {
+                case CollationEncodingEnum.UTF8:
+                    converter = Encoding.UTF8;
+                    break;
+                case CollationEncodingEnum.UTF16LE:
+                    converter = Encoding.Unicode;
+                    break;
+                case CollationEncodingEnum.UTF16BE:
+                    converter = Encoding.BigEndianUnicode;
+                    break;
+            }
+
+            b1 = converter.GetBytes(s1);
+            b2 = converter.GetBytes(s2);
+
+            return UnsafeNativeMethods.sqlite3_context_collcompare(context, b1, b1.Length, b2, b2.Length);
+#else
+      throw new NotImplementedException();
+#endif
+        }
+
+        internal override int ContextCollateCompare(CollationEncodingEnum enc, IntPtr context, char[] c1, char[] c2)
+        {
+#if !SQLITE_STANDARD
+            byte[] b1;
+            byte[] b2;
+            Encoding converter = null;
+
+            switch (enc)
+            {
+                case CollationEncodingEnum.UTF8:
+                    converter = Encoding.UTF8;
+                    break;
+                case CollationEncodingEnum.UTF16LE:
+                    converter = Encoding.Unicode;
+                    break;
+                case CollationEncodingEnum.UTF16BE:
+                    converter = Encoding.BigEndianUnicode;
+                    break;
+            }
+
+            b1 = converter.GetBytes(c1);
+            b2 = converter.GetBytes(c2);
+
+            return UnsafeNativeMethods.sqlite3_context_collcompare(context, b1, b1.Length, b2, b2.Length);
+#else
+      throw new NotImplementedException();
+#endif
+        }
+
+        internal override CollationSequence GetCollationSequence(SQLiteFunction func, IntPtr context)
+        {
+#if !SQLITE_STANDARD
+            var seq = new CollationSequence();
+            int len;
+            int type;
+            int enc;
+            IntPtr p = UnsafeNativeMethods.sqlite3_context_collseq(context, out type, out enc, out len);
+
+            if (p != null) seq.Name = UTF8ToString(p, len);
+            seq.Type = (CollationTypeEnum) type;
+            seq._func = func;
+            seq.Encoding = (CollationEncodingEnum) enc;
+
+            return seq;
+#else
+      throw new NotImplementedException();
+#endif
+        }
+
+        internal override long GetParamValueBytes(IntPtr p, int nDataOffset, byte[] bDest, int nStart, int nLength)
+        {
+            IntPtr ptr;
+            int nlen;
+            int nCopied = nLength;
+
+            nlen = UnsafeNativeMethods.sqlite3_value_bytes(p);
+            ptr = UnsafeNativeMethods.sqlite3_value_blob(p);
+
+            if (bDest == null) return nlen;
+
+            if (nCopied + nStart > bDest.Length) nCopied = bDest.Length - nStart;
+            if (nCopied + nDataOffset > nlen) nCopied = nlen - nDataOffset;
+
+            if (nCopied > 0)
+                Marshal.Copy((IntPtr) (ptr.ToInt32() + nDataOffset), bDest, nStart, nCopied);
+            else nCopied = 0;
+
+            return nCopied;
+        }
+
+        internal override double GetParamValueDouble(IntPtr ptr)
+        {
+            double value;
+#if !PLATFORM_COMPACTFRAMEWORK
+            value = UnsafeNativeMethods.sqlite3_value_double(ptr);
+#else
+      UnsafeNativeMethods.sqlite3_value_double_interop(ptr, out value);
+#endif
+            return value;
+        }
+
+        internal override int GetParamValueInt32(IntPtr ptr)
+        {
+            return UnsafeNativeMethods.sqlite3_value_int(ptr);
+        }
+
+        internal override long GetParamValueInt64(IntPtr ptr)
+        {
+            Int64 value;
+#if !PLATFORM_COMPACTFRAMEWORK
+            value = UnsafeNativeMethods.sqlite3_value_int64(ptr);
+#else
+      UnsafeNativeMethods.sqlite3_value_int64_interop(ptr, out value);
+#endif
+            return value;
+        }
+
+        internal override string GetParamValueText(IntPtr ptr)
+        {
+#if !SQLITE_STANDARD
+            int len;
+            return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text_interop(ptr, out len), len);
+#else
+      return UTF8ToString(UnsafeNativeMethods.sqlite3_value_text(ptr), -1);
+#endif
+        }
+
+        internal override TypeAffinity GetParamValueType(IntPtr ptr)
+        {
+            return UnsafeNativeMethods.sqlite3_value_type(ptr);
+        }
+
+        internal override void ReturnBlob(IntPtr context, byte[] value)
+        {
+            UnsafeNativeMethods.sqlite3_result_blob(context, value, value.Length, (IntPtr) (-1));
+        }
+
+        internal override void ReturnDouble(IntPtr context, double value)
+        {
+#if !PLATFORM_COMPACTFRAMEWORK
+            UnsafeNativeMethods.sqlite3_result_double(context, value);
+#else
+      UnsafeNativeMethods.sqlite3_result_double_interop(context, ref value);
+#endif
+        }
+
+        internal override void ReturnError(IntPtr context, string value)
+        {
+            UnsafeNativeMethods.sqlite3_result_error(context, ToUTF8(value), value.Length);
+        }
+
+        internal override void ReturnInt32(IntPtr context, int value)
+        {
+            UnsafeNativeMethods.sqlite3_result_int(context, value);
+        }
+
+        internal override void ReturnInt64(IntPtr context, long value)
+        {
+#if !PLATFORM_COMPACTFRAMEWORK
+            UnsafeNativeMethods.sqlite3_result_int64(context, value);
+#else
+      UnsafeNativeMethods.sqlite3_result_int64_interop(context, ref value);
+#endif
+        }
+
+        internal override void ReturnNull(IntPtr context)
+        {
+            UnsafeNativeMethods.sqlite3_result_null(context);
+        }
+
+        internal override void ReturnText(IntPtr context, string value)
+        {
+            byte[] b = ToUTF8(value);
+            UnsafeNativeMethods.sqlite3_result_text(context, ToUTF8(value), b.Length - 1, (IntPtr) (-1));
+        }
+
+        internal override IntPtr AggregateContext(IntPtr context)
+        {
+            return UnsafeNativeMethods.sqlite3_aggregate_context(context, 1);
+        }
+
+        internal override void SetPassword(byte[] passwordBytes)
+        {
+            int n = UnsafeNativeMethods.sqlite3_key(_sql, passwordBytes, passwordBytes.Length);
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void ChangePassword(byte[] newPasswordBytes)
+        {
+            int n = UnsafeNativeMethods.sqlite3_rekey(_sql, newPasswordBytes,
+                                                      (newPasswordBytes == null) ? 0 : newPasswordBytes.Length);
+            if (n > 0) throw new SQLiteException(n, SQLiteLastError());
+        }
+
+        internal override void SetUpdateHook(SQLiteUpdateCallback func)
+        {
+            UnsafeNativeMethods.sqlite3_update_hook(_sql, func, IntPtr.Zero);
+        }
+
+        internal override void SetCommitHook(SQLiteCommitCallback func)
+        {
+            UnsafeNativeMethods.sqlite3_commit_hook(_sql, func, IntPtr.Zero);
+        }
+
+        internal override void SetRollbackHook(SQLiteRollbackCallback func)
+        {
+            UnsafeNativeMethods.sqlite3_rollback_hook(_sql, func, IntPtr.Zero);
+        }
+
+        /// <summary>
+        /// Helper function to retrieve a column of data from an active statement.
+        /// </summary>
+        /// <param name="stmt">The statement being step()'d through</param>
+        /// <param name="index">The column index to retrieve</param>
+        /// <param name="typ">The type of data contained in the column.  If Uninitialized, this function will retrieve the datatype information.</param>
+        /// <returns>Returns the data in the column</returns>
+        internal override object GetValue(SQLiteStatement stmt, int index, SQLiteType typ)
+        {
+            if (IsNull(stmt, index)) return DBNull.Value;
+            TypeAffinity aff = typ.Affinity;
+            Type t = null;
+
+            if (typ.Type != DbType.Object)
+            {
+                t = SQLiteTypeToType(typ);
+                aff = TypeToAffinity(t);
+            }
+
+            switch (aff)
+            {
+                case TypeAffinity.Blob:
+                    if (typ.Type == DbType.Guid && typ.Affinity == TypeAffinity.Text)
+                        return new Guid(GetText(stmt, index));
+
+                    var n = (int) GetBytes(stmt, index, 0, null, 0, 0);
+                    var b = new byte[n];
+                    GetBytes(stmt, index, 0, b, 0, n);
+
+                    if (typ.Type == DbType.Guid && n == 16)
+                        return new Guid(b);
+
+                    return b;
+                case TypeAffinity.DateTime:
+                    return GetDateTime(stmt, index);
+                case TypeAffinity.Double:
+                    if (t == null) return GetDouble(stmt, index);
+                    else
+                        return Convert.ChangeType(GetDouble(stmt, index), t, null);
+                case TypeAffinity.Int64:
+                    if (t == null) return GetInt64(stmt, index);
+                    else
+                        return Convert.ChangeType(GetInt64(stmt, index), t, null);
+                default:
+                    return GetText(stmt, index);
+            }
+        }
+
+        internal override int GetCursorForTable(SQLiteStatement stmt, int db, int rootPage)
+        {
+#if !SQLITE_STANDARD
+            return UnsafeNativeMethods.sqlite3_table_cursor(stmt._sqlite_stmt, db, rootPage);
+#else
+      return -1;
+#endif
+        }
+
+        internal override long GetRowIdForCursor(SQLiteStatement stmt, int cursor)
+        {
+#if !SQLITE_STANDARD
+            long rowid;
+            int rc = UnsafeNativeMethods.sqlite3_cursor_rowid(stmt._sqlite_stmt, cursor, out rowid);
+            if (rc == 0) return rowid;
+
+            return 0;
+#else
+      return 0;
+#endif
+        }
+
+        internal override void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode,
+                                                          out int onError, out string collationSequence)
+        {
+#if !SQLITE_STANDARD
+            IntPtr coll;
+            int colllen;
+            int rc;
+
+            rc = UnsafeNativeMethods.sqlite3_index_column_info_interop(_sql, ToUTF8(database), ToUTF8(index),
+                                                                       ToUTF8(column), out sortMode, out onError,
+                                                                       out coll, out colllen);
+            if (rc != 0) throw new SQLiteException(rc, "");
+
+            collationSequence = UTF8ToString(coll, colllen);
 #else
       sortMode = 0;
       onError = 2;
-      collationSequence = "BINARY";
-#endif
-    }
-  }
-}
+      collationSequence = "BINARY";
+#endif
+        }
+    }
+}