/// <summary> /// Create a composite schema of both the partitioned columns and the underlying loader columns. /// </summary> /// <param name="ectx">The exception context.</param> /// <param name="cols">The partitioned columns.</param> /// <param name="subLoader">The sub loader.</param> /// <returns>The resulting schema.</returns> private Schema CreateSchema(IExceptionContext ectx, Column[] cols, IDataLoader subLoader) { Contracts.AssertValue(cols); Contracts.AssertValue(subLoader); var builder = new SchemaBuilder(); builder.AddColumns(cols.Select(c => new Schema.DetachedColumn(c.Name, ColumnTypeExtensions.PrimitiveTypeFromKind(c.Type.Value), null))); var colSchema = builder.GetSchema(); var subSchema = subLoader.Schema; if (subSchema.Count == 0) { return(colSchema); } else { var schemas = new Schema[] { subSchema, colSchema }; return(new ZipBinding(schemas).OutputSchema); } }
public Bindings(ModelLoadContext ctx, DatabaseLoader parent) { Contracts.AssertValue(ctx); // *** Binary format *** // int: number of columns // foreach column: // int: id of column name // byte: DataKind // byte: bool of whether this is a key type // for a key type: // ulong: count for key range // byte: bool of whether the source index is valid // for a valid source index: // int: source index int cinfo = ctx.Reader.ReadInt32(); Contracts.CheckDecode(cinfo > 0); Infos = new ColInfo[cinfo]; for (int iinfo = 0; iinfo < cinfo; iinfo++) { string name = ctx.LoadNonEmptyString(); PrimitiveDataViewType itemType; var kind = (InternalDataKind)ctx.Reader.ReadByte(); Contracts.CheckDecode(Enum.IsDefined(typeof(InternalDataKind), kind)); bool isKey = ctx.Reader.ReadBoolByte(); if (isKey) { ulong count; Contracts.CheckDecode(KeyDataViewType.IsValidDataType(kind.ToType())); count = ctx.Reader.ReadUInt64(); Contracts.CheckDecode(0 < count); itemType = new KeyDataViewType(kind.ToType(), count); } else { itemType = ColumnTypeExtensions.PrimitiveTypeFromKind(kind); } int? sourceIndex = null; bool hasSourceIndex = ctx.Reader.ReadBoolByte(); if (hasSourceIndex) { sourceIndex = ctx.Reader.ReadInt32(); } Infos[iinfo] = new ColInfo(name, sourceIndex, itemType); } OutputSchema = ComputeOutputSchema(); }
public Bindings(DatabaseLoader parent, Column[] cols) { Contracts.AssertNonEmpty(cols); using (var ch = parent._host.Start("Binding")) { // Make sure all columns have at least one source range. foreach (var col in cols) { if (col.Source < 0) { throw ch.ExceptUserArg(nameof(Column.Source), "Source column index must be non-negative"); } } Infos = new ColInfo[cols.Length]; // This dictionary is used only for detecting duplicated column names specified by user. var nameToInfoIndex = new Dictionary <string, int>(Infos.Length); for (int iinfo = 0; iinfo < Infos.Length; iinfo++) { var col = cols[iinfo]; ch.CheckNonWhiteSpace(col.Name, nameof(col.Name)); string name = col.Name.Trim(); if (iinfo == nameToInfoIndex.Count && nameToInfoIndex.ContainsKey(name)) { ch.Info("Duplicate name(s) specified - later columns will hide earlier ones"); } PrimitiveDataViewType itemType; if (col.KeyCount != null) { itemType = ConstructKeyType(col.Type, col.KeyCount); } else { itemType = ColumnTypeExtensions.PrimitiveTypeFromType(col.Type.ToType()); } Infos[iinfo] = new ColInfo(name, col.Source, itemType); nameToInfoIndex[name] = iinfo; } } OutputSchema = ComputeOutputSchema(); }
public Bindings(ModelLoadContext ctx, DatabaseLoader parent) { Contracts.AssertValue(ctx); // *** Binary format *** // int: number of columns // foreach column: // int: id of column name // byte: DataKind // byte: bool of whether this is a key type // for a key type: // ulong: count for key range // int: number of segments // foreach segment: // string id: name // int: min // int: lim // byte: force vector (verWrittenCur: verIsVectorSupported) int cinfo = ctx.Reader.ReadInt32(); Contracts.CheckDecode(cinfo > 0); Infos = new ColInfo[cinfo]; for (int iinfo = 0; iinfo < cinfo; iinfo++) { string name = ctx.LoadNonEmptyString(); PrimitiveDataViewType itemType; var kind = (InternalDataKind)ctx.Reader.ReadByte(); Contracts.CheckDecode(Enum.IsDefined(typeof(InternalDataKind), kind)); bool isKey = ctx.Reader.ReadBoolByte(); if (isKey) { ulong count; Contracts.CheckDecode(KeyDataViewType.IsValidDataType(kind.ToType())); count = ctx.Reader.ReadUInt64(); Contracts.CheckDecode(0 < count); itemType = new KeyDataViewType(kind.ToType(), count); } else { itemType = ColumnTypeExtensions.PrimitiveTypeFromKind(kind); } int cseg = ctx.Reader.ReadInt32(); Segment[] segs; if (cseg == 0) { segs = null; } else { Contracts.CheckDecode(cseg > 0); segs = new Segment[cseg]; for (int iseg = 0; iseg < cseg; iseg++) { string columnName = ctx.LoadStringOrNull(); int min = ctx.Reader.ReadInt32(); int lim = ctx.Reader.ReadInt32(); Contracts.CheckDecode(0 <= min && min < lim); bool forceVector = ctx.Reader.ReadBoolByte(); segs[iseg] = (columnName is null) ? new Segment(min, lim, forceVector) : new Segment(columnName, forceVector); } } // Note that this will throw if the segments are ill-structured, including the case // of multiple variable segments (since those segments will overlap and overlapping // segments are illegal). Infos[iinfo] = ColInfo.Create(name, itemType, segs, false); } OutputSchema = ComputeOutputSchema(); }
public Bindings(DatabaseLoader parent, Column[] cols) { Contracts.AssertNonEmpty(cols); using (var ch = parent._host.Start("Binding")) { Infos = new ColInfo[cols.Length]; // This dictionary is used only for detecting duplicated column names specified by user. var nameToInfoIndex = new Dictionary <string, int>(Infos.Length); for (int iinfo = 0; iinfo < Infos.Length; iinfo++) { var col = cols[iinfo]; ch.CheckNonWhiteSpace(col.Name, nameof(col.Name)); string name = col.Name.Trim(); if (iinfo == nameToInfoIndex.Count && nameToInfoIndex.ContainsKey(name)) { ch.Info("Duplicate name(s) specified - later columns will hide earlier ones"); } PrimitiveDataViewType itemType; if (col.KeyCount != null) { itemType = ConstructKeyType(col.Type, col.KeyCount); } else { ch.CheckUserArg(Enum.IsDefined(typeof(DbType), col.Type), nameof(Column.Type), "Bad item type"); itemType = ColumnTypeExtensions.PrimitiveTypeFromType(col.Type.ToType()); } Segment[] segs = null; if (col.Source != null) { segs = new Segment[col.Source.Length]; for (int i = 0; i < segs.Length; i++) { var range = col.Source[i]; Segment seg; if (range.Name is null) { int min = range.Min; ch.CheckUserArg(0 <= min, nameof(range.Min)); int max = range.Max; ch.CheckUserArg(min <= max, nameof(range.Max)); seg = new Segment(min, max + 1, range.ForceVector); } else { string columnName = range.Name; ch.CheckUserArg(columnName != null, nameof(range.Name)); seg = new Segment(columnName, range.ForceVector); } segs[i] = seg; } } Infos[iinfo] = ColInfo.Create(name, itemType, segs, true); nameToInfoIndex[name] = iinfo; } } OutputSchema = ComputeOutputSchema(); }
public static InternalSchemaDefinition Create(Type userType, SchemaDefinition userSchemaDefinition) { Contracts.AssertValue(userType); Contracts.AssertValueOrNull(userSchemaDefinition); if (userSchemaDefinition == null) { userSchemaDefinition = SchemaDefinition.Create(userType); } Column[] dstCols = new Column[userSchemaDefinition.Count]; for (int i = 0; i < userSchemaDefinition.Count; ++i) { var col = userSchemaDefinition[i]; if (col.MemberName == null) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "Null field name detected in schema definition"); } bool isVector; Type dataItemType; MemberInfo memberInfo = null; if (col.Generator == null) { memberInfo = userType.GetField(col.MemberName); if (memberInfo == null) { memberInfo = userType.GetProperty(col.MemberName); } if (memberInfo == null) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "No field or property with name '{0}' found in type '{1}'", col.MemberName, userType.FullName); } //Clause to handle the field that may be used to expose the cursor channel. //This field does not need a column. if ((memberInfo is FieldInfo && (memberInfo as FieldInfo).FieldType == typeof(IChannel)) || (memberInfo is PropertyInfo && (memberInfo as PropertyInfo).PropertyType == typeof(IChannel))) { continue; } GetVectorAndItemType(memberInfo, out isVector, out dataItemType); } else { var parameterType = col.ReturnType; if (parameterType == null) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "No return parameter found in computed column."); } GetVectorAndItemType("returnType", parameterType, null, out isVector, out dataItemType); } // Infer the column name. var colName = string.IsNullOrEmpty(col.ColumnName) ? col.MemberName : col.ColumnName; // REVIEW: Because order is defined, we allow duplicate column names, since producing an IDataView // with duplicate column names is completely legal. Possible objection is that we should make it less // convenient to produce "hidden" columns, since this may not be of practical use to users. DataViewType colType; if (col.ColumnType == null) { // Infer a type as best we can. PrimitiveDataViewType itemType = ColumnTypeExtensions.PrimitiveTypeFromType(dataItemType); colType = isVector ? new VectorDataViewType(itemType) : (DataViewType)itemType; } else { // Make sure that the types are compatible with the declared type, including // whether it is a vector type. VectorDataViewType columnVectorType = col.ColumnType as VectorDataViewType; if (isVector != (columnVectorType != null)) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "Column '{0}' is supposed to be {1}, but type of associated field '{2}' is {3}", colName, columnVectorType != null ? "vector" : "scalar", col.MemberName, isVector ? "vector" : "scalar"); } DataViewType itemType = columnVectorType?.ItemType ?? col.ColumnType; if (itemType.RawType != dataItemType) { throw Contracts.ExceptParam(nameof(userSchemaDefinition), "Column '{0}' is supposed to have item type {1}, but associated field has type {2}", colName, itemType.RawType, dataItemType); } colType = col.ColumnType; } dstCols[i] = col.Generator != null ? new Column(colName, colType, col.Generator, col.AnnotationInfos) : new Column(colName, colType, memberInfo, col.AnnotationInfos); } return(new InternalSchemaDefinition(dstCols)); }