@@ -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 ; }
0 commit comments