private static DataType GetPropertyDataType(LazyStringValue docId, OlapColumn prop, ref IList data) { DataType propType; switch (prop.Type & BlittableJsonReaderBase.TypesMask) { case BlittableJsonToken.Integer: propType = DataType.Int64; data ??= new List <long>(); break; case BlittableJsonToken.LazyNumber: var lnv = (LazyNumberValue)prop.Value; if (lnv.TryParseULong(out var ulongValue)) { prop.Value = ulongValue; propType = DataType.Int64; data ??= new List <long>(); } else if (lnv.TryParseDecimal(out var decimalValue)) { prop.Value = decimalValue; propType = DataType.Decimal; data ??= new List <decimal>(); } else { prop.Value = (double)lnv; propType = DataType.Double; data ??= new List <double>(); } break; case BlittableJsonToken.CompressedString: case BlittableJsonToken.String: var str = prop.Value.ToString(); if (TryParseDate(str, out var dto)) { propType = DataType.DateTimeOffset; data ??= new List <DateTimeOffset>(); prop.Value = dto; break; } if (TryParseTimeSpan(str, out var ts)) { propType = DataType.TimeSpan; data ??= new List <TimeSpan>(); prop.Value = ts; break; } propType = DataType.String; data ??= new List <string>(); break; case BlittableJsonToken.Boolean: propType = DataType.Boolean; data ??= new List <bool>(); break; case BlittableJsonToken.StartObject: propType = GetTypeFromObject(docId, prop, ref data); break; default: throw new NotSupportedException($"Unsupported {nameof(BlittableJsonToken)} '{prop.Type}'. " + $"On document '{docId}', property '{prop.Name}'"); } return(propType); }
private static DataType GetTypeFromObject(LazyStringValue docId, OlapColumn prop, ref IList data) { using (var objectValue = (BlittableJsonReaderObject)prop.Value) { if (objectValue.Count < 2 || objectValue.TryGetMember(nameof(SqlDocumentTransformer.VarcharFunctionCall.Type), out object dbType) == false || objectValue.TryGetMember(nameof(SqlDocumentTransformer.VarcharFunctionCall.Value), out object fieldValue) == false) { prop.Value = objectValue.ToString(); data ??= new List <string>(); return(DataType.String); } DataType propType; object value; var type = (DbType)Enum.Parse(typeof(DbType), dbType.ToString(), ignoreCase: true); switch (type) { case DbType.Byte: value = Convert.ToByte(fieldValue); propType = DataType.Byte; data ??= new List <byte>(); break; case DbType.SByte: value = Convert.ToSByte(fieldValue); propType = DataType.SignedByte; data ??= new List <sbyte>(); break; case DbType.Int16: value = Convert.ToInt16(fieldValue); propType = DataType.Short; data ??= new List <short>(); break; case DbType.Int32: value = Convert.ToInt32(fieldValue); propType = DataType.Int32; data ??= new List <int>(); break; case DbType.Int64: value = Convert.ToInt64(fieldValue); propType = DataType.Int64; data ??= new List <long>(); break; case DbType.UInt16: value = Convert.ToUInt16(fieldValue); propType = DataType.UnsignedInt16; data ??= new List <ushort>(); break; case DbType.UInt32: value = Convert.ToUInt32(fieldValue); propType = DataType.UnsignedInt32; data ??= new List <uint>(); break; case DbType.UInt64: value = Convert.ToUInt64(fieldValue); propType = DataType.UnsignedInt64; data ??= new List <ulong>(); break; case DbType.Single: value = Convert.ToSingle(fieldValue); propType = DataType.Float; data ??= new List <float>(); break; case DbType.Double: value = Convert.ToDouble(fieldValue); propType = DataType.Double; data ??= new List <double>(); break; case DbType.Decimal: value = Convert.ToDecimal(fieldValue); propType = DataType.Decimal; data ??= new List <decimal>(); break; default: throw new NotSupportedException($"Unsupported type '{dbType}' in object '{prop.Name}', On document '{docId}'"); } prop.Value = value; return(propType); } }
private void AddProperty(LazyStringValue docId, OlapColumn prop) { var propName = prop.Name; var newField = _dataTypes.TryGetValue(propName, out var dataType) == false; _group.Data.TryGetValue(propName, out var data); if (prop.Type == BlittableJsonToken.Null) { if (newField) { UpdateField(DataType.Unspecified, propName, data, _group); } else { AddDefaultData(data, dataType, 1); } return; } var propType = GetPropertyDataType(docId, prop, ref data); if (newField) { UpdateField(dataType = propType, propName, data, _group); } else if (dataType == DataType.Unspecified) { // existing field that had no values, until now // need to change the field type and add default values to fields' data Debug.Assert(data.Count == 0, "Invalid data. Data type is 'Unspecified', but data.Count = " + data.Count); UpdateField(dataType = propType, propName, data, _group); } else if (propType != dataType) { // data type change if (TryChangeDataType(dataType, propType, data, out data)) { // change previous data from 'long' to 'double' / 'decimal' // or from 'decimal' to 'double' UpdateField(dataType = propType, propName, data, _group, addDefaultData: false); } else if (TryChangeValueType(dataType, propType, prop.Value, out var newValue)) { // change current value from 'long' to 'double' / 'decimal' // or from 'decimal' to 'double' prop.Value = newValue; } } try { AddNewValue(data, dataType, prop.Value); } catch (Exception e) { throw new InvalidOperationException($"Failed to add value '{prop.Value}' to DataField of type '{dataType}'. " + $"On document '{docId}', property '{prop.Name}'", e); } }