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

Giorgi / DuckDB.NET / 22237670288

20 Feb 2026 07:15PM UTC coverage: 89.875% (+0.2%) from 89.659%
22237670288

push

github

Giorgi
Fix decimal precision and support scale > 28

Replace lossy double-based Math.Pow(10, scale) with
pre-computed decimal and BigInteger lookup tables.

Use direct decimal constructor and mantissa extraction
instead of arithmetic reconstruction, avoiding
intermediate precision loss.

Handle HugeInt decimals with scale > 28 (beyond .NET
decimal's maximum) by truncating excess digits via
BigInteger division.

1236 of 1431 branches covered (86.37%)

Branch coverage included in aggregate %.

76 of 76 new or added lines in 5 files covered. (100.0%)

11 existing lines in 3 files now uncovered.

2510 of 2737 relevant lines covered (91.71%)

523497.92 hits per line

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

81.82
/DuckDB.NET.Data/DataChunk/Writer/VectorDataWriterBase.cs
1
using System.Runtime.CompilerServices;
2

3
namespace DuckDB.NET.Data.DataChunk.Writer;
4

5
internal unsafe class VectorDataWriterBase(IntPtr vector, void* vectorData, DuckDBType columnType) : IDisposable, IDuckDBDataWriter
1,563✔
6
{
7
    private ulong* validity;
8

9
    internal IntPtr Vector => vector;
869,399✔
10
    internal DuckDBType ColumnType => columnType;
3,905,243✔
11

12
    public void WriteNull(ulong rowIndex)
13
    {
14
        if (validity == default)
5,266,947✔
15
        {
16
            NativeMethods.Vectors.DuckDBVectorEnsureValidityWritable(Vector);
775✔
17
            validity = NativeMethods.Vectors.DuckDBVectorGetValidity(Vector);
775✔
18
        }
19

20
        NativeMethods.ValidityMask.DuckDBValiditySetRowValidity(validity, rowIndex, false);
5,266,947✔
21
    }
5,266,947✔
22

23
    public void WriteValue<T>(T value, ulong rowIndex)
24
    {
25
        if (value == null)
26,864,327✔
26
        {
27
            WriteNull(rowIndex);
5,266,947✔
28
            return;
5,266,947✔
29
        }
30

31
        _ = value switch
21,597,380!
32
        {
21,597,380✔
33
            bool val => AppendBool(val, rowIndex),
1,123,380✔
34

21,597,380✔
35
            sbyte val => AppendNumeric(val, rowIndex),
1,193,462✔
36
            short val => AppendNumeric(val, rowIndex),
1,131,593✔
37
            int val => AppendNumeric(val, rowIndex),
1,648,150✔
38
            long val => AppendNumeric(val, rowIndex),
1,247,162✔
39

21,597,380✔
40
            byte val => AppendNumeric(val, rowIndex),
1,122,724✔
41
            ushort val => AppendNumeric(val, rowIndex),
1,121,050✔
42
            uint val => AppendNumeric(val, rowIndex),
1,122,405✔
43
            ulong val => AppendNumeric(val, rowIndex),
1,119,984✔
44

21,597,380✔
45
            float val => AppendNumeric(val, rowIndex),
1,120,246✔
46
            double val => AppendNumeric(val, rowIndex),
1,121,182✔
47

21,597,380✔
48
            decimal val => AppendDecimal(val, rowIndex),
1,177,454✔
49
            BigInteger val => AppendBigInteger(val, rowIndex),
1,507,108✔
50

21,597,380✔
51
            Enum val => AppendEnum(val, rowIndex),
563,443✔
52

21,597,380✔
53
            string val => AppendString(val, rowIndex),
1,432,246✔
54
            Guid val => AppendGuid(val, rowIndex),
1,285,951✔
55
            DateTime val => AppendDateTime(val, rowIndex),
767,861✔
56
            TimeSpan val => AppendTimeSpan(val, rowIndex),
751,446✔
57
            DuckDBDateOnly val => AppendDateOnly(val, rowIndex),
120✔
58
            DuckDBTimeOnly val => AppendTimeOnly(val, rowIndex),
60✔
UNCOV
59
            DateOnly val => AppendDateOnly(val, rowIndex),
×
UNCOV
60
            TimeOnly val => AppendTimeOnly(val, rowIndex),
×
61
            DateTimeOffset val => AppendDateTimeOffset(val, rowIndex),
120✔
62
            ICollection val => AppendCollection(val, rowIndex),
1,040,233✔
63
            _ => ThrowException<T>()
×
64
        };
21,597,380✔
65
    }
×
66

67
    internal virtual bool AppendBool(bool value, ulong rowIndex) => ThrowException<bool>();
×
68

69
    internal virtual bool AppendDecimal(decimal value, ulong rowIndex) => ThrowException<decimal>();
×
70

71
    internal virtual bool AppendTimeSpan(TimeSpan value, ulong rowIndex) => ThrowException<TimeSpan>();
×
72

73
    internal virtual bool AppendGuid(Guid value, ulong rowIndex) => ThrowException<Guid>();
×
74

75
    internal virtual bool AppendBlob(byte* value, int length, ulong rowIndex) => ThrowException<byte[]>();
×
76

77
    internal virtual bool AppendString(string value, ulong rowIndex) => ThrowException<string>();
×
78

79
    internal virtual bool AppendDateTime(DateTime value, ulong rowIndex) => ThrowException<DateTime>();
×
80

81
    internal virtual bool AppendDateOnly(DateOnly value, ulong rowIndex) => ThrowException<DateOnly>();
×
82

83
    internal virtual bool AppendTimeOnly(TimeOnly value, ulong rowIndex) => ThrowException<TimeOnly>();
×
84

85
    internal virtual bool AppendDateOnly(DuckDBDateOnly value, ulong rowIndex) => ThrowException<DuckDBDateOnly>();
×
86

87
    internal virtual bool AppendTimeOnly(DuckDBTimeOnly value, ulong rowIndex) => ThrowException<DuckDBTimeOnly>();
×
88

UNCOV
89
    internal virtual bool AppendDateTimeOffset(DateTimeOffset value, ulong rowIndex) => ThrowException<DateTimeOffset>();
×
90

91
    internal virtual bool AppendNumeric<T>(T value, ulong rowIndex) where T : unmanaged => ThrowException<T>();
3✔
92

93
    internal virtual bool AppendBigInteger(BigInteger value, ulong rowIndex) => ThrowException<BigInteger>();
×
94

95
    internal virtual bool AppendEnum<TEnum>(TEnum value, ulong rowIndex) where TEnum : Enum => ThrowException<TEnum>();
×
96

UNCOV
97
    internal virtual bool AppendCollection(ICollection value, ulong rowIndex) => ThrowException<ICollection>();
×
98

99
    private bool ThrowException<T>()
100
    {
101
        throw new InvalidOperationException($"Cannot write {typeof(T).Name} to {columnType} column");
3✔
102
    }
103

104
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
105
    internal bool AppendValueInternal<T>(T value, ulong rowIndex) where T : unmanaged
106
    {
107
        ((T*)vectorData)[rowIndex] = value;
20,726,916✔
108
        return true;
20,726,916✔
109
    }
110

111
    internal void InitializeWriter()
112
    {
113
        validity = default;
1,697✔
114
        vectorData = NativeMethods.Vectors.DuckDBVectorGetData(Vector);
1,697✔
115
    }
1,697✔
116

117
    public virtual void Dispose()
118
    {
119

120
    }
1,194✔
121
}
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