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

Giorgi / DuckDB.NET / 21786556530

07 Feb 2026 08:39PM UTC coverage: 89.155% (-0.07%) from 89.223%
21786556530

push

github

Giorgi
Added support for clearing in-progress adapter

Requires DuckDB 1.5

1199 of 1393 branches covered (86.07%)

Branch coverage included in aggregate %.

6 of 8 new or added lines in 1 file covered. (75.0%)

193 existing lines in 43 files now uncovered.

2336 of 2572 relevant lines covered (90.82%)

557295.56 hits per line

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

90.76
/DuckDB.NET.Data/DataChunk/Reader/NumericVectorDataReader.cs
1
using System.Runtime.CompilerServices;
2

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

5
internal sealed class NumericVectorDataReader : VectorDataReaderBase
6
{
7
    private const int VarIntHeaderSize = 3;
8

9
    internal unsafe NumericVectorDataReader(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
44,916✔
10
    {
11
    }
44,916✔
12

13
    protected override T GetValidValue<T>(ulong offset, Type targetType)
14
    {
15
        var isFloatingNumericType = TypeExtensions.IsFloatingNumericType<T>();
2,795,260✔
16
        var isIntegralNumericType = TypeExtensions.IsIntegralNumericType<T>();
2,795,260✔
17

18
        if (!(isIntegralNumericType || isFloatingNumericType))
2,795,260✔
19
        {
20
            return base.GetValidValue<T>(offset, targetType);
18,858✔
21
        }
22

23
        //If T is integral type and column is also integral read the data and use Unsafe.As<> or Convert.ChangeType to change type
24
        //If T is floating and column is floating too, read data and cast to T
25
        //Otherwise use the non-generic path
26
        if (isIntegralNumericType)
2,776,402✔
27
        {
28
            return DuckDBType switch
1,277,445!
29
            {
1,277,445✔
30
                DuckDBType.TinyInt => GetUnmanagedTypeValue<sbyte, T>(offset),
96✔
31
                DuckDBType.SmallInt => GetUnmanagedTypeValue<short, T>(offset),
96✔
32
                DuckDBType.Integer => GetUnmanagedTypeValue<int, T>(offset),
957,384✔
33
                DuckDBType.BigInt => GetUnmanagedTypeValue<long, T>(offset),
150,474✔
34
                DuckDBType.UnsignedTinyInt => GetUnmanagedTypeValue<byte, T>(offset),
96✔
35
                DuckDBType.UnsignedSmallInt => GetUnmanagedTypeValue<ushort, T>(offset),
96✔
36
                DuckDBType.UnsignedInteger => GetUnmanagedTypeValue<uint, T>(offset),
96✔
37
                DuckDBType.UnsignedBigInt => GetUnmanagedTypeValue<ulong, T>(offset),
168✔
38
                DuckDBType.HugeInt => GetBigInteger<T>(offset, false),
66✔
39
                DuckDBType.UnsignedHugeInt => GetBigInteger<T>(offset, true),
36✔
40
                DuckDBType.VarInt => GetBigInteger<T>(offset),
168,837✔
UNCOV
41
                _ => base.GetValidValue<T>(offset, targetType)
×
42
            };
1,277,445✔
43
        }
44

45
        return DuckDBType switch
1,498,957!
46
        {
1,498,957✔
47
            DuckDBType.Float => (T)(object)GetFieldData<float>(offset),
754,380✔
48
            DuckDBType.Double => (T)(object)GetFieldData<double>(offset),
744,577✔
UNCOV
49
            _ => base.GetValidValue<T>(offset, targetType)
×
50
        };
1,498,957✔
51
    }
52

53
    internal override object GetValue(ulong offset, Type targetType)
54
    {
55
        var value = DuckDBType switch
10,636,680!
56
        {
10,636,680✔
57
            DuckDBType.TinyInt => GetFieldData<sbyte>(offset),
1,125,600✔
58
            DuckDBType.SmallInt => GetFieldData<short>(offset),
1,123,595✔
59
            DuckDBType.Integer => GetFieldData<int>(offset),
391,170✔
60
            DuckDBType.BigInt => GetFieldData<long>(offset),
1,217,684✔
61
            DuckDBType.UnsignedTinyInt => GetFieldData<byte>(offset),
1,117,916✔
62
            DuckDBType.UnsignedSmallInt => GetFieldData<ushort>(offset),
1,116,638✔
63
            DuckDBType.UnsignedInteger => GetFieldData<uint>(offset),
1,128,761✔
64
            DuckDBType.UnsignedBigInt => GetFieldData<ulong>(offset),
1,134,817✔
65
            DuckDBType.Float => GetFieldData<float>(offset),
377,818✔
66
            DuckDBType.Double => GetFieldData<double>(offset),
375,231✔
67
            DuckDBType.HugeInt => GetBigInteger(offset, false),
749,349✔
68
            DuckDBType.UnsignedHugeInt => GetBigInteger(offset, true),
740,574✔
69
            DuckDBType.VarInt => GetBigInteger<BigInteger>(offset),
37,527✔
UNCOV
70
            _ => base.GetValue(offset, targetType)
×
71
        };
10,636,680✔
72

73
        if (targetType.IsNumeric())
10,636,680✔
74
        {
75
            try
76
            {
77
                return Convert.ChangeType(value, targetType);
10,617,822✔
78
            }
79
            catch (OverflowException)
15✔
80
            {
81
                throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {targetType.Name} in column {ColumnName}");
15✔
82
            }
83
        }
84

85
        throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {targetType.Name} in column {ColumnName}");
18,858✔
86
    }
10,617,807✔
87

88
    internal unsafe BigInteger GetBigInteger(ulong offset, bool unsigned)
89
    {
90
        if (unsigned)
2,611,120✔
91
        {
92
            var unsignedHugeInt = (DuckDBUHugeInt*)DataPointer + offset;
740,610✔
93
            return unsignedHugeInt->ToBigInteger();
740,610✔
94
        }
95
        else
96
        {
97
            var hugeInt = (DuckDBHugeInt*)DataPointer + offset;
1,870,510✔
98
            return hugeInt->ToBigInteger();
1,870,510✔
99
        }
100
    }
101

102
    private unsafe T GetBigInteger<T>(ulong offset)
103
    {
104
        var data = (DuckDBString*)DataPointer + offset;
206,364✔
105

106
        if (data->Length < VarIntHeaderSize + 1)
206,364!
107
        {
UNCOV
108
            throw new DuckDBException("Invalid blob size for Varint.");
×
109
        }
110

111
        var buffer = new ReadOnlySpan<byte>(data->Data, data->Length);
206,364✔
112

113
        var isNegative = (buffer[0] & 0x80) == 0;
206,364✔
114

115
        var bytes = new List<byte>(data->Length - VarIntHeaderSize);
206,364✔
116

117
        for (var index = VarIntHeaderSize; index < buffer.Length; index++)
2,345,586✔
118
        {
119
            if (isNegative)
966,429✔
120
            {
121
                bytes.Add((byte)~buffer[index]);
470,001✔
122
            }
123
            else
124
            {
125
                bytes.Add(buffer[index]);
496,428✔
126
            }
127
        }
128

129
        var bigIntegerDigits = new Stack<char>();
206,364✔
130

131
        while (bytes.Count > 0)
2,451,543✔
132
        {
133
            var quotient = new List<char>();
2,245,179✔
134

135
            byte remainder = 0;
2,245,179✔
136

137
            foreach (var @byte in bytes)
21,970,122✔
138
            {
139
                var newValue = remainder * 256 + @byte;
8,739,882✔
140
                quotient.Add(DigitToChar(newValue / 10));
8,739,882✔
141

142
                remainder = (byte)(newValue % 10);
8,739,882✔
143
            }
144

145
            bigIntegerDigits.Push(DigitToChar(remainder));
2,245,179✔
146

147
            // Remove leading zeros from the quotient
148
            bytes.Clear();
2,245,179✔
149

150
            foreach (var digit in quotient)
21,970,122✔
151
            {
152
                if (digit != '0' || bytes.Count > 0)
8,739,882✔
153
                {
154
                    bytes.Add(CharToDigit(digit));
7,773,453✔
155
                }
156
            }
157
        }
158

159
        if (isNegative)
206,364✔
160
        {
161
            bigIntegerDigits.Push('-');
102,342✔
162
        }
163

164
        var integer = BigInteger.Parse(new string(bigIntegerDigits.ToArray()));
206,364✔
165

166
        try
167
        {
168
            return CastTo<T>(integer);
206,364✔
169
        }
170
        catch (OverflowException)
92,709✔
171
        {
172
            throw new InvalidCastException($"Cannot cast from {nameof(BigInteger)} to {typeof(T).Name} in column {ColumnName}");
92,709✔
173
        }
174

175
        char DigitToChar(int c) => (char)(c + '0');
10,985,061✔
176

177
        byte CharToDigit(char digit) => (byte)(digit - '0');
7,773,453✔
178
    }
113,655✔
179

180
    private T GetBigInteger<T>(ulong offset, bool unsigned)
181
    {
182
        var bigInteger = GetBigInteger(offset, unsigned);
102✔
183

184
        try
185
        {
186
            return CastTo<T>(bigInteger);
102✔
187
        }
UNCOV
188
        catch (OverflowException)
×
189
        {
UNCOV
190
            throw new InvalidCastException($"Cannot cast from {nameof(BigInteger)} to {typeof(T).Name} in column {ColumnName}");
×
191
        }
192
    }
102✔
193

194
    private static T CastTo<T>(BigInteger bigInteger)
195
    {
196
        if (typeof(T) == typeof(byte))
206,466✔
197
        {
198
            return (T)(object)(byte)bigInteger;
18,759✔
199
        }
200

201
        if (typeof(T) == typeof(sbyte))
187,707✔
202
        {
203
            return (T)(object)(sbyte)bigInteger;
18,762✔
204
        }
205

206
        if (typeof(T) == typeof(short))
168,945✔
207
        {
208
            return (T)(object)(short)bigInteger;
18,762✔
209
        }
210

211
        if (typeof(T) == typeof(ushort))
150,183✔
212
        {
213
            return (T)(object)(ushort)bigInteger;
18,759✔
214
        }
215

216
        if (typeof(T) == typeof(int))
131,424✔
217
        {
218
            return (T)(object)(int)bigInteger;
18,762✔
219
        }
220

221
        if (typeof(T) == typeof(uint))
112,662✔
222
        {
223
            return (T)(object)(uint)bigInteger;
18,762✔
224
        }
225

226
        if (typeof(T) == typeof(long))
93,900✔
227
        {
228
            return (T)(object)(long)bigInteger;
18,762✔
229
        }
230

231
        if (typeof(T) == typeof(ulong))
75,138✔
232
        {
233
            return (T)(object)(ulong)bigInteger;
18,762✔
234
        }
235

236
        return (T)(object)bigInteger;
56,376✔
237
    }
238

239
    private TResult GetUnmanagedTypeValue<TQuery, TResult>(ulong offset) where TQuery : unmanaged
240
        , INumberBase<TQuery>
241
    {
242
        var resultType = typeof(TResult);
1,108,506✔
243
        var value = GetFieldData<TQuery>(offset);
1,108,506✔
244

245
        if (typeof(TQuery) == resultType)
1,108,506✔
246
        {
247
            return Unsafe.As<TQuery, TResult>(ref value);
1,107,807✔
248
        }
249

250
        try
251
        {
252
            if (resultType == typeof(byte))
699✔
253
            {
254
                return (TResult)(object)byte.CreateChecked(value);
90✔
255
            }
256
            if (resultType == typeof(sbyte))
609✔
257
            {
258
                return (TResult)(object)sbyte.CreateChecked(value);
90✔
259
            }
260
            if (resultType == typeof(short))
519✔
261
            {
262
                return (TResult)(object)short.CreateChecked(value);
90✔
263
            }
264
            if (resultType == typeof(ushort))
429✔
265
            {
266
                return (TResult)(object)ushort.CreateChecked(value);
90✔
267
            }
268
            if (resultType == typeof(int))
339✔
269
            {
270
                return (TResult)(object)int.CreateChecked(value);
87✔
271
            }
272
            if (resultType == typeof(uint))
252✔
273
            {
274
                return (TResult)(object)uint.CreateChecked(value);
90✔
275
            }
276
            if (resultType == typeof(long))
162✔
277
            {
278
                return (TResult)(object)long.CreateChecked(value);
81✔
279
            }
280
            if (resultType == typeof(ulong))
81!
281
            {
282
                return (TResult)(object)ulong.CreateChecked(value);
81✔
283
            }
284

UNCOV
285
            return (TResult)Convert.ChangeType(value, resultType);
×
286
        }
287
        catch (OverflowException)
243✔
288
        {
289
            throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {resultType.Name} in column {ColumnName}");
243✔
290
        }
291
    }
456✔
292
}
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