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.
Inheritance: SqliteConvert, IDisposable
Exemple #1
0
        /// <summary>
        /// Called by SqliteBase derived classes, this function binds all user-defined functions to a connection.
        /// It is done this way so that all user-defined functions will access the database using the same encoding scheme
        /// as the connection (UTF-8 or UTF-16).
        /// </summary>
        /// <param name="sqlbase">The base object on which the functions are to bind</param>
        /// <returns>Returns an array of functions which the connection object should retain until the connection is closed.</returns>
        internal static SqliteFunction[] BindFunctions(SqliteBase sqlbase)
        {
            SqliteFunction        f;
            List <SqliteFunction> lFunctions = new List <SqliteFunction>();

            foreach (SqliteFunctionAttribute pr in _registeredFunctions)
            {
                f              = (SqliteFunction)Activator.CreateInstance(pr._instanceType);
                f._base        = sqlbase;
                f._InvokeFunc  = (pr.FuncType == FunctionType.Scalar) ? new SqliteCallback(f.ScalarCallback) : null;
                f._StepFunc    = (pr.FuncType == FunctionType.Aggregate) ? new SqliteCallback(f.StepCallback) : null;
                f._FinalFunc   = (pr.FuncType == FunctionType.Aggregate) ? new SqliteFinalCallback(f.FinalCallback) : null;
                f._CompareFunc = (pr.FuncType == FunctionType.Collation) ? new SqliteCollation(f.CompareCallback) : null;

                if (pr.FuncType != FunctionType.Collation)
                {
                    sqlbase.CreateFunction(pr.Name, pr.Arguments, f._InvokeFunc, f._StepFunc, f._FinalFunc);
                }
                else
                {
                    sqlbase.CreateCollation(pr.Name, f._CompareFunc);
                }
                lFunctions.Add(f);
            }

            SqliteFunction[] arFunctions = new SqliteFunction[lFunctions.Count];
            lFunctions.CopyTo(arFunctions, 0);

            return(arFunctions);
        }
Exemple #2
0
        /// <summary>
        /// Disposes of any active contextData variables that were not automatically cleaned up.  Sometimes this can happen if
        /// someone closes the connection while a DataReader is open.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);

            IDisposable disp;

            foreach (KeyValuePair <long, object> kv in _contextDataList)
            {
                disp = kv.Value as IDisposable;
                if (disp != null)
                {
                    disp.Dispose();
                }
            }
            _contextDataList.Clear();

            _InvokeFunc      = null;
            _StepFunc        = null;
            _FinalFunc       = null;
            _CompareFunc     = null;
            _base            = null;
            _contextDataList = null;

            GC.SuppressFinalize(this);
        }
Exemple #3
0
        /// <summary>
        /// Disposes and finalizes the statement
        /// </summary>
        public void Dispose()
        {
            _sql.FinalizeStatement(this);

            _paramNames   = null;
            _paramValues  = null;
            _sql          = null;
            _sqlStatement = null;

            GC.SuppressFinalize(this);
        }
Exemple #4
0
        /// <summary>
        /// Initializes the statement and attempts to get all information about parameters in the statement
        /// </summary>
        /// <param name="sqlbase">The base Sqlite object</param>
        /// <param name="stmt">The statement</param>
        /// <param name="strCommand">The command text for this statement</param>
        /// <param name="previous">The previous command in a multi-statement command</param>
        internal SqliteStatement(SqliteBase sqlbase, IntPtr stmt, string strCommand, SqliteStatement previous)
        {
            _sql          = sqlbase;
            _sqlite_stmt  = stmt;
            _sqlStatement = strCommand;

            // Determine parameters for this statement (if any) and prepare space for them.
            int    nCmdStart = 0;
            int    n         = _sql.Bind_ParamCount(this);
            int    x;
            string s;

            if (n > 0)
            {
                if (previous != null)
                {
                    nCmdStart = previous._unnamedParameters;
                }

                _paramNames  = new string[n];
                _paramValues = new SqliteParameter[n];

                for (x = 0; x < n; x++)
                {
                    s = _sql.Bind_ParamName(this, x + 1);
                    if (String.IsNullOrEmpty(s))
                    {
                        s = String.Format(CultureInfo.InvariantCulture, ";{0}", nCmdStart);
                        nCmdStart++;
                        _unnamedParameters++;
                    }
                    _paramNames[x]  = s;
                    _paramValues[x] = null;
                }
            }
        }
Exemple #5
0
    /// <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();

      KeyValuePair<string, string>[] opts = ParseConnectionString();
      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))
        throw new ArgumentException("Data Source cannot be empty.  Use :memory: to open an in-memory database");

      if (String.Compare(fileName, ":MEMORY:", true, CultureInfo.InvariantCulture) == 0)
        fileName = ":memory:";
#if PLATFORM_COMPACTFRAMEWORK
      else if (fileName.StartsWith(".\\"))
        fileName = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1);
#endif
      string bt = FindKey (opts, "busy_timeout", "30");
      try {
	      _busyTimeout = Int32.Parse (bt);
      } catch (Exception) {
	      // ignore
      }

      try
      {
        bool bUTF16 = (Convert.ToBoolean(FindKey(opts, "UseUTF16Encoding", "False"), CultureInfo.InvariantCulture) == true);
        SqliteDateFormats dateFormat = String.Compare(FindKey(opts, "DateTimeFormat", "ISO8601"), "ticks", true, CultureInfo.InvariantCulture) == 0 ? SqliteDateFormats.Ticks : SqliteDateFormats.ISO8601;

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

        fileName = ExpandFileName(fileName);

        try
        {
          if (System.IO.File.Exists(fileName) == false)
            throw new System.IO.FileNotFoundException(String.Format(CultureInfo.CurrentCulture, "Unable to locate file \"{0}\", creating new database.", fileName));
        }
        catch
        {
        }

        _sql.Open(fileName);

        _binaryGuid = (Convert.ToBoolean(FindKey(opts, "BinaryGUID", "True"), CultureInfo.InvariantCulture) == true);

#if MONO_SUPPORT_PASSWORDS
	// Not used under mono now
        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;
#endif
        _dataSource = System.IO.Path.GetFileNameWithoutExtension(fileName);

        OnStateChange(ConnectionState.Open);
        _version++;

        using (SqliteCommand cmd = CreateCommand())
        {
          string defValue;

          defValue = FindKey(opts, "Synchronous", "Normal");
          if (String.Compare(defValue, "Normal", true, CultureInfo.InvariantCulture) != 0)
          {
            cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA Synchronous={0}", defValue);
            cmd.ExecuteNonQuery();
          }

          defValue = FindKey(opts, "Cache Size", "2000");
          if (Convert.ToInt32(defValue) != 2000)
          {
            cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA Cache_Size={0}", defValue);
            cmd.ExecuteNonQuery();
          }

          if (fileName != ":memory:")
          {
            defValue = FindKey(opts, "Page Size", "1024");
            if (Convert.ToInt32(defValue) != 1024)
            {
              cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA Page_Size={0}", defValue);
              cmd.ExecuteNonQuery();
            }
          }
        }

#if !PLATFORM_COMPACTFRAMEWORK
        if (FindKey(opts, "Enlist", "Y").ToUpper()[0] == 'Y' && System.Transactions.Transaction.Current != null)
          EnlistTransaction(System.Transactions.Transaction.Current);
#endif
      }
      catch (SqliteException)
      {
        OnStateChange(ConnectionState.Broken);
        throw;
      }
    }
Exemple #6
0
    /// <summary>
    /// When the database connection is closed, all commands linked to this connection are automatically reset.
    /// </summary>
    public override void Close()
    {
      if (_sql != null)
      {
        // Force any commands associated with this connection to release their unmanaged
        // resources.  The commands are still valid and will automatically re-acquire the
        // unmanaged resources the next time they are run -- provided this connection is
        // re-opened before then.
        lock (_commandList)
        {
          foreach (SqliteCommand cmd in _commandList)
            cmd.ClearCommands();
        }

#if !PLATFORM_COMPACTFRAMEWORK
        if (_enlistment != null)
        {
          // If the connection is enlisted in a transaction scope and the scope is still active,
          // we cannot truly shut down this connection until the scope has completed.  Therefore make a
          // hidden connection temporarily to hold open the connection until the scope has completed.
          SqliteConnection cnn = new SqliteConnection();
          cnn._sql = _sql;
          cnn._transactionLevel = _transactionLevel;
          cnn._enlistment = _enlistment;
          cnn._connectionState = _connectionState;
          cnn._version = _version;

          cnn._enlistment._transaction._cnn = cnn;
          cnn._enlistment._disposeConnection = true;
        }
        else
        {
          _sql.Close();
        }
        _enlistment = null;
#else
        _sql.Close();
#endif
        _sql = null;
        _transactionLevel = 0;
      }

      OnStateChange(ConnectionState.Closed);
    }
Exemple #7
0
    /// <summary>
    /// Initializes the connection with the specified connection string
    /// </summary>
    /// <param name="connectionString">The connection string to use on the connection</param>
    public SqliteConnection(string connectionString)
    {
      _sql = null;
      _connectionState = ConnectionState.Closed;
      _connectionString = "";
      _transactionLevel = 0;
      _busyTimeout = 30;
      _version = 0;
      _commandList = new List<SqliteCommand>();

      if (connectionString != null)
        ConnectionString = connectionString;
    }
Exemple #8
0
    /// <summary>
    /// Called by SqliteBase derived classes, this function binds all user-defined functions to a connection.
    /// It is done this way so that all user-defined functions will access the database using the same encoding scheme
    /// as the connection (UTF-8 or UTF-16).
    /// </summary>
    /// <param name="sqlbase">The base object on which the functions are to bind</param>
    /// <returns>Returns an array of functions which the connection object should retain until the connection is closed.</returns>
    internal static SqliteFunction[] BindFunctions(SqliteBase sqlbase)
    {
      SqliteFunction f;
      List<SqliteFunction> lFunctions = new List<SqliteFunction>();

      foreach (SqliteFunctionAttribute pr in _registeredFunctions)
      {
        f = (SqliteFunction)Activator.CreateInstance(pr._instanceType);
        f._base = sqlbase;
        f._InvokeFunc = (pr.FuncType == FunctionType.Scalar) ? new SqliteCallback(f.ScalarCallback) : null;
        f._StepFunc = (pr.FuncType == FunctionType.Aggregate) ? new SqliteCallback(f.StepCallback) : null;
        f._FinalFunc = (pr.FuncType == FunctionType.Aggregate) ? new SqliteFinalCallback(f.FinalCallback) : null;
        f._CompareFunc = (pr.FuncType == FunctionType.Collation) ? new SqliteCollation(f.CompareCallback) : null;

        if (pr.FuncType != FunctionType.Collation)
          sqlbase.CreateFunction(pr.Name, pr.Arguments, f._InvokeFunc, f._StepFunc, f._FinalFunc);
        else
          sqlbase.CreateCollation(pr.Name, f._CompareFunc);
        lFunctions.Add(f);
      }

      SqliteFunction[] arFunctions = new SqliteFunction[lFunctions.Count];
      lFunctions.CopyTo(arFunctions, 0);

      return arFunctions;

    }
Exemple #9
0
    /// <summary>
    /// Disposes of any active contextData variables that were not automatically cleaned up.  Sometimes this can happen if
    /// someone closes the connection while a DataReader is open.
    /// </summary>
    public void Dispose()
    {
      Dispose(true);

      IDisposable disp;

      foreach (KeyValuePair<long, object> kv in _contextDataList)
      {
        disp = kv.Value as IDisposable;
        if (disp != null)
          disp.Dispose();
      }
      _contextDataList.Clear();

      _InvokeFunc = null;
      _StepFunc = null;
      _FinalFunc = null;
      _CompareFunc = null;
      _base = null;
      _contextDataList = null;

      GC.SuppressFinalize(this);
    }
Exemple #10
0
    /// <summary>
    /// Initializes the statement and attempts to get all information about parameters in the statement
    /// </summary>
    /// <param name="sqlbase">The base Sqlite object</param>
    /// <param name="stmt">The statement</param>
    /// <param name="strCommand">The command text for this statement</param>
    /// <param name="previous">The previous command in a multi-statement command</param>
    internal SqliteStatement(SqliteBase sqlbase, IntPtr stmt, string strCommand, SqliteStatement previous)
    {
      _sql     = sqlbase;
      _sqlite_stmt = stmt;
      _sqlStatement  = strCommand;

      // Determine parameters for this statement (if any) and prepare space for them.
      int nCmdStart = 0;
      int n = _sql.Bind_ParamCount(this);
      int x;
      string s;

      if (n > 0)
      {
        if (previous != null)
          nCmdStart = previous._unnamedParameters;

        _paramNames = new string[n];
        _paramValues = new SqliteParameter[n];

        for (x = 0; x < n; x++)
        {
          s = _sql.Bind_ParamName(this, x + 1);
          if (String.IsNullOrEmpty(s))
          {
            s = String.Format(CultureInfo.InvariantCulture, ";{0}", nCmdStart);
            nCmdStart++;
            _unnamedParameters++;
          }
          _paramNames[x] = s;
          _paramValues[x] = null;
        }
      }
    }
Exemple #11
0
    /// <summary>
    /// Disposes and finalizes the statement
    /// </summary>
    public void Dispose()
    {
      _sql.FinalizeStatement(this);

      _paramNames = null;
      _paramValues = null;
      _sql = null;
      _sqlStatement = null;

      GC.SuppressFinalize(this);
    }