Skip to content

Commit

Permalink
apacheGH-38483: [C#] Add support for more decimal conversions (apache…
Browse files Browse the repository at this point in the history
…#38508)

### What changes are included in this PR?

Adds support for decimal128 <-> string and decimal256 <-> string.
Adds support for decimal256 <-> SqlDecimal.

### Are these changes tested?

Yes

### Are there any user-facing changes?

APIs have been added to support these conversions.
* Closes: apache#38483

Authored-by: Curt Hagenlocher <curt@hagenlocher.org>
Signed-off-by: Curt Hagenlocher <curt@hagenlocher.org>
  • Loading branch information
CurtHagenlocher authored and loicalleyne committed Nov 13, 2023
1 parent 987f0cc commit 7b2fd3b
Show file tree
Hide file tree
Showing 6 changed files with 761 additions and 3 deletions.
40 changes: 40 additions & 0 deletions csharp/src/Apache.Arrow/Arrays/Decimal128Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,37 @@ public Builder AppendRange(IEnumerable<decimal> values)
return Instance;
}

public Builder Append(string value)
{
if (value == null)
{
AppendNull();
}
else
{
Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, ByteWidth, bytes);
Append(bytes);
}

return Instance;
}

public Builder AppendRange(IEnumerable<string> values)
{
if (values == null)
{
throw new ArgumentNullException(nameof(values));
}

foreach (string s in values)
{
Append(s);
}

return Instance;
}

#if !NETSTANDARD1_3
public Builder Append(SqlDecimal value)
{
Expand Down Expand Up @@ -120,6 +151,15 @@ public Decimal128Array(ArrayData data)
return DecimalUtility.GetDecimal(ValueBuffer, index, Scale, ByteWidth);
}

public string GetString(int index)
{
if (IsNull(index))
{
return null;
}
return DecimalUtility.GetString(ValueBuffer, index, Precision, Scale, ByteWidth);
}

#if !NETSTANDARD1_3
public SqlDecimal? GetSqlDecimal(int index)
{
Expand Down
98 changes: 97 additions & 1 deletion csharp/src/Apache.Arrow/Arrays/Decimal256Array.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@

using System;
using System.Collections.Generic;
#if !NETSTANDARD1_3
using System.Data.SqlTypes;
#endif
using System.Diagnostics;
using System.Numerics;
using Apache.Arrow.Arrays;
using Apache.Arrow.Types;

Expand Down Expand Up @@ -61,6 +63,68 @@ public Builder AppendRange(IEnumerable<decimal> values)
return Instance;
}

public Builder Append(string value)
{
if (value == null)
{
AppendNull();
}
else
{
Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, ByteWidth, bytes);
Append(bytes);
}

return Instance;
}

public Builder AppendRange(IEnumerable<string> values)
{
if (values == null)
{
throw new ArgumentNullException(nameof(values));
}

foreach (string s in values)
{
Append(s);
}

return Instance;
}

#if !NETSTANDARD1_3
public Builder Append(SqlDecimal value)
{
Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
DecimalUtility.GetBytes(value, DataType.Precision, DataType.Scale, bytes);
if (!value.IsPositive)
{
var span = bytes.CastTo<long>();
span[2] = -1;
span[3] = -1;
}

return Append(bytes);
}

public Builder AppendRange(IEnumerable<SqlDecimal> values)
{
if (values == null)
{
throw new ArgumentNullException(nameof(values));
}

foreach (SqlDecimal d in values)
{
Append(d);
}

return Instance;
}
#endif

public Builder Set(int index, decimal value)
{
Span<byte> bytes = stackalloc byte[DataType.ByteWidth];
Expand Down Expand Up @@ -92,5 +156,37 @@ public Decimal256Array(ArrayData data)

return DecimalUtility.GetDecimal(ValueBuffer, index, Scale, ByteWidth);
}

public string GetString(int index)
{
if (IsNull(index))
{
return null;
}
return DecimalUtility.GetString(ValueBuffer, index, Precision, Scale, ByteWidth);
}

#if !NETSTANDARD1_3
public bool TryGetSqlDecimal(int index, out SqlDecimal? value)
{
if (IsNull(index))
{
value = null;
return true;
}

const int longWidth = 4;
var span = ValueBuffer.Span.CastTo<long>().Slice(index * longWidth);
if ((span[2] == 0 && span[3] == 0) ||
(span[2] == -1 && span[3] == -1))
{
value = DecimalUtility.GetSqlDecimal128(ValueBuffer, 2 * index, Precision, Scale);
return true;
}

value = null;
return false;
}
#endif
}
}
Loading

0 comments on commit 7b2fd3b

Please sign in to comment.