Example #1
0
    ///////////////////////////////////////////////////////////////////////////////////////////////

    // It isn't necessary to cleanup any functions we've registered.  If the connection
    // goes to the pool and is resurrected later, re-registered functions will overwrite the
    // previous functions.  The SQLiteFunctionCookieHandle will take care of freeing unmanaged
    // resources belonging to the previously-registered functions.
    internal override void Close(bool canThrow)
    {
      if (_sql != null)
      {
          if (!_sql.OwnHandle)
          {
              _sql = null;
              return;
          }

          if (_usePool)
          {
              if (SQLiteBase.ResetConnection(_sql, _sql, canThrow))
              {
#if INTEROP_VIRTUAL_TABLE
                  DisposeModules();
#endif

                  SQLiteConnectionPool.Add(_fileName, _sql, _poolVersion);

#if !NET_COMPACT_20 && TRACE_CONNECTION
                  Trace.WriteLine(String.Format("Close (Pool) Success: {0}", _sql));
#endif
              }
#if !NET_COMPACT_20 && TRACE_CONNECTION
              else
              {
                  Trace.WriteLine(String.Format("Close (Pool) Failure: {0}", _sql));
              }
#endif
          }
          else
          {
              _sql.Dispose();
          }
          _sql = null;
      }
    }
Example #2
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;
          SQLiteErrorCode n;

#if !SQLITE_STANDARD
          if ((connectionFlags & SQLiteConnectionFlags.NoExtensionFunctions) != SQLiteConnectionFlags.NoExtensionFunctions)
          {
            n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), openFlags, out 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, out 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);
    }
        ///////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Adds a connection to the pool of those associated with the
        /// specified database file name.
        /// </summary>
        /// <param name="fileName">
        /// The database file name.
        /// </param>
        /// <param name="handle">
        /// The database connection handle.
        /// </param>
        /// <param name="version">
        /// The connection pool version at the point the database connection
        /// handle was received from the connection pool.  This is also the
        /// connection pool version that the database connection handle was
        /// created under.
        /// </param>
        internal static void Add(
            string fileName,
            SQLiteConnectionHandle handle,
            int version
            )
        {
            ISQLiteConnectionPool connectionPool = GetConnectionPool();

            if (connectionPool != null)
            {
                connectionPool.Add(fileName, handle, version);
            }
            else
            {
                lock (_syncRoot)
                {
                    //
                    // NOTE: If the queue does not exist in the pool, then it
                    //       must have been cleared sometime after the
                    //       connection was created.
                    //
                    PoolQueue queue;

                    if (_queueList.TryGetValue(fileName, out queue) &&
                        (version == queue.PoolVersion))
                    {
                        ResizePool(queue, true);

                        Queue<WeakReference> poolQueue = queue.Queue;
                        if (poolQueue == null) return;

                        poolQueue.Enqueue(new WeakReference(handle, false));
                        Interlocked.Increment(ref _poolClosed);
                    }
                    else
                    {
                        handle.Close();
                    }

                    GC.KeepAlive(handle);
                }
            }
        }
Example #4
0
    ///////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Constructs the object used to interact with the SQLite core library
    /// using the UTF-8 text encoding.
    /// </summary>
    /// <param name="fmt">
    /// The DateTime format to be used when converting string values to a
    /// DateTime and binding DateTime parameters.
    /// </param>
    /// <param name="kind">
    /// The <see cref="DateTimeKind" /> to be used when creating DateTime
    /// values.
    /// </param>
    /// <param name="fmtString">
    /// The format string to be used when parsing and formatting DateTime
    /// values.
    /// </param>
    /// <param name="db">
    /// The native handle to be associated with the database connection.
    /// </param>
    /// <param name="fileName">
    /// The fully qualified file name associated with <paramref name="db "/>.
    /// </param>
    /// <param name="ownHandle">
    /// Non-zero if the newly created object instance will need to dispose
    /// of <paramref name="db" /> when it is no longer needed.
    /// </param>
    internal SQLite3(
        SQLiteDateFormats fmt,
        DateTimeKind kind,
        string fmtString,
        IntPtr db,
        string fileName,
        bool ownHandle
        )
      : base(fmt, kind, fmtString)
    {
        if (db != IntPtr.Zero)
        {
            _sql = new SQLiteConnectionHandle(db, ownHandle);
            _fileName = fileName;

            SQLiteConnection.OnChanged(null, new ConnectionEventArgs(
                SQLiteConnectionEventType.NewCriticalHandle, null, null,
                null, null, _sql, fileName, new object[] { fmt, kind,
                fmtString, db, fileName, ownHandle }));
        }
    }
        ///////////////////////////////////////////////////////////////////////

        internal SQLiteStatementHandle(SQLiteConnectionHandle cnn, IntPtr stmt)
            : this()
        {
#if PLATFORM_COMPACTFRAMEWORK
            lock (syncRoot)
#endif
            {
                this.cnn = cnn;
                SetHandle(stmt);
            }
        }
        ///////////////////////////////////////////////////////////////////////

        internal SQLiteBackupHandle(SQLiteConnectionHandle cnn, IntPtr backup)
            : this()
        {
#if PLATFORM_COMPACTFRAMEWORK
            lock (syncRoot)
#endif
            {
                this.cnn = cnn;
                SetHandle(backup);
            }
        }
Example #7
0
    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;
    }
Example #8
0
    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;
    }
Example #9
0
    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));
            }
        }
    }
Example #10
0
    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);
            }
        }
    }
Example #11
0
    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;
    }