/******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; #if !PLATFORM_COMPACTFRAMEWORK using System.Runtime.InteropServices; #endif /// /// This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement /// a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. /// internal abstract class SQLiteBase : SQLiteConvert, IDisposable { #region Private Constants /// /// The error code used for logging exceptions caught in user-provided /// code. /// internal const int COR_E_EXCEPTION = unchecked((int)0x80131500); #endregion ///////////////////////////////////////////////////////////////////////// internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind, string fmtString) : base(fmt, kind, fmtString) { } /// /// Returns a string representing the active version of SQLite /// internal abstract string Version { get; } /// /// Returns an integer representing the active version of SQLite /// internal abstract int VersionNumber { get; } /// /// Returns the rowid of the most recent successful INSERT into the database from this connection. /// internal abstract long LastInsertRowId { get; } /// /// Returns the number of changes the last executing insert/update caused. /// internal abstract int Changes { get; } /// /// Returns the amount of memory (in bytes) currently in use by the SQLite core library. This is not really a per-connection /// value, it is global to the process. /// internal abstract long MemoryUsed { get; } /// /// Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset. /// This is not really a per-connection value, it is global to the process. /// internal abstract long MemoryHighwater { get; } /// /// Returns non-zero if the underlying native connection handle is owned by this instance. /// internal abstract bool OwnHandle { get; } /// /// Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled. /// If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is /// global to the process. /// /// Non-zero to enable memory usage tracking, zero otherwise. /// A standard SQLite return code (i.e. zero for success and non-zero for failure). internal abstract SQLiteErrorCode SetMemoryStatus(bool value); /// /// Shutdown the SQLite engine so that it can be restarted with different config options. /// We depend on auto initialization to recover. /// internal abstract SQLiteErrorCode Shutdown(); /// /// Determines if the associated native connection handle is open. /// /// /// Non-zero if a database connection is open. /// internal abstract bool IsOpen(); /// /// Opens a database. /// /// /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection /// to bind all attributed user-defined functions and collating sequences to the new connection. /// /// The filename of the database to open. SQLite automatically creates it if it doesn't exist. /// The flags associated with the parent connection object /// The open flags to use when creating the connection /// The maximum size of the pool for the given filename /// If true, the connection can be pulled from the connection pool internal abstract void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool); /// /// Closes the currently-open database. /// /// /// After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated /// memory associated with the user-defined functions and collating sequences tied to the closed connection. /// /// Non-zero if the operation is allowed to throw exceptions, zero otherwise. internal abstract void Close(bool canThrow); /// /// Sets the busy timeout on the connection. SQLiteCommand will call this before executing any command. /// /// The number of milliseconds to wait before returning SQLITE_BUSY internal abstract void SetTimeout(int nTimeoutMS); /// /// Returns the text of the last error issued by SQLite /// /// internal abstract string GetLastError(); /// /// When pooling is enabled, force this connection to be disposed rather than returned to the pool /// internal abstract void ClearPool(); /// /// When pooling is enabled, returns the number of pool entries matching the current file name. /// /// The number of pool entries matching the current file name. internal abstract int CountPool(); /// /// Prepares a SQL statement for execution. /// /// The source connection preparing the command. Can be null for any caller except LINQ /// The SQL command text to prepare /// The previous statement in a multi-statement command, or null if no previous statement exists /// The timeout to wait before aborting the prepare /// The remainder of the statement that was not processed. Each call to prepare parses the /// SQL up to to either the end of the text or to the first semi-colon delimiter. The remaining text is returned /// here for a subsequent call to Prepare() until all the text has been processed. /// Returns an initialized SQLiteStatement. internal abstract SQLiteStatement Prepare(SQLiteConnection cnn, string strSql, SQLiteStatement previous, uint timeoutMS, out string strRemain); /// /// Steps through a prepared statement. /// /// The SQLiteStatement to step through /// True if a row was returned, False if not. internal abstract bool Step(SQLiteStatement stmt); /// /// Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, /// transparently attempt to rebuild the SQL statement and throw an error if that was not possible. /// /// The statement to reset /// Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock internal abstract SQLiteErrorCode Reset(SQLiteStatement stmt); /// /// Attempts to interrupt the query currently executing on the associated /// native database connection. /// internal abstract void Cancel(); /// /// This function binds a user-defined functions to the connection. /// /// /// The object instance containing /// the metadata for the function to be bound. /// /// /// The object instance that implements the /// function to be bound. /// /// /// The flags associated with the parent connection object. /// internal abstract void BindFunction(SQLiteFunctionAttribute functionAttribute, SQLiteFunction function, SQLiteConnectionFlags flags); internal abstract void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value); internal abstract void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, Int32 value); internal abstract void Bind_UInt32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, UInt32 value); internal abstract void Bind_Int64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, Int64 value); internal abstract void Bind_UInt64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, UInt64 value); internal abstract void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value); internal abstract void Bind_Blob(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, byte[] blobData); internal abstract void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt); internal abstract void Bind_Null(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index); internal abstract int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags); internal abstract string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index); internal abstract int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName); internal abstract int ColumnCount(SQLiteStatement stmt); internal abstract string ColumnName(SQLiteStatement stmt, int index); internal abstract TypeAffinity ColumnAffinity(SQLiteStatement stmt, int index); internal abstract string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity); internal abstract int ColumnIndex(SQLiteStatement stmt, string columnName); internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index); internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index); internal abstract string ColumnTableName(SQLiteStatement stmt, int index); internal abstract void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement); internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence); internal abstract double GetDouble(SQLiteStatement stmt, int index); internal abstract SByte GetSByte(SQLiteStatement stmt, int index); internal abstract Byte GetByte(SQLiteStatement stmt, int index); internal abstract Int16 GetInt16(SQLiteStatement stmt, int index); internal abstract UInt16 GetUInt16(SQLiteStatement stmt, int index); internal abstract Int32 GetInt32(SQLiteStatement stmt, int index); internal abstract UInt32 GetUInt32(SQLiteStatement stmt, int index); internal abstract Int64 GetInt64(SQLiteStatement stmt, int index); internal abstract UInt64 GetUInt64(SQLiteStatement stmt, int index); internal abstract string GetText(SQLiteStatement stmt, int index); internal abstract long GetBytes(SQLiteStatement stmt, int index, int nDataoffset, byte[] bDest, int nStart, int nLength); internal abstract long GetChars(SQLiteStatement stmt, int index, int nDataoffset, char[] bDest, int nStart, int nLength); internal abstract DateTime GetDateTime(SQLiteStatement stmt, int index); internal abstract bool IsNull(SQLiteStatement stmt, int index); internal abstract void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16); internal abstract void CreateFunction(string strFunction, int nArgs, bool needCollSeq, SQLiteCallback func, SQLiteCallback funcstep, SQLiteFinalCallback funcfinal); internal abstract CollationSequence GetCollationSequence(SQLiteFunction func, IntPtr context); internal abstract int ContextCollateCompare(CollationEncodingEnum enc, IntPtr context, string s1, string s2); internal abstract int ContextCollateCompare(CollationEncodingEnum enc, IntPtr context, char[] c1, char[] c2); internal abstract int AggregateCount(IntPtr context); internal abstract IntPtr AggregateContext(IntPtr context); internal abstract long GetParamValueBytes(IntPtr ptr, int nDataOffset, byte[] bDest, int nStart, int nLength); internal abstract double GetParamValueDouble(IntPtr ptr); internal abstract int GetParamValueInt32(IntPtr ptr); internal abstract Int64 GetParamValueInt64(IntPtr ptr); internal abstract string GetParamValueText(IntPtr ptr); internal abstract TypeAffinity GetParamValueType(IntPtr ptr); internal abstract void ReturnBlob(IntPtr context, byte[] value); internal abstract void ReturnDouble(IntPtr context, double value); internal abstract void ReturnError(IntPtr context, string value); internal abstract void ReturnInt32(IntPtr context, Int32 value); internal abstract void ReturnInt64(IntPtr context, Int64 value); internal abstract void ReturnNull(IntPtr context); internal abstract void ReturnText(IntPtr context, string value); #if INTEROP_VIRTUAL_TABLE /// /// Calls the native SQLite core library in order to create a disposable /// module containing the implementation of a virtual table. /// /// /// The module object to be used when creating the native disposable module. /// /// /// The flags for the associated object instance. /// internal abstract void CreateModule(SQLiteModule module, SQLiteConnectionFlags flags); /// /// Calls the native SQLite core library in order to cleanup the resources /// associated with a module containing the implementation of a virtual table. /// /// /// The module object previously passed to the /// method. /// /// /// The flags for the associated object instance. /// internal abstract void DisposeModule(SQLiteModule module, SQLiteConnectionFlags flags); /// /// Calls the native SQLite core library in order to declare a virtual table /// in response to a call into the /// or virtual table methods. /// /// /// The virtual table module that is to be responsible for the virtual table /// being declared. /// /// /// The string containing the SQL statement describing the virtual table to /// be declared. /// /// /// Upon success, the contents of this parameter are undefined. Upon failure, /// it should contain an appropriate error message. /// /// /// A standard SQLite return code. /// internal abstract SQLiteErrorCode DeclareVirtualTable(SQLiteModule module, string strSql, ref string error); /// /// Calls the native SQLite core library in order to declare a virtual table /// function in response to a call into the /// or virtual table methods. /// /// /// The virtual table module that is to be responsible for the virtual table /// function being declared. /// /// /// The number of arguments to the function being declared. /// /// /// The name of the function being declared. /// /// /// Upon success, the contents of this parameter are undefined. Upon failure, /// it should contain an appropriate error message. /// /// /// A standard SQLite return code. /// internal abstract SQLiteErrorCode DeclareVirtualFunction(SQLiteModule module, int argumentCount, string name, ref string error); #endif /// /// Enables or disabled extension loading by SQLite. /// /// /// True to enable loading of extensions, false to disable. /// internal abstract void SetLoadExtension(bool bOnOff); /// /// Loads a SQLite extension library from the named file. /// /// /// The name of the dynamic link library file containing the extension. /// /// /// The name of the exported function used to initialize the extension. /// If null, the default "sqlite3_extension_init" will be used. /// internal abstract void LoadExtension(string fileName, string procName); /// /// Enables or disabled extened result codes returned by SQLite /// /// true to enable extended result codes, false to disable. /// internal abstract void SetExtendedResultCodes(bool bOnOff); /// /// Returns the numeric result code for the most recent failed SQLite API call /// associated with the database connection. /// /// Result code internal abstract SQLiteErrorCode ResultCode(); /// /// Returns the extended numeric result code for the most recent failed SQLite API call /// associated with the database connection. /// /// Extended result code internal abstract SQLiteErrorCode ExtendedResultCode(); /// /// Add a log message via the SQLite sqlite3_log interface. /// /// Error code to be logged with the message. /// String to be logged. Unlike the SQLite sqlite3_log() /// interface, this should be pre-formatted. Consider using the /// String.Format() function. /// internal abstract void LogMessage(SQLiteErrorCode iErrCode, string zMessage); #if INTEROP_CODEC internal abstract void SetPassword(byte[] passwordBytes); internal abstract void ChangePassword(byte[] newPasswordBytes); #endif internal abstract void SetAuthorizerHook(SQLiteAuthorizerCallback func); internal abstract void SetUpdateHook(SQLiteUpdateCallback func); internal abstract void SetCommitHook(SQLiteCommitCallback func); internal abstract void SetTraceCallback(SQLiteTraceCallback func); internal abstract void SetRollbackHook(SQLiteRollbackCallback func); internal abstract SQLiteErrorCode SetLogCallback(SQLiteLogCallback func); /// /// Checks if the SQLite core library has been initialized in the current process. /// /// /// Non-zero if the SQLite core library has been initialized in the current process, /// zero otherwise. /// internal abstract bool IsInitialized(); internal abstract int GetCursorForTable(SQLiteStatement stmt, int database, int rootPage); internal abstract long GetRowIdForCursor(SQLiteStatement stmt, int cursor); internal abstract object GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, SQLiteType typ); /// /// Returns non-zero if the given database connection is in autocommit mode. /// Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN /// statement. Autocommit mode is re-enabled by a COMMIT or ROLLBACK. /// internal abstract bool AutoCommit { get; } internal abstract SQLiteErrorCode FileControl(string zDbName, int op, IntPtr pArg); /// /// Creates a new SQLite backup object based on the provided destination /// database connection. The source database connection is the one /// associated with this object. The source and destination database /// connections cannot be the same. /// /// The destination database connection. /// The destination database name. /// The source database name. /// The newly created backup object. internal abstract SQLiteBackup InitializeBackup( SQLiteConnection destCnn, string destName, string sourceName); /// /// Copies up to N pages from the source database to the destination /// database associated with the specified backup object. /// /// The backup object to use. /// /// The number of pages to copy or negative to copy all remaining pages. /// /// /// Set to true if the operation needs to be retried due to database /// locking issues. /// /// /// True if there are more pages to be copied, false otherwise. /// internal abstract bool StepBackup(SQLiteBackup backup, int nPage, out bool retry); /// /// Returns the number of pages remaining to be copied from the source /// database to the destination database associated with the specified /// backup object. /// /// The backup object to check. /// The number of pages remaining to be copied. internal abstract int RemainingBackup(SQLiteBackup backup); /// /// Returns the total number of pages in the source database associated /// with the specified backup object. /// /// The backup object to check. /// The total number of pages in the source database. internal abstract int PageCountBackup(SQLiteBackup backup); /// /// Destroys the backup object, rolling back any backup that may be in /// progess. /// /// The backup object to destroy. internal abstract void FinishBackup(SQLiteBackup backup); /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable Members public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// #region IDisposable "Pattern" Members private bool disposed; private void CheckDisposed() /* throw */ { #if THROW_ON_DISPOSED if (disposed) throw new ObjectDisposedException(typeof(SQLiteBase).Name); #endif } /////////////////////////////////////////////////////////////////////////////////////////////// protected virtual void Dispose(bool disposing) { if (!disposed) { //if (disposing) //{ // //////////////////////////////////// // // dispose managed resources here... // //////////////////////////////////// //} ////////////////////////////////////// // release unmanaged resources here... ////////////////////////////////////// disposed = true; } } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// #region Destructor ~SQLiteBase() { Dispose(false); } #endregion /////////////////////////////////////////////////////////////////////////////////////////////// // These statics are here for lack of a better place to put them. // They exist here because they are called during the finalization of // a SQLiteStatementHandle, SQLiteConnectionHandle, and SQLiteFunctionCookieHandle. // Therefore these functions have to be static, and have to be low-level. /////////////////////////////////////////////////////////////////////////////////////////////// private static string[] _errorMessages = { /* SQLITE_OK */ "not an error", /* SQLITE_ERROR */ "SQL logic error or missing database", /* SQLITE_INTERNAL */ "internal logic error", /* SQLITE_PERM */ "access permission denied", /* SQLITE_ABORT */ "callback requested query abort", /* SQLITE_BUSY */ "database is locked", /* SQLITE_LOCKED */ "database table is locked", /* SQLITE_NOMEM */ "out of memory", /* SQLITE_READONLY */ "attempt to write a readonly database", /* SQLITE_INTERRUPT */ "interrupted", /* SQLITE_IOERR */ "disk I/O error", /* SQLITE_CORRUPT */ "database disk image is malformed", /* SQLITE_NOTFOUND */ "unknown operation", /* SQLITE_FULL */ "database or disk is full", /* SQLITE_CANTOPEN */ "unable to open database file", /* SQLITE_PROTOCOL */ "locking protocol", /* SQLITE_EMPTY */ "table contains no data", /* SQLITE_SCHEMA */ "database schema has changed", /* SQLITE_TOOBIG */ "string or blob too big", /* SQLITE_CONSTRAINT */ "constraint failed", /* SQLITE_MISMATCH */ "datatype mismatch", /* SQLITE_MISUSE */ "library routine called out of sequence", /* SQLITE_NOLFS */ "large file support is disabled", /* SQLITE_AUTH */ "authorization denied", /* SQLITE_FORMAT */ "auxiliary database format error", /* SQLITE_RANGE */ "bind or column index out of range", /* SQLITE_NOTADB */ "file is encrypted or is not a database" }; /////////////////////////////////////////////////////////////////////////////////////////////// /// /// Returns the error message for the specified SQLite return code using /// the internal static lookup table. /// /// The SQLite return code. /// The error message or null if it cannot be found. private static string FallbackGetErrorString(SQLiteErrorCode rc) { if (_errorMessages == null) return null; int index = (int)rc; if ((index < 0) || (index >= _errorMessages.Length)) index = (int)SQLiteErrorCode.Error; /* Make into generic error. */ return _errorMessages[index]; } /// /// Returns the error message for the specified SQLite return code using /// the sqlite3_errstr() function, falling back to the internal lookup /// table if necessary. /// /// The SQLite return code. /// The error message or null if it cannot be found. internal static string GetErrorString(SQLiteErrorCode rc) { try { IntPtr ptr = UnsafeNativeMethods.sqlite3_errstr(rc); if (ptr != IntPtr.Zero) { #if !PLATFORM_COMPACTFRAMEWORK return Marshal.PtrToStringAnsi(ptr); #else return UTF8ToString(ptr, -1); #endif } } catch (EntryPointNotFoundException) { // do nothing. } return FallbackGetErrorString(rc); } internal static string GetLastError(SQLiteConnectionHandle hdl, IntPtr db) { if ((hdl == null) || (db == IntPtr.Zero)) return "null connection or database handle"; string result = null; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { if (!hdl.IsInvalid && !hdl.IsClosed) { #if !SQLITE_STANDARD int len; result = UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg_interop(db, out len), len); #else result = UTF8ToString(UnsafeNativeMethods.sqlite3_errmsg(db), -1); #endif } else { result = "closed or invalid connection handle"; } } } GC.KeepAlive(hdl); return result; } internal static void FinishBackup(SQLiteConnectionHandle hdl, IntPtr backup) { if ((hdl == null) || (backup == IntPtr.Zero)) return; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { #if !SQLITE_STANDARD SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_backup_finish_interop(backup); #else SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_backup_finish(backup); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null); } } } internal static void FinalizeStatement(SQLiteConnectionHandle hdl, IntPtr stmt) { if ((hdl == null) || (stmt == IntPtr.Zero)) return; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { #if !SQLITE_STANDARD SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_finalize_interop(stmt); #else SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_finalize(stmt); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, null); } } } internal static void CloseConnection(SQLiteConnectionHandle hdl, IntPtr db) { if ((hdl == null) || (db == IntPtr.Zero)) return; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { #if !SQLITE_STANDARD SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db); #else ResetConnection(hdl, db, false); SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } #if !INTEROP_LEGACY_CLOSE internal static void CloseConnectionV2(SQLiteConnectionHandle hdl, IntPtr db) { if ((hdl == null) || (db == IntPtr.Zero)) return; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { #if !SQLITE_STANDARD SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db); #else ResetConnection(hdl, db, false); SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_v2(db); #endif if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db)); } } } #endif internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow) { if ((hdl == null) || (db == IntPtr.Zero)) return false; bool result = false; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { if (canThrow && hdl.IsInvalid) throw new InvalidOperationException("The connection handle is invalid."); if (canThrow && hdl.IsClosed) throw new InvalidOperationException("The connection handle is closed."); if (!hdl.IsInvalid && !hdl.IsClosed) { IntPtr stmt = IntPtr.Zero; SQLiteErrorCode n; do { stmt = UnsafeNativeMethods.sqlite3_next_stmt(db, stmt); if (stmt != IntPtr.Zero) { #if !SQLITE_STANDARD n = UnsafeNativeMethods.sqlite3_reset_interop(stmt); #else n = UnsafeNativeMethods.sqlite3_reset(stmt); #endif } } while (stmt != IntPtr.Zero); // // NOTE: Is a transaction NOT pending on the connection? // if (IsAutocommit(hdl, db)) { result = true; } else { n = UnsafeNativeMethods.sqlite3_exec( db, ToUTF8("ROLLBACK"), IntPtr.Zero, IntPtr.Zero, out stmt); if (n == SQLiteErrorCode.Ok) { result = true; } else if (canThrow) { throw new SQLiteException(n, GetLastError(hdl, db)); } } } } } GC.KeepAlive(hdl); return result; } internal static bool IsAutocommit(SQLiteConnectionHandle hdl, IntPtr db) { if ((hdl == null) || (db == IntPtr.Zero)) return false; bool result = false; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { #if PLATFORM_COMPACTFRAMEWORK lock (hdl.syncRoot) #else lock (hdl) #endif { if (!hdl.IsInvalid && !hdl.IsClosed) result = (UnsafeNativeMethods.sqlite3_get_autocommit(db) == 1); } } GC.KeepAlive(hdl); /* NOTE: Unreachable code. */ return result; } } internal interface ISQLiteSchemaExtensions { void BuildTempSchema(SQLiteConnection cnn); } [Flags] internal enum SQLiteOpenFlagsEnum { None = 0, ReadOnly = 0x01, ReadWrite = 0x02, Create = 0x04, Uri = 0x40, SharedCache = 0x01000000, Default = 0x06, } /// /// The extra behavioral flags that can be applied to a connection. /// [Flags()] public enum SQLiteConnectionFlags { /// /// No extra flags. /// None = 0x0, /// /// Enable logging of all SQL statements to be prepared. /// LogPrepare = 0x1, /// /// Enable logging of all bound parameter types and raw values. /// LogPreBind = 0x2, /// /// Enable logging of all bound parameter strongly typed values. /// LogBind = 0x4, /// /// Enable logging of all exceptions caught from user-provided /// managed code called from native code via delegates. /// LogCallbackException = 0x8, /// /// Enable logging of backup API errors. /// LogBackup = 0x10, /// /// Skip adding the extension functions provided by the native /// interop assembly. /// NoExtensionFunctions = 0x20, /// /// When binding parameter values with the /// type, use the interop method that accepts an /// value. /// BindUInt32AsInt64 = 0x40, /// /// When binding parameter values, always bind them as though they were /// plain text (i.e. no numeric, date/time, or other conversions should /// be attempted). /// BindAllAsText = 0x80, /// /// When returning column values, always return them as though they were /// plain text (i.e. no numeric, date/time, or other conversions should /// be attempted). /// GetAllAsText = 0x100, /// /// Prevent this object instance from /// loading extensions. /// NoLoadExtension = 0x200, /// /// Prevent this object instance from /// creating virtual table modules. /// NoCreateModule = 0x400, /// /// Skip binding any functions provided by other managed assemblies when /// opening the connection. /// NoBindFunctions = 0x800, /// /// Skip setting the logging related properties of the /// object instance that was passed to /// the method. /// NoLogModule = 0x1000, /// /// Enable logging of all virtual table module errors seen by the /// method. /// LogModuleError = 0x2000, /// /// Enable logging of certain virtual table module exceptions that cannot /// be easily discovered via other means. /// LogModuleException = 0x4000, /// /// When binding and returning column values, always treat them as though /// they were plain text (i.e. no numeric, date/time, or other conversions /// should be attempted). /// BindAndGetAllAsText = BindAllAsText | GetAllAsText, /// /// Enable all logging. /// LogAll = LogPrepare | LogPreBind | LogBind | LogCallbackException | LogBackup | LogModuleError | LogModuleException, /// /// The default extra flags for new connections. /// Default = LogCallbackException | LogModuleException } // These are the options to the internal sqlite3_config call. internal enum SQLiteConfigOpsEnum { SQLITE_CONFIG_NONE = 0, // nil SQLITE_CONFIG_SINGLETHREAD = 1, // nil SQLITE_CONFIG_MULTITHREAD = 2, // nil SQLITE_CONFIG_SERIALIZED = 3, // nil SQLITE_CONFIG_MALLOC = 4, // sqlite3_mem_methods* SQLITE_CONFIG_GETMALLOC = 5, // sqlite3_mem_methods* SQLITE_CONFIG_SCRATCH = 6, // void*, int sz, int N SQLITE_CONFIG_PAGECACHE = 7, // void*, int sz, int N SQLITE_CONFIG_HEAP = 8, // void*, int nByte, int min SQLITE_CONFIG_MEMSTATUS = 9, // boolean SQLITE_CONFIG_MUTEX = 10, // sqlite3_mutex_methods* SQLITE_CONFIG_GETMUTEX = 11, // sqlite3_mutex_methods* // previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused SQLITE_CONFIG_LOOKASIDE = 13, // int int SQLITE_CONFIG_PCACHE = 14, // sqlite3_pcache_methods* SQLITE_CONFIG_GETPCACHE = 15, // sqlite3_pcache_methods* SQLITE_CONFIG_LOG = 16, // xFunc, void* } }