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

Giorgi / DuckDB.NET / 20383681089

19 Dec 2025 10:02PM UTC coverage: 89.294% (+0.03%) from 89.262%
20383681089

push

github

Giorgi
Drop .Net Standard support

1183 of 1379 branches covered (85.79%)

Branch coverage included in aggregate %.

19 of 22 new or added lines in 13 files covered. (86.36%)

16 existing lines in 9 files now uncovered.

2295 of 2516 relevant lines covered (91.22%)

567948.85 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;
2
using System.Collections.Generic;
3
using System.Numerics;
4
using System.Runtime.CompilerServices;
5
using DuckDB.NET.Data.Extensions;
6
using DuckDB.NET.Native;
7

8
namespace DuckDB.NET.Data.DataChunk.Reader;
9

10
internal sealed class NumericVectorDataReader : VectorDataReaderBase
11
{
12
    private const int VarIntHeaderSize = 3;
13

14
    internal unsafe NumericVectorDataReader(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
44,752✔
15
    {
16
    }
44,752✔
17

18
    protected override T GetValidValue<T>(ulong offset, Type targetType)
19
    {
20
        var isFloatingNumericType = TypeExtensions.IsFloatingNumericType<T>();
2,791,873✔
21
        var isIntegralNumericType = TypeExtensions.IsIntegralNumericType<T>();
2,791,873✔
22

23
        if (!(isIntegralNumericType || isFloatingNumericType))
2,791,873✔
24
        {
25
            return base.GetValidValue<T>(offset, targetType);
18,857✔
26
        }
27

28
        //If T is integral type and column is also integral read the data and use Unsafe.As<> or Convert.ChangeType to change type
29
        //If T is floating and column is floating too, read data and cast to T
30
        //Otherwise use the non-generic path
31
        if (isIntegralNumericType)
2,773,016✔
32
        {
33
            return DuckDBType switch
1,275,962!
34
            {
1,275,962✔
35
                DuckDBType.TinyInt => GetUnmanagedTypeValue<sbyte, T>(offset),
96✔
36
                DuckDBType.SmallInt => GetUnmanagedTypeValue<short, T>(offset),
96✔
37
                DuckDBType.Integer => GetUnmanagedTypeValue<int, T>(offset),
955,910✔
38
                DuckDBType.BigInt => GetUnmanagedTypeValue<long, T>(offset),
150,474✔
39
                DuckDBType.UnsignedTinyInt => GetUnmanagedTypeValue<byte, T>(offset),
96✔
40
                DuckDBType.UnsignedSmallInt => GetUnmanagedTypeValue<ushort, T>(offset),
96✔
41
                DuckDBType.UnsignedInteger => GetUnmanagedTypeValue<uint, T>(offset),
96✔
42
                DuckDBType.UnsignedBigInt => GetUnmanagedTypeValue<ulong, T>(offset),
168✔
43
                DuckDBType.HugeInt => GetBigInteger<T>(offset, false),
66✔
44
                DuckDBType.UnsignedHugeInt => GetBigInteger<T>(offset, true),
36✔
45
                DuckDBType.VarInt => GetBigInteger<T>(offset),
168,828✔
46
                _ => base.GetValidValue<T>(offset, targetType)
×
47
            };
1,275,962✔
48
        }
49

50
        return DuckDBType switch
1,497,054!
51
        {
1,497,054✔
52
            DuckDBType.Float => (T)(object)GetFieldData<float>(offset),
746,693✔
53
            DuckDBType.Double => (T)(object)GetFieldData<double>(offset),
750,361✔
54
            _ => base.GetValidValue<T>(offset, targetType)
×
55
        };
1,497,054✔
56
    }
57

58
    internal override object GetValue(ulong offset, Type targetType)
59
    {
60
        var value = DuckDBType switch
10,621,687!
61
        {
10,621,687✔
62
            DuckDBType.TinyInt => GetFieldData<sbyte>(offset),
1,124,513✔
63
            DuckDBType.SmallInt => GetFieldData<short>(offset),
1,116,062✔
64
            DuckDBType.Integer => GetFieldData<int>(offset),
393,242✔
65
            DuckDBType.BigInt => GetFieldData<long>(offset),
1,214,544✔
66
            DuckDBType.UnsignedTinyInt => GetFieldData<byte>(offset),
1,127,012✔
67
            DuckDBType.UnsignedSmallInt => GetFieldData<ushort>(offset),
1,121,090✔
68
            DuckDBType.UnsignedInteger => GetFieldData<uint>(offset),
1,117,258✔
69
            DuckDBType.UnsignedBigInt => GetFieldData<ulong>(offset),
1,124,013✔
70
            DuckDBType.Float => GetFieldData<float>(offset),
376,332✔
71
            DuckDBType.Double => GetFieldData<double>(offset),
374,751✔
72
            DuckDBType.HugeInt => GetBigInteger(offset, false),
749,223✔
73
            DuckDBType.UnsignedHugeInt => GetBigInteger(offset, true),
746,122✔
74
            DuckDBType.VarInt => GetBigInteger<BigInteger>(offset),
37,525✔
75
            _ => base.GetValue(offset, targetType)
×
76
        };
10,621,687✔
77

78
        if (targetType.IsNumeric())
10,621,687✔
79
        {
80
            try
81
            {
82
                return Convert.ChangeType(value, targetType);
10,602,830✔
83
            }
84
            catch (OverflowException)
15✔
85
            {
86
                throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {targetType.Name} in column {ColumnName}");
15✔
87
            }
88
        }
89

90
        throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {targetType.Name} in column {ColumnName}");
18,857✔
91
    }
10,602,815✔
92

93
    internal unsafe BigInteger GetBigInteger(ulong offset, bool unsigned)
94
    {
95
        if (unsigned)
2,616,554✔
96
        {
97
            var unsignedHugeInt = (DuckDBUHugeInt*)DataPointer + offset;
746,158✔
98
            return unsignedHugeInt->ToBigInteger();
746,158✔
99
        }
100
        else
101
        {
102
            var hugeInt = (DuckDBHugeInt*)DataPointer + offset;
1,870,396✔
103
            return hugeInt->ToBigInteger();
1,870,396✔
104
        }
105
    }
106

107
    private unsafe T GetBigInteger<T>(ulong offset)
108
    {
109
        var data = (DuckDBString*)DataPointer + offset;
206,353✔
110

111
        if (data->Length < VarIntHeaderSize + 1)
206,353!
112
        {
113
            throw new DuckDBException("Invalid blob size for Varint.");
×
114
        }
115

116
        var buffer = new ReadOnlySpan<byte>(data->Data, data->Length);
206,353✔
117

118
        var isNegative = (buffer[0] & 0x80) == 0;
206,353✔
119

120
        var bytes = new List<byte>(data->Length - VarIntHeaderSize);
206,353✔
121

122
        for (var index = VarIntHeaderSize; index < buffer.Length; index++)
2,345,212✔
123
        {
124
            if (isNegative)
966,253✔
125
            {
126
                bytes.Add((byte)~buffer[index]);
470,001✔
127
            }
128
            else
129
            {
130
                bytes.Add(buffer[index]);
496,252✔
131
            }
132
        }
133

134
        var bigIntegerDigits = new Stack<char>();
206,353✔
135

136
        while (bytes.Count > 0)
2,451,114✔
137
        {
138
            var quotient = new List<char>();
2,244,761✔
139

140
            byte remainder = 0;
2,244,761✔
141

142
            foreach (var @byte in bytes)
21,962,114✔
143
            {
144
                var newValue = remainder * 256 + @byte;
8,736,296✔
145
                quotient.Add(DigitToChar(newValue / 10));
8,736,296✔
146

147
                remainder = (byte)(newValue % 10);
8,736,296✔
148
            }
149

150
            bigIntegerDigits.Push(DigitToChar(remainder));
2,244,761✔
151

152
            // Remove leading zeros from the quotient
153
            bytes.Clear();
2,244,761✔
154

155
            foreach (var digit in quotient)
21,962,114✔
156
            {
157
                if (digit != '0' || bytes.Count > 0)
8,736,296✔
158
                {
159
                    bytes.Add(CharToDigit(digit));
7,770,043✔
160
                }
161
            }
162
        }
163

164
        if (isNegative)
206,353✔
165
        {
166
            bigIntegerDigits.Push('-');
102,342✔
167
        }
168

169
        var integer = BigInteger.Parse(new string(bigIntegerDigits.ToArray()));
206,353✔
170

171
        try
172
        {
173
            return CastTo<T>(integer);
206,353✔
174
        }
175
        catch (OverflowException)
92,701✔
176
        {
177
            throw new InvalidCastException($"Cannot cast from {nameof(BigInteger)} to {typeof(T).Name} in column {ColumnName}");
92,701✔
178
        }
179

180
        char DigitToChar(int c) => (char)(c + '0');
10,981,057✔
181

182
        byte CharToDigit(char digit) => (byte)(digit - '0');
7,770,043✔
183
    }
113,652✔
184

185
    private T GetBigInteger<T>(ulong offset, bool unsigned)
186
    {
187
        var bigInteger = GetBigInteger(offset, unsigned);
102✔
188

189
        try
190
        {
191
            return CastTo<T>(bigInteger);
102✔
192
        }
193
        catch (OverflowException)
×
194
        {
195
            throw new InvalidCastException($"Cannot cast from {nameof(BigInteger)} to {typeof(T).Name} in column {ColumnName}");
×
196
        }
197
    }
102✔
198

199
    private static T CastTo<T>(BigInteger bigInteger)
200
    {
201
        if (typeof(T) == typeof(byte))
206,455✔
202
        {
203
            return (T)(object)(byte)bigInteger;
18,758✔
204
        }
205

206
        if (typeof(T) == typeof(sbyte))
187,697✔
207
        {
208
            return (T)(object)(sbyte)bigInteger;
18,761✔
209
        }
210

211
        if (typeof(T) == typeof(short))
168,936✔
212
        {
213
            return (T)(object)(short)bigInteger;
18,761✔
214
        }
215

216
        if (typeof(T) == typeof(ushort))
150,175✔
217
        {
218
            return (T)(object)(ushort)bigInteger;
18,758✔
219
        }
220

221
        if (typeof(T) == typeof(int))
131,417✔
222
        {
223
            return (T)(object)(int)bigInteger;
18,761✔
224
        }
225

226
        if (typeof(T) == typeof(uint))
112,656✔
227
        {
228
            return (T)(object)(uint)bigInteger;
18,761✔
229
        }
230

231
        if (typeof(T) == typeof(long))
93,895✔
232
        {
233
            return (T)(object)(long)bigInteger;
18,761✔
234
        }
235

236
        if (typeof(T) == typeof(ulong))
75,134✔
237
        {
238
            return (T)(object)(ulong)bigInteger;
18,761✔
239
        }
240

241
        return (T)(object)bigInteger;
56,373✔
242
    }
243

244
    private TResult GetUnmanagedTypeValue<TQuery, TResult>(ulong offset) where TQuery : unmanaged, INumberBase<TQuery>
245
    {
246
        var resultType = typeof(TResult);
1,107,032✔
247
        var value = GetFieldData<TQuery>(offset);
1,107,032✔
248

249
        if (typeof(TQuery) == resultType)
1,107,032✔
250
        {
251
            return Unsafe.As<TQuery, TResult>(ref value);
1,106,333✔
252
        }
253

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

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

© 2025 Coveralls, Inc