public static void Initialize() { if (SQLite3.StaticIsInitialized()) { return; } if (!AppDomain.CurrentDomain.IsDefaultAppDomain() && UnsafeNativeMethods.GetSettingValue("Force_SQLiteLog", null) == null) { return; } lock (SQLiteLog.syncRoot) { if (SQLiteLog._domainUnload == null) { SQLiteLog._domainUnload = new EventHandler(SQLiteLog.DomainUnload); AppDomain.CurrentDomain.DomainUnload += SQLiteLog._domainUnload; } if (SQLiteLog._sql == null) { SQLiteLog._sql = new SQLite3(SQLiteDateFormats.ISO8601, DateTimeKind.Unspecified, null, IntPtr.Zero, null, false); } if (SQLiteLog._callback == null) { SQLiteLog._callback = new SQLiteLogCallback(SQLiteLog.LogCallback); SQLiteErrorCode sQLiteErrorCode = SQLiteLog._sql.SetLogCallback(SQLiteLog._callback); if (sQLiteErrorCode != SQLiteErrorCode.Ok) { throw new SQLiteException(sQLiteErrorCode, "Failed to initialize logging."); } } SQLiteLog._enabled = true; SQLiteLog.AddDefaultHandler(); } }
private static void DomainUnload(object sender, EventArgs e) { lock (SQLiteLog.syncRoot) { SQLiteLog.RemoveDefaultHandler(); SQLiteLog._enabled = false; if (SQLiteLog._sql != null) { SQLiteErrorCode sQLiteErrorCode = SQLiteLog._sql.Shutdown(); if (sQLiteErrorCode != SQLiteErrorCode.Ok) { throw new SQLiteException(sQLiteErrorCode, "Failed to shutdown interface."); } sQLiteErrorCode = SQLiteLog._sql.SetLogCallback(null); if (sQLiteErrorCode != SQLiteErrorCode.Ok) { throw new SQLiteException(sQLiteErrorCode, "Failed to shutdown logging."); } } if (SQLiteLog._callback != null) { SQLiteLog._callback = null; } if (SQLiteLog._domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= SQLiteLog._domainUnload; SQLiteLog._domainUnload = null; } } }
public static extern SQLiteErrorCode sqlite3_config_log_arm64(SQLiteConfigOpsEnum op, IntPtr p2, IntPtr p3, IntPtr p4, IntPtr p5, IntPtr p6, IntPtr p7, IntPtr p8, SQLiteLogCallback func, IntPtr pvUser);
/////////////////////////////////////////////////////////////////////// #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Handles the AppDomain being unloaded. /// </summary> /// <param name="sender">Should be null.</param> /// <param name="e">The data associated with this event.</param> private static void DomainUnload( object sender, EventArgs e ) { lock (syncRoot) { // // NOTE: Remove the default log event handler. // RemoveDefaultHandler(); // // NOTE: Disable logging. If necessary, it can be re-enabled // later by the Initialize method. // _enabled = false; #if !USE_INTEROP_DLL || !INTEROP_LOG // // BUGBUG: This will cause serious problems if other AppDomains // have any open SQLite connections; however, there is // currently no way around this limitation. // if (_sql != null) { SQLiteErrorCode rc = _sql.Shutdown(); if (rc != SQLiteErrorCode.Ok) { throw new SQLiteException(rc, "Failed to shutdown interface."); } rc = _sql.SetLogCallback(null); if (rc != SQLiteErrorCode.Ok) { throw new SQLiteException(rc, "Failed to shutdown logging."); } } // // BUGFIX: Make sure to reset the callback for next time. This // must be done after it has been succesfully removed // as logging callback by the SQLite core library as we // cannot allow native code to refer to a delegate that // has been garbage collected. // if (_callback != null) { _callback = null; } #endif // // NOTE: Remove the event handler for the DomainUnload event // that we added earlier. // if (_domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= _domainUnload; _domainUnload = null; } } }
/////////////////////////////////////////////////////////////////////// /// <summary> /// Initializes the SQLite logging facilities. /// </summary> /// <param name="className"> /// The name of the managed class that called this method. This /// parameter may be null. /// </param> internal static void Initialize( string className ) { // // NOTE: See if the logging subsystem has been totally disabled. // If so, do nothing. // if (UnsafeNativeMethods.GetSettingValue( "No_SQLiteLog", null) != null) { return; } /////////////////////////////////////////////////////////////// // // NOTE: Keep track of exactly how many times this method is // called (i.e. per-AppDomain, of course). // Interlocked.Increment(ref _initializeCallCount); /////////////////////////////////////////////////////////////// // // NOTE: First, check if the managed logging subsystem is always // supposed to at least attempt to initialize itself. In // order to do this, several fairly complex steps must be // taken, including calling a P/Invoke (interop) method; // therefore, by default, attempt to perform these steps // once. // if (UnsafeNativeMethods.GetSettingValue( "Initialize_SQLiteLog", null) == null) { if (Interlocked.Increment(ref _attemptedInitialize) > 1) { Interlocked.Decrement(ref _attemptedInitialize); return; } } /////////////////////////////////////////////////////////////////// // // BUFXIX: Cannot initialize the logging interface if the SQLite // core library has already been initialized anywhere in // the process (see ticket [2ce0870fad]). // if (SQLite3.StaticIsInitialized()) { return; } /////////////////////////////////////////////////////////////////// #if !PLATFORM_COMPACTFRAMEWORK // // BUGFIX: To avoid nasty situations where multiple AppDomains are // attempting to initialize and/or shutdown what is really // a shared native resource (i.e. the SQLite core library // is loaded per-process and has only one logging callback, // not one per-AppDomain, which it knows nothing about), // prevent all non-default AppDomains from registering a // log handler unless the "Force_SQLiteLog" environment // variable is used to manually override this safety check. // if (!AppDomain.CurrentDomain.IsDefaultAppDomain() && UnsafeNativeMethods.GetSettingValue("Force_SQLiteLog", null) == null) { return; } #endif /////////////////////////////////////////////////////////////////// lock (syncRoot) { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: Add an event handler for the DomainUnload event so // that we can unhook our logging managed function // pointer from the native SQLite code prior to it // being invalidated. // // BUGFIX: Make sure this event handler is only added one // time (per-AppDomain). // if (_domainUnload == null) { _domainUnload = new EventHandler(DomainUnload); AppDomain.CurrentDomain.DomainUnload += _domainUnload; } #endif /////////////////////////////////////////////////////////////// #if USE_INTEROP_DLL && INTEROP_LOG // // NOTE: Attempt to setup interop assembly log callback. // This may fail, e.g. if the SQLite core library // has somehow been initialized. An exception will // be raised in that case. // SQLiteErrorCode rc = SQLite3.ConfigureLogForInterop( className); if (rc != SQLiteErrorCode.Ok) { throw new SQLiteException(rc, "Failed to configure interop assembly logging."); } #else // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) { _sql = new SQLite3( SQLiteDateFormats.Default, DateTimeKind.Unspecified, null, IntPtr.Zero, null, false); } // // NOTE: Create a single "global" (i.e. per-process) callback // to register with SQLite. This callback will pass the // event on to any registered handler. We only want to // do this once. // if (_callback == null) { _callback = new SQLiteLogCallback(LogCallback); SQLiteErrorCode rc = _sql.SetLogCallback(_callback); if (rc != SQLiteErrorCode.Ok) { _callback = null; /* UNDO */ throw new SQLiteException(rc, "Failed to configure managed assembly logging."); } } #endif /////////////////////////////////////////////////////////////// // // NOTE: Logging is enabled by default unless the configuration // setting "Disable_SQLiteLog" is present. // if (UnsafeNativeMethods.GetSettingValue( "Disable_SQLiteLog", null) == null) { _enabled = true; } /////////////////////////////////////////////////////////////// // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } }
/// <summary> /// Allows the setting of a logging callback invoked by SQLite when a /// log event occurs. Only one callback may be set. If NULL is passed, /// the logging callback is unregistered. /// </summary> /// <param name="func">The callback function to invoke.</param> /// <returns>Returns a result code</returns> internal override SQLiteErrorCode SetLogCallback(SQLiteLogCallback func) { SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_config_log( SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, IntPtr.Zero); return rc; }
internal abstract int SetLogCallback(SQLiteLogCallback func);
internal abstract SQLiteErrorCode SetLogCallback(SQLiteLogCallback func);
/////////////////////////////////////////////////////////////////////// #if !PLATFORM_COMPACTFRAMEWORK /// <summary> /// Handles the AppDomain being unloaded. /// </summary> /// <param name="sender">Should be null.</param> /// <param name="e">The data associated with this event.</param> private static void DomainUnload( object sender, EventArgs e ) { lock (syncRoot) { // // NOTE: Remove the default log event handler. // RemoveDefaultHandler(); // // NOTE: Disable logging. If necessary, it can be re-enabled // later by the Initialize method. // _enabled = false; #if !INTEROP_LOG // // BUGBUG: This will cause serious problems if other AppDomains // have any open SQLite connections; however, there is // currently no way around this limitation. // if (_sql != null) { SQLiteErrorCode rc = _sql.Shutdown(); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "Failed to shutdown interface."); rc = _sql.SetLogCallback(null); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "Failed to shutdown logging."); } // // BUGFIX: Make sure to reset the callback for next time. This // must be done after it has been succesfully removed // as logging callback by the SQLite core library as we // cannot allow native code to refer to a delegate that // has been garbage collected. // if (_callback != null) { _callback = null; } #endif // // NOTE: Remove the event handler for the DomainUnload event // that we added earlier. // if (_domainUnload != null) { AppDomain.CurrentDomain.DomainUnload -= _domainUnload; _domainUnload = null; } } }
/////////////////////////////////////////////////////////////////////// /// <summary> /// Initializes the SQLite logging facilities. /// </summary> public static void Initialize() { // // BUFXIX: We cannot initialize the logging interface if the SQLite // core library has already been initialized anywhere in // the process (see ticket [2ce0870fad]). // if (SQLite3.StaticIsInitialized()) return; #if !PLATFORM_COMPACTFRAMEWORK // // BUGFIX: To avoid nasty situations where multiple AppDomains are // attempting to initialize and/or shutdown what is really // a shared native resource (i.e. the SQLite core library // is loaded per-process and has only one logging callback, // not one per-AppDomain, which it knows nothing about), // prevent all non-default AppDomains from registering a // log handler unless the "Force_SQLiteLog" environment // variable is used to manually override this safety check. // if (!AppDomain.CurrentDomain.IsDefaultAppDomain() && UnsafeNativeMethods.GetSettingValue("Force_SQLiteLog", null) == null) { return; } #endif lock (syncRoot) { #if !PLATFORM_COMPACTFRAMEWORK // // NOTE: Add an event handler for the DomainUnload event so // that we can unhook our logging managed function // pointer from the native SQLite code prior to it // being invalidated. // // BUGFIX: Make sure this event handler is only added one // time (per-AppDomain). // if (_domainUnload == null) { _domainUnload = new EventHandler(DomainUnload); AppDomain.CurrentDomain.DomainUnload += _domainUnload; } #endif #if !INTEROP_LOG // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) { _sql = new SQLite3( SQLiteDateFormats.Default, DateTimeKind.Unspecified, null, IntPtr.Zero, null, false); } // // NOTE: Create a single "global" (i.e. per-process) callback // to register with SQLite. This callback will pass the // event on to any registered handler. We only want to // do this once. // if (_callback == null) { _callback = new SQLiteLogCallback(LogCallback); SQLiteErrorCode rc = _sql.SetLogCallback(_callback); if (rc != SQLiteErrorCode.Ok) throw new SQLiteException(rc, "Failed to initialize logging."); } #endif // // NOTE: Logging is enabled by default. // _enabled = true; // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } }
/// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString">ConnectionString</see> /// </summary> public override void Open() { if (_connectionState != ConnectionState.Closed) throw new InvalidOperationException(); Close(); SortedList<string, string> opts = ParseConnectionString(_connectionString); string fileName; if (Convert.ToInt32(FindKey(opts, "Version", "3"), CultureInfo.InvariantCulture) != 3) throw new NotSupportedException("Only SQLite Version 3 is supported at this time"); fileName = FindKey(opts, "Data Source", ""); if (String.IsNullOrEmpty(fileName)) { fileName = FindKey(opts, "Uri", ""); if (String.IsNullOrEmpty(fileName)) throw new ArgumentException("Data Source cannot be empty. Use :memory: to open an in-memory database"); else fileName = MapUriPath(fileName); } if (String.Compare(fileName, ":MEMORY:", StringComparison.OrdinalIgnoreCase) == 0) fileName = ":memory:"; else { #if PLATFORM_COMPACTFRAMEWORK if (fileName.StartsWith(".\\")) fileName = Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1); #endif fileName = ExpandFileName(fileName); } try { bool usePooling = (SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", Boolean.FalseString)) == true); int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", "100"), CultureInfo.InvariantCulture); _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", "30"), CultureInfo.CurrentCulture); _defaultIsolation = (IsolationLevel)Enum.Parse(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", "Serializable"), true); if (_defaultIsolation != IsolationLevel.Serializable && _defaultIsolation != IsolationLevel.ReadCommitted) throw new NotSupportedException("Invalid Default IsolationLevel specified"); //string temp = FindKey(opts, "DateTimeFormat", "ISO8601"); //if (String.Compare(temp, "ticks", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.Ticks; //else if (String.Compare(temp, "julianday", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.JulianDay; if (_sql == null) { bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true); SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true); if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16() _sql = new SQLite3_UTF16(dateFormat); else _sql = new SQLite3(dateFormat); if (_sql != null && _logHandler != null) { if (_logCallback == null) _logCallback = new SQLiteLogCallback(LogCallback); if (_logCallback != null) _sql.SetLogCallback(_logCallback); } } SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None; if (SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false) flags |= SQLiteOpenFlagsEnum.Create; if (SQLiteConvert.ToBoolean(FindKey(opts, "Read Only", Boolean.FalseString)) == true) { flags |= SQLiteOpenFlagsEnum.ReadOnly; // SQLite will return SQLITE_MISUSE on ReadOnly and Create flags &= ~SQLiteOpenFlagsEnum.Create; } else { flags |= SQLiteOpenFlagsEnum.ReadWrite; } _sql.Open(fileName, flags, maxPoolSize, usePooling); _binaryGuid = (SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", Boolean.TrueString)) == true); string password = FindKey(opts, "Password", null); if (String.IsNullOrEmpty(password) == false) _sql.SetPassword(System.Text.UTF8Encoding.UTF8.GetBytes(password)); else if (_password != null) _sql.SetPassword(_password); _password = null; _dataSource = Path.GetFileNameWithoutExtension(fileName); _version++; ConnectionState oldstate = _connectionState; _connectionState = ConnectionState.Open; try { using (SQLiteCommand cmd = CreateCommand()) { string defValue; if (fileName != ":memory:") { defValue = FindKey(opts, "Page Size", "1024"); if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 1024) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA page_size={0}", defValue); cmd.ExecuteNonQuery(); } } defValue = FindKey(opts, "Max Page Count", "0"); if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 0) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA max_page_count={0}", defValue); cmd.ExecuteNonQuery(); } defValue = FindKey(opts, "Legacy Format", Boolean.FalseString); cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA legacy_file_format={0}", SQLiteConvert.ToBoolean(defValue) == true ? "ON" : "OFF"); cmd.ExecuteNonQuery(); defValue = FindKey(opts, "Synchronous", "Normal"); if (String.Compare(defValue, "Full", StringComparison.OrdinalIgnoreCase) != 0) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA synchronous={0}", defValue); cmd.ExecuteNonQuery(); } defValue = FindKey(opts, "Cache Size", "2000"); if (Convert.ToInt32(defValue, CultureInfo.InvariantCulture) != 2000) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA cache_size={0}", defValue); cmd.ExecuteNonQuery(); } defValue = FindKey(opts, "Journal Mode", "Delete"); if (String.Compare(defValue, "Default", StringComparison.OrdinalIgnoreCase) != 0) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA journal_mode={0}", defValue); cmd.ExecuteNonQuery(); } defValue = FindKey(opts, "Foreign Keys", Boolean.FalseString); cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA foreign_keys={0}", SQLiteConvert.ToBoolean(defValue) == true ? "ON" : "OFF"); cmd.ExecuteNonQuery(); } if (_commitHandler != null) _sql.SetCommitHook(_commitCallback); if (_updateHandler != null) _sql.SetUpdateHook(_updateCallback); if (_rollbackHandler != null) _sql.SetRollbackHook(_rollbackCallback); #if !PLATFORM_COMPACTFRAMEWORK if (Transactions.Transaction.Current != null && SQLiteConvert.ToBoolean(FindKey(opts, "Enlist", Boolean.TrueString)) == true) EnlistTransaction(Transactions.Transaction.Current); #endif _connectionState = oldstate; OnStateChange(ConnectionState.Open); } catch { _connectionState = oldstate; throw; } } catch (SQLiteException) { Close(); throw; } }
/// <summary> /// Allows the setting of a logging callback invoked by SQLite when a /// log event occurs. Only one callback may be set. If NULL is passed, /// the logging callback is unregistered. /// </summary> /// <param name="func">The callback function to invoke.</param> /// <returns>Returns a result code</returns> internal override int SetLogCallback(SQLiteLogCallback func) { //int rc = UnsafeNativeMethods.sqlite3_config( // (int)SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, (IntPtr)0); return 0; }
internal static extern SQLiteErrorCode sqlite3_config_log(SQLiteConfigOpsEnum op, SQLiteLogCallback func, IntPtr pvUser);
public static extern SQLiteErrorCode sqlite3_config_log(SQLiteConfigOpsEnum op, SQLiteLogCallback func, IntPtr pvUser);
/// <summary> /// Initializes the SQLite logging facilities. /// </summary> public static void Initialize() { // // BUFXIX: We cannot initialize the logging interface if the SQLite // core library has already been initialized anywhere in // the process (see ticket [2ce0870fad]). // if (SQLite3.StaticIsInitialized()) { return; } // // BUGFIX: To avoid nasty situations where multiple AppDomains are // attempting to initialize and/or shutdown what is really // a shared native resource (i.e. the SQLite core library // is loaded per-process and has only one logging callback, // not one per-AppDomain, which it knows nothing about), // prevent all non-default AppDomains from registering a // log handler unless the "Force_SQLiteLog" environment // variable is used to manually override this safety check. // if (!AppDomain.CurrentDomain.IsDefaultAppDomain() && Environment.GetEnvironmentVariable("Force_SQLiteLog") == null) { return; } lock (syncRoot) { // // NOTE: Add an event handler for the DomainUnload event so // that we can unhook our logging managed function // pointer from the native SQLite code prior to it // being invalidated. // // BUGFIX: Make sure this event handler is only added one // time (per-AppDomain). // if (_domainUnload == null) { _domainUnload = new EventHandler(DomainUnload); AppDomain.CurrentDomain.DomainUnload += _domainUnload; } // // NOTE: Create an instance of the SQLite wrapper class. // if (_sql == null) { _sql = new SQLite3(SQLiteDateFormats.Default, DateTimeKind.Unspecified); } // // NOTE: Create a single "global" (i.e. per-process) callback // to register with SQLite. This callback will pass the // event on to any registered handler. We only want to // do this once. // if (_callback == null) { _callback = new SQLiteLogCallback(LogCallback); SQLiteErrorCode rc = _sql.SetLogCallback(_callback); if (rc != SQLiteErrorCode.Ok) { throw new SQLiteException(rc, "Failed to initialize logging."); } } // // NOTE: Logging is enabled by default. // _enabled = true; // // NOTE: For now, always setup the default log event handler. // AddDefaultHandler(); } }
internal static extern int sqlite3_config(int op, SQLiteLogCallback func, IntPtr pvUser);
/// <summary> /// Allows the setting of a logging callback invoked by SQLite when a /// log event occurs. Only one callback may be set. If NULL is passed, /// the logging callback is unregistered. /// </summary> /// <param name="func">The callback function to invoke.</param> /// <returns>Returns a result code</returns> internal override int SetLogCallback(SQLiteLogCallback func) { int rc = UnsafeNativeMethods.sqlite3_config((int)SQLiteConfigOpsEnum.SQLITE_CONFIG_LOG, func, (IntPtr)0); return(rc); }