Skip to content

Commit

Permalink
fix(csharp/src/Drivers/Apache/Spark): correct precision/scale handlin…
Browse files Browse the repository at this point in the history
…g with zeros in fractional portion (apache#2198)

Fixed two bugs
1. scale should be able to be the same as precision
2. when leading zeros in fractional portion and positive exponent, the
significant digits where not calculated correctly.
  • Loading branch information
birschick-bq committed Sep 27, 2024
1 parent d204b82 commit c391168
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 2 deletions.
10 changes: 8 additions & 2 deletions csharp/src/Drivers/Apache/Hive2/DecimalUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ internal static void GetBytes(string value, int precision, int scale, int byteWi
{
throw new ArgumentOutOfRangeException(nameof(precision), precision, "precision value must be greater than zero.");
}
if (scale < 0 || scale >= precision)
if (scale < 0 || scale > precision)
{
throw new ArgumentOutOfRangeException(nameof(scale), scale, "scale value must be in the range 0 .. precision.");
}
Expand Down Expand Up @@ -165,8 +165,14 @@ private static void ProcessDecimal(ReadOnlySpan<char> value, int precision, int
frac_length = Math.Max(Math.Min(frac_length - exponent, tempSignificant.Length - int_length), 0);
}
// Reset the integer and fractional span
integerSpan = tempSignificant.Slice(0, int_length);
fractionalSpan = tempSignificant.Slice(int_length, frac_length);
integerSpan = tempSignificant.Slice(0, int_length);
// Trim leading zeros fron new integer span
while (integerSpan.Length > 0 && integerSpan[0] == AsciiZero)
{
integerSpan = integerSpan.Slice(1);
int_length -= 1;
}
}

int neededPrecision = int_length + frac_length;
Expand Down
5 changes: 5 additions & 0 deletions csharp/test/Drivers/Apache/Hive2/DecimalUtilityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ public static IEnumerable<object[]> Decimal128Data()
yield return new object[] { "-0.1E0", 38, 3, 16, new byte[] { 156, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, new SqlDecimal(-0.1) };
yield return new object[] { "-1e-1", 38, 3, 16, new byte[] { 156, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, new SqlDecimal(-0.1) };
yield return new object[] { "-0.01e1", 38, 3, 16, new byte[] { 156, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, new SqlDecimal(-0.1) };

yield return new object[] { "0.99999999999999999999999999999999999999", 38, 38, 16, new byte[] { 255, 255, 255, 255, 63, 34, 138, 9, 122, 196, 134, 90, 168, 76, 59, 75 } };
yield return new object[] { "0.99999999999999999999999999999999999999E0", 38, 38, 16, new byte[] { 255, 255, 255, 255, 63, 34, 138, 9, 122, 196, 134, 90, 168, 76, 59, 75 } };
yield return new object[] { "9.99999999999999999999999999999999999990e-1", 38, 38, 16, new byte[] { 255, 255, 255, 255, 63, 34, 138, 9, 122, 196, 134, 90, 168, 76, 59, 75 } };
yield return new object[] { "0.0000000000000000000000000000000000000099999999999999999999999999999999999999e38", 38, 38, 16, new byte[] { 255, 255, 255, 255, 63, 34, 138, 9, 122, 196, 134, 90, 168, 76, 59, 75 } };
}

private static SqlDecimal GetSqlDecimal128(in byte[] valueBuffer, int index, int precision, int scale)
Expand Down

0 comments on commit c391168

Please sign in to comment.