/// <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> /// <remarks> /// The wrapper functions that interop with SQLite will create a unique cookie value, which internally is a pointer to /// all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks. /// </remarks> /// <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; f._CompareFunc16 = (pr.FuncType == FunctionType.Collation) ? new SqliteCollation(f.CompareCallback16) : null; if (pr.FuncType != FunctionType.Collation) { sqlbase.CreateFunction(pr.Name, pr.Arguments, (f is SqliteFunctionEx), f._InvokeFunc, f._StepFunc, f._FinalFunc); } else { sqlbase.CreateCollation(pr.Name, f._CompareFunc, f._CompareFunc16); } lFunctions.Add(f); } SqliteFunction[] arFunctions = new SqliteFunction[lFunctions.Count]; lFunctions.CopyTo(arFunctions, 0); return(arFunctions); }
internal static void Dispose(this SqliteConnectionHandle connection) { try { SqliteBase.CloseConnection(connection); } catch (SqliteException) { } }
internal static void Dispose(this SqliteStatementHandle statement) { try { SqliteBase.FinalizeStatement(statement); } catch (SqliteException) { } }
/// <summary> /// Disposes and finalizes the statement /// </summary> public void Dispose() { if (_sqlite_stmt != null) { _sqlite_stmt.Dispose(); } _sqlite_stmt = null; _paramNames = null; _paramValues = null; _sql = null; _sqlStmt = null; _paramList = null; }
/// <summary> /// Placeholder for a user-defined disposal routine /// </summary> /// <param name="disposing">True if the object is being disposed explicitly</param> protected virtual void Dispose(bool disposing) { if (disposing) { IDisposable disp; foreach (KeyValuePair <SqliteValueHandle, AggregateData> kv in _contextDataList) { disp = kv.Value._data as IDisposable; if (disp != null) { disp.Dispose(); } } _contextDataList.Clear(); _InvokeFunc = null; _StepFunc = null; _FinalFunc = null; _CompareFunc = null; _base = null; _contextDataList = null; } }
/// <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, SQLitePCL.ISQLiteStatement stmt, string strCommand, SqliteStatement previous) { _sql = sqlbase; _sqlite_stmt = stmt; this._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; } } }
/// <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> /// <remarks> /// The wrapper functions that interop with SQLite will create a unique cookie value, which internally is a pointer to /// all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks. /// </remarks> /// <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; f._CompareFunc16 = (pr.FuncType == FunctionType.Collation) ? new SqliteCollation(f.CompareCallback16) : null; if (pr.FuncType != FunctionType.Collation) sqlbase.CreateFunction(pr.Name, pr.Arguments, (f is SqliteFunctionEx), f._InvokeFunc, f._StepFunc, f._FinalFunc); else sqlbase.CreateCollation(pr.Name, f._CompareFunc, f._CompareFunc16); lFunctions.Add(f); } SqliteFunction[] arFunctions = new SqliteFunction[lFunctions.Count]; lFunctions.CopyTo(arFunctions, 0); return arFunctions; }
/// <summary> /// Placeholder for a user-defined disposal routine /// </summary> /// <param name="disposing">True if the object is being disposed explicitly</param> protected virtual void Dispose(bool disposing) { if (disposing) { IDisposable disp; foreach (KeyValuePair<SqliteValueHandle, AggregateData> kv in _contextDataList) { disp = kv.Value._data as IDisposable; if (disp != null) disp.Dispose(); } _contextDataList.Clear(); _InvokeFunc = null; _StepFunc = null; _FinalFunc = null; _CompareFunc = null; _base = null; _contextDataList = null; } }
/// <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(); //There will be no connection string, so eliminating things that depend on the values therein //Dictionary<string, string> opts = ParseConnectionString(_connectionString); //Empty list of options: Dictionary<string, string> opts = new Dictionary<string, string>(); //Shouldn't need the version //if (Convert.ToInt32(FindKey(opts, "Version", "3"), CultureInfo.InvariantCulture) != 3) { // throw new NotSupportedException("Only SQLite Version 3 is supported at this time"); //} //Shouldn't need the filename string fileName = ""; //string 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"); // } // fileName = MapUriPath(fileName); //} //if (String.Compare(fileName, ":MEMORY:", StringComparison.OrdinalIgnoreCase) == 0) { // fileName = ":memory:"; //} //else { // fileName = this.ExpandFileName(fileName); //} try { bool usePooling = SqliteConvert.ToBoolean(FindKey(opts, "Pooling", Boolean.FalseString)); bool bUTF16 = SqliteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)); int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", "100")); _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"); } var dateFormat = (SqliteDateFormats) Enum.Parse(typeof(SqliteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true); //string temp = FindKey(opts, "DateTimeFormat", "ISO8601"); //if (String.Compare(temp, "ticks", true, CultureInfo.InvariantCulture) == 0) dateFormat = SQLiteDateFormats.Ticks; //else if (String.Compare(temp, "julianday", true, CultureInfo.InvariantCulture) == 0) dateFormat = SQLiteDateFormats.JulianDay; // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16() this._sql = new SqliteConnectionWrapper(_sqliteDbConnection, dateFormat); //TODO: Make sure I don't need to do something like this: //this._sql = bUTF16 ? new SQLite3_UTF16(dateFormat) : new SQLite3(dateFormat); SqliteOpenFlagsEnum flags = SqliteOpenFlagsEnum.None; if (SqliteConvert.ToBoolean(FindKey(opts, "Read Only", Boolean.FalseString))) { flags |= SqliteOpenFlagsEnum.ReadOnly; } else { flags |= SqliteOpenFlagsEnum.ReadWrite; if (SqliteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false) { flags |= SqliteOpenFlagsEnum.Create; } } if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionComplete", Boolean.FalseString))) { flags |= SqliteOpenFlagsEnum.FileProtectionComplete; } if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionCompleteUnlessOpen", Boolean.FalseString))) { flags |= SqliteOpenFlagsEnum.FileProtectionCompleteUnlessOpen; } if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionCompleteUntilFirstUserAuthentication", Boolean.FalseString))) { flags |= SqliteOpenFlagsEnum.FileProtectionCompleteUntilFirstUserAuthentication; } if (SqliteConvert.ToBoolean(FindKey(opts, "FileProtectionNone", Boolean.FalseString))) { flags |= SqliteOpenFlagsEnum.FileProtectionNone; } _sql.Open(fileName, flags, maxPoolSize, usePooling); _binaryGuid = SqliteConvert.ToBoolean(FindKey(opts, "BinaryGUID", Boolean.TrueString)); string password = FindKey(opts, "Password", null); if (String.IsNullOrEmpty(password) == false) { _sql.SetPassword(password); } else if (_password != null) { _sql.SetPassword(_password); } _password = null; // TODO : _dataSource = Path.GetFileNameWithoutExtension(fileName); _dataSource = fileName; OnStateChange(ConnectionState.Open); _version++; 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) ? "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(); } } if (_commitHandler != null) { _sql.SetCommitHook(_commitCallback); } if (_updateHandler != null) { _sql.SetUpdateHook(_updateCallback); } if (_rollbackHandler != null) { _sql.SetRollbackHook(_rollbackCallback); } if (global::Portable.Transactions.Transaction.Current != null && SqliteConvert.ToBoolean(FindKey(opts, "Enlist", Boolean.TrueString))) EnlistTransaction(global::Portable.Transactions.Transaction.Current); } catch (SqliteException) { Close(); throw; } }
/// <summary> /// When the database connection is closed, all commands linked to this connection are automatically reset. /// </summary> public override void Close() { if (_sql != null) { 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. var cnn = new SqliteAdoConnection(_sqliteDbConnection, _cryptEngine) { _sql = this._sql, _transactionLevel = this._transactionLevel, _enlistment = this._enlistment, _connectionState = this._connectionState, _version = this._version }; cnn._enlistment._transaction._cnn = cnn; cnn._enlistment._disposeConnection = true; _sql = null; _enlistment = null; } if (_sql != null) { _sql.Dispose(); //_sql.Close(); } _sql = null; _transactionLevel = 0; } OnStateChange(ConnectionState.Closed); }
/// <summary> /// Disposes of the SqliteAdoConnection, closing it if it is active. /// </summary> public override void Dispose() { if (_sql != null) _sql.Dispose(); _sql = null; _cryptEngine = null; _sqliteDbConnection = null; base.Dispose(); Close(); }
/////<overloads> ///// Constructs a new SqliteAdoConnection object ///// </overloads> ///// <summary> ///// Default constructor ///// </summary> //public SqliteAdoConnection() // : this("") { //} ///// <summary> ///// Initializes the connection with the specified connection string ///// </summary> ///// <param name="connectionString">The connection string to use on the connection</param> //public SqliteAdoConnection(string connectionString) { // _sql = null; // _connectionState = ConnectionState.Closed; // _connectionString = ""; // _transactionLevel = 0; // _version = 0; // //_commandList = new List<WeakReference>(); // if (connectionString != null) // ConnectionString = connectionString; //} #endregion /// <summary> /// Initializes the connection with the specified SQLite connection /// </summary> /// <param name="connection">The SQLite connection to be wrap as an ADO connection</param> /// <param name="cryptEngine">The cryptographic engine to be used for encryption operations</param> public SqliteAdoConnection(SQLitePCL.ISQLiteConnection connection, IObjectCryptEngine cryptEngine) { if (connection == null) throw new ArgumentNullException("connection"); _sqliteDbConnection = connection; _cryptEngine = cryptEngine; _sql = null; _connectionState = ConnectionState.Closed; _connectionString = ""; _transactionLevel = 0; _version = 0; //_commandList = new List<WeakReference>(); }
/// <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, SQLitePCL.ISQLiteStatement stmt, string strCommand, SqliteStatement previous) { _sql = sqlbase; _sqlite_stmt = stmt; this._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; } } }