public void AddColumnsFromBlock(DataBlock.ReadOnlyDataBlock values) { List <ColumnDetails> columnsToAdd = new List <ColumnDetails>(); // Find the ID column // [The existing one, or one marked as primary key on the block, or one ending with 'ID', or the first column] ColumnDetails idColumn = _partitions[0].IDColumn ?? values.Columns.FirstOrDefault((cd) => cd.IsPrimaryKey) ?? values.Columns.FirstOrDefault((cd) => cd.Name.EndsWith("ID")) ?? values.Columns.FirstOrDefault(); // Mark the ID column idColumn.IsPrimaryKey = true; for (int columnIndex = 0; columnIndex < values.ColumnCount; ++columnIndex) { ColumnDetails details = values.Columns[columnIndex]; bool hasNonDefaultValues = false; // If this column was already added, no need to scan these values if (_partitions[0].ContainsColumn(details.Name)) { continue; } // Figure out the column type. Did the DataBlock provide one? Type determinedType = ColumnFactory.GetTypeFromTypeString(details.Type); // If not, is the DataBlock column array typed? determinedType = determinedType ?? values.GetTypeForColumn(columnIndex); if (determinedType == typeof(object) || determinedType == typeof(Value)) { determinedType = null; } // Get the column default, if provided, or the default for the type, if provided object columnDefault = details.Default; if (columnDefault == null && determinedType != null) { columnDefault = ColumnFactory.GetDefaultValueFromTypeString(determinedType.Name); } Type inferredType = null; Value v = Value.Create(null); DateTime defaultUtc = default(DateTime).ToUniversalTime(); for (int rowIndex = 0; rowIndex < values.RowCount; ++rowIndex) { object value = values[rowIndex, columnIndex]; // Identify the best type for all block values, if no type was already determined if (determinedType == null) { v.Assign(value); Type newBestType = v.BestType(inferredType); // If the type has changed, get an updated default value if (newBestType != determinedType) { columnDefault = ColumnFactory.GetDefaultValueFromTypeString(newBestType.Name); inferredType = newBestType; } } // Track whether any non-default values were seen [could be raw types or Value wrapper] if (hasNonDefaultValues == false && value != null && !value.Equals("") && !value.Equals(defaultUtc)) { if (columnDefault == null || value.Equals(columnDefault) == false) { hasNonDefaultValues = true; } } } // Set the column type if (String.IsNullOrEmpty(details.Type) || details.Type.Equals(Arriba.Model.Column.ColumnDetails.UnknownType)) { details.Type = ColumnFactory.GetCanonicalTypeName(determinedType ?? inferredType ?? typeof(string)); } // Add the column if it had any non-default values (and didn't already exist) if (hasNonDefaultValues || details.IsPrimaryKey) { columnsToAdd.Add(details); } } // Add the discovered columns. If any names match existing columns they'll be merged properly in Partition.AddColumn. AddColumns(columnsToAdd); }