This is an automated email from the ASF dual-hosted git repository.

CurtHagenlocher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-dotnet.git


The following commit(s) were added to refs/heads/main by this push:
     new 3ea9aaa  Unambiguously equate decimal16 with SqlDecimal in Variant API 
(#342)
3ea9aaa is described below

commit 3ea9aaae80c2a8a406d0726a01950e4f31032b98
Author: Curt Hagenlocher <[email protected]>
AuthorDate: Wed Apr 29 17:11:42 2026 -0700

    Unambiguously equate decimal16 with SqlDecimal in Variant API (#342)
    
    ## What's Changed
    
    Unambiguously equate `decimal16` with `SqlDecimal` in Variant API
    
    Closes #333.
---
 .../Shredding/VariantShredder.cs                   |   4 +-
 .../VariantJson/VariantJsonConverter.cs            |   6 +-
 src/Apache.Arrow.Scalars/Variant/VariantValue.cs   | 125 ++++++++++-----------
 .../Variant/VariantValueWriter.cs                  |  16 ++-
 .../Shredding/ShreddedVariantReaderTests.cs        |   2 +-
 .../ParquetTestingVectorTests.cs                   |   2 +-
 .../VariantSqlDecimalTests.cs                      |  60 +++++-----
 .../VariantValueTests.cs                           |  30 ++---
 8 files changed, 116 insertions(+), 129 deletions(-)

diff --git a/src/Apache.Arrow.Operations/Shredding/VariantShredder.cs 
b/src/Apache.Arrow.Operations/Shredding/VariantShredder.cs
index 0a825b3..ef2ed11 100644
--- a/src/Apache.Arrow.Operations/Shredding/VariantShredder.cs
+++ b/src/Apache.Arrow.Operations/Shredding/VariantShredder.cs
@@ -283,8 +283,8 @@ namespace Apache.Arrow.Operations.Shredding
                 case ShredType.Float: return value.AsFloat();
                 case ShredType.Double: return value.AsDouble();
                 case ShredType.Decimal4:
-                case ShredType.Decimal8:
-                case ShredType.Decimal16: return value.AsDecimal();
+                case ShredType.Decimal8: return value.AsDecimal();
+                case ShredType.Decimal16: return value.AsSqlDecimal();
                 case ShredType.Date: return value.AsDateDays();
                 case ShredType.Timestamp: return value.AsTimestampMicros();
                 case ShredType.TimestampNtz: return 
value.AsTimestampNtzMicros();
diff --git a/src/Apache.Arrow.Operations/VariantJson/VariantJsonConverter.cs 
b/src/Apache.Arrow.Operations/VariantJson/VariantJsonConverter.cs
index 843cd69..de11c97 100644
--- a/src/Apache.Arrow.Operations/VariantJson/VariantJsonConverter.cs
+++ b/src/Apache.Arrow.Operations/VariantJson/VariantJsonConverter.cs
@@ -243,10 +243,8 @@ namespace Apache.Arrow.Operations.VariantJson
                     writer.WriteNumberValue(value.AsDecimal());
                     break;
                 case VariantPrimitiveType.Decimal16:
-                    if (value.IsSqlDecimalStorage)
-                        writer.WriteRawValue(value.AsSqlDecimal().ToString());
-                    else
-                        writer.WriteNumberValue(value.AsDecimal());
+                    // SqlDecimal.ToString() is culture-agnostic and produces 
a plain decimal string without exponent
+                    writer.WriteRawValue(value.AsSqlDecimal().ToString());
                     break;
                 case VariantPrimitiveType.Date:
                     DateTime date = value.AsDate();
diff --git a/src/Apache.Arrow.Scalars/Variant/VariantValue.cs 
b/src/Apache.Arrow.Scalars/Variant/VariantValue.cs
index 8848ca7..005a4e9 100644
--- a/src/Apache.Arrow.Scalars/Variant/VariantValue.cs
+++ b/src/Apache.Arrow.Scalars/Variant/VariantValue.cs
@@ -19,6 +19,9 @@ using System.Data.SqlTypes;
 using System.Globalization;
 using System.Linq;
 using System.Runtime.CompilerServices;
+#if !NET8_0_OR_GREATER
+using System.Runtime.InteropServices;
+#endif
 
 namespace Apache.Arrow.Scalars.Variant
 {
@@ -109,27 +112,15 @@ namespace Apache.Arrow.Scalars.Variant
         public static VariantValue FromDecimal8(decimal value) =>
             new VariantValue(VariantPrimitiveType.Decimal8, (object)value);
 
-        /// <summary>Creates a Decimal16 variant value.</summary>
-        public static VariantValue FromDecimal16(decimal value) =>
-            new VariantValue(VariantPrimitiveType.Decimal16, (object)value);
-
         /// <summary>
-        /// Creates a Decimal16 variant value from a <see cref="SqlDecimal"/>, 
always
-        /// producing <see cref="VariantPrimitiveType.Decimal16"/>. Values 
exceeding
-        /// <see cref="decimal"/> range are stored as <see cref="SqlDecimal"/>.
-        /// Use this when the target type is known (e.g. materializing a 
Decimal16
-        /// shredded column); use <see cref="FromSqlDecimal(SqlDecimal)"/> 
when you
-        /// want the smallest decimal type that fits the value.
+        /// Creates a Decimal16 variant value. Decimal16 covers the full 
Parquet
+        /// 38-digit decimal range, which exceeds the <see cref="decimal"/> 
96-bit
+        /// mantissa, so the API uses <see cref="SqlDecimal"/> uniformly. Use
+        /// <see cref="FromSqlDecimal(SqlDecimal)"/> when you want the smallest
+        /// decimal type that fits the value.
         /// </summary>
-        public static VariantValue FromDecimal16(SqlDecimal value)
-        {
-            if (value.Data[3] != 0)
-            {
-                SqlDecimal normalized = SqlDecimal.ConvertToPrecScale(value, 
38, value.Scale);
-                return new VariantValue(VariantPrimitiveType.Decimal16, 
(object)normalized);
-            }
-            return new VariantValue(VariantPrimitiveType.Decimal16, 
(object)value.Value);
-        }
+        public static VariantValue FromDecimal16(SqlDecimal value) =>
+            new VariantValue(VariantPrimitiveType.Decimal16, (object)value);
 
         /// <summary>
         /// Creates a decimal variant value, choosing the smallest decimal type
@@ -152,37 +143,47 @@ namespace Apache.Arrow.Scalars.Variant
             {
                 return FromDecimal8(value);
             }
-            return FromDecimal16(value);
+            return new VariantValue(VariantPrimitiveType.Decimal16, 
(object)new SqlDecimal(value));
         }
 
         /// <summary>
-        /// Creates a decimal variant value from a <see cref="SqlDecimal"/>.
-        /// Values fitting in <see cref="decimal"/> are stored as 
Decimal4/8/16 using
-        /// the smallest type. Values exceeding <see cref="decimal"/> range 
are stored
-        /// as Decimal16 with <see cref="SqlDecimal"/> storage.
+        /// Creates a decimal variant value from a <see cref="SqlDecimal"/>, 
choosing
+        /// the smallest decimal type that fits. Values exceeding <see 
cref="decimal"/>
+        /// range produce a Decimal16.
         /// </summary>
         public static VariantValue FromSqlDecimal(SqlDecimal value)
         {
-            int[] data = value.Data;
+#if NET8_0_OR_GREATER
+            Span<uint> data = stackalloc uint[4];
+            value.WriteTdsValue(data);
+#else
+            ReadOnlySpan<uint> data = MemoryMarshal.Cast<int, 
uint>(value.Data);
+#endif
+
             // SqlDecimal.Data: [0]=least-significant, [3]=most-significant
-            if (data[3] != 0)
+            if (data[3] == 0 && value.Precision - value.Scale <= 28)
             {
-                // Exceeds 96 bits — must store as SqlDecimal
-                SqlDecimal normalized = SqlDecimal.ConvertToPrecScale(value, 
38, value.Scale);
-                return new VariantValue(VariantPrimitiveType.Decimal16, 
(object)normalized);
+                try
+                {
+                    // Fits in decimal — convert and dispatch
+                    decimal d = value.Value;
+                    if (data[2] == 0 && data[1] == 0)
+                    {
+                        return FromDecimal4(d);
+                    }
+                    if (data[2] == 0)
+                    {
+                        return FromDecimal8(d);
+                    }
+                }
+                catch (OverflowException)
+                {
+                    // Value exceeds decimal range — fall back to Decimal16
+                }
             }
 
-            // Fits in decimal — convert and dispatch
-            decimal d = value.Value;
-            if (data[2] == 0 && data[1] == 0)
-            {
-                return FromDecimal4(d);
-            }
-            if (data[2] == 0)
-            {
-                return FromDecimal8(d);
-            }
-            return FromDecimal16(d);
+            // Exceeds 96 bits — must store as SqlDecimal
+            return new VariantValue(VariantPrimitiveType.Decimal16, 
(object)value);
         }
 
         /// <summary>Creates a Date variant value from days since 
epoch.</summary>
@@ -355,51 +356,45 @@ namespace Apache.Arrow.Scalars.Variant
             return BitConverter.Int64BitsToDouble(_inlineValue);
         }
 
-        /// <summary>Gets a decimal value (works for Decimal4, Decimal8, and 
Decimal16).</summary>
-        /// <remarks>
-        /// For Decimal16 values stored as <see cref="SqlDecimal"/> (exceeding 
96 bits),
-        /// this will throw <see cref="OverflowException"/>. Use <see 
cref="AsSqlDecimal()"/> instead.
-        /// </remarks>
+        /// <summary>
+        /// Gets a decimal value. Supported for Decimal4 and Decimal8 only.
+        /// Decimal16 can hold 38-digit values that exceed <see 
cref="decimal"/>
+        /// range, so use <see cref="AsSqlDecimal()"/> for Decimal16 instead.
+        /// </summary>
         public decimal AsDecimal()
         {
             if (_primitiveType == VariantPrimitiveType.Decimal4 ||
-                _primitiveType == VariantPrimitiveType.Decimal8 ||
-                _primitiveType == VariantPrimitiveType.Decimal16)
+                _primitiveType == VariantPrimitiveType.Decimal8)
             {
-                if (_objectValue is SqlDecimal sd)
-                    return sd.Value;
                 return (decimal)_objectValue;
             }
+            if (_primitiveType == VariantPrimitiveType.Decimal16)
+            {
+                throw new InvalidOperationException(
+                    "Cannot read Decimal16 as System.Decimal; use 
AsSqlDecimal() instead.");
+            }
             throw new InvalidOperationException($"Cannot read decimal from 
variant type {_primitiveType}.");
         }
 
         /// <summary>
-        /// Gets a decimal value as a <see cref="SqlDecimal"/> (works for 
Decimal4, Decimal8, and Decimal16).
-        /// Unlike <see cref="AsDecimal()"/>, this method does not throw for 
large Decimal16 values.
+        /// Gets a decimal value as a <see cref="SqlDecimal"/>. Works for 
Decimal4,
+        /// Decimal8, and Decimal16 (including values that exceed <see 
cref="decimal"/>
+        /// range).
         /// </summary>
         public SqlDecimal AsSqlDecimal()
         {
             if (_primitiveType == VariantPrimitiveType.Decimal4 ||
-                _primitiveType == VariantPrimitiveType.Decimal8 ||
-                _primitiveType == VariantPrimitiveType.Decimal16)
+                _primitiveType == VariantPrimitiveType.Decimal8)
             {
-                if (_objectValue is SqlDecimal sd)
-                    return sd;
                 return new SqlDecimal((decimal)_objectValue);
             }
+            if (_primitiveType == VariantPrimitiveType.Decimal16)
+            {
+                return (SqlDecimal)_objectValue;
+            }
             throw new InvalidOperationException($"Cannot read decimal from 
variant type {_primitiveType}.");
         }
 
-        /// <summary>
-        /// Returns true when the decimal value is stored internally as <see 
cref="SqlDecimal"/>
-        /// (i.e., it exceeds the range of <see cref="decimal"/>).
-        /// </summary>
-        internal bool IsSqlDecimalStorage =>
-            (_primitiveType == VariantPrimitiveType.Decimal4 ||
-             _primitiveType == VariantPrimitiveType.Decimal8 ||
-             _primitiveType == VariantPrimitiveType.Decimal16) &&
-            _objectValue is SqlDecimal;
-
         /// <summary>Gets the Date value as days since epoch.</summary>
         public int AsDateDays()
         {
diff --git a/src/Apache.Arrow.Scalars/Variant/VariantValueWriter.cs 
b/src/Apache.Arrow.Scalars/Variant/VariantValueWriter.cs
index 781f4a4..7adc36b 100644
--- a/src/Apache.Arrow.Scalars/Variant/VariantValueWriter.cs
+++ b/src/Apache.Arrow.Scalars/Variant/VariantValueWriter.cs
@@ -17,6 +17,9 @@ using System;
 using System.Buffers;
 using System.Collections.Generic;
 using System.Data.SqlTypes;
+#if !NET8_0_OR_GREATER
+using System.Runtime.InteropServices;
+#endif
 using System.Text;
 
 namespace Apache.Arrow.Scalars.Variant
@@ -397,12 +400,17 @@ namespace Apache.Arrow.Scalars.Variant
             
buf.Append(VariantEncodingHelper.MakePrimitiveHeader(VariantPrimitiveType.Decimal16));
 
             bool positive = value.IsPositive;
-            byte scale = (byte)value.Scale;
-            int[] data = value.Data;
+            byte scale = value.Scale;
+#if NET8_0_OR_GREATER
+            Span<uint> data = stackalloc uint[4];
+            value.WriteTdsValue(data);
+#else
+            ReadOnlySpan<uint> data = MemoryMarshal.Cast<int, 
uint>(value.Data);
+#endif
 
             // SqlDecimal.Data: [0]=least-significant, [3]=most-significant
-            long lo = ((long)(uint)data[1] << 32) | (uint)data[0];
-            long hi = ((long)(uint)data[3] << 32) | (uint)data[2];
+            long lo = ((long)data[1] << 32) | data[0];
+            long hi = ((long)data[3] << 32) | data[2];
 
             if (!positive)
             {
diff --git 
a/test/Apache.Arrow.Operations.Tests/Shredding/ShreddedVariantReaderTests.cs 
b/test/Apache.Arrow.Operations.Tests/Shredding/ShreddedVariantReaderTests.cs
index 1cf52f6..3b1fcf4 100644
--- a/test/Apache.Arrow.Operations.Tests/Shredding/ShreddedVariantReaderTests.cs
+++ b/test/Apache.Arrow.Operations.Tests/Shredding/ShreddedVariantReaderTests.cs
@@ -481,7 +481,7 @@ namespace Apache.Arrow.Operations.Tests.Shredding
             // is retained with SqlDecimal storage inside the VariantValue.
             VariantValue v = array.GetLogicalVariantValue(0);
             Assert.Equal(expected, v.AsSqlDecimal());
-            Assert.Throws<OverflowException>(() => v.AsDecimal());
+            Assert.Throws<InvalidOperationException>(() => v.AsDecimal());
         }
 
         /// <summary>
diff --git a/test/Apache.Arrow.Scalars.Tests/ParquetTestingVectorTests.cs 
b/test/Apache.Arrow.Scalars.Tests/ParquetTestingVectorTests.cs
index a3c6ee3..b2b3529 100644
--- a/test/Apache.Arrow.Scalars.Tests/ParquetTestingVectorTests.cs
+++ b/test/Apache.Arrow.Scalars.Tests/ParquetTestingVectorTests.cs
@@ -331,7 +331,7 @@ namespace Apache.Arrow.Scalars.Tests
                     // JSON may lose precision for large decimals (e.g. 
1.2345678912345678e+16
                     // loses the fractional part). Use relative tolerance 
comparison.
                     double expectedD16 = expected.GetDouble();
-                    double actualD16 = (double)actual.AsDecimal();
+                    double actualD16 = actual.AsSqlDecimal().ToDouble();
                     double relError = Math.Abs(expectedD16 - actualD16) / 
Math.Max(1.0, Math.Abs(expectedD16));
                     Assert.True(relError < 1e-10,
                         $"{context}: decimal16 relative error {relError:E3} 
exceeds tolerance. " +
diff --git a/test/Apache.Arrow.Scalars.Tests/VariantSqlDecimalTests.cs 
b/test/Apache.Arrow.Scalars.Tests/VariantSqlDecimalTests.cs
index a0be0e9..f2e539f 100644
--- a/test/Apache.Arrow.Scalars.Tests/VariantSqlDecimalTests.cs
+++ b/test/Apache.Arrow.Scalars.Tests/VariantSqlDecimalTests.cs
@@ -167,13 +167,30 @@ namespace Apache.Arrow.Scalars.Tests
         // FromSqlDecimal — large values produce Decimal16
         // ---------------------------------------------------------------
 
+        [Fact]
+        public void Decimal16_FromDecimalAndFromSqlDecimal_SameValue_AreEqual()
+        {
+            // A value requiring all 96 bits — auto-sizes to Decimal16 via 
FromDecimal,
+            // and constructs the same Decimal16 via 
FromDecimal16(SqlDecimal). The two
+            // must be equal and have the same hash code regardless of how 
_objectValue
+            // is boxed internally.
+            decimal d = 79228162514264337593543950335m;
+            VariantValue fromDecimal = VariantValue.FromDecimal(d);
+            VariantValue fromSqlDecimal = VariantValue.FromDecimal16(new 
SqlDecimal(d));
+
+            Assert.Equal(VariantPrimitiveType.Decimal16, 
fromDecimal.PrimitiveType);
+            Assert.Equal(VariantPrimitiveType.Decimal16, 
fromSqlDecimal.PrimitiveType);
+            Assert.Equal(fromDecimal, fromSqlDecimal);
+            Assert.Equal(fromDecimal.GetHashCode(), 
fromSqlDecimal.GetHashCode());
+        }
+
         [Fact]
         public void FromSqlDecimal_LargeValue_ProducesDecimal16()
         {
             SqlDecimal sd = 
SqlDecimal.Parse("99999999999999999999999999999999999999");
             VariantValue vv = VariantValue.FromSqlDecimal(sd);
             Assert.Equal(VariantPrimitiveType.Decimal16, vv.PrimitiveType);
-            Assert.True(vv.IsSqlDecimalStorage);
+            Assert.Equal(sd, vv.AsSqlDecimal());
         }
 
         // ---------------------------------------------------------------
@@ -198,15 +215,15 @@ namespace Apache.Arrow.Scalars.Tests
         }
 
         // ---------------------------------------------------------------
-        // AsDecimal from SqlDecimal-stored Decimal16 throws OverflowException
+        // AsDecimal on Decimal16 always throws (regardless of internal 
storage)
         // ---------------------------------------------------------------
 
         [Fact]
-        public void AsDecimal_FromSqlDecimalStored_Throws()
+        public void AsDecimal_OnLargeDecimal16_Throws()
         {
             SqlDecimal sd = 
SqlDecimal.Parse("99999999999999999999999999999999999999");
             VariantValue vv = VariantValue.FromSqlDecimal(sd);
-            Assert.Throws<OverflowException>(() => vv.AsDecimal());
+            Assert.Throws<InvalidOperationException>(() => vv.AsDecimal());
         }
 
         // ---------------------------------------------------------------
@@ -271,7 +288,6 @@ namespace Apache.Arrow.Scalars.Tests
             // Should not throw — should use SqlDecimal path
             VariantValue vv = reader.ToVariantValue();
             Assert.Equal(VariantPrimitiveType.Decimal16, vv.PrimitiveType);
-            Assert.True(vv.IsSqlDecimalStorage);
 
             SqlDecimal result = vv.AsSqlDecimal();
             Assert.Equal(SqlDecimal.Parse("79228162514264337593543950336"), 
result);
@@ -293,15 +309,14 @@ namespace Apache.Arrow.Scalars.Tests
             VariantValue vv2 = reader.ToVariantValue();
 
             Assert.Equal(VariantPrimitiveType.Decimal16, vv2.PrimitiveType);
-            Assert.True(vv2.IsSqlDecimalStorage);
             Assert.Equal(original, vv2.AsSqlDecimal());
         }
 
         [Fact]
-        public void RoundTrip_Materialize_SmallDecimal16_UsesDecimalStorage()
+        public void RoundTrip_Materialize_SmallDecimal16()
         {
-            decimal d = 12345.67m;
-            VariantValue vv1 = VariantValue.FromDecimal16(d);
+            SqlDecimal sd = new SqlDecimal(12345.67m);
+            VariantValue vv1 = VariantValue.FromDecimal16(sd);
             VariantBuilder builder = new VariantBuilder();
             (byte[] metadata, byte[] value) = builder.Encode(vv1);
 
@@ -309,8 +324,7 @@ namespace Apache.Arrow.Scalars.Tests
             VariantValue vv2 = reader.ToVariantValue();
 
             Assert.Equal(VariantPrimitiveType.Decimal16, vv2.PrimitiveType);
-            Assert.False(vv2.IsSqlDecimalStorage);
-            Assert.Equal(d, vv2.AsDecimal());
+            Assert.Equal(sd, vv2.AsSqlDecimal());
         }
 
         // ---------------------------------------------------------------
@@ -434,7 +448,6 @@ namespace Apache.Arrow.Scalars.Tests
             SqlDecimal sd = new SqlDecimal(0m);
             VariantValue vv = VariantValue.FromSqlDecimal(sd);
             Assert.Equal(VariantPrimitiveType.Decimal4, vv.PrimitiveType);
-            Assert.False(vv.IsSqlDecimalStorage);
             Assert.Equal(0m, vv.AsDecimal());
         }
 
@@ -443,27 +456,13 @@ namespace Apache.Arrow.Scalars.Tests
         // ---------------------------------------------------------------
 
         [Fact]
-        public void 
FromSqlDecimal_96BitBoundary_ProducesDecimal16WithDecimalStorage()
+        public void FromSqlDecimal_96BitBoundary_ProducesDecimal16()
         {
             // A value that needs all 96 bits: data[2] != 0 but data[3] == 0
             SqlDecimal sd = new SqlDecimal(79228162514264337593543950335m);
             VariantValue vv = VariantValue.FromSqlDecimal(sd);
             Assert.Equal(VariantPrimitiveType.Decimal16, vv.PrimitiveType);
-            Assert.False(vv.IsSqlDecimalStorage); // stored as decimal, not 
SqlDecimal
-            Assert.Equal(79228162514264337593543950335m, vv.AsDecimal());
-        }
-
-        // ---------------------------------------------------------------
-        // AsDecimal on Decimal16 that was created via FromSqlDecimal but fits
-        // ---------------------------------------------------------------
-
-        [Fact]
-        public void AsDecimal_FromSqlDecimalThatFits()
-        {
-            // 96-bit value goes through FromSqlDecimal -> stored as decimal
-            SqlDecimal sd = new SqlDecimal(79228162514264337593543950335m);
-            VariantValue vv = VariantValue.FromSqlDecimal(sd);
-            Assert.Equal(79228162514264337593543950335m, vv.AsDecimal());
+            Assert.Equal(sd, vv.AsSqlDecimal());
         }
 
         // ---------------------------------------------------------------
@@ -512,7 +511,6 @@ namespace Apache.Arrow.Scalars.Tests
             Assert.True(materialized.IsObject);
             IReadOnlyDictionary<string, VariantValue> fields = 
materialized.AsObject();
             Assert.Equal(sd, fields["big"].AsSqlDecimal());
-            Assert.True(fields["big"].IsSqlDecimalStorage);
             Assert.Equal(42.5m, fields["small"].AsDecimal());
         }
 
@@ -534,10 +532,8 @@ namespace Apache.Arrow.Scalars.Tests
             Assert.True(materialized.IsArray);
             IReadOnlyList<VariantValue> elements = materialized.AsArray();
             Assert.Equal(3, elements.Count);
-            Assert.True(elements[0].IsSqlDecimalStorage);
             Assert.Equal(large, elements[0].AsSqlDecimal());
-            Assert.False(elements[1].IsSqlDecimalStorage);
-            Assert.Equal(42.5m, elements[1].AsDecimal());
+            Assert.Equal(new SqlDecimal(42.5m), elements[1].AsSqlDecimal());
             Assert.Equal(1.23m, elements[2].AsDecimal());
         }
 
diff --git a/test/Apache.Arrow.Scalars.Tests/VariantValueTests.cs 
b/test/Apache.Arrow.Scalars.Tests/VariantValueTests.cs
index e5187dc..6c4d829 100644
--- a/test/Apache.Arrow.Scalars.Tests/VariantValueTests.cs
+++ b/test/Apache.Arrow.Scalars.Tests/VariantValueTests.cs
@@ -152,10 +152,17 @@ namespace Apache.Arrow.Scalars.Tests
         [Fact]
         public void Decimal16()
         {
-            decimal d = 79228162514264337593543950335m;
-            VariantValue v = VariantValue.FromDecimal16(d);
+            SqlDecimal sd = new SqlDecimal(79228162514264337593543950335m);
+            VariantValue v = VariantValue.FromDecimal16(sd);
             Assert.Equal(VariantPrimitiveType.Decimal16, v.PrimitiveType);
-            Assert.Equal(d, v.AsDecimal());
+            Assert.Equal(sd, v.AsSqlDecimal());
+        }
+
+        [Fact]
+        public void AsDecimal_OnDecimal16_Throws()
+        {
+            VariantValue v = VariantValue.FromDecimal16(new SqlDecimal(42.5m));
+            Assert.Throws<InvalidOperationException>(() => v.AsDecimal());
         }
 
         [Fact]
@@ -458,23 +465,6 @@ namespace Apache.Arrow.Scalars.Tests
             Assert.Equal(fromDecimal4.GetHashCode(), 
fromSqlDecimal.GetHashCode());
         }
 
-        [Fact]
-        public void IsSqlDecimalStorage_FalseForNonDecimalTypes()
-        {
-            Assert.False(VariantValue.FromInt32(42).IsSqlDecimalStorage);
-            Assert.False(VariantValue.FromString("hello").IsSqlDecimalStorage);
-            Assert.False(VariantValue.Null.IsSqlDecimalStorage);
-            Assert.False(VariantValue.FromDouble(3.14).IsSqlDecimalStorage);
-        }
-
-        [Fact]
-        public void IsSqlDecimalStorage_FalseForDecimalStoredValues()
-        {
-            Assert.False(VariantValue.FromDecimal4(42.5m).IsSqlDecimalStorage);
-            
Assert.False(VariantValue.FromDecimal8(123456789.12m).IsSqlDecimalStorage);
-            
Assert.False(VariantValue.FromDecimal16(42.5m).IsSqlDecimalStorage);
-        }
-
         // ---------------------------------------------------------------
         // ToString with SqlDecimal storage
         // ---------------------------------------------------------------

Reply via email to