Beispiel #1
0
        /// <summary>
        /// Initializes a command with the given SQL, connection and transaction
        /// </summary>
        /// <param name="commandText">The SQL command text</param>
        /// <param name="connection">The connection to associate with the command</param>
        /// <param name="transaction">The transaction the command should be associated with</param>
        public SQLiteCommand(string commandText, SQLiteConnection connection, SQLiteTransaction transaction)
        {
            _commandTimeout      = 30;
            _parameterCollection = new SQLiteParameterCollection(this);
            _designTimeVisible   = true;
            _updateRowSource     = UpdateRowSource.None;

            if (commandText != null)
            {
                CommandText = commandText;
            }

            if (connection != null)
            {
                DbConnection    = connection;
                _commandTimeout = connection.DefaultTimeout;
            }

            if (transaction != null)
            {
                Transaction = transaction;
            }

            SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
                                           SQLiteConnectionEventType.NewCommand, null, transaction, this,
                                           null, null, null, null));
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Creates a <see cref="SQLiteBlob" /> object.  This will not work
        /// for tables that were created WITHOUT ROWID.
        /// </summary>
        /// <param name="connection">
        /// The connection to use when opening the blob object.
        /// </param>
        /// <param name="databaseName">
        /// The name of the database containing the blob object.
        /// </param>
        /// <param name="tableName">
        /// The name of the table containing the blob object.
        /// </param>
        /// <param name="columnName">
        /// The name of the column containing the blob object.
        /// </param>
        /// <param name="rowId">
        /// The integer identifier for the row associated with the desired
        /// blob object.
        /// </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(
            SQLiteConnection connection,
            string databaseName,
            string tableName,
            string columnName,
            long rowId,
            bool readOnly
            )
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            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.");
            }

            SQLiteBlobHandle blob = null;

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

                SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_blob_open(
                    handle, SQLiteConvert.ToUTF8(databaseName),
                    SQLiteConvert.ToUTF8(tableName), SQLiteConvert.ToUTF8(
                        columnName), rowId, readOnly ? 0 : 1, ref ptrBlob);

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

                blob = new SQLiteBlobHandle(handle, ptrBlob);
            }

            SQLiteConnection.OnChanged(connection, new ConnectionEventArgs(
                                           SQLiteConnectionEventType.NewCriticalHandle, null, null,
                                           null, null, blob, null, new object[] { typeof(SQLiteBlob),
                                                                                  databaseName, tableName, columnName, rowId, readOnly }));

            return(new SQLiteBlob(sqlite3, blob));
        }
Beispiel #3
0
        internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool)
        {
            //
            // NOTE: If the database connection is currently open, attempt to
            //       close it now.  This must be done because the file name or
            //       other parameters that may impact the underlying database
            //       connection may have changed.
            //
            if (_sql != null)
            {
                Close(true);
            }

            //
            // NOTE: If the connection was not closed successfully, throw an
            //       exception now.
            //
            if (_sql != null)
            {
                throw new SQLiteException("connection handle is still active");
            }

            _usePool  = usePool;
            _fileName = strFilename;

            if (usePool)
            {
                _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);

#if !NET_COMPACT_20 && TRACE_CONNECTION
                Trace.WriteLine(String.Format("Open16 (Pool): {0}", (_sql != null) ? _sql.ToString() : "<null>"));
#endif
            }

            if (_sql == null)
            {
                try
                {
                    // do nothing.
                }
                finally /* NOTE: Thread.Abort() protection. */
                {
                    IntPtr          db = IntPtr.Zero;
                    SQLiteErrorCode n;

#if !SQLITE_STANDARD
                    if ((connectionFlags & SQLiteConnectionFlags.NoExtensionFunctions) != SQLiteConnectionFlags.NoExtensionFunctions)
                    {
                        n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), openFlags, ref db);
                    }
                    else
#endif
                    {
                        //
                        // NOTE: This flag check is designed to enforce the constraint that opening
                        //       a database file that does not already exist requires specifying the
                        //       "Create" flag, even when a native API is used that does not accept
                        //       a flags parameter.
                        //
                        if (((openFlags & SQLiteOpenFlagsEnum.Create) != SQLiteOpenFlagsEnum.Create) && !File.Exists(strFilename))
                        {
                            throw new SQLiteException(SQLiteErrorCode.CantOpen, strFilename);
                        }

                        n = UnsafeNativeMethods.sqlite3_open16(strFilename, ref db);
                    }

#if !NET_COMPACT_20 && TRACE_CONNECTION
                    Trace.WriteLine(String.Format("Open16: {0}", db));
#endif

                    if (n != SQLiteErrorCode.Ok)
                    {
                        throw new SQLiteException(n, null);
                    }
                    _sql = new SQLiteConnectionHandle(db, true);
                }
                lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }

                SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                                               SQLiteConnectionEventType.NewCriticalHandle, null, null,
                                               null, null, _sql, strFilename, new object[] { strFilename,
                                                                                             connectionFlags, openFlags, maxPoolSize, usePool }));
            }

            // Bind functions to this connection.  If any previous functions of the same name
            // were already bound, then the new bindings replace the old.
            if ((connectionFlags & SQLiteConnectionFlags.NoBindFunctions) != SQLiteConnectionFlags.NoBindFunctions)
            {
                if (_functions == null)
                {
                    _functions = new List <SQLiteFunction>();
                }

                _functions.AddRange(new List <SQLiteFunction>(SQLiteFunction.BindFunctions(this, connectionFlags)));
            }

            SetTimeout(0);
            GC.KeepAlive(_sql);
        }
Beispiel #4
0
        internal override void Open(string strFilename, string vfsName, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool)
        {
            //
            // NOTE: If the database connection is currently open, attempt to
            //       close it now.  This must be done because the file name or
            //       other parameters that may impact the underlying database
            //       connection may have changed.
            //
            if (_sql != null)
            {
                Close(false);
            }

            //
            // NOTE: If the connection was not closed successfully, throw an
            //       exception now.
            //
            if (_sql != null)
            {
                throw new SQLiteException("connection handle is still active");
            }

            _usePool  = usePool;
            _fileName = strFilename;
            _flags    = connectionFlags;

            if (usePool)
            {
                _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion);

                SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                                               SQLiteConnectionEventType.OpenedFromPool, null, null,
                                               null, null, _sql, strFilename, new object[] {
                    typeof(SQLite3_UTF16), strFilename, vfsName,
                    connectionFlags, openFlags, maxPoolSize, usePool,
                    _poolVersion
                }));

#if !NET_COMPACT_20 && TRACE_CONNECTION
                Trace.WriteLine(HelperMethods.StringFormat(
                                    CultureInfo.CurrentCulture,
                                    "Open16 (Pool): {0}",
                                    HandleToString()));
#endif
            }

            if (_sql == null)
            {
                try
                {
                    // do nothing.
                }
                finally /* NOTE: Thread.Abort() protection. */
                {
                    IntPtr          db = IntPtr.Zero;
                    SQLiteErrorCode n;

                    int extFuncs = HelperMethods.HasFlags(connectionFlags, SQLiteConnectionFlags.NoExtensionFunctions) ? 0 : 1;

#if !SQLITE_STANDARD
                    if ((vfsName != null) || (extFuncs != 0))
                    {
                        n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), ToUTF8(vfsName), openFlags, extFuncs, ref db);
                    }
                    else
#endif
                    {
                        //
                        // NOTE: This flag check is designed to enforce the constraint that opening
                        //       a database file that does not already exist requires specifying the
                        //       "Create" flag, even when a native API is used that does not accept
                        //       a flags parameter.
                        //
                        if (((openFlags & SQLiteOpenFlagsEnum.Create) != SQLiteOpenFlagsEnum.Create) && !File.Exists(strFilename))
                        {
                            throw new SQLiteException(SQLiteErrorCode.CantOpen, strFilename);
                        }

                        if (vfsName != null)
                        {
                            throw new SQLiteException(SQLiteErrorCode.CantOpen, HelperMethods.StringFormat(
                                                          CultureInfo.CurrentCulture,
                                                          "cannot open using UTF-16 and VFS \"{0}\": need interop assembly", vfsName));
                        }

                        n = UnsafeNativeMethods.sqlite3_open16(strFilename, ref db);
                    }

#if !NET_COMPACT_20 && TRACE_CONNECTION
                    Trace.WriteLine(HelperMethods.StringFormat(
                                        CultureInfo.CurrentCulture,
                                        "Open16: {0}", db));
#endif

                    if (n != SQLiteErrorCode.Ok)
                    {
                        throw new SQLiteException(n, null);
                    }
                    _sql = new SQLiteConnectionHandle(db, true);
                }
                lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ }

                SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                                               SQLiteConnectionEventType.NewCriticalHandle, null,
                                               null, null, null, _sql, strFilename, new object[] {
                    typeof(SQLite3_UTF16), strFilename, vfsName,
                    connectionFlags, openFlags, maxPoolSize, usePool
                }));
            }

            // Bind functions to this connection.  If any previous functions of the same name
            // were already bound, then the new bindings replace the old.
            if (!HelperMethods.HasFlags(connectionFlags, SQLiteConnectionFlags.NoBindFunctions))
            {
                if (_functions == null)
                {
                    _functions = new Dictionary <SQLiteFunctionAttribute, SQLiteFunction>();
                }

                foreach (KeyValuePair <SQLiteFunctionAttribute, SQLiteFunction> pair
                         in SQLiteFunction.BindFunctions(this, connectionFlags))
                {
                    _functions[pair.Key] = pair.Value;
                }
            }

            SetTimeout(0);
            GC.KeepAlive(_sql);
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Disposes of the command and clears all member variables
        /// </summary>
        /// <param name="disposing">Whether or not the class is being explicitly or implicitly disposed</param>
        protected override void Dispose(bool disposing)
        {
            SQLiteConnection.OnChanged(_cnn, new ConnectionEventArgs(
                                           SQLiteConnectionEventType.DisposingCommand, null, _transaction, this,
                                           null, null, null, new object[] { disposing, disposed }));

            bool skippedDispose = false;

            try
            {
                if (!disposed)
                {
                    if (disposing)
                    {
                        ////////////////////////////////////
                        // dispose managed resources here...
                        ////////////////////////////////////

                        // If a reader is active on this command, don't destroy the command, instead let the reader do it
                        SQLiteDataReader reader = null;
                        if (_activeReader != null)
                        {
                            try
                            {
                                reader = _activeReader.Target as SQLiteDataReader;
                            }
                            catch (InvalidOperationException)
                            {
                            }
                        }

                        if (reader != null)
                        {
                            reader._disposeCommand = true;
                            _activeReader          = null;
                            skippedDispose         = true;
                            return;
                        }

                        Connection = null;
                        _parameterCollection.Clear();
                        _commandText = null;
                    }

                    //////////////////////////////////////
                    // release unmanaged resources here...
                    //////////////////////////////////////
                }
            }
            finally
            {
                if (!skippedDispose)
                {
                    base.Dispose(disposing);

                    //
                    // NOTE: Everything should be fully disposed at this point.
                    //
                    disposed = true;
                }
            }
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////

        #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));
        }