/// <summary>
    /// Creates a disposable module containing the implementation of a virtual
    /// table.
    /// </summary>
    /// <param name="module">
    /// The module object to be used when creating the disposable module.
    /// </param>
    public void CreateModule(
        SQLiteModule module
        )
    {
        CheckDisposed();

        if (_sql == null)
            throw new InvalidOperationException(
                "Database connection not valid for creating modules.");

        if ((_flags & SQLiteConnectionFlags.NoCreateModule) == SQLiteConnectionFlags.NoCreateModule)
            throw new SQLiteException("Creating modules is disabled for this database connection.");

        _sql.CreateModule(module, _flags);
    }
 /// <summary>
 /// Calls the native SQLite core library in order to declare a virtual table
 /// in response to a call into the <see cref="ISQLiteNativeModule.xCreate" />
 /// or <see cref="ISQLiteNativeModule.xConnect" /> virtual table methods.
 /// </summary>
 /// <param name="module">
 /// The virtual table module that is to be responsible for the virtual table
 /// being declared.
 /// </param>
 /// <param name="strSql">
 /// The string containing the SQL statement describing the virtual table to
 /// be declared.
 /// </param>
 /// <param name="error">
 /// Upon success, the contents of this parameter are undefined.  Upon failure,
 /// it should contain an appropriate error message.
 /// </param>
 /// <returns>
 /// A standard SQLite return code.
 /// </returns>
 internal abstract SQLiteErrorCode DeclareVirtualTable(SQLiteModule module, string strSql, ref string error);
 /// <summary>
 /// Calls the native SQLite core library in order to declare a virtual table
 /// function in response to a call into the <see cref="ISQLiteNativeModule.xCreate" />
 /// or <see cref="ISQLiteNativeModule.xConnect" /> virtual table methods.
 /// </summary>
 /// <param name="module">
 /// The virtual table module that is to be responsible for the virtual table
 /// function being declared.
 /// </param>
 /// <param name="argumentCount">
 /// The number of arguments to the function being declared.
 /// </param>
 /// <param name="name">
 /// The name of the function being declared.
 /// </param>
 /// <param name="error">
 /// Upon success, the contents of this parameter are undefined.  Upon failure,
 /// it should contain an appropriate error message.
 /// </param>
 /// <returns>
 /// A standard SQLite return code.
 /// </returns>
 internal abstract SQLiteErrorCode DeclareVirtualFunction(SQLiteModule module, int argumentCount, string name, ref string error);
        ///////////////////////////////////////////////////////////////////////

        #region Static Table Lookup Methods
        /// <summary>
        /// Reads and returns the native pointer to the sqlite3_vtab derived
        /// structure based on the native pointer to the sqlite3_vtab_cursor
        /// derived structure.
        /// </summary>
        /// <param name="module">
        /// The <see cref="SQLiteModule" /> object instance to be used.
        /// </param>
        /// <param name="pCursor">
        /// The native pointer to the sqlite3_vtab_cursor derived structure
        /// from which to read the native pointer to the sqlite3_vtab derived
        /// structure.
        /// </param>
        /// <returns>
        /// The native pointer to the sqlite3_vtab derived structure -OR-
        /// <see cref="IntPtr.Zero" /> if it cannot be determined.
        /// </returns>
        private static IntPtr TableFromCursor(
            SQLiteModule module,
            IntPtr pCursor
            )
        {
            if (pCursor == IntPtr.Zero)
                return IntPtr.Zero;

            return Marshal.ReadIntPtr(pCursor);
        }
 /// <summary>
 /// Calls the native SQLite core library in order to cleanup the resources
 /// associated with a module containing the implementation of a virtual table.
 /// </summary>
 /// <param name="module">
 /// The module object previously passed to the <see cref="CreateModule" />
 /// method.
 /// </param>
 /// <param name="flags">
 /// The flags for the associated <see cref="SQLiteConnection" /> object instance.
 /// </param>
 internal abstract void DisposeModule(SQLiteModule module, SQLiteConnectionFlags flags);
        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Arranges for the specified error message to be placed into the
        /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
        /// existing error message, if any.
        /// </summary>
        /// <param name="module">
        /// The <see cref="SQLiteModule" /> object instance to be used.
        /// </param>
        /// <param name="pCursor">
        /// The native pointer to the sqlite3_vtab_cursor derived structure
        /// used to get the native pointer to the sqlite3_vtab derived
        /// structure.
        /// </param>
        /// <param name="logErrors">
        /// Non-zero if this error message should also be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="logExceptions">
        /// Non-zero if caught exceptions should be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="error">
        /// The error message.
        /// </param>
        /// <returns>
        /// Non-zero upon success.
        /// </returns>
        private static bool SetCursorError(
            SQLiteModule module,
            IntPtr pCursor,
            bool logErrors,
            bool logExceptions,
            string error
            )
        {
            if (pCursor == IntPtr.Zero)
                return false;

            IntPtr pVtab = TableFromCursor(module, pCursor);

            if (pVtab == IntPtr.Zero)
                return false;

            return SetTableError(
                module, pVtab, logErrors, logExceptions, error);
        }
        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Arranges for the specified error message to be placed into the
        /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
        /// existing error message, if any.
        /// </summary>
        /// <param name="module">
        /// The <see cref="SQLiteModule" /> object instance to be used.
        /// </param>
        /// <param name="cursor">
        /// The <see cref="SQLiteVirtualTableCursor" /> object instance used to
        /// lookup the native pointer to the sqlite3_vtab derived structure.
        /// </param>
        /// <param name="logErrors">
        /// Non-zero if this error message should also be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="logExceptions">
        /// Non-zero if caught exceptions should be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="error">
        /// The error message.
        /// </param>
        /// <returns>
        /// Non-zero upon success.
        /// </returns>
        private static bool SetCursorError(
            SQLiteModule module,
            SQLiteVirtualTableCursor cursor,
            bool logErrors,
            bool logExceptions,
            string error
            )
        {
            if (cursor == null)
                return false;

            IntPtr pCursor = cursor.NativeHandle;

            if (pCursor == IntPtr.Zero)
                return false;

            return SetCursorError(
                module, pCursor, logErrors, logExceptions, error);
        }
        ///////////////////////////////////////////////////////////////////////

        #region Static Error Handling Helper Methods
        /// <summary>
        /// Arranges for the specified error message to be placed into the
        /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
        /// existing error message, if any.
        /// </summary>
        /// <param name="module">
        /// The <see cref="SQLiteModule" /> object instance to be used.
        /// </param>
        /// <param name="pVtab">
        /// The native pointer to the sqlite3_vtab derived structure.
        /// </param>
        /// <param name="logErrors">
        /// Non-zero if this error message should also be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="logExceptions">
        /// Non-zero if caught exceptions should be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="error">
        /// The error message.
        /// </param>
        /// <returns>
        /// Non-zero upon success.
        /// </returns>
        private static bool SetTableError(
            SQLiteModule module,
            IntPtr pVtab,
            bool logErrors,
            bool logExceptions,
            string error
            )
        {
            try
            {
                if (logErrors)
                {
                    SQLiteLog.LogMessage(SQLiteErrorCode.Error,
                        String.Format(CultureInfo.CurrentCulture,
                        "Virtual table error: {0}", error)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }

            bool success = false;
            IntPtr pNewError = IntPtr.Zero;

            try
            {
                if (pVtab == IntPtr.Zero)
                    return false;

                int offset = 0;

                offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
                    sizeof(int));

                offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
                    IntPtr.Size);

                IntPtr pOldError = SQLiteMarshal.ReadIntPtr(pVtab, offset);

                if (pOldError != IntPtr.Zero)
                {
                    SQLiteMemory.Free(pOldError); pOldError = IntPtr.Zero;
                    SQLiteMarshal.WriteIntPtr(pVtab, offset, pOldError);
                }

                if (error == null)
                    return true;

                pNewError = SQLiteString.Utf8IntPtrFromString(error);
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pNewError);
                success = true;
            }
            catch (Exception e) /* NOTE: Must catch ALL. */
            {
                try
                {
                    if (logExceptions)
                    {
                        SQLiteLog.LogMessage(SQLiteBase.COR_E_EXCEPTION,
                            String.Format(CultureInfo.CurrentCulture,
                            "Caught exception in \"SetTableError\" method: {0}",
                            e)); /* throw */
                    }
                }
                catch
                {
                    // do nothing.
                }
            }
            finally
            {
                if (!success && (pNewError != IntPtr.Zero))
                {
                    SQLiteMemory.Free(pNewError);
                    pNewError = IntPtr.Zero;
                }
            }

            return success;
        }
        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Arranges for the specified error message to be placed into the
        /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
        /// existing error message, if any.
        /// </summary>
        /// <param name="module">
        /// The <see cref="SQLiteModule" /> object instance to be used.
        /// </param>
        /// <param name="table">
        /// The <see cref="SQLiteVirtualTable" /> object instance used to
        /// lookup the native pointer to the sqlite3_vtab derived structure.
        /// </param>
        /// <param name="logErrors">
        /// Non-zero if this error message should also be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="logExceptions">
        /// Non-zero if caught exceptions should be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="error">
        /// The error message.
        /// </param>
        /// <returns>
        /// Non-zero upon success.
        /// </returns>
        private static bool SetTableError(
            SQLiteModule module,
            SQLiteVirtualTable table,
            bool logErrors,
            bool logExceptions,
            string error
            )
        {
            if (table == null)
                return false;

            IntPtr pVtab = table.NativeHandle;

            if (pVtab == IntPtr.Zero)
                return false;

            return SetTableError(
                module, pVtab, logErrors, logExceptions, error);
        }
            ///////////////////////////////////////////////////////////////////

            #region Public Constructors
            /// <summary>
            /// Constructs an instance of this class.
            /// </summary>
            /// <param name="module">
            /// The <see cref="SQLiteModule" /> object instance used to provide
            /// an implementation of the <see cref="ISQLiteNativeModule" />
            /// interface.
            /// </param>
            public SQLiteNativeModule(
                SQLiteModule module
                )
            {
                this.module = module;
            }
            ///////////////////////////////////////////////////////////////////

            /// <summary>
            /// Disposes of this object instance.
            /// </summary>
            /// <param name="disposing">
            /// Non-zero if this method is being called from the
            /// <see cref="Dispose()" /> method.  Zero if this method is being
            /// called from the finalizer.
            /// </param>
            private /* protected virtual */ void Dispose(bool disposing)
            {
                if (!disposed)
                {
                    //if (disposing)
                    //{
                    //    ////////////////////////////////////
                    //    // dispose managed resources here...
                    //    ////////////////////////////////////
                    //}

                    //////////////////////////////////////
                    // release unmanaged resources here...
                    //////////////////////////////////////

                    //
                    // NOTE: The module is not owned by us; therefore, do not
                    //       dispose it.
                    //
                    if (module != null)
                        module = null;

                    disposed = true;
                }
            }
        ///////////////////////////////////////////////////////////////////////

        #region Static Error Handling Helper Methods
        /// <summary>
        /// Arranges for the specified error message to be placed into the
        /// zErrMsg field of a sqlite3_vtab derived structure, freeing the
        /// existing error message, if any.
        /// </summary>
        /// <param name="module">
        /// The <see cref="SQLiteModule" /> object instance to be used.
        /// </param>
        /// <param name="pVtab">
        /// The native pointer to the sqlite3_vtab derived structure.
        /// </param>
        /// <param name="logErrors">
        /// Non-zero if this error message should also be logged using the
        /// <see cref="SQLiteLog" /> class.
        /// </param>
        /// <param name="error">
        /// The error message.
        /// </param>
        /// <returns>
        /// Non-zero upon success.
        /// </returns>
        private static bool SetTableError(
            SQLiteModule module,
            IntPtr pVtab,
            bool logErrors,
            string error
            )
        {
            try
            {
                if (logErrors)
                {
                    SQLiteLog.LogMessage(SQLiteErrorCode.Error,
                        String.Format(CultureInfo.CurrentCulture,
                        "Virtual table error: {0}", error)); /* throw */
                }
            }
            catch
            {
                // do nothing.
            }

            if (pVtab == IntPtr.Zero)
                return false;

            int offset = 0;

            offset = SQLiteMarshal.NextOffsetOf(offset, IntPtr.Size,
                sizeof(int));

            offset = SQLiteMarshal.NextOffsetOf(offset, sizeof(int),
                IntPtr.Size);

            IntPtr pError = SQLiteMarshal.ReadIntPtr(pVtab, offset);

            if (pError != IntPtr.Zero)
            {
                SQLiteMemory.Free(pError); pError = IntPtr.Zero;
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
            }

            if (error == null)
                return true;

            bool success = false;

            try
            {
                pError = SQLiteString.Utf8IntPtrFromString(error);
                SQLiteMarshal.WriteIntPtr(pVtab, offset, pError);
                success = true;
            }
            finally
            {
                if (!success && (pError != IntPtr.Zero))
                {
                    SQLiteMemory.Free(pError);
                    pError = IntPtr.Zero;
                }
            }

            return success;
        }
    /// <summary>
    /// Calls the native SQLite core library in order to declare a virtual table
    /// function in response to a call into the <see cref="ISQLiteNativeModule.xCreate" />
    /// or <see cref="ISQLiteNativeModule.xConnect" /> virtual table methods.
    /// </summary>
    /// <param name="module">
    /// The virtual table module that is to be responsible for the virtual table
    /// function being declared.
    /// </param>
    /// <param name="argumentCount">
    /// The number of arguments to the function being declared.
    /// </param>
    /// <param name="name">
    /// The name of the function being declared.
    /// </param>
    /// <param name="error">
    /// Upon success, the contents of this parameter are undefined.  Upon failure,
    /// it should contain an appropriate error message.
    /// </param>
    /// <returns>
    /// A standard SQLite return code.
    /// </returns>
    internal override SQLiteErrorCode DeclareVirtualFunction(
        SQLiteModule module,
        int argumentCount,
        string name,
        ref string error
        )
    {
        if (_sql == null)
        {
            error = "connection has an invalid handle";
            return SQLiteErrorCode.Error;
        }

        IntPtr pName = IntPtr.Zero;

        try
        {
            pName = SQLiteString.Utf8IntPtrFromString(name);

            SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_overload_function(
                _sql, pName, argumentCount);

            if (n != SQLiteErrorCode.Ok) error = GetLastError();

            return n;
        }
        finally
        {
            if (pName != IntPtr.Zero)
            {
                SQLiteMemory.Free(pName);
                pName = IntPtr.Zero;
            }
        }
    }
    /// <summary>
    /// Calls the native SQLite core library in order to declare a virtual table
    /// in response to a call into the <see cref="ISQLiteNativeModule.xCreate" />
    /// or <see cref="ISQLiteNativeModule.xConnect" /> virtual table methods.
    /// </summary>
    /// <param name="module">
    /// The virtual table module that is to be responsible for the virtual table
    /// being declared.
    /// </param>
    /// <param name="strSql">
    /// The string containing the SQL statement describing the virtual table to
    /// be declared.
    /// </param>
    /// <param name="error">
    /// Upon success, the contents of this parameter are undefined.  Upon failure,
    /// it should contain an appropriate error message.
    /// </param>
    /// <returns>
    /// A standard SQLite return code.
    /// </returns>
    internal override SQLiteErrorCode DeclareVirtualTable(
        SQLiteModule module,
        string strSql,
        ref string error
        )
    {
        if (_sql == null)
        {
            error = "connection has an invalid handle";
            return SQLiteErrorCode.Error;
        }

        IntPtr pSql = IntPtr.Zero;

        try
        {
            pSql = SQLiteString.Utf8IntPtrFromString(strSql);

            SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_declare_vtab(
                _sql, pSql);

            if ((n == SQLiteErrorCode.Ok) && (module != null))
                module.Declared = true;

            if (n != SQLiteErrorCode.Ok) error = GetLastError();

            return n;
        }
        finally
        {
            if (pSql != IntPtr.Zero)
            {
                SQLiteMemory.Free(pSql);
                pSql = IntPtr.Zero;
            }
        }
    }
    /// <summary>
    /// Calls the native SQLite core library in order to cleanup the resources
    /// associated with a module containing the implementation of a virtual table.
    /// </summary>
    /// <param name="module">
    /// The module object previously passed to the <see cref="CreateModule" />
    /// method.
    /// </param>
    /// <param name="flags">
    /// The flags for the associated <see cref="SQLiteConnection" /> object instance.
    /// </param>
    internal override void DisposeModule(SQLiteModule module, SQLiteConnectionFlags flags)
    {
        if (module == null)
            throw new ArgumentNullException("module");

        module.Dispose();
    }
    /// <summary>
    /// Calls the native SQLite core library in order to create a disposable
    /// module containing the implementation of a virtual table.
    /// </summary>
    /// <param name="module">
    /// The module object to be used when creating the native disposable module.
    /// </param>
    /// <param name="flags">
    /// The flags for the associated <see cref="SQLiteConnection" /> object instance.
    /// </param>
    internal override void CreateModule(SQLiteModule module, SQLiteConnectionFlags flags)
    {
        if (module == null)
            throw new ArgumentNullException("module");

        if ((flags & SQLiteConnectionFlags.NoLogModule) != SQLiteConnectionFlags.NoLogModule)
        {
            module.LogErrors = ((flags & SQLiteConnectionFlags.LogModuleError) == SQLiteConnectionFlags.LogModuleError);
            module.LogExceptions = ((flags & SQLiteConnectionFlags.LogModuleException) == SQLiteConnectionFlags.LogModuleException);
        }

        if (_sql == null)
            throw new SQLiteException("connection has an invalid handle");

        SetLoadExtension(true);
        LoadExtension(UnsafeNativeMethods.SQLITE_DLL, "sqlite3_vtshim_init");

        if (module.CreateDisposableModule(_sql))
        {
            if (_modules == null)
                _modules = new Dictionary<string, SQLiteModule>();

            _modules.Add(module.Name, module);

            if (_usePool)
            {
                _usePool = false;

#if !NET_COMPACT_20 && TRACE_CONNECTION
                Trace.WriteLine(String.Format("CreateModule (Pool) Disabled: {0}", _sql));
#endif
            }
        }
        else
        {
            throw new SQLiteException(GetLastError());
        }
    }