• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Giorgi / DuckDB.NET / 22921736195

10 Mar 2026 07:24PM UTC coverage: 89.526% (+0.08%) from 89.45%
22921736195

push

github

Giorgi
Update global.json

1255 of 1463 branches covered (85.78%)

Branch coverage included in aggregate %.

2651 of 2900 relevant lines covered (91.41%)

447643.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/DuckDB.NET.Data/DataChunk/Reader/DecimalVectorDataReader.cs
1
namespace DuckDB.NET.Data.DataChunk.Reader;
2

3
internal sealed class DecimalVectorDataReader : VectorDataReaderBase
4
{
5
    private readonly BigInteger bigIntRemainderShift;
6
    private readonly DuckDBType decimalType;
7
    private readonly NumericVectorDataReader numericVectorDataReader;
8

9
    internal unsafe DecimalVectorDataReader(IntPtr vector, void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
969✔
10
    {
11
        using var logicalType = NativeMethods.Vectors.DuckDBVectorGetColumnType(vector);
969✔
12
        Scale = NativeMethods.LogicalType.DuckDBDecimalScale(logicalType);
969✔
13
        Precision = NativeMethods.LogicalType.DuckDBDecimalWidth(logicalType);
969✔
14
        decimalType = NativeMethods.LogicalType.DuckDBDecimalInternalType(logicalType);
969✔
15

16
        // SmallInt/Integer/BigInt paths have scale ≤ 18, always within range.
17
        if (Scale > DecimalExtensions.MaxDecimalScale)
969✔
18
        {
19
            // Scale > 28: precompute the shift divisor for truncating the remainder to decimal range.
20
            bigIntRemainderShift = DecimalExtensions.BigIntPowersOfTen[Scale - DecimalExtensions.MaxDecimalScale];
27✔
21
        }
22

23
        numericVectorDataReader = new NumericVectorDataReader(dataPointer, validityMaskPointer, columnType, columnName);
969✔
24
    }
1,938✔
25

26
    internal byte Scale { get; }
3,423,426✔
27

28
    internal byte Precision { get; }
6✔
29

30
    protected override T GetValidValue<T>(ulong offset, Type targetType)
31
    {
32
        if (DuckDBType != DuckDBType.Decimal)
1,180,914!
33
        {
34
            return base.GetValidValue<T>(offset, targetType);
×
35
        }
36

37
        var value = GetDecimal(offset);
1,180,914✔
38
        return (T)(object)value; //JIT will optimize the casts at least for not nullable T
1,180,914✔
39
    }
40

41
    internal override object GetValue(ulong offset, Type targetType)
42
    {
43
        if (DuckDBType != DuckDBType.Decimal)
159!
44
        {
45
            return base.GetValue(offset, targetType);
×
46
        }
47

48
        return GetDecimal(offset);
159✔
49
    }
50

51
    private decimal GetDecimal(ulong offset)
52
    {
53
        switch (decimalType)
1,181,073!
54
        {
55
            case DuckDBType.SmallInt:
56
                {
57
                    var raw = GetFieldData<short>(offset);
126✔
58
                    return new decimal(Math.Abs(raw), 0, 0, raw < 0, Scale);
126✔
59
                }
60
            case DuckDBType.Integer:
61
                {
62
                    var raw = GetFieldData<int>(offset);
129✔
63
                    return new decimal(Math.Abs(raw), 0, 0, raw < 0, Scale);
129✔
64
                }
65
            case DuckDBType.BigInt:
66
                {
67
                    var raw = GetFieldData<long>(offset);
60,123✔
68
                    var abs = (ulong)Math.Abs(raw);
60,123✔
69
                    return new decimal((int)abs, (int)(abs >> 32), 0, raw < 0, Scale);
60,123✔
70
                }
71
            case DuckDBType.HugeInt:
72
                {
73
                    var hugeInt = numericVectorDataReader.GetBigInteger(offset, false);
1,120,695✔
74

75
                    var result = (decimal)BigInteger.DivRem(hugeInt, DecimalExtensions.BigIntPowersOfTen[Scale], out var remainder);
1,120,695✔
76

77
                    if (Scale <= DecimalExtensions.MaxDecimalScale)
1,120,695✔
78
                    {
79
                        result += decimal.Divide((decimal)remainder, DecimalExtensions.PowersOfTen[Scale]);
1,120,656✔
80
                    }
81
                    else
82
                    {
83
                        // Scale > 28: remainder can exceed decimal range.
84
                        // Shift it down to fit, losing digits beyond decimal's 28-29 digit precision.
85
                        var shiftedRemainder = remainder / bigIntRemainderShift;
39✔
86
                        result += (decimal)shiftedRemainder / DecimalExtensions.PowersOfTen[DecimalExtensions.MaxDecimalScale];
39✔
87
                    }
88

89
                    return result;
1,120,695✔
90
                }
91
            default: throw new DuckDBException($"Invalid type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}");
×
92
        }
93
    }
94

95
    internal override void Reset(IntPtr vector)
96
    {
97
        base.Reset(vector);
45✔
98
        numericVectorDataReader.Reset(vector);
45✔
99
    }
45✔
100

101
    public override void Dispose()
102
    {
103
        numericVectorDataReader.Dispose();
228✔
104
        base.Dispose();
228✔
105
    }
228✔
106
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc