From 108de12a2283e3642d9ca49c8486e6ed1f132a36 Mon Sep 17 00:00:00 2001 From: DarkWanderer Date: Mon, 1 Jun 2020 21:03:35 +0300 Subject: [PATCH] Fixed serialization of small negative decimals #33 --- ClickHouse.Client.Tests/TestUtilities.cs | 4 ++++ ClickHouse.Client/Formats/BinaryStreamWriter.cs | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/ClickHouse.Client.Tests/TestUtilities.cs b/ClickHouse.Client.Tests/TestUtilities.cs index 05b6b573..b6b2022e 100644 --- a/ClickHouse.Client.Tests/TestUtilities.cs +++ b/ClickHouse.Client.Tests/TestUtilities.cs @@ -80,6 +80,10 @@ public static IEnumerable GetDataTypeSamples() yield return new DataTypeSample("Decimal64(7)", typeof(decimal), "toDecimal64(1.2345, 7)", new decimal(1.2345)); yield return new DataTypeSample("Decimal128(9)", typeof(decimal), "toDecimal128(12.34, 9)", new decimal(12.34)); + yield return new DataTypeSample("Decimal32(3)", typeof(decimal), "toDecimal32(-123.45, 3)", new decimal(-123.45)); + yield return new DataTypeSample("Decimal64(7)", typeof(decimal), "toDecimal64(-1.2345, 7)", new decimal(-1.2345)); + yield return new DataTypeSample("Decimal128(9)", typeof(decimal), "toDecimal128(-12.34, 9)", new decimal(-12.34)); + yield return new DataTypeSample("Array(Int32)", typeof(int[]), "array(1, 2, 3)", new[] { 1, 2, 3 }); yield return new DataTypeSample("Nullable(Int32)", typeof(int?), "toInt32OrNull('123')", 123); diff --git a/ClickHouse.Client/Formats/BinaryStreamWriter.cs b/ClickHouse.Client/Formats/BinaryStreamWriter.cs index 59d6bddc..5c248421 100644 --- a/ClickHouse.Client/Formats/BinaryStreamWriter.cs +++ b/ClickHouse.Client/Formats/BinaryStreamWriter.cs @@ -61,9 +61,18 @@ public void WriteValue(object data, ClickHouseType databaseType) case ClickHouseTypeCode.Decimal: var dti = (DecimalType)databaseType; var value = new BigInteger(MathUtils.ShiftDecimalPlaces(Convert.ToDecimal(data), dti.Scale)); - var dbytes = new byte[dti.Size]; - value.ToByteArray().CopyTo(dbytes, 0); - writer.Write(dbytes); + var biBytes = value.ToByteArray(); + var decimalBytes = new byte[dti.Size]; + biBytes.CopyTo(decimalBytes, 0); + + // If a negative BigInteger is not long enough to fill the whole buffer, the remainder needs to be filled with 0xFF + if (value < 0) + { + for (int i = biBytes.Length; i < dti.Size; i++) + decimalBytes[i] = 0xFF; + } + + writer.Write(decimalBytes); break; case ClickHouseTypeCode.String: