Esempio n. 1
0
        private void CheckTypeDetermination(string numericColumnTypeName)
        {
            // Create a numeric column with 0-10 in it
            IUntypedColumn column = ColumnFactory.Build(new ColumnDetails("Unused", numericColumnTypeName, 10), 0);

            column.SetSize(10);
            for (int i = 0; i < 10; ++i)
            {
                column[(ushort)i] = i;
            }

            // Include 0, 2, 4, 6, 8 in the results
            ShortSet matches = new ShortSet(10);

            for (int i = 0; i < 10; i += 2)
            {
                matches.Add((ushort)i);
            }

            // Ask for the Min and verify both the value and type are correct
            // This verifies the type checks in BaseAggregator.Aggregate determine type correctly
            MinAggregator aggregator = new MinAggregator();
            object        context    = aggregator.CreateContext();
            object        result     = aggregator.Aggregate(context, matches, new IUntypedColumn[] { column });

            Assert.AreEqual(column[0], result);
        }
Esempio n. 2
0
        /// <summary>
        ///  Change the type of a column to a new type. Values are copied from the existing
        ///  column to the new one, if value conversion is possible.
        /// </summary>
        /// <param name="details">Details with existing name and new other details</param>
        public void AlterColumn(ColumnDetails details)
        {
            if (details == null)
            {
                throw new ArgumentNullException("details");
            }

            if (!this.Columns.ContainsKey(details.Name))
            {
                throw new ArribaException(StringExtensions.Format("Column '{0}' does not exist; it can't be altered.", details.Name));
            }

            // Get the old column and build the new one
            IUntypedColumn currentcolumn     = this.Columns[details.Name];
            IUntypedColumn replacementColumn = ColumnFactory.Build(details, currentcolumn.Count);

            // Size the new column and copy each value to it
            ushort count = this.Count;

            replacementColumn.SetSize(count);
            for (ushort i = 0; i < count; ++i)
            {
                replacementColumn[i] = currentcolumn[i];
            }

            // Store the new column
            this.Columns[details.Name]         = replacementColumn;
            this.DetailsByColumn[details.Name] = details;
        }
Esempio n. 3
0
        /// <summary>
        ///  Add a new column with the given details. Columns must be added before values can be set on them.
        /// </summary>
        /// <param name="details">Details of the column to add</param>
        /// <param name="initialCapacity">suggested initial capacity of the column</param>
        public void AddColumn(ColumnDetails details, ushort initialCapacity)
        {
            if (details == null)
            {
                throw new ArgumentNullException("details");
            }

            if (this.Columns.ContainsKey(details.Name))
            {
                if (!this.DetailsByColumn[details.Name].Type.Equals(details.Type))
                {
                    AlterColumn(details);
                    return;
                }

                // If the column exists and type matches, we can only update side details (alias)
                this.DetailsByColumn[details.Name] = details;
            }
            else
            {
                if (details.IsPrimaryKey)
                {
                    ColumnDetails idColumnDetails = this.IDColumn;
                    if (idColumnDetails != null)
                    {
                        throw new ArribaException(StringExtensions.Format("Column '{0}' to be added is marked as the primary key but cannot be added because column '{1}' is already the primary key column.", details.Name, idColumnDetails.Name));
                    }
                }

                IUntypedColumn newColumn = ColumnFactory.Build(details, initialCapacity);
                this.Columns[details.Name]         = newColumn;
                this.DetailsByColumn[details.Name] = details;
                newColumn.SetSize(_itemCount);
            }
        }
Esempio n. 4
0
            public ushort[] FindOrAssignLIDs(Partition p, DataBlock.ReadOnlyDataBlock values, int idColumnIndex, AddOrUpdateMode mode)
            {
                // TODO: consider keeping one instance of the worker long term? if so, this becomes a private class field
                ValueTypeReference <T> vtr = new ValueTypeReference <T>();
                Value v = Value.Create(null);

                ushort[] itemLIDs = new ushort[values.RowCount];
                int      addCount = 0;

                IUntypedColumn idColumn      = p.Columns[p.IDColumn.Name];
                IColumn <T>    typedIdColumn = null;

                if (typeof(T) == idColumn.ColumnType)
                {
                    typedIdColumn = (IColumn <T>)idColumn.InnerColumn;
                }

                for (int index = 0; index < values.RowCount; ++index)
                {
                    // Look for the LIDs a
                    T externalID = values.GetValueT <T>(index, idColumnIndex);
                    if (typedIdColumn != null)
                    {
                        typedIdColumn.TryGetIndexOf(externalID, out itemLIDs[index]);
                    }
                    else
                    {
                        idColumn.TryGetIndexOf(externalID, out itemLIDs[index]);
                    }

                    if (itemLIDs[index] == ushort.MaxValue)
                    {
                        addCount++;
                    }

                    // Verify this item was routed to the right partition
                    vtr.Value = externalID;
                    v.Assign(vtr);
                    int idHash = v.GetHashCode();
                    if (!p.Mask.Matches(idHash))
                    {
                        throw new ArribaException(StringExtensions.Format("Item with ID '{0}', hash '{1:x}' incorrectly routed to Partition {2}.", externalID, idHash, p.Mask));
                    }
                }

                // Go back and add the items which need to be added in a batch
                if (mode != AddOrUpdateMode.UpdateAndIgnoreAdds)
                {
                    Dictionary <T, ushort> newlyAssignedLIDs = null;

                    for (int index = 0; index < values.RowCount; ++index)
                    {
                        T      idValue = values.GetValueT <T>(index, idColumnIndex);
                        ushort lid     = itemLIDs[index];

                        // If this is an add...
                        if (lid == ushort.MaxValue)
                        {
                            // If we have adds, we'll need to track new IDs
                            if (newlyAssignedLIDs == null)
                            {
                                newlyAssignedLIDs = new Dictionary <T, ushort>(addCount);
                            }

                            T externalID = idValue;

                            // If this ID was already added in this batch, this time it's an update
                            if (newlyAssignedLIDs.TryGetValue(externalID, out lid) == false)
                            {
                                // If in "UpdateOnly" mode, throw
                                if (mode == AddOrUpdateMode.UpdateOnly)
                                {
                                    throw new ArribaWriteException(externalID, p.IDColumn.Name, externalID,
                                                                   new ArribaException("AddOrUpdate was in UpdateOnly mode but contained a new ID, which is an error."));
                                }

                                // If this was a new item and not added in this batch, assign it a LID
                                lid = p._itemCount;

                                if (lid == ushort.MaxValue)
                                {
                                    throw new ArribaWriteException(externalID, p.IDColumn.Name, externalID,
                                                                   new ArribaException("Column full in Partition. Unable to add items."));
                                }

                                p._itemCount++;
                                idColumn.SetSize((ushort)(p._itemCount));

                                if (typedIdColumn != null)
                                {
                                    typedIdColumn[lid] = externalID;
                                }
                                else
                                {
                                    idColumn[lid] = externalID;
                                }

                                newlyAssignedLIDs[externalID] = lid;
                            }
                        }

                        itemLIDs[index] = lid;
                    }

                    // Commit the updates to the values column if the column requires it (FastAddSortedColumn does)
                    if (idColumn is ICommittable)
                    {
                        (idColumn as ICommittable).Commit();
                    }
                }

                return(itemLIDs);
            }