Skip to content

Commit c0fbd97

Browse files
committed
fixed the decimal data type
1 parent 36affea commit c0fbd97

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

src/SciSharp.MySQL.Replication/Types/NewDecimalType.cs

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ public void LoadMetadataValue(ColumnMetadata columnMetadata)
3232
};
3333

3434
// Calculate storage size (MySQL packs 9 digits into 4 bytes)
35-
decimalOptions.IntegerBytes = (decimalOptions.Precision - decimalOptions.Scale + 8) / 9 * 4;
36-
decimalOptions.FractionBytes = (decimalOptions.Scale + 8) / 9 * 4;
35+
decimalOptions.IntegerBytes = CalculateByteCount(decimalOptions.Precision - decimalOptions.Scale);
36+
decimalOptions.FractionBytes = CalculateByteCount(decimalOptions.Scale);
3737

3838
columnMetadata.Options = decimalOptions;
3939
}
@@ -49,34 +49,32 @@ public object ReadValue(ref SequenceReader<byte> reader, ColumnMetadata columnMe
4949
var options = columnMetadata.Options as DecimalOptions;
5050

5151
reader.TryPeek(out byte signByte);
52-
bool negative = (signByte & 0x80) == 0x80;
52+
bool negative = (signByte & 0x80) == 0x00;
53+
signByte ^= 0x80;
5354

5455
// Read integer part
55-
var intPart = ReadCompactDecimal(ref reader, (int)Math.Min(options.IntegerBytes, reader.Remaining), true);
56-
57-
// Read fraction part
58-
var fracPart = ReadCompactDecimal(ref reader, (int)Math.Min(options.FractionBytes, reader.Remaining), false);
56+
var intPart = ReadCompactDecimal(ref reader, options.IntegerBytes, negative, signByte);
57+
58+
// Read integer part
59+
var fractionPart = ReadCompactDecimal(ref reader, options.FractionBytes, negative);
5960

6061
// Convert to decimal using direct decimal operations
61-
decimal intDecimal = (decimal)intPart;
62-
63-
// Calculate the fractional part as decimal
64-
decimal fracDecimal = 0;
62+
decimal fraction = (decimal)fractionPart;
6563

66-
if (fracPart > 0)
64+
if (options.Scale > 0)
6765
{
6866
// Create the appropriate scaling factor based on the scale
6967
decimal scaleFactor = (decimal)Math.Pow(10, options.Scale);
70-
fracDecimal = (decimal)fracPart / scaleFactor;
68+
fraction = fraction / scaleFactor;
7169
}
7270

73-
var result = intDecimal + fracDecimal;
71+
var result = (decimal)intPart + fraction;
7472

7573
// Apply sign
7674
return negative ? -result : result;
7775
}
7876

79-
private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, int byteCount, bool isIntegerPart)
77+
private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, int byteCount, bool flip, byte? signByteOverride = null)
8078
{
8179
if (byteCount == 0)
8280
return BigInteger.Zero;
@@ -86,8 +84,8 @@ private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, in
8684
reader.Advance(byteCount);
8785

8886
// Handle sign bit in the integer part
89-
if (isIntegerPart)
90-
bytes[0] &= 0x7F; // Clear the sign bit
87+
if (signByteOverride.HasValue)
88+
bytes[0] = signByteOverride.Value;
9189

9290
// Process each 4-byte group
9391
BigInteger result = BigInteger.Zero;
@@ -100,7 +98,12 @@ private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, in
10098
// Combine bytes in group (big-endian within the group)
10199
for (int j = 0; j < groupSize; j++)
102100
{
103-
value = (value << 8) | bytes[i + j];
101+
var cellValue = bytes[i + j];
102+
103+
if (flip)
104+
cellValue = (byte)(~cellValue);
105+
106+
value = (value << 8) | cellValue;
104107
}
105108

106109
// Each group represents a specific number of decimal digits
@@ -111,6 +114,14 @@ private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, in
111114
return result;
112115
}
113116

117+
private int CalculateByteCount(int digits)
118+
{
119+
if (digits == 0)
120+
return 0;
121+
122+
return digits / 9 * 4 + (digits % 9 / 2) + (digits % 2);
123+
}
124+
114125
class DecimalOptions
115126
{
116127
public int Precision { get; set; }

tests/Test/DataTypesTest.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,20 @@ await TestDataType<string>("varchar_table", currentValue, currentValue + " Updat
9898
});
9999
}
100100

101-
//[Fact]
101+
[Fact]
102102
public async Task TestDecimalType()
103103
{
104104
var currentValue = 123.45m;
105105
await TestDataType<decimal>("decimal_table", currentValue, currentValue + 10.55m, (reader, index) =>
106106
{
107107
return reader.GetDecimal(index);
108108
});
109+
110+
currentValue = -123.45m;
111+
await TestDataType<decimal>("decimal_table", currentValue, currentValue + 10.55m, (reader, index) =>
112+
{
113+
return reader.GetDecimal(index);
114+
});
109115
}
110116

111117
[Fact]

0 commit comments

Comments
 (0)