/// <summary> /// Converts a value to its string representation for use as a parameter in a SQL command. /// </summary> /// <remarks> /// WARNING: The string returned by this method is NOT escaped. Do not include it directly in SQL. /// </remarks> /// <param name="value">Value to convert to a string.</param> /// <param name="truncated">The number of characters truncated off the result string.</param> /// <returns>The converted string value.</returns> protected static string ConvertToString(object value, out int truncated) { truncated = 0; if (value == null) { return(string.Empty); } else { Type runtimeType = value.GetType(); if (runtimeType == typeof(string)) { string result = (string)value; // loss of precision if (result.Length > 4000) { truncated = result.Length - 4000; result = result.Substring(0, 4000); } return(result); } else if ( runtimeType == typeof(sbyte) || runtimeType == typeof(short) || runtimeType == typeof(int) || runtimeType == typeof(byte) || runtimeType == typeof(ushort) || runtimeType == typeof(long) || runtimeType == typeof(uint) || runtimeType == typeof(ulong) || runtimeType == typeof(float) || runtimeType == typeof(double) || runtimeType == typeof(IPAddress)) { return(value.ToString()); } else if (runtimeType == typeof(bool)) { if ((bool)value) { return("1"); } else { return("0"); } } else if (runtimeType == typeof(Guid)) { return(((Guid)value).ToString("D")); } else if (runtimeType == typeof(byte[])) { string result = TSharkTypeParser.ConstructHexBytes((byte[])value); // loss of precision if (result.Length > 8000) { truncated = result.Length - 8000; result = result.Substring(0, 8000); } return(result); } else if (runtimeType == typeof(DateTime)) { return(((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss.FFFFFFF")); } else if (runtimeType == typeof(TimeSpan)) { return(((TimeSpan)value).TotalSeconds.ToString()); } else if (runtimeType == typeof(object[])) { object[] valueArray = (object[])value; StringBuilder builder = new StringBuilder("{ "); truncated = 0; for (int i = 0; i < valueArray.Length; i++) { if (i > 0) { builder.Append(", "); } int truncatedTemp; builder.Append(ConvertToString(valueArray[i], out truncatedTemp)); truncated += truncatedTemp; } builder.Append(" }"); // loss of precision if (builder.Length > 4000) { truncated += builder.Length - 4000; builder.Length = 4000; } return(builder.ToString()); } else { throw new Exception(string.Format("Unexpected column value type: {0}", runtimeType)); } } }
/// <summary> /// Called internally by the asynchronous row writing thread to recursively insert a row and all its children into the database. /// </summary> /// <param name="parent">Parent row, or null if none.</param> /// <param name="row">Row to insert.</param> /// <param name="rowInfo">Additional row information accumulated during recursion, or null if none.</param> private void WriteRowInternal(CapDataRow parent, CapDataRow row, RowInfo rowInfo) { bool includeRowInfo = (rowInfo != null); if (rowInfo == null && row.Table.Equals("geninfo", StringComparison.OrdinalIgnoreCase)) { string path = Convert.ToString(row.Columns["file"]); long number = Convert.ToInt64(row.Columns["num"]); DateTime timestamp = TSharkTypeParser.ParseDateTime(Convert.ToString(row.Columns["timestamp"])); rowInfo = CreateRowInfo(path, number, timestamp); } if (Filter != null) { if (Filter.FilterTable(row.Table) == DataFilterType.Deny) { foreach (CapDataRow childRow in row.ChildRows) { WriteRowInternal(parent, childRow, rowInfo); } return; } } TableDefinition tableDefinition = GetTableDefinition(row.Table); List <string> columnNames = new List <string>(); List <object> columnValues = new List <object>(); string parentColumnName = null; bool createForeignKey = false; bool createSourceFileForeignKey = false; int generatedColumnCount = 0; int truncated; List <string> truncatedColumns = null; if (includeRowInfo) { createSourceFileForeignKey = !tableDefinition.Columns.ContainsKey("_sourcefileid"); columnNames.Add("_sourcefileid"); columnNames.Add("_number"); columnNames.Add("_timestamp"); ColumnDefinition columnInfo; columnInfo = CreateOrUpdateColumnDefinition(tableDefinition, "_sourcefileid", ColumnType.Integer64Bit, 0); columnValues.Add(ConvertColumnValue(rowInfo.SourceFileID, columnInfo.SqlType, columnInfo.SqlPrecision, out truncated)); columnInfo = CreateOrUpdateColumnDefinition(tableDefinition, "_number", ColumnType.Integer64Bit, 0); columnValues.Add(ConvertColumnValue(rowInfo.Number, columnInfo.SqlType, columnInfo.SqlPrecision, out truncated)); columnInfo = CreateOrUpdateColumnDefinition(tableDefinition, "_timestamp", ColumnType.DateTime, 0); columnValues.Add(ConvertColumnValue(rowInfo.Timestamp, columnInfo.SqlType, columnInfo.SqlPrecision, out truncated)); generatedColumnCount += 3; } if (parent != null) { parentColumnName = string.Format("parent_{0}", parent.Table); createForeignKey = !tableDefinition.Columns.ContainsKey(parentColumnName); ColumnDefinition columnInfo = CreateOrUpdateColumnDefinition(tableDefinition, parentColumnName, ColumnType.Integer64Bit, 0); columnNames.Add(parentColumnName); columnValues.Add(ConvertColumnValue(parent.ID, columnInfo.SqlType, columnInfo.SqlPrecision, out truncated)); generatedColumnCount++; } foreach (KeyValuePair <string, object> column in row.Columns) { bool dropColumn = false; // comment out the next if-block to enable storage of binary data in the database, this can be very storage intensive // binary data is stored in the database as variable length strings and may be arbitrarily truncated to fit if (column.Value is byte[]) { dropColumn = true; } if (Filter != null) { if (Filter.FilterColumn(row.Table, column.Key) == DataFilterType.Deny) { dropColumn = true; } } if (!dropColumn) { ColumnType sqlType; int sqlPrecision; GetSqlTypeAndPrecision(column.Value, out sqlType, out sqlPrecision); ColumnDefinition columnInfo = CreateOrUpdateColumnDefinition(tableDefinition, column.Key, sqlType, sqlPrecision); object convertedColumnValue = ConvertColumnValue(column.Value, columnInfo.SqlType, columnInfo.SqlPrecision, out truncated); if (truncated > 0) { if (truncatedColumns == null) { truncatedColumns = new List <string>(); } truncatedColumns.Add(column.Key); } columnNames.Add(column.Key); columnValues.Add(convertedColumnValue); } } if (!tableDefinition.Committed) { CreateTable(tableDefinition); } if (!disableForeignKeys) { if (createForeignKey) { //Log.WriteInfo("Creating foreign key.\nFrom table: {0}\nTo table: {1}", row.Table, parent.Table); CreateForeignKey(row.Table, parentColumnName, parent.Table); } if (createSourceFileForeignKey) { CreateSourceFileForeignKey(row.Table); } } row.ID = InsertRow(tableDefinition, columnNames, columnValues); if (truncatedColumns != null) { foreach (string truncatedColumn in truncatedColumns) { Log.WriteWarning("Truncated column value.\nTable: {0}\nID: {1}\nColumn: {2}", tableDefinition.Name, row.ID, truncatedColumn); } } foreach (CapDataRow childRow in row.ChildRows) { WriteRowInternal(row, childRow, rowInfo); } }