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

Giorgi / DuckDB.NET / 35471425363

19 Sep 2026 09:46PM UTC coverage: 88.269% (-1.1%) from 89.361%
35471425363

push

github

Giorgi
Drop the enable_http_logging grouping case

DuckDB main no longer has the enable_http_logging setting, so the
connection string builder does not expose it and the lookup returned
null. No remaining option combines the http and logging segments, so
the case has no replacement here. develop keeps it while it targets
v1.5.5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QEQt5x6WgR3rH3Zsd1guVT

1587 of 1885 branches covered (84.19%)

Branch coverage included in aggregate %.

3161 of 3494 relevant lines covered (90.47%)

375857.45 hits per line

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

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

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

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

10
    internal unsafe NumericVectorDataReader(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
45,396 ✔
11
    {
12
    }
45,396 ✔
13

14
    protected override T GetValidValue<T>(ulong offset)
15
    {
16
        var isFloatingNumericType = TypeExtensions.IsFloatingNumericType<T>();
4,054,030 ✔
17
        var isIntegralNumericType = TypeExtensions.IsIntegralNumericType<T>();
4,054,030 ✔
18

19
        if (!(isIntegralNumericType || isFloatingNumericType))
4,054,030 ✔
20
        {
21
            return base.GetValidValue<T>(offset);
18,858 ✔
22
        }
23

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

46
        return DuckDBType switch
2,249,641 !
47
        {
2,249,641 ✔
48
            DuckDBType.Float => (T)(object)GetFieldData<float>(offset),
1,135,062 ✔
49
            DuckDBType.Double => (T)(object)GetFieldData<double>(offset),
1,114,579 ✔
50
            _ => base.GetValidValue<T>(offset)
×
51
        };
2,249,641 ✔
52
    }
53

54
    internal override object GetValue(ulong offset, Type targetType)
55
    {
56
        var value = DuckDBType switch
9,624,463 !
57
        {
9,624,463 ✔
58
            DuckDBType.TinyInt => GetFieldData<sbyte>(offset),
1,121,689 ✔
59
            DuckDBType.SmallInt => GetFieldData<short>(offset),
1,120,506 ✔
60
            DuckDBType.Integer => GetFieldData<int>(offset),
31,500 ✔
61
            DuckDBType.BigInt => GetFieldData<long>(offset),
1,321,573 ✔
62
            DuckDBType.UnsignedTinyInt => GetFieldData<byte>(offset),
1,117,685 ✔
63
            DuckDBType.UnsignedSmallInt => GetFieldData<ushort>(offset),
1,124,497 ✔
64
            DuckDBType.UnsignedInteger => GetFieldData<uint>(offset),
1,127,996 ✔
65
            DuckDBType.UnsignedBigInt => GetFieldData<ulong>(offset),
1,121,587 ✔
66
            DuckDBType.Float => GetFieldData<float>(offset),
78 ✔
67
            DuckDBType.Double => GetFieldData<double>(offset),
264 ✔
68
            DuckDBType.HugeInt => GetBigInteger(offset, false),
747,193 ✔
69
            DuckDBType.UnsignedHugeInt => GetBigInteger(offset, true),
752,368 ✔
70
            DuckDBType.VarInt => GetBigInteger<BigInteger>(offset),
37,527 ✔
71
            _ => base.GetValue(offset, targetType)
×
72
        };
9,624,463 ✔
73

74
        // Fast path: when the boxed value already has the requested type (the common case for
75
        // GetValue(ordinal)/this[ordinal], which read using the column's natural ClrType), skip the
76
        // Convert.ChangeType machinery entirely. ChangeType does not early-out on same-type for
77
        // IConvertible values — it re-boxes via ToXxx() — so this also removes a redundant box.
78
        if (value.GetType() == targetType)
9,624,463 ✔
79
        {
80
            return value;
9,605,527 ✔
81
        }
82

83
        if (targetType.IsNumeric())
18,936 ✔
84
        {
85
            try
86
            {
87
                return Convert.ChangeType(value, targetType);
78 ✔
88
            }
89
            catch (OverflowException)
15 ✔
90
            {
91
                throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {targetType.Name} in column {ColumnName}");
15 ✔
92
            }
93
        }
94

95
        throw new InvalidCastException($"Cannot cast from {value.GetType().Name} to {targetType.Name} in column {ColumnName}");
18,858 ✔
96
    }
63 ✔
97

98
    internal unsafe BigInteger GetBigInteger(ulong offset, bool unsigned)
99
    {
100
        if (unsigned)
2,620,475 ✔
101
        {
102
            var unsignedHugeInt = (DuckDBUHugeInt*)DataPointer + offset;
752,404 ✔
103
            return unsignedHugeInt->ToBigInteger();
752,404 ✔
104
        }
105
        else
106
        {
107
            var hugeInt = (DuckDBHugeInt*)DataPointer + offset;
1,868,071 ✔
108
            return hugeInt->ToBigInteger();
1,868,071 ✔
109
        }
110
    }
111

112
    private unsafe T GetBigInteger<T>(ulong offset)
113
    {
114
        var data = (DuckDBString*)DataPointer + offset;
206,364 ✔
115

116
        if (data->Length < VarIntHeaderSize + 1)
206,364 !
117
        {
118
            throw new DuckDBException("Invalid blob size for Varint.");
×
119
        }
120

121
        var buffer = new ReadOnlySpan<byte>(data->Data, data->Length);
206,364 ✔
122
        var isPositive = (buffer[0] & 0x80) != 0;
206,364 ✔
123
        var source = buffer.Slice(VarIntHeaderSize);
206,364 ✔
124

125
        byte[]? rented = null;
206,364 ✔
126

127
        try
128
        {
129
            if (isPositive) return ConvertNumeric<BigInteger, T>(new BigInteger(source, isUnsigned: true, isBigEndian: true));
310,386 ✔
130

131
            // Negative values need byte complementing — use stack for small payloads, pool for large.
132
            Span<byte> payload = source.Length <= 128
102,342 !
133
                ? stackalloc byte[source.Length]
102,342 ✔
134
                : (rented = ArrayPool<byte>.Shared.Rent(source.Length)).AsSpan(0, source.Length);
102,342 ✔
135

136
            for (var i = 0; i < source.Length; i++)
1,144,686 ✔
137
            {
138
                payload[i] = (byte)~source[i];
470,001 ✔
139
            }
140

141
            return ConvertNumeric<BigInteger, T>(-new BigInteger(payload, isUnsigned: true, isBigEndian: true));
102,342 ✔
142
        }
143
        catch (OverflowException)
92,709 ✔
144
        {
145
            throw new InvalidCastException($"Cannot cast from {nameof(BigInteger)} to {typeof(T).Name} in column {ColumnName}");
92,709 ✔
146
        }
147
        finally
148
        {
149
            if (rented != null)
206,364 !
150
            {
151
                ArrayPool<byte>.Shared.Return(rented);
×
152
            }
153
        }
206,364 ✔
154
    }
113,655 ✔
155

156
    private T GetBigInteger<T>(ulong offset, bool unsigned)
157
    {
158
        var bigInteger = GetBigInteger(offset, unsigned);
102 ✔
159

160
        try
161
        {
162
            return ConvertNumeric<BigInteger, T>(bigInteger);
102 ✔
163
        }
164
        catch (OverflowException)
×
165
        {
166
            throw new InvalidCastException($"Cannot cast from {nameof(BigInteger)} to {typeof(T).Name} in column {ColumnName}");
×
167
        }
168
    }
102 ✔
169

170
    private TResult GetUnmanagedTypeValue<TQuery, TResult>(ulong offset) where TQuery : unmanaged, INumberBase<TQuery>
171
    {
172
        var value = GetFieldData<TQuery>(offset);
1,616,592 ✔
173

174
        try
175
        {
176
            return ConvertNumeric<TQuery, TResult>(value);
1,616,592 ✔
177
        }
178
        catch (OverflowException)
243 ✔
179
        {
180
            throw new InvalidCastException($"Cannot cast from {typeof(TQuery).Name} to {typeof(TResult).Name} in column {ColumnName}");
243 ✔
181
        }
182
    }
1,616,349 ✔
183

184
    private static TResult ConvertNumeric<TSource, TResult>(TSource value) where TSource : INumberBase<TSource>
185
    {
186
        if (typeof(TSource) == typeof(TResult))
1,823,058 ✔
187
            return Unsafe.As<TSource, TResult>(ref value);
1,672,269 ✔
188

189
        if (typeof(TResult) == typeof(byte))       return (TResult)(object)byte.CreateChecked(value);
169,638 ✔
190
        if (typeof(TResult) == typeof(sbyte))      return (TResult)(object)sbyte.CreateChecked(value);
150,792 ✔
191
        if (typeof(TResult) == typeof(short))      return (TResult)(object)short.CreateChecked(value);
131,940 ✔
192
        if (typeof(TResult) == typeof(ushort))     return (TResult)(object)ushort.CreateChecked(value);
113,085 ✔
193
        if (typeof(TResult) == typeof(int))        return (TResult)(object)int.CreateChecked(value);
94,236 ✔
194
        if (typeof(TResult) == typeof(uint))       return (TResult)(object)uint.CreateChecked(value);
75,390 ✔
195
        if (typeof(TResult) == typeof(long))       return (TResult)(object)long.CreateChecked(value);
56,529 ✔
196
        if (typeof(TResult) == typeof(ulong))      return (TResult)(object)ulong.CreateChecked(value);
37,686 !
197
        if (typeof(TResult) == typeof(BigInteger)) return (TResult)(object)BigInteger.CreateChecked(value);
×
198

199
        throw new InvalidCastException($"Cannot convert {typeof(TSource).Name} to {typeof(TResult).Name}");
×
200
    }
201
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc