Permalink
Browse files

BigDecimal type is now fully tested and intigrated into to FluentCass…

…andra
  • Loading branch information...
1 parent a80fb8c commit 65b37284392ba66aaea9666dde8d84860952233a @nberardi nberardi committed May 16, 2012
@@ -32,10 +32,10 @@ public override Void Execute()
};
if (SuperColumnName != null)
- parent.SuperColumn = SuperColumnName.GetValue(schema.SuperColumnNameType) as CassandraObject;
+ parent.SuperColumn = SuperColumnName.GetValue(schema.SuperColumnNameType);
var column = new CassandraColumn {
- Name = ColumnName.GetValue(schema.ColumnNameType) as CassandraObject,
+ Name = ColumnName.GetValue(schema.ColumnNameType),
Value = ColumnValue,
Timestamp = Timestamp,
Ttl = TimeToLive
@@ -29,7 +29,10 @@ public BigDecimal(decimal value)
Array.Copy(bytes, unscaledValueBytes, unscaledValueBytes.Length);
var unscaledValue = new BigInteger(unscaledValueBytes);
- var scale = BitConverter.ToInt32(bytes, 12);
+ var scale = bytes[14];
+
+ if (bytes[15] == 128)
+ unscaledValue *= BigInteger.MinusOne;
_unscaledValue = unscaledValue;
_scale = scale;
@@ -71,14 +74,24 @@ public BigDecimal(byte[] value)
public bool IsZero { get { return _unscaledValue.IsZero; } }
public int Sign { get { return _unscaledValue.Sign; } }
+ public override string ToString()
+ {
+ var number = _unscaledValue.ToString("G");
+
+ if (_scale > 0)
+ return number.Insert(number.Length - _scale, ".");
+
+ return number;
+ }
+
public byte[] ToByteArray()
{
var unscaledValue = _unscaledValue.ToByteArray();
var scale = BitConverter.GetBytes(_scale);
var bytes = new byte[unscaledValue.Length + scale.Length];
Array.Copy(unscaledValue, 0, bytes, 0, unscaledValue.Length);
- Array.Copy(scale, 0, bytes, unscaledValue.Length, bytes.Length);
+ Array.Copy(scale, 0, bytes, unscaledValue.Length, scale.Length);
return bytes;
}
@@ -220,6 +233,12 @@ private static byte[] FromDecimal(decimal d)
public static explicit operator float(BigDecimal value) { return value.ToType<float>(); }
public static explicit operator double(BigDecimal value) { return value.ToType<double>(); }
public static explicit operator decimal(BigDecimal value) { return value.ToType<decimal>(); }
+ public static explicit operator BigInteger(BigDecimal value)
+ {
+ var scaleDivisor = BigInteger.Pow(new BigInteger(10), value._scale);
+ var scaledValue = BigInteger.Divide(value._unscaledValue, scaleDivisor);
+ return scaledValue;
+ }
public static implicit operator BigDecimal(byte value) { return new BigDecimal(value); }
public static implicit operator BigDecimal(sbyte value) { return new BigDecimal(value); }
@@ -232,6 +251,7 @@ private static byte[] FromDecimal(decimal d)
public static implicit operator BigDecimal(float value) { return new BigDecimal(value); }
public static implicit operator BigDecimal(double value) { return new BigDecimal(value); }
public static implicit operator BigDecimal(decimal value) { return new BigDecimal(value); }
+ public static implicit operator BigDecimal(BigInteger value) { return new BigDecimal(value, 0); }
#endregion
@@ -26,6 +26,9 @@ public override bool CanConvertFrom(Type sourceType)
if (sourceType == typeof(BigInteger))
return true;
+ if (sourceType == typeof(BigDecimal))
+ return true;
+
switch (Type.GetTypeCode(sourceType))
{
case TypeCode.Byte:
@@ -67,6 +70,9 @@ public override bool CanConvertTo(Type destinationType)
if (destinationType == typeof(BigInteger))
return true;
+ if (destinationType == typeof(BigDecimal))
+ return true;
+
switch (Type.GetTypeCode(destinationType))
{
case TypeCode.Byte:
@@ -260,41 +266,18 @@ public byte[] FromBigEndian(byte[] value, Type destinationType)
private static byte[] FromDecimal(decimal d)
{
- byte[] bytes = new byte[16];
-
- int[] bits = decimal.GetBits(d);
- int lo = bits[0];
- int mid = bits[1];
- int hi = bits[2];
- int flags = bits[3];
-
- bytes[0] = (byte)lo;
- bytes[1] = (byte)(lo >> 8);
- bytes[2] = (byte)(lo >> 0x10);
- bytes[3] = (byte)(lo >> 0x18);
- bytes[4] = (byte)mid;
- bytes[5] = (byte)(mid >> 8);
- bytes[6] = (byte)(mid >> 0x10);
- bytes[7] = (byte)(mid >> 0x18);
- bytes[8] = (byte)hi;
- bytes[9] = (byte)(hi >> 8);
- bytes[10] = (byte)(hi >> 0x10);
- bytes[11] = (byte)(hi >> 0x18);
- bytes[12] = (byte)flags;
- bytes[13] = (byte)(flags >> 8);
- bytes[14] = (byte)(flags >> 0x10);
- bytes[15] = (byte)(flags >> 0x18);
-
- return bytes;
+ // we are now always saving byte arrays in BigDecimal format since they are often more compact than the .NET Decimal Type
+ var bigDecimal = new BigDecimal(d);
+ return bigDecimal.ToByteArray();
}
private static decimal ToDecimal(byte[] bytes)
{
if (bytes.Length != 16)
- return FromJavaBigDecimalToDecimal(bytes);
+ return FromBigDecimalToDecimal(bytes);
try { return FromDotNetDecimalToDecimal(bytes); }
- catch { return FromJavaBigDecimalToDecimal(bytes); }
+ catch { return FromBigDecimalToDecimal(bytes); }
}
private static decimal FromDotNetDecimalToDecimal(byte[] bytes)
@@ -308,7 +291,7 @@ private static decimal FromDotNetDecimalToDecimal(byte[] bytes)
return new decimal(bits);
}
- private static decimal FromJavaBigDecimalToDecimal(byte[] bytes)
+ private static decimal FromBigDecimalToDecimal(byte[] bytes)
{
var bigDec = new BigDecimal(bytes);
return (decimal)bigDec;
@@ -1,4 +1,5 @@
using System;
+using System.Numerics;
namespace FluentCassandra.Types
{
@@ -53,5 +54,13 @@ internal static Guid ToGuidFromBigEndianBytes(this byte[] value)
ReverseHighFieldTimestamp(buffer);
return new Guid(buffer);
}
+
+ internal static BigDecimal ToBigDecimalFromBigEndianBytes(this byte[] value)
+ {
+ var buffer = (byte[])value.Clone();
+ Array.Reverse(buffer);
+
+ return new BigDecimal(buffer);
+ }
}
}
@@ -7,34 +7,92 @@ internal class DecimalTypeConverter : CassandraObjectConverter<BigDecimal>
{
public override bool CanConvertFrom(Type sourceType)
{
- if (Type.GetTypeCode(sourceType) != TypeCode.Object)
- return true;
+ switch (Type.GetTypeCode(sourceType))
+ {
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.SByte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
- return sourceType == typeof(byte[]);
+ default:
+ return sourceType == typeof(byte[]) || sourceType == typeof(BigInteger) || sourceType == typeof(BigDecimal);
+ }
}
public override bool CanConvertTo(Type destinationType)
{
- if (Type.GetTypeCode(destinationType) != TypeCode.Object)
- return true;
+ switch (Type.GetTypeCode(destinationType))
+ {
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.SByte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Decimal:
+ return true;
- return destinationType == typeof(byte[]);
+ default:
+ return destinationType == typeof(byte[]) || destinationType == typeof(BigInteger) || destinationType == typeof(BigDecimal);
+ }
}
public override BigDecimal ConvertFromInternal(object value)
{
if (value is byte[])
return ((byte[])value).FromBytes<BigDecimal>();
- return (BigDecimal)Convert.ChangeType(value, typeof(BigDecimal));
+ if (value is BigDecimal) return (BigDecimal)value;
+
+ if (value is byte) return (BigDecimal)(byte)value;
+ if (value is short) return (BigDecimal)(short)value;
+ if (value is int) return (BigDecimal)(int)value;
+ if (value is long) return (BigDecimal)(long)value;
+ if (value is sbyte) return (BigDecimal)(sbyte)value;
+ if (value is ushort) return (BigDecimal)(ushort)value;
+ if (value is uint) return (BigDecimal)(uint)value;
+ if (value is ulong) return (BigDecimal)(ulong)value;
+ if (value is float) return (BigDecimal)(float)value;
+ if (value is double) return (BigDecimal)(double)value;
+ if (value is decimal) return (BigDecimal)(decimal)value;
+ if (value is BigInteger) return (BigDecimal)(BigInteger)value;
+
+ return default(BigDecimal);
}
public override object ConvertToInternal(BigDecimal value, Type destinationType)
{
if (destinationType == typeof(byte[]))
return value.ToBytes();
- return Convert.ChangeType(value, destinationType);
+ if (destinationType == typeof(BigDecimal)) return value;
+
+ if (destinationType == typeof(byte)) return (byte)value;
+ if (destinationType == typeof(short)) return (short)value;
+ if (destinationType == typeof(int)) return (int)value;
+ if (destinationType == typeof(long)) return (long)value;
+ if (destinationType == typeof(sbyte)) return (sbyte)value;
+ if (destinationType == typeof(ushort)) return (ushort)value;
+ if (destinationType == typeof(uint)) return (uint)value;
+ if (destinationType == typeof(ulong)) return (ulong)value;
+ if (destinationType == typeof(float)) return (float)value;
+ if (destinationType == typeof(double)) return (double)value;
+ if (destinationType == typeof(decimal)) return (decimal)value;
+ if (destinationType == typeof(BigInteger)) return (BigInteger)value;
+
+ return null;
}
}
}
@@ -20,7 +20,7 @@ public void Dispose()
_db.Dispose();
}
- [Fact(Skip="Need to work on later")]
+ [Fact]
public void Test()
{
// arrange
@@ -49,6 +49,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="BigDecimalTest.cs" />
<Compile Include="Bugs\Issue25JavaBigDecimalBinaryConversion.cs" />
<Compile Include="CassandraDatabaseSetupFixture.cs" />
<Compile Include="CassandraQueryTest.cs" />

0 comments on commit 65b3728

Please sign in to comment.