/// <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="flags">The flags associated with the parent connection 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, SQLiteConnectionFlags flags, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous) { _sql = sqlbase; _sqlite_stmt = stmt; _sqlStatement = strCommand; _flags = flags; // Determine parameters for this statement (if any) and prepare space for them. int nCmdStart = 0; int n = _sql.Bind_ParamCount(this, _flags); 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, _flags, 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> /// <param name="flags">The flags associated with the parent connection object</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, SQLiteConnectionFlags flags) { SQLiteFunction f; List <SQLiteFunction> lFunctions = new List <SQLiteFunction>(); foreach (SQLiteFunctionAttribute pr in _registeredFunctions) { f = (SQLiteFunction)Activator.CreateInstance(pr._instanceType); f._base = sqlbase; f._flags = flags; 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 SQLiteStatement(SQLiteBase sqlbase, SQLiteConnectionFlags flags, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous) { this._sql = sqlbase; this._sqlite_stmt = stmt; this._sqlStatement = strCommand; this._flags = flags; int num = 0; int num1 = this._sql.Bind_ParamCount(this, this._flags); if (num1 > 0) { if (previous != null) { num = previous._unnamedParameters; } this._paramNames = new string[num1]; this._paramValues = new SQLiteParameter[num1]; for (int i = 0; i < num1; i++) { string str = this._sql.Bind_ParamName(this, this._flags, i + 1); if (string.IsNullOrEmpty(str)) { CultureInfo invariantCulture = CultureInfo.InvariantCulture; object[] objArray = new object[] { num }; str = HelperMethods.StringFormat(invariantCulture, ";{0}", objArray); num++; this._unnamedParameters++; } this._paramNames[i] = str; this._paramValues[i] = null; } } }
internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt) { switch (_datetimeFormat) { case SQLiteDateFormats.Ticks: case SQLiteDateFormats.JulianDay: case SQLiteDateFormats.UnixEpoch: { base.Bind_DateTime(stmt, flags, index, dt); break; } default: { #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { SQLiteStatementHandle handle = (stmt != null) ? stmt._sqlite_stmt : null; LogBind(handle, index, dt); } #endif Bind_Text(stmt, flags, index, ToString(dt)); break; } } }
protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { foreach (KeyValuePair <IntPtr, SQLiteFunction.AggregateData> keyValuePair in this._contextDataList) { IDisposable value = keyValuePair.Value._data as IDisposable; if (value == null) { continue; } value.Dispose(); } this._contextDataList.Clear(); this._contextDataList = null; this._flags = SQLiteConnectionFlags.None; this._InvokeFunc = null; this._StepFunc = null; this._FinalFunc = null; this._CompareFunc = null; this._base = null; } this.disposed = true; } }
/// <summary> /// This function binds a user-defined functions to a connection. /// </summary> /// <param name="sqliteBase"> /// The <see cref="SQLiteBase" /> object instance associated with the /// <see cref="SQLiteConnection" /> that the function should be bound to. /// </param> /// <param name="functionAttribute"> /// The <see cref="SQLiteFunctionAttribute"/> object instance containing /// the metadata for the function to be bound. /// </param> /// <param name="function"> /// The <see cref="SQLiteFunction"/> object instance that implements the /// function to be bound. /// </param> /// <param name="flags"> /// The flags associated with the parent connection object. /// </param> internal static void BindFunction( SQLiteBase sqliteBase, SQLiteFunctionAttribute functionAttribute, SQLiteFunction function, SQLiteConnectionFlags flags ) { if (sqliteBase == null) { throw new ArgumentNullException("sqliteBase"); } if (functionAttribute == null) { throw new ArgumentNullException("functionAttribute"); } if (function == null) { throw new ArgumentNullException("function"); } FunctionType functionType = functionAttribute.FuncType; function._base = sqliteBase; function._flags = flags; function._InvokeFunc = (functionType == FunctionType.Scalar) ? new SQLiteCallback(function.ScalarCallback) : null; function._StepFunc = (functionType == FunctionType.Aggregate) ? new SQLiteCallback(function.StepCallback) : null; function._FinalFunc = (functionType == FunctionType.Aggregate) ? new SQLiteFinalCallback(function.FinalCallback) : null; function._CompareFunc = (functionType == FunctionType.Collation) ? new SQLiteCollation(function.CompareCallback) : null; function._CompareFunc16 = (functionType == FunctionType.Collation) ? new SQLiteCollation(function.CompareCallback16) : null; string name = functionAttribute.Name; if (functionType != FunctionType.Collation) { bool needCollSeq = (function is SQLiteFunctionEx); sqliteBase.CreateFunction( name, functionAttribute.Arguments, needCollSeq, function._InvokeFunc, function._StepFunc, function._FinalFunc); } else { sqliteBase.CreateCollation( name, function._CompareFunc, function._CompareFunc16); } }
private static void DefaultTypeNameWarning(DbType dbType, SQLiteConnectionFlags flags, string typeName) { if ((flags & SQLiteConnectionFlags.TraceWarning) == SQLiteConnectionFlags.TraceWarning) { CultureInfo currentCulture = CultureInfo.CurrentCulture; object[] objArray = new object[] { typeName, dbType }; Trace.WriteLine(HelperMethods.StringFormat(currentCulture, "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", objArray)); } }
private static void DefaultDbTypeWarning(string typeName, SQLiteConnectionFlags flags, DbType?dbType) { if (!string.IsNullOrEmpty(typeName) && (flags & SQLiteConnectionFlags.TraceWarning) == SQLiteConnectionFlags.TraceWarning) { CultureInfo currentCulture = CultureInfo.CurrentCulture; object[] objArray = new object[] { dbType, typeName }; Trace.WriteLine(HelperMethods.StringFormat(currentCulture, "WARNING: Type mapping failed, returning default type {0} for name \"{1}\".", objArray)); } }
public SQLiteConnectionLock(SQLiteConnectionHandle handle, SQLiteConnectionFlags flags, bool autoLock) { this.handle = handle; this.flags = flags; if (autoLock) { this.Lock(); } }
internal static bool UnbindAllFunctions(SQLiteBase sqlbase, SQLiteConnectionFlags flags, bool registered) { SQLiteFunction sQLiteFunction; if (sqlbase == null) { return(false); } IDictionary <SQLiteFunctionAttribute, SQLiteFunction> functions = sqlbase.Functions; if (functions == null) { return(false); } bool flag = true; if (!registered) { functions = new Dictionary <SQLiteFunctionAttribute, SQLiteFunction>(functions); foreach (KeyValuePair <SQLiteFunctionAttribute, SQLiteFunction> function in functions) { SQLiteFunctionAttribute key = function.Key; if (key == null) { continue; } SQLiteFunction value = function.Value; if (value == null || !SQLiteFunction.UnbindFunction(sqlbase, key, value, flags)) { flag = false; } else { sqlbase.Functions.Remove(key); } } } else { foreach (KeyValuePair <SQLiteFunctionAttribute, object> _registeredFunction in SQLiteFunction._registeredFunctions) { SQLiteFunctionAttribute sQLiteFunctionAttribute = _registeredFunction.Key; if (sQLiteFunctionAttribute == null || functions.TryGetValue(sQLiteFunctionAttribute, out sQLiteFunction) && sQLiteFunction != null && SQLiteFunction.UnbindFunction(sqlbase, sQLiteFunctionAttribute, sQLiteFunction, flags)) { continue; } flag = false; } } return(flag); }
internal override void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt) { SQLiteStatementHandle _sqliteStmt; switch (this._datetimeFormat) { case SQLiteDateFormats.Ticks: case SQLiteDateFormats.JulianDay: case SQLiteDateFormats.UnixEpoch: { base.Bind_DateTime(stmt, flags, index, dt); return; } case SQLiteDateFormats.ISO8601: { if (HelperMethods.LogBind(flags)) { if (stmt != null) { _sqliteStmt = stmt._sqlite_stmt; } else { _sqliteStmt = null; } SQLite3.LogBind(_sqliteStmt, index, dt); } this.Bind_Text(stmt, flags, index, base.ToString(dt)); return; } default: { if (HelperMethods.LogBind(flags)) { if (stmt != null) { _sqliteStmt = stmt._sqlite_stmt; } else { _sqliteStmt = null; } SQLite3.LogBind(_sqliteStmt, index, dt); } this.Bind_Text(stmt, flags, index, base.ToString(dt)); return; } } }
internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool) { if (_sql != null) { return; } _usePool = usePool; _fileName = strFilename; if (usePool) { _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion); #if DEBUG && !NET_COMPACT_20 Trace.WriteLine(String.Format("Open (Pool): {0}", (_sql != null) ? _sql.ToString() : "<null>")); #endif } if (_sql == null) { IntPtr db; #if !SQLITE_STANDARD int n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), (int)openFlags, out db); #else if ((openFlags & SQLiteOpenFlagsEnum.Create) == 0 && System.IO.File.Exists(strFilename) == false) { throw new SQLiteException((int)SQLiteErrorCode.CantOpen, strFilename); } int n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db); #endif #if DEBUG && !NET_COMPACT_20 Trace.WriteLine(String.Format("Open: {0}", db)); #endif if (n > 0) { throw new SQLiteException(n, null); } _sql = new SQLiteConnectionHandle(db); lock (_sql) { /* HACK: Force the SyncBlock to be "created" now. */ } } _functionsArray = SQLiteFunction.BindFunctions(this, connectionFlags); SetTimeout(0); GC.KeepAlive(_sql); }
internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value) { SQLiteStatementHandle _sqliteStmt = stmt._sqlite_stmt; if (HelperMethods.LogBind(flags)) { SQLite3.LogBind(_sqliteStmt, index, value); } SQLiteErrorCode sQLiteErrorCode = UnsafeNativeMethods.sqlite3_bind_text16(_sqliteStmt, index, value, value.Length * 2, (IntPtr)(-1)); if (sQLiteErrorCode != SQLiteErrorCode.Ok) { throw new SQLiteException(sQLiteErrorCode, this.GetLastError()); } }
internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1)); if (n != SQLiteErrorCode.Ok) { throw new SQLiteException(n, GetLastError()); } }
private void InvokeBindValueCallback(int index, SQLiteParameter parameter, out bool complete) { SQLiteTypeCallbacks sQLiteTypeCallback; complete = false; SQLiteConnectionFlags sQLiteConnectionFlag = this._flags; SQLiteStatement sQLiteStatement = this; sQLiteStatement._flags = sQLiteStatement._flags & (SQLiteConnectionFlags.LogPrepare | SQLiteConnectionFlags.LogPreBind | SQLiteConnectionFlags.LogBind | SQLiteConnectionFlags.LogCallbackException | SQLiteConnectionFlags.LogBackup | SQLiteConnectionFlags.NoExtensionFunctions | SQLiteConnectionFlags.BindUInt32AsInt64 | SQLiteConnectionFlags.BindAllAsText | SQLiteConnectionFlags.GetAllAsText | SQLiteConnectionFlags.NoLoadExtension | SQLiteConnectionFlags.NoCreateModule | SQLiteConnectionFlags.NoBindFunctions | SQLiteConnectionFlags.NoLogModule | SQLiteConnectionFlags.LogModuleError | SQLiteConnectionFlags.LogModuleException | SQLiteConnectionFlags.TraceWarning | SQLiteConnectionFlags.ConvertInvariantText | SQLiteConnectionFlags.BindInvariantText | SQLiteConnectionFlags.NoConnectionPool | SQLiteConnectionFlags.UseConnectionPool | SQLiteConnectionFlags.UseConnectionTypes | SQLiteConnectionFlags.NoGlobalTypes | SQLiteConnectionFlags.StickyHasRows | SQLiteConnectionFlags.StrictEnlistment | SQLiteConnectionFlags.MapIsolationLevels | SQLiteConnectionFlags.DetectTextAffinity | SQLiteConnectionFlags.DetectStringType | SQLiteConnectionFlags.NoConvertSettings | SQLiteConnectionFlags.BindDateTimeWithKind | SQLiteConnectionFlags.RollbackOnException | SQLiteConnectionFlags.DenyOnException | SQLiteConnectionFlags.InterruptOnException | SQLiteConnectionFlags.UnbindFunctionsOnClose | SQLiteConnectionFlags.NoVerifyTextAffinity | SQLiteConnectionFlags.UseConnectionReadValueCallbacks | SQLiteConnectionFlags.UseParameterNameForTypeName | SQLiteConnectionFlags.UseParameterDbTypeForTypeName | SQLiteConnectionFlags.NoVerifyTypeAffinity | SQLiteConnectionFlags.AllowNestedTransactions | SQLiteConnectionFlags.BindDecimalAsText | SQLiteConnectionFlags.GetDecimalAsText | SQLiteConnectionFlags.BindInvariantDecimal | SQLiteConnectionFlags.GetInvariantDecimal | SQLiteConnectionFlags.BindAndGetAllAsText | SQLiteConnectionFlags.ConvertAndBindInvariantText | SQLiteConnectionFlags.BindAndGetAllAsInvariantText | SQLiteConnectionFlags.ConvertAndBindAndGetAllAsInvariantText | SQLiteConnectionFlags.UseParameterAnythingForTypeName | SQLiteConnectionFlags.LogAll | SQLiteConnectionFlags.LogDefault | SQLiteConnectionFlags.Default | SQLiteConnectionFlags.DefaultAndLogAll); try { if (parameter != null) { SQLiteConnection connection = SQLiteStatement.GetConnection(this); if (connection != null) { string typeName = parameter.TypeName; if (typeName == null && (this._flags & SQLiteConnectionFlags.UseParameterNameForTypeName) == SQLiteConnectionFlags.UseParameterNameForTypeName) { typeName = parameter.ParameterName; } if (typeName == null && (this._flags & SQLiteConnectionFlags.UseParameterDbTypeForTypeName) == SQLiteConnectionFlags.UseParameterDbTypeForTypeName) { typeName = SQLiteConvert.DbTypeToTypeName(connection, parameter.DbType, this._flags); } if (typeName != null) { if (connection.TryGetTypeCallbacks(typeName, out sQLiteTypeCallback) && sQLiteTypeCallback != null) { SQLiteBindValueCallback bindValueCallback = sQLiteTypeCallback.BindValueCallback; if (bindValueCallback != null) { object bindValueUserData = sQLiteTypeCallback.BindValueUserData; bindValueCallback(this._sql, this._command, sQLiteConnectionFlag, parameter, typeName, index, bindValueUserData, out complete); } } } } } } finally { this._flags |= SQLiteConnectionFlags.UseConnectionBindValueCallbacks; } }
internal static TypeAffinity TypeToAffinity(Type typ, SQLiteConnectionFlags flags) { TypeCode typeCode = Type.GetTypeCode(typ); if (typeCode == TypeCode.Object) { if (typ != typeof(byte[]) && typ != typeof(Guid)) { return(TypeAffinity.Text); } return(TypeAffinity.Blob); } if (typeCode == TypeCode.Decimal && (flags & SQLiteConnectionFlags.GetDecimalAsText) == SQLiteConnectionFlags.GetDecimalAsText) { return(TypeAffinity.Text); } return(SQLiteConvert._typecodeAffinities[(int)typeCode]); }
internal override void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool) { if (_sql != null) { return; } _usePool = usePool; if (usePool) { _fileName = strFilename; _sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out _poolVersion); } if (_sql == null) { IntPtr db; #if !SQLITE_STANDARD int n = UnsafeNativeMethods.sqlite3_open16_interop(ToUTF8(strFilename), (int)openFlags, out db); #else if ((openFlags & SQLiteOpenFlagsEnum.Create) == 0 && System.IO.File.Exists(strFilename) == false) { throw new SQLiteException((int)SQLiteErrorCode.CantOpen, strFilename); } int n = UnsafeNativeMethods.sqlite3_open16(strFilename, out db); #endif #if DEBUG && !NET_COMPACT_20 Trace.WriteLine(String.Format("Open: {0}", db)); #endif if (n > 0) { throw new SQLiteException(n, null); } _sql = db; } _functionsArray = SQLiteFunction.BindFunctions(this, connectionFlags); }
/// <summary> /// Turn a datatable into a table in the temporary database for the connection /// </summary> /// <param name="cnn">The connection to make the temporary table in</param> /// <param name="table">The table to write out</param> /// <param name="dest">The temporary table name to write to</param> private void DataTableToTable(SQLiteConnection cnn, DataTable table, string dest) { StringBuilder sql = new StringBuilder(); SQLiteCommandBuilder builder = new SQLiteCommandBuilder(); using (SQLiteCommand cmd = cnn.CreateCommand()) using (DataTable source = new DataTable()) { sql.AppendFormat(CultureInfo.InvariantCulture, "CREATE TEMP TABLE {0} (", builder.QuoteIdentifier(dest)); string separator = String.Empty; SQLiteConnectionFlags flags = cnn.Flags; foreach (DataColumn dc in table.Columns) { DbType dbtypeName = SQLiteConvert.TypeToDbType(dc.DataType); string typeName = SQLiteConvert.DbTypeToTypeName(cnn, dbtypeName, flags); sql.AppendFormat(CultureInfo.InvariantCulture, "{2}{0} {1} COLLATE NOCASE", builder.QuoteIdentifier(dc.ColumnName), typeName, separator); separator = ", "; } sql.Append(")"); cmd.CommandText = sql.ToString(); cmd.ExecuteNonQuery(); cmd.CommandText = String.Format("SELECT * FROM TEMP.{0} WHERE 1=2", builder.QuoteIdentifier(dest)); using (SQLiteDataAdapter adp = new SQLiteDataAdapter(cmd)) { builder.DataAdapter = adp; adp.Fill(source); foreach (DataRow row in table.Rows) { object[] arr = row.ItemArray; source.Rows.Add(arr); } adp.Update(source); } } }
/////////////////////////////////////////////////////////////////////////////////////////////// /// <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 (!disposed) { if (disposing) { //////////////////////////////////// // dispose managed resources here... //////////////////////////////////// IDisposable disp; foreach (KeyValuePair <IntPtr, AggregateData> kv in _contextDataList) { disp = kv.Value._data as IDisposable; if (disp != null) { disp.Dispose(); } } _contextDataList.Clear(); _contextDataList = null; _flags = SQLiteConnectionFlags.None; _InvokeFunc = null; _StepFunc = null; _FinalFunc = null; _CompareFunc = null; _base = null; } ////////////////////////////////////// // release unmanaged resources here... ////////////////////////////////////// disposed = true; } }
public static SQLiteStreamChangeSetIterator Create(Stream stream, SQLiteConnectionFlags flags) { if (stream == null) { throw new ArgumentNullException("stream"); } SQLiteStreamAdapter sQLiteStreamAdapter = null; SQLiteStreamChangeSetIterator sQLiteStreamChangeSetIterator = null; IntPtr zero = IntPtr.Zero; try { sQLiteStreamAdapter = new SQLiteStreamAdapter(stream, flags); SQLiteErrorCode sQLiteErrorCode = UnsafeNativeMethods.sqlite3changeset_start_strm(ref zero, sQLiteStreamAdapter.GetInputDelegate(), IntPtr.Zero); if (sQLiteErrorCode != SQLiteErrorCode.Ok) { throw new SQLiteException(sQLiteErrorCode, "sqlite3changeset_start_strm"); } sQLiteStreamChangeSetIterator = new SQLiteStreamChangeSetIterator(sQLiteStreamAdapter, zero, true); } finally { if (sQLiteStreamChangeSetIterator == null) { if (zero != IntPtr.Zero) { UnsafeNativeMethods.sqlite3changeset_finalize(zero); zero = IntPtr.Zero; } if (sQLiteStreamAdapter != null) { sQLiteStreamAdapter.Dispose(); sQLiteStreamAdapter = null; } } } return(sQLiteStreamChangeSetIterator); }
/// <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="flags">The flags associated with the parent connection 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, SQLiteConnectionFlags flags, SQLiteStatementHandle stmt, string strCommand, SQLiteStatement previous) { _sql = sqlbase; _sqlite_stmt = stmt; _sqlStatement = strCommand; _flags = flags; // Determine parameters for this statement (if any) and prepare space for them. int nCmdStart = 0; int n = _sql.Bind_ParamCount(this, _flags); 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, _flags, x + 1); if (String.IsNullOrEmpty(s)) { s = HelperMethods.StringFormat(CultureInfo.InvariantCulture, ";{0}", nCmdStart); nCmdStart++; _unnamedParameters++; } _paramNames[x] = s; _paramValues[x] = null; } } }
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(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; _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(UnsafeNativeMethods.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 = ((connectionFlags & SQLiteConnectionFlags.NoExtensionFunctions) != SQLiteConnectionFlags.NoExtensionFunctions) ? 1 : 0; #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, UnsafeNativeMethods.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(UnsafeNativeMethods.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 ((connectionFlags & SQLiteConnectionFlags.NoBindFunctions) != 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> /// This function binds a user-defined functions to the connection. /// </summary> /// <param name="functionAttribute"> /// The <see cref="SQLiteFunctionAttribute"/> object instance containing /// the metadata for the function to be bound. /// </param> /// <param name="function"> /// The <see cref="SQLiteFunction"/> object instance that implements the /// function to be bound. /// </param> /// <param name="flags"> /// The flags associated with the parent connection object. /// </param> internal abstract void BindFunction(SQLiteFunctionAttribute functionAttribute, SQLiteFunction function, SQLiteConnectionFlags flags);
internal abstract int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName);
internal abstract void Bind_DateTime(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, DateTime dt);
internal abstract int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags);
/// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString" />. /// </summary> public override void Open() { CheckDisposed(); OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.Opening, null, null, null, null, null)); if (_connectionState != ConnectionState.Closed) throw new InvalidOperationException(); Close(); SortedList<string, string> opts = ParseConnectionString( _connectionString, _parseViaFramework); OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.ConnectionString, null, null, null, _connectionString, opts)); object enumValue; enumValue = TryParseEnum(typeof(SQLiteConnectionFlags), FindKey(opts, "Flags", DefaultFlags.ToString()), true); _flags = (enumValue is SQLiteConnectionFlags) ? (SQLiteConnectionFlags)enumValue : DefaultFlags; bool fullUri = false; string fileName; if (Convert.ToInt32(FindKey(opts, "Version", DefaultVersion.ToString()), CultureInfo.InvariantCulture) != DefaultVersion) throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, "Only SQLite Version {0} is supported at this time", DefaultVersion)); fileName = FindKey(opts, "Data Source", DefaultDataSource); if (String.IsNullOrEmpty(fileName)) { fileName = FindKey(opts, "Uri", DefaultUri); if (String.IsNullOrEmpty(fileName)) { fileName = FindKey(opts, "FullUri", DefaultFullUri); if (String.IsNullOrEmpty(fileName)) throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Data Source cannot be empty. Use {0} to open an in-memory database", MemoryFileName)); else fullUri = true; } else fileName = MapUriPath(fileName); } bool isMemory = (String.Compare(fileName, MemoryFileName, StringComparison.OrdinalIgnoreCase) == 0); if (!fullUri) { if (isMemory) fileName = MemoryFileName; else { #if PLATFORM_COMPACTFRAMEWORK if (fileName.StartsWith("./") || fileName.StartsWith(".\\")) fileName = Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1); #endif bool toFullPath = SQLiteConvert.ToBoolean(FindKey(opts, "ToFullPath", DefaultToFullPath.ToString())); fileName = ExpandFileName(fileName, toFullPath); } } try { bool usePooling = SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", DefaultPooling.ToString())); int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", DefaultMaxPoolSize.ToString()), CultureInfo.InvariantCulture); _defaultTimeout = Convert.ToInt32(FindKey(opts, "Default Timeout", DefaultConnectionTimeout.ToString()), CultureInfo.InvariantCulture); enumValue = TryParseEnum(typeof(IsolationLevel), FindKey(opts, "Default IsolationLevel", DefaultIsolationLevel.ToString()), true); _defaultIsolation = (enumValue is IsolationLevel) ? (IsolationLevel)enumValue : DefaultIsolationLevel; if (_defaultIsolation != IsolationLevel.Serializable && _defaultIsolation != IsolationLevel.ReadCommitted) throw new NotSupportedException("Invalid Default IsolationLevel specified"); _baseSchemaName = FindKey(opts, "BaseSchemaName", DefaultBaseSchemaName); if (_sql == null) { SetupSQLiteBase(opts); } SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None; if (!SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", DefaultFailIfMissing.ToString()))) flags |= SQLiteOpenFlagsEnum.Create; if (SQLiteConvert.ToBoolean(FindKey(opts, "Read Only", DefaultReadOnly.ToString()))) { flags |= SQLiteOpenFlagsEnum.ReadOnly; // SQLite will return SQLITE_MISUSE on ReadOnly and Create flags &= ~SQLiteOpenFlagsEnum.Create; } else { flags |= SQLiteOpenFlagsEnum.ReadWrite; } if (fullUri) flags |= SQLiteOpenFlagsEnum.Uri; _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling); _binaryGuid = SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", DefaultBinaryGUID.ToString())); #if INTEROP_CODEC string hexPassword = FindKey(opts, "HexPassword", DefaultHexPassword); if (!String.IsNullOrEmpty(hexPassword)) { string error = null; byte[] hexPasswordBytes = FromHexString(hexPassword, ref error); if (hexPasswordBytes == null) { throw new FormatException(String.Format( CultureInfo.CurrentCulture, "Cannot parse 'HexPassword' property value into byte values: {0}", error)); } _sql.SetPassword(hexPasswordBytes); } else { string password = FindKey(opts, "Password", DefaultPassword); if (!String.IsNullOrEmpty(password)) _sql.SetPassword(UTF8Encoding.UTF8.GetBytes(password)); else if (_password != null) _sql.SetPassword(_password); } _password = null; #endif if (!fullUri) _dataSource = Path.GetFileNameWithoutExtension(fileName); else _dataSource = fileName; _version++; ConnectionState oldstate = _connectionState; _connectionState = ConnectionState.Open; try { string strValue; bool boolValue; strValue = FindKey(opts, "SetDefaults", DefaultSetDefaults.ToString()); boolValue = SQLiteConvert.ToBoolean(strValue); if (boolValue) { using (SQLiteCommand cmd = CreateCommand()) { int intValue; if (!fullUri && !isMemory) { strValue = FindKey(opts, "Page Size", DefaultPageSize.ToString()); intValue = Convert.ToInt32(strValue, CultureInfo.InvariantCulture); if (intValue != DefaultPageSize) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA page_size={0}", intValue); cmd.ExecuteNonQuery(); } } strValue = FindKey(opts, "Max Page Count", DefaultMaxPageCount.ToString()); intValue = Convert.ToInt32(strValue, CultureInfo.InvariantCulture); if (intValue != DefaultMaxPageCount) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA max_page_count={0}", intValue); cmd.ExecuteNonQuery(); } strValue = FindKey(opts, "Legacy Format", DefaultLegacyFormat.ToString()); boolValue = SQLiteConvert.ToBoolean(strValue); if (boolValue != DefaultLegacyFormat) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA legacy_file_format={0}", boolValue ? "ON" : "OFF"); cmd.ExecuteNonQuery(); } strValue = FindKey(opts, "Synchronous", DefaultSynchronous.ToString()); enumValue = TryParseEnum(typeof(SQLiteSynchronousEnum), strValue, true); if (!(enumValue is SQLiteSynchronousEnum) || ((SQLiteSynchronousEnum)enumValue != DefaultSynchronous)) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA synchronous={0}", strValue); cmd.ExecuteNonQuery(); } strValue = FindKey(opts, "Cache Size", DefaultCacheSize.ToString()); intValue = Convert.ToInt32(strValue, CultureInfo.InvariantCulture); if (intValue != DefaultCacheSize) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA cache_size={0}", intValue); cmd.ExecuteNonQuery(); } strValue = FindKey(opts, "Journal Mode", DefaultJournalMode.ToString()); enumValue = TryParseEnum(typeof(SQLiteJournalModeEnum), strValue, true); if (!(enumValue is SQLiteJournalModeEnum) || ((SQLiteJournalModeEnum)enumValue != DefaultJournalMode)) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA journal_mode={0}", strValue); cmd.ExecuteNonQuery(); } strValue = FindKey(opts, "Foreign Keys", DefaultForeignKeys.ToString()); boolValue = Convert.ToBoolean(strValue, CultureInfo.InvariantCulture); if (boolValue != DefaultForeignKeys) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA foreign_keys={0}", boolValue ? "ON" : "OFF"); cmd.ExecuteNonQuery(); } } } if (_commitHandler != null) _sql.SetCommitHook(_commitCallback); if (_updateHandler != null) _sql.SetUpdateHook(_updateCallback); if (_rollbackHandler != null) _sql.SetRollbackHook(_rollbackCallback); #if !PLATFORM_COMPACTFRAMEWORK System.Transactions.Transaction transaction = Transactions.Transaction.Current; if (transaction != null && SQLiteConvert.ToBoolean(FindKey(opts, "Enlist", DefaultEnlist.ToString()))) { EnlistTransaction(transaction); } #endif _connectionState = oldstate; StateChangeEventArgs eventArgs = null; OnStateChange(ConnectionState.Open, ref eventArgs); OnChanged(this, new ConnectionEventArgs( SQLiteConnectionEventType.Opened, eventArgs, null, null, null, null)); } catch { _connectionState = oldstate; throw; } } catch (SQLiteException) { Close(); throw; } }
/// <summary> /// Initializes the connection with the specified connection string. /// </summary> /// <param name="connectionString"> /// The connection string to use. /// </param> /// <param name="parseViaFramework"> /// Non-zero to parse the connection string using the built-in (i.e. /// framework provided) parser when opening the connection. /// </param> public SQLiteConnection(string connectionString, bool parseViaFramework) { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if !INTEROP_LOG SQLiteLog.Initialize(); #endif #if !PLATFORM_COMPACTFRAMEWORK && !INTEROP_LEGACY_CLOSE && SQLITE_STANDARD // // NOTE: Check if the sqlite3_close_v2() native API should be available // to use. This must be done dynamically because the delegate set // here is used by the SQLiteConnectionHandle class, which is a // CriticalHandle derived class (i.e. protected by a constrained // execution region). Therefore, if the underlying native entry // point is unavailable, an exception will be raised even if it is // never actually called (i.e. because the runtime eagerly prepares // all the methods in the call graph of the constrained execution // region). // lock (_syncRoot) { if (_versionNumber == 0) { _versionNumber = SQLite3.SQLiteVersionNumber; if (_versionNumber >= 3007014) SQLiteConnectionHandle.closeConnection = SQLiteBase.CloseConnectionV2; } } #endif #if INTEROP_LOG if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok) { UnsafeNativeMethods.sqlite3_log( SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized.")); } #endif _parseViaFramework = parseViaFramework; _flags = SQLiteConnectionFlags.Default; _connectionState = ConnectionState.Closed; _connectionString = null; if (connectionString != null) ConnectionString = connectionString; }
internal override void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value) { SQLiteStatementHandle handle = stmt._sqlite_stmt; #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { LogBind(handle, index, value); } #endif SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_bind_text16(handle, index, value, value.Length * 2, (IntPtr)(-1)); if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError()); }
internal override int Bind_ParamCount(SQLiteStatement stmt, SQLiteConnectionFlags flags) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int value = UnsafeNativeMethods.sqlite3_bind_parameter_count(handle); #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { //IntPtr handleIntPtr = handle; //SQLiteLog.LogMessage(0, String.Format( // "Statement {0} paramter count is {1}.", // handleIntPtr, value)); } #endif return value; }
/// <summary> /// This function binds a user-defined functions to a connection. /// </summary> /// <param name="sqliteBase"> /// The <see cref="SQLiteBase" /> object instance associated with the /// <see cref="SQLiteConnection" /> that the function should be bound to. /// </param> /// <param name="functionAttribute"> /// The <see cref="SQLiteFunctionAttribute"/> object instance containing /// the metadata for the function to be bound. /// </param> /// <param name="function"> /// The <see cref="SQLiteFunction"/> object instance that implements the /// function to be bound. /// </param> /// <param name="flags"> /// The flags associated with the parent connection object. /// </param> internal static void BindFunction( SQLiteBase sqliteBase, SQLiteFunctionAttribute functionAttribute, SQLiteFunction function, SQLiteConnectionFlags flags ) { if (sqliteBase == null) throw new ArgumentNullException("sqliteBase"); if (functionAttribute == null) throw new ArgumentNullException("functionAttribute"); if (function == null) throw new ArgumentNullException("function"); FunctionType functionType = functionAttribute.FuncType; function._base = sqliteBase; function._flags = flags; function._InvokeFunc = (functionType == FunctionType.Scalar) ? new SQLiteCallback(function.ScalarCallback) : null; function._StepFunc = (functionType == FunctionType.Aggregate) ? new SQLiteCallback(function.StepCallback) : null; function._FinalFunc = (functionType == FunctionType.Aggregate) ? new SQLiteFinalCallback(function.FinalCallback) : null; function._CompareFunc = (functionType == FunctionType.Collation) ? new SQLiteCollation(function.CompareCallback) : null; function._CompareFunc16 = (functionType == FunctionType.Collation) ? new SQLiteCollation(function.CompareCallback16) : null; string name = functionAttribute.Name; if (functionType != FunctionType.Collation) { bool needCollSeq = (function is SQLiteFunctionEx); sqliteBase.CreateFunction( name, functionAttribute.Arguments, needCollSeq, function._InvokeFunc, function._StepFunc, function._FinalFunc); } else { sqliteBase.CreateCollation( name, function._CompareFunc, function._CompareFunc16); } }
/// <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> /// <param name="flags">The flags associated with the parent connection object</param> /// <returns>Returns a logical list of functions which the connection should retain until it is closed.</returns> internal static IEnumerable<SQLiteFunction> BindFunctions(SQLiteBase sqlbase, SQLiteConnectionFlags flags) { List<SQLiteFunction> lFunctions = new List<SQLiteFunction>(); foreach (SQLiteFunctionAttribute pr in _registeredFunctions) { SQLiteFunction f = (SQLiteFunction)Activator.CreateInstance(pr.InstanceType); BindFunction(sqlbase, pr, f, flags); lFunctions.Add(f); } return lFunctions; }
internal override string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index) { SQLiteStatementHandle handle = stmt._sqlite_stmt; string name; #if !SQLITE_STANDARD int len; name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name_interop(handle, index, out len), len); #else name = UTF8ToString(UnsafeNativeMethods.sqlite3_bind_parameter_name(handle, index), -1); #endif #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { //IntPtr handleIntPtr = handle; //SQLiteLog.LogMessage(0, String.Format( // "Statement {0} paramter #{1} name is {{{2}}}.", // handleIntPtr, index, name)); } #endif return name; }
/// <summary> /// Calls the native SQLite core library in order to cleanup the resources /// associated with a module containing the implementation of a virtual table. /// </summary> /// <param name="module"> /// The module object previously passed to the <see cref="CreateModule" /> /// method. /// </param> /// <param name="flags"> /// The flags for the associated <see cref="SQLiteConnection" /> object instance. /// </param> internal abstract void DisposeModule(SQLiteModule module, SQLiteConnectionFlags flags);
/// <summary> /// Opens a database. /// </summary> /// <remarks> /// Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection /// to bind all attributed user-defined functions and collating sequences to the new connection. /// </remarks> /// <param name="strFilename">The filename of the database to open. SQLite automatically creates it if it doesn't exist.</param> /// <param name="connectionFlags">The flags associated with the parent connection object</param> /// <param name="openFlags">The open flags to use when creating the connection</param> /// <param name="maxPoolSize">The maximum size of the pool for the given filename</param> /// <param name="usePool">If true, the connection can be pulled from the connection pool</param> internal abstract void Open(string strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, int maxPoolSize, bool usePool);
internal abstract object GetValue(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, SQLiteType typ);
/// <summary> /// Initializes the connection with a pre-existing native connection handle. /// </summary> /// <param name="db"> /// The native connection handle to use. /// </param> /// <param name="fileName"> /// The file name corresponding to the native connection handle. /// </param> /// <param name="ownHandle"> /// Non-zero if this instance owns the native connection handle and /// should dispose of it when it is no longer needed. /// </param> internal SQLiteConnection(IntPtr db, string fileName, bool ownHandle) : this() { _sql = new SQLite3( SQLiteDateFormats.Default, DateTimeKind.Unspecified, null, db, fileName, ownHandle); _flags = SQLiteConnectionFlags.None; _connectionState = (db != IntPtr.Zero) ? ConnectionState.Open : ConnectionState.Closed; _connectionString = null; /* unknown */ }
internal abstract void Bind_Double(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, double value);
internal abstract void Bind_Blob(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, byte[] blobData);
/// <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) { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if !PLATFORM_COMPACTFRAMEWORK SQLiteLog.Initialize(); #endif _flags = SQLiteConnectionFlags.Default; _connectionState = ConnectionState.Closed; _connectionString = ""; //_commandList = new List<WeakReference>(); if (connectionString != null) ConnectionString = connectionString; }
internal abstract void Bind_Null(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index);
/////////////////////////////////////////////////////////////////////////////////////////////// /// <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 (!disposed) { if (disposing) { //////////////////////////////////// // dispose managed resources here... //////////////////////////////////// IDisposable disp; foreach (KeyValuePair<IntPtr, AggregateData> kv in _contextDataList) { disp = kv.Value._data as IDisposable; if (disp != null) disp.Dispose(); } _contextDataList.Clear(); _contextDataList = null; _flags = SQLiteConnectionFlags.None; _InvokeFunc = null; _StepFunc = null; _FinalFunc = null; _CompareFunc = null; _base = null; } ////////////////////////////////////// // release unmanaged resources here... ////////////////////////////////////// disposed = true; } }
internal abstract string Bind_ParamName(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index);
internal SQLiteChangeSetBase(SQLiteConnectionHandle handle, SQLiteConnectionFlags flags) : base(handle, flags, true) { }
/// <summary> /// Invokes the parameter binding callback configured for the database /// type name associated with the specified column. If no parameter /// binding callback is available for the database type name, do /// nothing. /// </summary> /// <param name="index"> /// The index of the column being read. /// </param> /// <param name="parameter"> /// The <see cref="SQLiteParameter" /> instance being bound to the /// command. /// </param> /// <param name="complete"> /// Non-zero if the default handling for the parameter binding call /// should be skipped (i.e. the parameter should not be bound at all). /// Great care should be used when setting this to non-zero. /// </param> private void InvokeBindValueCallback( int index, SQLiteParameter parameter, out bool complete ) { complete = false; SQLiteConnectionFlags oldFlags = _flags; _flags &= ~SQLiteConnectionFlags.UseConnectionBindValueCallbacks; try { if (parameter == null) { return; } SQLiteConnection connection = GetConnection(this); if (connection == null) { return; } // // NOTE: First, always look for an explicitly set database type // name. // string typeName = parameter.TypeName; if (typeName == null) { // // NOTE: Are we allowed to fallback to using the parameter name // as the basis for looking up the binding callback? // if (HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.UseParameterNameForTypeName)) { typeName = parameter.ParameterName; } } if (typeName == null) { // // NOTE: Are we allowed to fallback to using the database type // name translated from the DbType as the basis for looking // up the binding callback? // if (HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.UseParameterDbTypeForTypeName)) { typeName = SQLiteConvert.DbTypeToTypeName( connection, parameter.DbType, _flags); } } if (typeName == null) { return; } SQLiteTypeCallbacks callbacks; if (!connection.TryGetTypeCallbacks(typeName, out callbacks) || (callbacks == null)) { return; } SQLiteBindValueCallback callback = callbacks.BindValueCallback; if (callback == null) { return; } object userData = callbacks.BindValueUserData; callback( _sql, _command, oldFlags, parameter, typeName, index, userData, out complete); /* throw */ } finally { _flags |= SQLiteConnectionFlags.UseConnectionBindValueCallbacks; } }
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); }
internal abstract void Bind_Int32(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, Int32 value);
internal override int Bind_ParamIndex(SQLiteStatement stmt, SQLiteConnectionFlags flags, string paramName) { SQLiteStatementHandle handle = stmt._sqlite_stmt; int index = UnsafeNativeMethods.sqlite3_bind_parameter_index(handle, ToUTF8(paramName)); #if !PLATFORM_COMPACTFRAMEWORK if ((flags & SQLiteConnectionFlags.LogBind) == SQLiteConnectionFlags.LogBind) { //IntPtr handleIntPtr = handle; //SQLiteLog.LogMessage(0, String.Format( // "Statement {0} paramter index of name {{{1}}} is #{2}.", // handleIntPtr, paramName, index)); } #endif return index; }
/// <summary> /// Opens the connection using the parameters found in the <see cref="ConnectionString">ConnectionString</see> /// </summary> public override void Open() { CheckDisposed(); if (_connectionState != ConnectionState.Closed) throw new InvalidOperationException(); Close(); SortedList<string, string> opts = ParseConnectionString(_connectionString); _flags = (SQLiteConnectionFlags)Enum.Parse(typeof(SQLiteConnectionFlags), FindKey(opts, "Flags", "Default"), true); 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)) { fileName = FindKey(opts, "Uri", ""); if (String.IsNullOrEmpty(fileName)) throw new ArgumentException("Data Source cannot be empty. Use :memory: to open an in-memory database"); else fileName = MapUriPath(fileName); } if (String.Compare(fileName, ":MEMORY:", StringComparison.OrdinalIgnoreCase) == 0) fileName = ":memory:"; else { #if PLATFORM_COMPACTFRAMEWORK if (fileName.StartsWith("./") || fileName.StartsWith(".\\")) fileName = Path.GetDirectoryName(System.Reflection.Assembly.GetCallingAssembly().GetName().CodeBase) + fileName.Substring(1); #endif fileName = ExpandFileName(fileName); } try { bool usePooling = (SQLiteConvert.ToBoolean(FindKey(opts, "Pooling", Boolean.FalseString)) == true); int maxPoolSize = Convert.ToInt32(FindKey(opts, "Max Pool Size", "100"), CultureInfo.InvariantCulture); _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"); _baseSchemaName = FindKey(opts, "BaseSchemaName", DefaultBaseSchemaName); //string temp = FindKey(opts, "DateTimeFormat", "ISO8601"); //if (String.Compare(temp, "ticks", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.Ticks; //else if (String.Compare(temp, "julianday", StringComparison.OrdinalIgnoreCase) == 0) dateFormat = SQLiteDateFormats.JulianDay; if (_sql == null) { bool bUTF16 = (SQLiteConvert.ToBoolean(FindKey(opts, "UseUTF16Encoding", Boolean.FalseString)) == true); SQLiteDateFormats dateFormat = (SQLiteDateFormats)Enum.Parse(typeof(SQLiteDateFormats), FindKey(opts, "DateTimeFormat", "ISO8601"), true); DateTimeKind kind = (DateTimeKind)Enum.Parse(typeof(DateTimeKind), FindKey(opts, "DateTimeKind", "Unspecified"), true); if (bUTF16) // SQLite automatically sets the encoding of the database to UTF16 if called from sqlite3_open16() _sql = new SQLite3_UTF16(dateFormat, kind); else _sql = new SQLite3(dateFormat, kind); } SQLiteOpenFlagsEnum flags = SQLiteOpenFlagsEnum.None; if (SQLiteConvert.ToBoolean(FindKey(opts, "FailIfMissing", Boolean.FalseString)) == false) flags |= SQLiteOpenFlagsEnum.Create; if (SQLiteConvert.ToBoolean(FindKey(opts, "Read Only", Boolean.FalseString)) == true) { flags |= SQLiteOpenFlagsEnum.ReadOnly; // SQLite will return SQLITE_MISUSE on ReadOnly and Create flags &= ~SQLiteOpenFlagsEnum.Create; } else { flags |= SQLiteOpenFlagsEnum.ReadWrite; } _sql.Open(fileName, _flags, flags, maxPoolSize, usePooling); _binaryGuid = (SQLiteConvert.ToBoolean(FindKey(opts, "BinaryGUID", Boolean.TrueString)) == true); 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; _dataSource = Path.GetFileNameWithoutExtension(fileName); _version++; ConnectionState oldstate = _connectionState; _connectionState = ConnectionState.Open; try { 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) == true ? "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", "Default"); if (String.Compare(defValue, "Default", StringComparison.OrdinalIgnoreCase) != 0) { cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA journal_mode={0}", defValue); cmd.ExecuteNonQuery(); } defValue = FindKey(opts, "Foreign Keys", Boolean.FalseString); cmd.CommandText = String.Format(CultureInfo.InvariantCulture, "PRAGMA foreign_keys={0}", SQLiteConvert.ToBoolean(defValue) == true ? "ON" : "OFF"); cmd.ExecuteNonQuery(); } if (_commitHandler != null) _sql.SetCommitHook(_commitCallback); if (_updateHandler != null) _sql.SetUpdateHook(_updateCallback); if (_rollbackHandler != null) _sql.SetRollbackHook(_rollbackCallback); #if !PLATFORM_COMPACTFRAMEWORK if (Transactions.Transaction.Current != null && SQLiteConvert.ToBoolean(FindKey(opts, "Enlist", Boolean.TrueString)) == true) EnlistTransaction(Transactions.Transaction.Current); #endif _connectionState = oldstate; OnStateChange(ConnectionState.Open); } catch { _connectionState = oldstate; throw; } } catch (SQLiteException) { Close(); throw; } }
internal abstract void Bind_UInt64(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, UInt64 value);
/// <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> /// <param name="flags">The flags associated with the parent connection object</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, SQLiteConnectionFlags flags) { SQLiteFunction f; List<SQLiteFunction> lFunctions = new List<SQLiteFunction>(); foreach (SQLiteFunctionAttribute pr in _registeredFunctions) { f = (SQLiteFunction)Activator.CreateInstance(pr._instanceType); f._base = sqlbase; f._flags = flags; 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 abstract void Bind_Text(SQLiteStatement stmt, SQLiteConnectionFlags flags, int index, string value);