Ejemplo n.º 1
0
        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);
        }