in Arriba/Arriba/Model/Table.cs [331:411]
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);
}