예제 #1
0
        /// <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);

                    int rc = _sql.SetLogCallback(_callback);

                    if (rc != 0)
                    {
                        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();
            }
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Static "Factory" Methods
        /// <summary>
        /// Creates a <see cref="SQLiteBlob" /> object.  This will not work
        /// for tables that were created WITHOUT ROWID -OR- if the query
        /// does not include the "rowid" column or one of its aliases -OR-
        /// if the <see cref="SQLiteDataReader" /> was not created with the
        /// <see cref="CommandBehavior.KeyInfo" /> flag.
        /// </summary>
        /// <param name="dataReader">
        /// The <see cref="SQLiteDataReader" /> instance with a result set
        /// containing the desired blob column.
        /// </param>
        /// <param name="i">
        /// The index of the blob column.
        /// </param>
        /// <param name="readOnly">
        /// Non-zero to open the blob object for read-only access.
        /// </param>
        /// <returns>
        /// The newly created <see cref="SQLiteBlob" /> instance -OR- null
        /// if an error occurs.
        /// </returns>
        public static SQLiteBlob Create(
            SQLiteDataReader dataReader,
            int i,
            bool readOnly
            )
        {
            SQLiteConnection connection = SQLiteDataReader.GetConnection(
                dataReader);

            if (connection == null)
            {
                throw new InvalidOperationException("Connection not available");
            }

            SQLite3 sqlite3 = connection._sql as SQLite3;

            if (sqlite3 == null)
            {
                throw new InvalidOperationException("Connection has no wrapper");
            }

            SQLiteConnectionHandle handle = sqlite3._sql;

            if (handle == null)
            {
                throw new InvalidOperationException("Connection has an invalid handle.");
            }

            long?rowId = dataReader.GetRowId(i);

            if (rowId == null)
            {
                throw new InvalidOperationException("No RowId is available");
            }

            SQLiteBlobHandle blob = null;

            try
            {
                // do nothing.
            }
            finally /* NOTE: Thread.Abort() protection. */
            {
                IntPtr ptrBlob = IntPtr.Zero;

                SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_blob_open(
                    sqlite3._sql, SQLiteConvert.ToUTF8(
                        dataReader.GetDatabaseName(i)), SQLiteConvert.ToUTF8(
                        dataReader.GetTableName(i)), SQLiteConvert.ToUTF8(
                        dataReader.GetName(i)), (long)rowId, readOnly ? 0 : 1,
                    ref ptrBlob);

                if (rc != SQLiteErrorCode.Ok)
                {
                    throw new SQLiteException(rc, null);
                }

                blob = new SQLiteBlobHandle(handle, ptrBlob);
            }

            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                                           SQLiteConnectionEventType.NewCriticalHandle, null,
                                           null, null, dataReader, blob, null, new object[] {
                typeof(SQLiteBlob), dataReader, i, readOnly
            }));

            return(new SQLiteBlob(sqlite3, blob));
        }