@@ -32,8 +32,8 @@ public void LoadMetadataValue(ColumnMetadata columnMetadata)
32
32
} ;
33
33
34
34
// 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 ) ;
37
37
38
38
columnMetadata . Options = decimalOptions ;
39
39
}
@@ -49,34 +49,32 @@ public object ReadValue(ref SequenceReader<byte> reader, ColumnMetadata columnMe
49
49
var options = columnMetadata . Options as DecimalOptions ;
50
50
51
51
reader . TryPeek ( out byte signByte ) ;
52
- bool negative = ( signByte & 0x80 ) == 0x80 ;
52
+ bool negative = ( signByte & 0x80 ) == 0x00 ;
53
+ signByte ^= 0x80 ;
53
54
54
55
// 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 ) ;
59
60
60
61
// 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 ;
65
63
66
- if ( fracPart > 0 )
64
+ if ( options . Scale > 0 )
67
65
{
68
66
// Create the appropriate scaling factor based on the scale
69
67
decimal scaleFactor = ( decimal ) Math . Pow ( 10 , options . Scale ) ;
70
- fracDecimal = ( decimal ) fracPart / scaleFactor ;
68
+ fraction = fraction / scaleFactor ;
71
69
}
72
70
73
- var result = intDecimal + fracDecimal ;
71
+ var result = ( decimal ) intPart + fraction ;
74
72
75
73
// Apply sign
76
74
return negative ? - result : result ;
77
75
}
78
76
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 )
80
78
{
81
79
if ( byteCount == 0 )
82
80
return BigInteger . Zero ;
@@ -86,8 +84,8 @@ private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, in
86
84
reader . Advance ( byteCount ) ;
87
85
88
86
// 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 ;
91
89
92
90
// Process each 4-byte group
93
91
BigInteger result = BigInteger . Zero ;
@@ -100,7 +98,12 @@ private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, in
100
98
// Combine bytes in group (big-endian within the group)
101
99
for ( int j = 0 ; j < groupSize ; j ++ )
102
100
{
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 ;
104
107
}
105
108
106
109
// Each group represents a specific number of decimal digits
@@ -111,6 +114,14 @@ private static BigInteger ReadCompactDecimal(ref SequenceReader<byte> reader, in
111
114
return result ;
112
115
}
113
116
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
+
114
125
class DecimalOptions
115
126
{
116
127
public int Precision { get ; set ; }
0 commit comments