public override bool TryGetValue(string keyword, out object value) { bool flag = base.TryGetValue(keyword, out value); if (this._properties.ContainsKey(keyword)) { PropertyDescriptor descriptor = this._properties[keyword] as PropertyDescriptor; if (descriptor == null) { return(flag); } if (flag) { if (descriptor.PropertyType == typeof(bool)) { value = SQLiteConvert.ToBoolean(value); return(flag); } value = TypeDescriptor.GetConverter(descriptor.PropertyType).ConvertFrom(value); return(flag); } DefaultValueAttribute attribute = descriptor.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute; if (attribute != null) { value = attribute.Value; flag = true; } } return(flag); }
static SQLiteFactory() { #if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY UnsafeNativeMethods.Initialize(); #endif #if USE_INTEROP_DLL && INTEROP_LOG if (UnsafeNativeMethods.sqlite3_config_log_interop() == SQLiteErrorCode.Ok) { UnsafeNativeMethods.sqlite3_log( SQLiteErrorCode.Ok, SQLiteConvert.ToUTF8("logging initialized.")); } #endif SQLiteLog.Initialize(); string version = #if NET_40 || NET_45 || NET_451 || NET_452 || NET_46 || NET_461 "4.0.0.0"; #else "3.5.0.0"; #endif _dbProviderServicesType = Type.GetType(HelperMethods.StringFormat(CultureInfo.InvariantCulture, "System.Data.Common.DbProviderServices, System.Data.Entity, Version={0}, Culture=neutral, PublicKeyToken=b77a5c561934e089", version), false); }
/// <summary> /// Parses the connection string into component parts /// </summary> /// <param name="connectionString">The connection string to parse</param> /// <returns>An array of key-value pairs representing each parameter of the connection string</returns> internal static System.Collections.Generic.SortedList <string, string> ParseConnectionString(string connectionString) { string s = connectionString; int n; SortedList <string, string> ls = new SortedList <string, string>(StringComparer.OrdinalIgnoreCase); // First split into semi-colon delimited values. The Split() function of SQLiteBase accounts for and properly // skips semi-colons in quoted strings string[] arParts = SQLiteConvert.Split(s, ';'); int x = arParts.Length; // For each semi-colon piece, split into key and value pairs by the presence of the = sign for (n = 0; n < x; n++) { int indexOf = arParts[n].IndexOf('='); if (indexOf != -1) { ls.Add(arParts[n].Substring(0, indexOf), arParts[n].Substring(indexOf + 1)); } else { throw new ArgumentException(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Invalid ConnectionString format for part \"{0}\"", arParts[n])); } } return(ls); }
/// <summary> /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>A SQLiteType structure</returns> private SQLiteType GetSQLiteType(int i) { SQLiteType typ; // Initialize the field types array if not already initialized if (_fieldTypeArray == null) { _fieldTypeArray = new SQLiteType[VisibleFieldCount]; } // Initialize this column's field type instance if (_fieldTypeArray[i] == null) { _fieldTypeArray[i] = new SQLiteType(); } typ = _fieldTypeArray[i]; // If not initialized, then fetch the declared column datatype and attempt to convert it // to a known DbType. if (typ.Affinity == TypeAffinity.Uninitialized) { typ.Type = SQLiteConvert.TypeNameToDbType(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity)); } else { typ.Affinity = _activeStatement._sql.ColumnAffinity(_activeStatement, i); } return(typ); }
public override Type GetFieldType(int i) { if ((i >= this.VisibleFieldCount) && (this._keyInfo != null)) { return(this._keyInfo.GetFieldType(i - this.VisibleFieldCount)); } return(SQLiteConvert.SQLiteTypeToType(this.GetSQLiteType(i))); }
/////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Creates a <see cref="SQLiteBlob" /> object. This will not work /// for tables that were created WITHOUT ROWID. /// </summary> /// <param name="connection"> /// The connection to use when opening the blob object. /// </param> /// <param name="databaseName"> /// The name of the database containing the blob object. /// </param> /// <param name="tableName"> /// The name of the table containing the blob object. /// </param> /// <param name="columnName"> /// The name of the column containing the blob object. /// </param> /// <param name="rowId"> /// The integer identifier for the row associated with the desired /// blob object. /// </param> /// <param name="readOnly"> /// Non-zero to open the blob object for read-only access. /// </param> /// <returns> /// The newly created <see cref="SQLiteBlob" /> instance -OR- null /// if an error occurs. /// </returns> public static SQLiteBlob Create( SQLiteConnection connection, string databaseName, string tableName, string columnName, long rowId, bool readOnly ) { if (connection == null) { throw new ArgumentNullException("connection"); } SQLite3 sqlite3 = connection._sql as SQLite3; if (sqlite3 == null) { throw new InvalidOperationException("Connection has no wrapper"); } SQLiteConnectionHandle handle = sqlite3._sql; if (handle == null) { throw new InvalidOperationException("Connection has an invalid handle."); } SQLiteBlobHandle blob = null; try { // do nothing. } finally /* NOTE: Thread.Abort() protection. */ { IntPtr ptrBlob = IntPtr.Zero; SQLiteErrorCode rc = UnsafeNativeMethods.sqlite3_blob_open( handle, SQLiteConvert.ToUTF8(databaseName), SQLiteConvert.ToUTF8(tableName), SQLiteConvert.ToUTF8( columnName), rowId, readOnly ? 0 : 1, ref ptrBlob); if (rc != SQLiteErrorCode.Ok) { throw new SQLiteException(rc, null); } blob = new SQLiteBlobHandle(handle, ptrBlob); } SQLiteConnection.OnChanged(connection, new ConnectionEventArgs( SQLiteConnectionEventType.NewCriticalHandle, null, null, null, null, blob, null, new object[] { typeof(SQLiteBlob), databaseName, tableName, columnName, rowId, readOnly })); return(new SQLiteBlob(sqlite3, blob)); }
/// <summary> /// Returns the .NET type of a given column /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>Type</returns> public override Type GetFieldType(int i) { if (i >= VisibleFieldCount && _keyInfo != null) { return(_keyInfo.GetFieldType(i - VisibleFieldCount)); } return(SQLiteConvert.SQLiteTypeToType(GetSQLiteType(i))); }
/// <summary> /// Converts a SQLiteType to a .NET Type object /// </summary> /// <param name="t">The SQLiteType to convert</param> /// <returns>Returns a .NET Type object</returns> internal static Type SQLiteTypeToType(SQLiteType t) { if (t.Type != DbType.Object) { return(SQLiteConvert.DbTypeToType(t.Type)); } return(_typeaffinities[(int)t.Affinity]); }
internal override void Bind_Text(SQLiteStatement stmt, int index, string value) { byte[] buffer = SQLiteConvert.ToUTF8(value); int errorCode = UnsafeNativeMethods.sqlite3_bind_text((IntPtr)stmt._sqlite_stmt, index, buffer, buffer.Length - 1, (IntPtr)(-1)); if (errorCode > 0) { throw new SQLiteException(errorCode, this.SQLiteLastError()); } }
/// <summary> /// Determines the data type of a column in a statement /// </summary> /// <param name="stmt">The statement to retrieve information for</param> /// <param name="i">The column to retrieve type information on</param> /// <param name="typ">The SQLiteType to receive the affinity for the given column</param> // internal static void ColumnToType(SQLiteStatement stmt, int i, SQLiteType typ) // { // typ.Type = TypeNameToDbType(stmt._sql.ColumnType(stmt, i, out typ.Affinity)); // } /// <summary> /// Converts a SQLiteType to a .NET Type object /// </summary> /// <param name="t">The SQLiteType to convert</param> /// <returns>Returns a .NET Type object</returns> internal static Type SQLiteTypeToType(SQLiteType t) { if (t.Type == DbType.Object) { return(_affinitytotype[(int)t.Affinity]); } else { return(SQLiteConvert.DbTypeToType(t.Type)); } }
/// <summary> /// Retrieves the name of the back-end datatype of the column /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>string</returns> public override string GetDataTypeName(int i) { CheckClosed(); SQLiteType typ = GetSQLiteType(i); if (typ.Type == DbType.Object) { return(SQLiteConvert.SQLiteTypeToType(typ).Name); } return(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity)); }
internal override void GetIndexColumnExtendedInfo(string database, string index, string column, out int sortMode, out int onError, out string collationSequence) { IntPtr ptr; int num; int errorCode = UnsafeNativeMethods.sqlite3_index_column_info_interop((IntPtr)this._sql, SQLiteConvert.ToUTF8(database), SQLiteConvert.ToUTF8(index), SQLiteConvert.ToUTF8(column), out sortMode, out onError, out ptr, out num); if (errorCode != 0) { throw new SQLiteException(errorCode, ""); } collationSequence = SQLiteConvert.UTF8ToString(ptr, num); }
/// <summary> /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>A SQLiteType structure</returns> private SQLiteType GetSQLiteType(int i) { if (_fieldTypeArray == null) { _fieldTypeArray = new SQLiteType[_fieldCount]; } if (_fieldTypeArray[i].Affinity == TypeAffinity.Uninitialized || _fieldTypeArray[i].Affinity == TypeAffinity.Null) { _fieldTypeArray[i].Type = SQLiteConvert.TypeNameToDbType(_activeStatement._sql.ColumnType(_activeStatement, i, out _fieldTypeArray[i].Affinity)); } return(_fieldTypeArray[i]); }
internal override void CreateCollation(string strCollation, SQLiteCollation func, SQLiteCollation func16) { int errorCode = UnsafeNativeMethods.sqlite3_create_collation((IntPtr)this._sql, SQLiteConvert.ToUTF8(strCollation), 2, IntPtr.Zero, func16); if (errorCode == 0) { UnsafeNativeMethods.sqlite3_create_collation((IntPtr)this._sql, SQLiteConvert.ToUTF8(strCollation), 1, IntPtr.Zero, func); } if (errorCode > 0) { throw new SQLiteException(errorCode, this.SQLiteLastError()); } }
internal override CollationSequence GetCollationSequence(SQLiteFunction func, IntPtr context) { int num; int num2; int num3; CollationSequence sequence = new CollationSequence(); IntPtr nativestring = UnsafeNativeMethods.sqlite3_context_collseq(context, out num2, out num3, out num); sequence.Name = SQLiteConvert.UTF8ToString(nativestring, num); sequence.Type = (CollationTypeEnum)num2; sequence._func = func; sequence.Encoding = (CollationEncodingEnum)num3; return(sequence); }
public override string GetDataTypeName(int i) { if ((i >= this.VisibleFieldCount) && (this._keyInfo != null)) { return(this._keyInfo.GetDataTypeName(i - this.VisibleFieldCount)); } SQLiteType sQLiteType = this.GetSQLiteType(i); if (sQLiteType.Type == DbType.Object) { return(SQLiteConvert.SQLiteTypeToType(sQLiteType).Name); } return(this._activeStatement._sql.ColumnType(this._activeStatement, i, out sQLiteType.Affinity)); }
internal override object GetValue(SQLiteStatement stmt, int index, SQLiteType typ) { if (this.IsNull(stmt, index)) { return(DBNull.Value); } TypeAffinity affinity = typ.Affinity; Type type = null; if (typ.Type != DbType.Object) { type = SQLiteConvert.SQLiteTypeToType(typ); affinity = SQLiteConvert.TypeToAffinity(type); } switch (affinity) { case TypeAffinity.Int64: if (type != null) { return(Convert.ChangeType(this.GetInt64(stmt, index), type, null)); } return(this.GetInt64(stmt, index)); case TypeAffinity.Double: if (type != null) { return(Convert.ChangeType(this.GetDouble(stmt, index), type, null)); } return(this.GetDouble(stmt, index)); case TypeAffinity.Blob: if ((typ.Type != DbType.Guid) || (typ.Affinity != TypeAffinity.Text)) { int nLength = (int)this.GetBytes(stmt, index, 0, null, 0, 0); byte[] bDest = new byte[nLength]; this.GetBytes(stmt, index, 0, bDest, 0, nLength); if ((typ.Type == DbType.Guid) && (nLength == 0x10)) { return(new Guid(bDest)); } return(bDest); } return(new Guid(this.GetText(stmt, index))); case TypeAffinity.DateTime: return(this.GetDateTime(stmt, index)); } return(this.GetText(stmt, index)); }
/// <summary> /// Retrieves the name of the back-end datatype of the column /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>string</returns> public override string GetDataTypeName(int i) { if (i >= VisibleFieldCount && _keyInfo != null) { return(_keyInfo.GetDataTypeName(i - VisibleFieldCount)); } SQLiteType typ = GetSQLiteType(i); if (typ.Type == DbType.Object) { return(SQLiteConvert.SQLiteTypeToType(typ).Name); } return(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity)); }
internal static void ResetConnection(SQLiteConnectionHandle db) { lock (_lock) { IntPtr zero = IntPtr.Zero; do { zero = UnsafeNativeMethods.sqlite3_next_stmt((IntPtr)db, zero); if (zero != IntPtr.Zero) { UnsafeNativeMethods.sqlite3_reset_interop(zero); } }while (zero != IntPtr.Zero); UnsafeNativeMethods.sqlite3_exec((IntPtr)db, SQLiteConvert.ToUTF8("ROLLBACK"), IntPtr.Zero, IntPtr.Zero, out zero); } }
internal override string ColumnType(SQLiteStatement stmt, int index, out TypeAffinity nAffinity) { int num; IntPtr nativestring = UnsafeNativeMethods.sqlite3_column_decltype_interop((IntPtr)stmt._sqlite_stmt, index, out num); nAffinity = this.ColumnAffinity(stmt, index); if (nativestring != IntPtr.Zero) { return(SQLiteConvert.UTF8ToString(nativestring, num)); } string[] typeDefinitions = stmt.TypeDefinitions; if (((typeDefinitions != null) && (index < typeDefinitions.Length)) && (typeDefinitions[index] != null)) { return(typeDefinitions[index]); } return(string.Empty); }
/// <summary> /// Helper function to retrieve a column of data from an active statement. /// </summary> /// <param name="stmt">The statement being step()'d through</param> /// <param name="index">The column index to retrieve</param> /// <param name="typ">The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information.</param> /// <returns>Returns the data in the column</returns> internal virtual object GetValue(SQLiteStatement stmt, int index, ref SQLiteType typ) { if (typ.Affinity == 0) { typ = SQLiteConvert.ColumnToType(stmt, index); } if (IsNull(stmt, index)) { return(DBNull.Value); } Type t = SQLiteConvert.SQLiteTypeToType(typ); switch (TypeToAffinity(t)) { case TypeAffinity.Blob: if (typ.Type == DbType.Guid && typ.Affinity == TypeAffinity.Text) { return(new Guid(GetText(stmt, index))); } int n = (int)GetBytes(stmt, index, 0, null, 0, 0); byte[] b = new byte[n]; GetBytes(stmt, index, 0, b, 0, n); if (typ.Type == DbType.Guid && n == 16) { return(new Guid(b)); } return(b); case TypeAffinity.DateTime: return(GetDateTime(stmt, index)); case TypeAffinity.Double: return(Convert.ChangeType(GetDouble(stmt, index), t, null)); case TypeAffinity.Int64: return(Convert.ChangeType(GetInt64(stmt, index), t, null)); default: return(GetText(stmt, index)); } }
private SQLiteType GetSQLiteType(int i) { if (this._fieldTypeArray == null) { this._fieldTypeArray = new SQLiteType[this.VisibleFieldCount]; } if (this._fieldTypeArray[i] == null) { this._fieldTypeArray[i] = new SQLiteType(); } SQLiteType type = this._fieldTypeArray[i]; if (type.Affinity == TypeAffinity.Uninitialized) { type.Type = SQLiteConvert.TypeNameToDbType(this._activeStatement._sql.ColumnType(this._activeStatement, i, out type.Affinity)); return(type); } type.Affinity = this._activeStatement._sql.ColumnAffinity(this._activeStatement, i); return(type); }
/// <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(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); } } }
internal override void ColumnMetaData(string dataBase, string table, string column, out string dataType, out string collateSequence, out bool notNull, out bool primaryKey, out bool autoIncrement) { IntPtr ptr; IntPtr ptr2; int num; int num2; int num3; int num5; int num6; int errorCode = UnsafeNativeMethods.sqlite3_table_column_metadata_interop((IntPtr)this._sql, SQLiteConvert.ToUTF8(dataBase), SQLiteConvert.ToUTF8(table), SQLiteConvert.ToUTF8(column), out ptr, out ptr2, out num, out num2, out num3, out num5, out num6); if (errorCode > 0) { throw new SQLiteException(errorCode, this.SQLiteLastError()); } dataType = SQLiteConvert.UTF8ToString(ptr, num5); collateSequence = SQLiteConvert.UTF8ToString(ptr2, num6); notNull = num == 1; primaryKey = num2 == 1; autoIncrement = num3 == 1; }
/// <summary> /// Helper function for retrieving values from the connectionstring /// </summary> /// <param name="keyword">The keyword to retrieve settings for</param> /// <param name="value">The resulting parameter value</param> /// <returns>Returns true if the value was found and returned</returns> public override bool TryGetValue(string keyword, out object value) { bool b = base.TryGetValue(keyword, out value); if (!_properties.ContainsKey(keyword)) { return(b); } PropertyDescriptor pd = _properties[keyword] as PropertyDescriptor; if (pd == null) { return(b); } // Attempt to coerce the value into something more solid if (b) { if (pd.PropertyType == typeof(Boolean)) { value = SQLiteConvert.ToBoolean(value); } else if (pd.PropertyType != typeof(byte[])) { value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value); } } else { DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute; if (att != null) { value = att.Value; b = true; } } return(b); }
internal override void Open(string strFilename, SQLiteOpenFlagsEnum flags, int maxPoolSize, bool usePool) { if (base._sql == null) { base._usePool = usePool; if (usePool) { base._fileName = strFilename; base._sql = SQLiteConnectionPool.Remove(strFilename, maxPoolSize, out this._poolVersion); } if (base._sql == null) { IntPtr ptr; int errorCode = UnsafeNativeMethods.sqlite3_open16_interop(SQLiteConvert.ToUTF8(strFilename), (int)flags, out ptr); if (errorCode > 0) { throw new SQLiteException(errorCode, null); } base._sql = ptr; } base._functionsArray = SQLiteFunction.BindFunctions(this); } }
internal DataTable GetSchemaTable(bool wantUniqueInfo, bool wantDefaultValue) { this.CheckClosed(); DataTable tbl = new DataTable("SchemaTable"); DataTable schema = null; string str2 = ""; string str3 = ""; string str4 = ""; tbl.Locale = CultureInfo.InvariantCulture; tbl.Columns.Add(SchemaTableColumn.ColumnName, typeof(string)); tbl.Columns.Add(SchemaTableColumn.ColumnOrdinal, typeof(int)); tbl.Columns.Add(SchemaTableColumn.ColumnSize, typeof(int)); tbl.Columns.Add(SchemaTableColumn.NumericPrecision, typeof(short)); tbl.Columns.Add(SchemaTableColumn.NumericScale, typeof(short)); tbl.Columns.Add(SchemaTableColumn.IsUnique, typeof(bool)); tbl.Columns.Add(SchemaTableColumn.IsKey, typeof(bool)); tbl.Columns.Add(SchemaTableOptionalColumn.BaseServerName, typeof(string)); tbl.Columns.Add(SchemaTableOptionalColumn.BaseCatalogName, typeof(string)); tbl.Columns.Add(SchemaTableColumn.BaseColumnName, typeof(string)); tbl.Columns.Add(SchemaTableColumn.BaseSchemaName, typeof(string)); tbl.Columns.Add(SchemaTableColumn.BaseTableName, typeof(string)); tbl.Columns.Add(SchemaTableColumn.DataType, typeof(Type)); tbl.Columns.Add(SchemaTableColumn.AllowDBNull, typeof(bool)); tbl.Columns.Add(SchemaTableColumn.ProviderType, typeof(int)); tbl.Columns.Add(SchemaTableColumn.IsAliased, typeof(bool)); tbl.Columns.Add(SchemaTableColumn.IsExpression, typeof(bool)); tbl.Columns.Add(SchemaTableOptionalColumn.IsAutoIncrement, typeof(bool)); tbl.Columns.Add(SchemaTableOptionalColumn.IsRowVersion, typeof(bool)); tbl.Columns.Add(SchemaTableOptionalColumn.IsHidden, typeof(bool)); tbl.Columns.Add(SchemaTableColumn.IsLong, typeof(bool)); tbl.Columns.Add(SchemaTableOptionalColumn.IsReadOnly, typeof(bool)); tbl.Columns.Add(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(Type)); tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object)); tbl.Columns.Add("DataTypeName", typeof(string)); tbl.Columns.Add("CollationType", typeof(string)); tbl.BeginLoadData(); for (int i = 0; i < this._fieldCount; i++) { string str6; bool flag; bool flag2; bool flag3; DataRow row = tbl.NewRow(); DbType typ = this.GetSQLiteType(i).Type; row[SchemaTableColumn.ColumnName] = this.GetName(i); row[SchemaTableColumn.ColumnOrdinal] = i; row[SchemaTableColumn.ColumnSize] = SQLiteConvert.DbTypeToColumnSize(typ); row[SchemaTableColumn.NumericPrecision] = SQLiteConvert.DbTypeToNumericPrecision(typ); row[SchemaTableColumn.NumericScale] = SQLiteConvert.DbTypeToNumericScale(typ); row[SchemaTableColumn.ProviderType] = this.GetSQLiteType(i).Type; row[SchemaTableColumn.IsLong] = false; row[SchemaTableColumn.AllowDBNull] = true; row[SchemaTableOptionalColumn.IsReadOnly] = false; row[SchemaTableOptionalColumn.IsRowVersion] = false; row[SchemaTableColumn.IsUnique] = false; row[SchemaTableColumn.IsKey] = false; row[SchemaTableOptionalColumn.IsAutoIncrement] = false; row[SchemaTableColumn.DataType] = this.GetFieldType(i); row[SchemaTableOptionalColumn.IsHidden] = false; str4 = this._command.Connection._sql.ColumnOriginalName(this._activeStatement, i); if (!string.IsNullOrEmpty(str4)) { row[SchemaTableColumn.BaseColumnName] = str4; } row[SchemaTableColumn.IsExpression] = string.IsNullOrEmpty(str4); row[SchemaTableColumn.IsAliased] = string.Compare(this.GetName(i), str4, true, CultureInfo.InvariantCulture) != 0; string str = this._command.Connection._sql.ColumnTableName(this._activeStatement, i); if (!string.IsNullOrEmpty(str)) { row[SchemaTableColumn.BaseTableName] = str; } str = this._command.Connection._sql.ColumnDatabaseName(this._activeStatement, i); if (!string.IsNullOrEmpty(str)) { row[SchemaTableOptionalColumn.BaseCatalogName] = str; } string dataType = null; if (string.IsNullOrEmpty(str4)) { goto Label_09B7; } this._command.Connection._sql.ColumnMetaData((string)row[SchemaTableOptionalColumn.BaseCatalogName], (string)row[SchemaTableColumn.BaseTableName], str4, out dataType, out str6, out flag, out flag2, out flag3); if (flag || flag2) { row[SchemaTableColumn.AllowDBNull] = false; } row[SchemaTableColumn.IsKey] = flag2; row[SchemaTableOptionalColumn.IsAutoIncrement] = flag3; row["CollationType"] = str6; string[] strArray = dataType.Split(new char[] { '(' }); if (strArray.Length > 1) { dataType = strArray[0]; strArray = strArray[1].Split(new char[] { ')' }); if (strArray.Length > 1) { strArray = strArray[0].Split(new char[] { ',', '.' }); if ((this.GetSQLiteType(i).Type == DbType.String) || (this.GetSQLiteType(i).Type == DbType.Binary)) { row[SchemaTableColumn.ColumnSize] = Convert.ToInt32(strArray[0], CultureInfo.InvariantCulture); } else { row[SchemaTableColumn.NumericPrecision] = Convert.ToInt32(strArray[0], CultureInfo.InvariantCulture); if (strArray.Length > 1) { row[SchemaTableColumn.NumericScale] = Convert.ToInt32(strArray[1], CultureInfo.InvariantCulture); } } } } if (wantDefaultValue) { using (SQLiteCommand command = new SQLiteCommand(string.Format(CultureInfo.InvariantCulture, "PRAGMA [{0}].TABLE_INFO([{1}])", new object[] { row[SchemaTableOptionalColumn.BaseCatalogName], row[SchemaTableColumn.BaseTableName] }), this._command.Connection)) { using (DbDataReader reader = command.ExecuteReader()) { while (reader.Read()) { if (string.Compare((string)row[SchemaTableColumn.BaseColumnName], reader.GetString(1), true, CultureInfo.InvariantCulture) == 0) { if (!reader.IsDBNull(4)) { row[SchemaTableOptionalColumn.DefaultValue] = reader[4]; } goto Label_075E; } } } } } Label_075E: if (wantUniqueInfo) { if ((((string)row[SchemaTableOptionalColumn.BaseCatalogName]) != str2) || (((string)row[SchemaTableColumn.BaseTableName]) != str3)) { str2 = (string)row[SchemaTableOptionalColumn.BaseCatalogName]; str3 = (string)row[SchemaTableColumn.BaseTableName]; string[] restrictionValues = new string[4]; restrictionValues[0] = (string)row[SchemaTableOptionalColumn.BaseCatalogName]; restrictionValues[2] = (string)row[SchemaTableColumn.BaseTableName]; schema = this._command.Connection.GetSchema("Indexes", restrictionValues); } foreach (DataRow row2 in schema.Rows) { string[] strArray3 = new string[5]; strArray3[0] = (string)row[SchemaTableOptionalColumn.BaseCatalogName]; strArray3[2] = (string)row[SchemaTableColumn.BaseTableName]; strArray3[3] = (string)row2["INDEX_NAME"]; DataTable table3 = this._command.Connection.GetSchema("IndexColumns", strArray3); foreach (DataRow row3 in table3.Rows) { if (string.Compare((string)row3["COLUMN_NAME"], str4, true, CultureInfo.InvariantCulture) == 0) { if ((table3.Rows.Count == 1) && !((bool)row[SchemaTableColumn.AllowDBNull])) { row[SchemaTableColumn.IsUnique] = row2["UNIQUE"]; } if (((table3.Rows.Count != 1) || !((bool)row2["PRIMARY_KEY"])) || (string.IsNullOrEmpty(dataType) || (string.Compare(dataType, "integer", true, CultureInfo.InvariantCulture) != 0))) { } break; } } } } if (string.IsNullOrEmpty(dataType)) { TypeAffinity affinity; dataType = this._activeStatement._sql.ColumnType(this._activeStatement, i, out affinity); } if (!string.IsNullOrEmpty(dataType)) { row["DataTypeName"] = dataType; } Label_09B7: tbl.Rows.Add(row); } if (this._keyInfo != null) { this._keyInfo.AppendSchemaTable(tbl); } tbl.AcceptChanges(); tbl.EndLoadData(); return(tbl); }
/// <summary> /// Perform the bind operation for an individual parameter /// </summary> /// <param name="index">The index of the parameter to bind</param> /// <param name="param">The parameter we're binding</param> private void BindParameter(int index, SQLiteParameter param) { if (param == null) { throw new SQLiteException("Insufficient parameters supplied to the command"); } if (HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.UseConnectionBindValueCallbacks)) { bool complete; InvokeBindValueCallback(index, param, out complete); if (complete) { return; } } object obj = param.Value; DbType objType = param.DbType; if ((obj != null) && (objType == DbType.Object)) { objType = SQLiteConvert.TypeToDbType(obj.GetType()); } if (SQLite3.ForceLogPrepare() || HelperMethods.LogPreBind(_flags)) { IntPtr handle = _sqlite_stmt; SQLiteLog.LogMessage(HelperMethods.StringFormat( CultureInfo.CurrentCulture, "Binding statement {0} paramter #{1} with database type {2} and raw value {{{3}}}...", handle, index, objType, obj)); } if ((obj == null) || Convert.IsDBNull(obj)) { _sql.Bind_Null(this, _flags, index); return; } CultureInfo invariantCultureInfo = CultureInfo.InvariantCulture; bool invariantText = HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.BindInvariantText); CultureInfo cultureInfo = CultureInfo.CurrentCulture; if (HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.ConvertInvariantText)) { cultureInfo = invariantCultureInfo; } if (HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.BindAllAsText)) { if (obj is DateTime) { _sql.Bind_DateTime(this, _flags, index, (DateTime)obj); } else { _sql.Bind_Text(this, _flags, index, invariantText ? SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) : SQLiteConvert.ToStringWithProvider(obj, cultureInfo)); } return; } bool invariantDecimal = HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.BindInvariantDecimal); if (HelperMethods.HasFlags( _flags, SQLiteConnectionFlags.BindDecimalAsText)) { if (obj is Decimal) { _sql.Bind_Text(this, _flags, index, invariantText || invariantDecimal ? SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) : SQLiteConvert.ToStringWithProvider(obj, cultureInfo)); return; } } switch (objType) { case DbType.Date: case DbType.Time: case DbType.DateTime: // // NOTE: The old method (commented below) does not honor the selected date format // for the connection. // _sql.Bind_DateTime(this, index, Convert.ToDateTime(obj, cultureInfo)); _sql.Bind_DateTime(this, _flags, index, (obj is string) ? _sql.ToDateTime((string)obj) : Convert.ToDateTime(obj, cultureInfo)); break; case DbType.Boolean: _sql.Bind_Boolean(this, _flags, index, SQLiteConvert.ToBoolean(obj, cultureInfo, true)); break; case DbType.SByte: _sql.Bind_Int32(this, _flags, index, Convert.ToSByte(obj, cultureInfo)); break; case DbType.Int16: _sql.Bind_Int32(this, _flags, index, Convert.ToInt16(obj, cultureInfo)); break; case DbType.Int32: _sql.Bind_Int32(this, _flags, index, Convert.ToInt32(obj, cultureInfo)); break; case DbType.Int64: _sql.Bind_Int64(this, _flags, index, Convert.ToInt64(obj, cultureInfo)); break; case DbType.Byte: _sql.Bind_UInt32(this, _flags, index, Convert.ToByte(obj, cultureInfo)); break; case DbType.UInt16: _sql.Bind_UInt32(this, _flags, index, Convert.ToUInt16(obj, cultureInfo)); break; case DbType.UInt32: _sql.Bind_UInt32(this, _flags, index, Convert.ToUInt32(obj, cultureInfo)); break; case DbType.UInt64: _sql.Bind_UInt64(this, _flags, index, Convert.ToUInt64(obj, cultureInfo)); break; case DbType.Single: case DbType.Double: case DbType.Currency: _sql.Bind_Double(this, _flags, index, Convert.ToDouble(obj, cultureInfo)); break; case DbType.Binary: _sql.Bind_Blob(this, _flags, index, (byte[])obj); break; case DbType.Guid: if (_command.Connection._binaryGuid == true) { _sql.Bind_Blob(this, _flags, index, ((Guid)obj).ToByteArray()); } else { _sql.Bind_Text(this, _flags, index, invariantText ? SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) : SQLiteConvert.ToStringWithProvider(obj, cultureInfo)); } break; case DbType.Decimal: // Dont store decimal as double ... loses precision _sql.Bind_Text(this, _flags, index, invariantText || invariantDecimal ? SQLiteConvert.ToStringWithProvider(Convert.ToDecimal(obj, cultureInfo), invariantCultureInfo) : SQLiteConvert.ToStringWithProvider(Convert.ToDecimal(obj, cultureInfo), cultureInfo)); break; default: _sql.Bind_Text(this, _flags, index, invariantText ? SQLiteConvert.ToStringWithProvider(obj, invariantCultureInfo) : SQLiteConvert.ToStringWithProvider(obj, cultureInfo)); break; } }
/// <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; } }
/// <summary> /// This function does all the nasty work at determining what keys need to be returned for /// a given statement. /// </summary> /// <param name="cnn"></param> /// <param name="reader"></param> /// <param name="stmt"></param> internal SQLiteKeyReader(SQLiteConnection cnn, SQLiteDataReader reader, SQLiteStatement stmt) { Dictionary <string, int> catalogs = new Dictionary <string, int>(); Dictionary <string, List <string> > tables = new Dictionary <string, List <string> >(); List <string> list; List <KeyInfo> keys = new List <KeyInfo>(); List <RowIdInfo> rowIds = new List <RowIdInfo>(); // Record the statement so we can use it later for sync'ing _stmt = stmt; // Fetch all the attached databases on this connection using (DataTable tbl = cnn.GetSchema("Catalogs")) { foreach (DataRow row in tbl.Rows) { catalogs.Add((string)row["CATALOG_NAME"], Convert.ToInt32(row["ID"], CultureInfo.InvariantCulture)); } } // Fetch all the unique tables and catalogs used by the current statement using (DataTable schema = reader.GetSchemaTable(false, false)) { foreach (DataRow row in schema.Rows) { // Check if column is backed to a table if (row[SchemaTableOptionalColumn.BaseCatalogName] == DBNull.Value) { continue; } // Record the unique table so we can look up its keys string catalog = (string)row[SchemaTableOptionalColumn.BaseCatalogName]; string table = (string)row[SchemaTableColumn.BaseTableName]; if (tables.ContainsKey(catalog) == false) { list = new List <string>(); tables.Add(catalog, list); } else { list = tables[catalog]; } if (list.Contains(table) == false) { list.Add(table); } } // For each catalog and each table, query the indexes for the table. // Find a primary key index if there is one. If not, find a unique index instead foreach (KeyValuePair <string, List <string> > pair in tables) { for (int i = 0; i < pair.Value.Count; i++) { string table = pair.Value[i]; DataRow preferredRow = null; using (DataTable tbl = cnn.GetSchema("Indexes", new string[] { pair.Key, null, table })) { // Loop twice. The first time looking for a primary key index, // the second time looking for a unique index for (int n = 0; n < 2 && preferredRow == null; n++) { foreach (DataRow row in tbl.Rows) { if (n == 0 && (bool)row["PRIMARY_KEY"] == true) { preferredRow = row; break; } else if (n == 1 && (bool)row["UNIQUE"] == true) { preferredRow = row; break; } } } if (preferredRow == null) // Unable to find any suitable index for this table so remove it { pair.Value.RemoveAt(i); i--; } else // We found a usable index, so fetch the necessary table details { using (DataTable tblTables = cnn.GetSchema("Tables", new string[] { pair.Key, null, table })) { // Find the root page of the table in the current statement and get the cursor that's iterating it int database = catalogs[pair.Key]; int rootPage = Convert.ToInt32(tblTables.Rows[0]["TABLE_ROOTPAGE"], CultureInfo.InvariantCulture); int cursor = stmt._sql.GetCursorForTable(stmt, database, rootPage); // Now enumerate the members of the index we're going to use using (DataTable indexColumns = cnn.GetSchema("IndexColumns", new string[] { pair.Key, null, table, (string)preferredRow["INDEX_NAME"] })) { // // NOTE: If this is actually a RowId (or alias), record that now. There should // be exactly one index column in that case. // bool isRowId = (string)preferredRow["INDEX_NAME"] == "sqlite_master_PK_" + table; KeyQuery query = null; List <string> cols = new List <string>(); for (int x = 0; x < indexColumns.Rows.Count; x++) { string columnName = SQLiteConvert.GetStringOrNull( indexColumns.Rows[x]["COLUMN_NAME"]); bool addKey = true; // If the column in the index already appears in the query, skip it foreach (DataRow row in schema.Rows) { if (row.IsNull(SchemaTableColumn.BaseColumnName)) { continue; } if ((string)row[SchemaTableColumn.BaseColumnName] == columnName && (string)row[SchemaTableColumn.BaseTableName] == table && (string)row[SchemaTableOptionalColumn.BaseCatalogName] == pair.Key) { if (isRowId) { RowIdInfo rowId = new RowIdInfo(); rowId.databaseName = pair.Key; rowId.tableName = table; rowId.column = (int)row[SchemaTableColumn.ColumnOrdinal]; rowIds.Add(rowId); } indexColumns.Rows.RemoveAt(x); x--; addKey = false; break; } } if (addKey == true) { cols.Add(columnName); } } // If the index is not a rowid alias, record all the columns // needed to make up the unique index and construct a SQL query for it if (!isRowId) { // Whatever remains of the columns we need that make up the index that are not // already in the query need to be queried separately, so construct a subquery if (cols.Count > 0) { string[] querycols = new string[cols.Count]; cols.CopyTo(querycols); query = new KeyQuery(cnn, pair.Key, table, querycols); } } // Create a KeyInfo struct for each column of the index for (int x = 0; x < indexColumns.Rows.Count; x++) { string columnName = SQLiteConvert.GetStringOrNull(indexColumns.Rows[x]["COLUMN_NAME"]); KeyInfo key = new KeyInfo(); key.rootPage = rootPage; key.cursor = cursor; key.database = database; key.databaseName = pair.Key; key.tableName = table; key.columnName = columnName; key.query = query; key.column = x; keys.Add(key); } } } } } } } } // Now we have all the additional columns we have to return in order to support // CommandBehavior.KeyInfo _keyInfo = new KeyInfo[keys.Count]; keys.CopyTo(_keyInfo); _rowIdInfo = new RowIdInfo[rowIds.Count]; rowIds.CopyTo(_rowIdInfo); }