/// <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); } }
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); }
/// <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; }
public void ColumnFactory_Build() { AssertBuild <string>(null); AssertBuild <Uri>(null); AssertBuild <DateTime>(DateTime.UtcNow); AssertBuild <bool>(true); AssertBuild <byte>((byte)1); AssertBuild <sbyte>((sbyte)1); AssertBuild <ushort>((ushort)1); AssertBuild <short>((short)1); AssertBuild <uint>((uint)1); AssertBuild <int>((int)1); AssertBuild <ulong>((ulong)1); AssertBuild <long>((long)1); AssertBuild <float>((float)1); AssertBuild <double>((double)1); AssertBuild <char>((char)1); IColumn <IList <string> > listColumn = (IColumn <IList <string> >)ColumnFactory.Build(typeof(IList <string>), null); Assert.NotNull(listColumn); IColumn <IDictionary <string, string> > dictionaryColumn = (IColumn <IDictionary <string, string> >)(ColumnFactory.Build(typeof(IDictionary <string, string>), null)); Assert.NotNull(dictionaryColumn); if (!Debugger.IsAttached) { Assert.Throws <NotImplementedException>(() => ColumnFactory.Build(typeof(Decimal))); Assert.Throws <NotSupportedException>(() => ColumnFactory.Build(typeof(DayOfWeek), DayOfWeek.Sunday)); } }
public void ColumnFactory_Build() { AssertBuild <string>(null); AssertBuild <Uri>(null); AssertBuild <DateTime>(DateTime.UtcNow); AssertBuild <bool>(true); AssertBuild <byte>((byte)1); AssertBuild <sbyte>((sbyte)1); AssertBuild <ushort>((ushort)1); AssertBuild <short>((short)1); AssertBuild <uint>((uint)1); AssertBuild <int>((int)1); AssertBuild <ulong>((ulong)1); AssertBuild <long>((long)1); AssertBuild <float>((float)1); AssertBuild <double>((double)1); AssertBuild <char>((char)1); AssertBuild <IList <byte> >(null); AssertBuild <IList <sbyte> >(null); AssertBuild <IList <ushort> >(null); AssertBuild <IList <short> >(null); AssertBuild <IList <uint> >(null); AssertBuild <IList <int> >(null); AssertBuild <IList <ulong> >(null); AssertBuild <IList <long> >(null); AssertBuild <IList <float> >(null); AssertBuild <IList <double> >(null); AssertBuild <IList <char> >(null); IColumn <IList <string> > listColumn = (IColumn <IList <string> >)ColumnFactory.Build(typeof(IList <string>), null); Assert.NotNull(listColumn); IColumn <IDictionary <string, string> > dictionaryColumn = (IColumn <IDictionary <string, string> >)(ColumnFactory.Build(typeof(IDictionary <string, string>), null)); Assert.NotNull(dictionaryColumn); // Verify collections are null by default if null passed as default Assert.Null(listColumn[0]); Assert.Null(dictionaryColumn[0]); // Verify collections not null by default if non-null passed as default listColumn = (IColumn <IList <string> >)ColumnFactory.Build(typeof(IList <string>), new object()); dictionaryColumn = (IColumn <IDictionary <string, string> >)(ColumnFactory.Build(typeof(IDictionary <string, string>), new object())); Assert.NotNull(listColumn[0]); Assert.NotNull(dictionaryColumn[0]); if (!Debugger.IsAttached) { Assert.Throws <NotImplementedException>(() => ColumnFactory.Build(typeof(Decimal))); Assert.Throws <NotImplementedException>(() => ColumnFactory.Build(typeof(ISet <int>))); Assert.Throws <NotSupportedException>(() => ColumnFactory.Build(typeof(DayOfWeek), DayOfWeek.Sunday)); } }
public void IColumnExtensions_FindComponent() { IColumn <object> column = ColumnFactory.Build(new ColumnDetails("sample", "string", null), 0); Assert.IsNotNull(column.FindComponent <IndexedColumn>()); Assert.IsNotNull(column.FindComponent <UntypedColumn <ByteBlock> >()); Assert.IsNotNull(column.FindComponent <ByteBlockColumn>()); Assert.IsNotNull(column.FindComponent <SortedColumn <ByteBlock> >()); Assert.IsNull(column.FindComponent <ValueTypeColumn <int> >()); IColumn c2 = new ValueTypeColumn <short>(short.MinValue); Assert.IsNull(c2.FindComponent <SortedColumn <short> >()); Assert.IsNotNull(c2.FindComponent <ValueTypeColumn <short> >()); }
public void TypedColumn_TimeSpan_Basic() { IColumn <object> c = ColumnFactory.Build(new ColumnDetails("Duration", "TimeSpan", null), 0); c.SetSize(10); c[0] = Value.Create(TimeSpan.FromMinutes(1)); c[1] = Value.Create("01:00:00"); c[2] = Value.Create("00:00:01"); c[3] = Value.Create("1"); CommitIfRequired(c); ShortSet longTimes = new ShortSet(c.Count); c.TryWhere(Operator.GreaterThan, TimeSpan.FromSeconds(30), longTimes, null); Assert.AreEqual("0, 1, 3", String.Join(", ", longTimes.Values)); }
public void Aggregator_BaseBehaviors() { AggregatorBaseBehaviors(new CountAggregator(), false); AggregatorBaseBehaviors(new SumAggregator()); AggregatorBaseBehaviors(new MinAggregator()); AggregatorBaseBehaviors(new MaxAggregator()); // Check BaseAggregator doesn't implement unexpected types or methods IUntypedColumn column = ColumnFactory.Build(new ColumnDetails("ID", "bool", false), 100); ShortSet sample = new ShortSet(100); sample.Or(new ushort[] { 1, 2, 3 }); IAggregator aggregator = new BaseAggregator(); Verify.Exception <NotImplementedException>(() => aggregator.Aggregate(null, sample, new IUntypedColumn[] { column })); Verify.Exception <NotImplementedException>(() => aggregator.Merge(null, new object[2])); }
private void AssertBuild <T>(object defaultValue) { IColumn column = ColumnFactory.BuildTyped <T>((T)defaultValue); Assert.NotNull(column); Assert.True(column is IColumn <T>); if (defaultValue != null) { column = ColumnFactory.Build(typeof(T), null); Assert.NotNull(column); Assert.True(column is IColumn <T>); column = ColumnFactory.Build(typeof(T)); Assert.NotNull(column); Assert.True(column is IColumn <T>); } }
public void IndexedColumn_HtmlSplitter() { IColumn <object> c = ColumnFactory.Build(new ColumnDetails("Description", "indexed[html]:sorted:string", null), 0); c.SetSize(4); c[0] = "<span title='nice'>First Value</span>"; c[1] = "<div>Second <b>Value</b> </div>"; c[2] = "this is a <b>different</b> value"; ColumnTests.AssertConsistent(c); // Verify words in html don't match (Splitter Should exclude) Assert.AreEqual("", ColumnTests.GetMatches(c, Operator.Matches, "span")); Assert.AreEqual("", ColumnTests.GetMatches(c, Operator.Matches, "nice")); Assert.AreEqual("", ColumnTests.GetMatches(c, Operator.Matches, "nbsp")); // Verify text within html does match Assert.AreEqual("0, 1, 2", ColumnTests.GetMatches(c, Operator.Matches, "value")); Assert.AreEqual("0", ColumnTests.GetMatches(c, Operator.Matches, "first")); Assert.AreEqual("2", ColumnTests.GetMatches(c, Operator.Matches, "different")); }
private void AggregatorBaseBehaviors(IAggregator aggregator, bool requiresColumns = true) { // Verify ToString returns the aggregator type, which matches the start of the class name string name = aggregator.ToString(); Assert.AreEqual(aggregator.GetType().Name.ToLowerInvariant(), (name + "aggregator").ToLowerInvariant()); // Verify Merge throws if the values are null Verify.Exception <ArgumentNullException>(() => aggregator.Merge(null, null)); // Verify Aggregate throws if the matches or columns are null Verify.Exception <ArgumentNullException>(() => aggregator.Aggregate(null, null, new IUntypedColumn[1] { ColumnFactory.Build(new ColumnDetails("ID", "int", null), 100) })); if (requiresColumns) { ShortSet sample = new ShortSet(100); sample.Or(new ushort[] { 1, 2, 3 }); Verify.Exception <ArgumentException>(() => aggregator.Aggregate(null, sample, null)); } }
public void TypedColumn_Boolean_Basic() { IColumn <object> c = ColumnFactory.Build(new ColumnDetails("IsDuplicate", "bool", true), 0); c.SetSize(5); c[0] = Value.Create(true); c[1] = Value.Create(false); c[2] = Value.Create("True"); c[3] = Value.Create("false"); CommitIfRequired(c); ShortSet set = new ShortSet(c.Count); // True - set and default set.Clear(); c.TryWhere(Operator.Equals, "true", set, null); Assert.AreEqual("0, 2, 4", String.Join(", ", set.Values)); // False - set set.Clear(); c.TryWhere(Operator.Equals, "false", set, null); Assert.AreEqual("1, 3", String.Join(", ", set.Values)); // False (Matches) set.Clear(); c.TryWhere(Operator.Matches, "false", set, null); Assert.AreEqual("1, 3", String.Join(", ", set.Values)); // Not False set.Clear(); c.TryWhere(Operator.NotEquals, "false", set, null); Assert.AreEqual("0, 2, 4", String.Join(", ", set.Values)); // Values works, *including if not asking for all items in order* bool[] values = (bool[])c.GetValues(new ushort[] { 3, 2, 1, 0 }); Assert.AreEqual("False, True, False, True", String.Join(", ", values)); }
public void ColumnFactory_BasicExtensibility() { CustomColumnSupport.RegisterCustomColumns(); // Registering the same name twice throws an exception Verify.Exception <ArribaException>(() => CustomColumnSupport.RegisterCustomColumns()); // Column factory can call custom column creators Assert.AreEqual("UntypedColumn<ComparableColor>;ColorColumn", WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "color", null), 0))); }
public void ColumnFactory_Basic() { string sortedColumnName = "FastAddSortedColumn"; // Strings Assert.AreEqual(string.Format("UntypedColumn<ByteBlock>;IndexedColumn[HtmlWordSplitter];{0}<ByteBlock>;ByteBlockColumn", sortedColumnName), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "html", null), 0))); Assert.AreEqual(string.Format("UntypedColumn<ByteBlock>;IndexedColumn[DefaultWordSplitter];{0}<ByteBlock>;ByteBlockColumn", sortedColumnName), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "json", null), 0))); Assert.AreEqual(string.Format("UntypedColumn<ByteBlock>;IndexedColumn[DefaultWordSplitter];{0}<ByteBlock>;ByteBlockColumn", sortedColumnName), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "string", null), 0))); // Special Types Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Guid"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "guid", null), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "DateTime"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "DateTime", null), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "TimeSpan"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "TimeSpan", null), 0))); Assert.AreEqual("UntypedColumn<Boolean>;BooleanColumn", WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "bool", null), 0))); // Supported Numeric Types (both naming styles) Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Byte"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "byte", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Int16"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "short", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Int16"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "Int16", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Int32"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "int", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Int32"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "Int32", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Int64"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "long", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Int64"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "Int64", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "UInt64"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "ulong", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "UInt64"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "UInt64", -1), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Single"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "Single", -1.0), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Single"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "float", -1.0), 0))); Assert.AreEqual(String.Format(_defaultWrappingFormatString, "Double"), WriteCompleteType(ColumnFactory.Build(new ColumnDetails("Unused", "double", -1), 0))); }
public virtual IColumn BuildColumn(string tableName, string columnName, Type type, object defaultValue = null) { return(ColumnFactory.Build(type, defaultValue)); }