• 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

87.24
/DuckDB.NET.Data/DataChunk/Reader/VectorDataReaderBase.cs
1
using System.IO;
2

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

5
internal class VectorDataReaderBase : IDisposable, IDuckDBDataReader
6
{
7
    private readonly unsafe ulong* validityMaskPointer;
8

9
    private Type? clrType;
10
    public Type ClrType => clrType ??= GetColumnType();
186,513✔
11

12
    private Type? providerSpecificClrType;
13
    public Type ProviderSpecificClrType => providerSpecificClrType ??= GetColumnProviderSpecificType();
189✔
14

15

16
    public string ColumnName { get; }
212,550✔
17
    public DuckDBType DuckDBType { get; }
21,528,006✔
18
    private protected unsafe void* DataPointer { get; }
21,433,941✔
19

20
    internal unsafe VectorDataReaderBase(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName)
58,335✔
21
    {
22
        DataPointer = dataPointer;
58,335✔
23
        this.validityMaskPointer = validityMaskPointer;
58,335✔
24

25
        DuckDBType = columnType;
58,335✔
26
        ColumnName = columnName;
58,335✔
27
    }
58,335✔
28

29
    public unsafe bool IsValid(ulong offset)
30
    {
31
        if (validityMaskPointer == default)
31,475,565✔
32
        {
33
            return true;
18,712,169✔
34
        }
35

36
        var validityMaskEntryIndex = offset / 64;
12,763,396✔
37
        var validityBitIndex = (int)(offset % 64);
12,763,396✔
38

39
        var validityMaskEntryPtr = validityMaskPointer + validityMaskEntryIndex;
12,763,396✔
40
        var validityBit = 1ul << validityBitIndex;
12,763,396✔
41

42
        var isValid = (*validityMaskEntryPtr & validityBit) != 0;
12,763,396✔
43
        return isValid;
12,763,396✔
44
    }
45

46
    public virtual T GetValue<T>(ulong offset)
47
    {
48
        var (isNullableValueType, targetType) = TypeExtensions.IsNullableValueType<T>();
5,634,741✔
49

50
        var isValid = IsValid(offset);
5,634,741✔
51

52
        //If nullable we can't use Unsafe.As because we don't have the underlying type as T so use the non-generic GetValue method.
53
        if (isNullableValueType)
5,634,741✔
54
        {
55
            return isValid
1,501,272✔
56
                ? (T)GetValue(offset, Nullable.GetUnderlyingType(targetType)!)
1,501,272✔
57
                : default!; //T is Nullable<> and we are returning null so suppress compiler warning.
1,501,272✔
58
        }
59

60
        //If we are here, T isn't Nullable<>. It can be either a value type or a class.
61
        //In both cases if the data is null we should throw.
62
        if (isValid)
4,133,469✔
63
        {
64
            return GetValidValue<T>(offset, targetType);
4,133,286✔
65
        }
66
        
67
        throw new InvalidCastException($"Column '{ColumnName}' value is null");
183✔
68
    }
69

70
    /// <summary>
71
    /// Called when the value at specified <param name="offset">offset</param> is valid (isn't null)
72
    /// </summary>
73
    /// <typeparam name="T">Type of the return value</typeparam>
74
    /// <param name="offset">Position to read the data from</param>
75
    /// <param name="targetType">Type of the return value</param>
76
    /// <returns>Data at the specified offset</returns>
77
    protected virtual T GetValidValue<T>(ulong offset, Type targetType)
78
    {
79
        return (T)GetValue(offset, targetType);
517,326✔
80
    }
81

82
    public object GetValue(ulong offset)
83
    {
84
        return GetValue(offset, ClrType);
166,599✔
85
    }
86

87
    internal virtual object GetValue(ulong offset, Type targetType)
88
    {
UNCOV
89
        return DuckDBType switch
×
UNCOV
90
        {
×
UNCOV
91
            DuckDBType.Invalid => throw new DuckDBException($"Invalid type for column {ColumnName}"),
×
UNCOV
92
            _ => throw new ArgumentException($"Unrecognised type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}")
×
UNCOV
93
        };
×
94
    }
95

96
    internal object GetProviderSpecificValue(ulong offset)
97
    {
98
        return GetValue(offset, ProviderSpecificClrType);
48✔
99
    }
100

101
    protected virtual Type GetColumnType()
102
    {
103
        return DuckDBType switch
39,333!
104
        {
39,333✔
UNCOV
105
            DuckDBType.Invalid => throw new DuckDBException($"Invalid type for column {ColumnName}"),
×
106
            DuckDBType.Boolean => typeof(bool),
66✔
107
            DuckDBType.TinyInt => typeof(sbyte),
39✔
108
            DuckDBType.SmallInt => typeof(short),
39✔
109
            DuckDBType.Integer => typeof(int),
222✔
110
            DuckDBType.BigInt => typeof(long),
219✔
111
            DuckDBType.UnsignedTinyInt => typeof(byte),
42✔
112
            DuckDBType.UnsignedSmallInt => typeof(ushort),
39✔
113
            DuckDBType.UnsignedInteger => typeof(uint),
39✔
114
            DuckDBType.UnsignedBigInt => typeof(ulong),
57✔
115
            DuckDBType.Float => typeof(float),
27✔
116
            DuckDBType.Double => typeof(double),
39✔
117
            DuckDBType.Timestamp => typeof(DateTime),
87✔
118
            DuckDBType.Interval => typeof(TimeSpan),
15✔
119
            DuckDBType.Date => typeof(DateOnly),
48✔
120
            DuckDBType.Time => typeof(TimeOnly),
96✔
121
            DuckDBType.TimeTz => typeof(DateTimeOffset),
21✔
122
            DuckDBType.HugeInt => typeof(BigInteger),
15✔
123
            DuckDBType.UnsignedHugeInt => typeof(BigInteger),
3✔
124
            DuckDBType.Varchar => typeof(string),
312✔
125
            DuckDBType.Decimal => typeof(decimal),
198✔
126
            DuckDBType.TimestampS => typeof(DateTime),
21✔
127
            DuckDBType.TimestampMs => typeof(DateTime),
21✔
128
            DuckDBType.TimestampNs => typeof(DateTime),
24✔
129
            DuckDBType.Blob => typeof(Stream),
9✔
130
            DuckDBType.Enum => typeof(string),
42✔
131
            DuckDBType.Uuid => typeof(Guid),
30✔
132
            DuckDBType.Struct => typeof(Dictionary<string, object>),
9✔
133
            DuckDBType.Bit => typeof(string),
6✔
134
            DuckDBType.TimestampTz => typeof(DateTime),
24✔
135
            DuckDBType.VarInt => typeof(BigInteger),
37,524✔
UNCOV
136
            _ => throw new ArgumentException($"Unrecognised type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}")
×
137
        };
39,333✔
138
    }
139

140
    protected virtual Type GetColumnProviderSpecificType()
141
    {
142
        return DuckDBType switch
123!
143
        {
123✔
UNCOV
144
            DuckDBType.Invalid => throw new DuckDBException($"Invalid type for column {ColumnName}"),
×
145
            DuckDBType.Boolean => typeof(bool),
3✔
146
            DuckDBType.TinyInt => typeof(sbyte),
3✔
147
            DuckDBType.SmallInt => typeof(short),
3✔
148
            DuckDBType.Integer => typeof(int),
9✔
149
            DuckDBType.BigInt => typeof(long),
3✔
150
            DuckDBType.UnsignedTinyInt => typeof(byte),
3✔
151
            DuckDBType.UnsignedSmallInt => typeof(ushort),
3✔
152
            DuckDBType.UnsignedInteger => typeof(uint),
3✔
153
            DuckDBType.UnsignedBigInt => typeof(ulong),
3✔
154
            DuckDBType.Float => typeof(float),
3✔
155
            DuckDBType.Double => typeof(double),
6✔
156
            DuckDBType.Timestamp => typeof(DuckDBTimestamp),
6✔
157
            DuckDBType.Interval => typeof(DuckDBInterval),
3✔
158
            DuckDBType.Date => typeof(DuckDBDateOnly),
6✔
159
            DuckDBType.Time => typeof(DuckDBTimeOnly),
3✔
160
            DuckDBType.TimeTz => typeof(DuckDBTimeTz),
3✔
161
            DuckDBType.HugeInt => typeof(DuckDBHugeInt),
3✔
162
            DuckDBType.UnsignedHugeInt => typeof(DuckDBUHugeInt),
3✔
163
            DuckDBType.Varchar => typeof(string),
3✔
164
            DuckDBType.Decimal => typeof(decimal),
12✔
165
            DuckDBType.TimestampS => typeof(DuckDBTimestamp),
3✔
166
            DuckDBType.TimestampMs => typeof(DuckDBTimestamp),
3✔
167
            DuckDBType.TimestampNs => typeof(DuckDBTimestamp),
3✔
168
            DuckDBType.Blob => typeof(Stream),
3✔
169
            DuckDBType.Enum => typeof(string),
9✔
170
            DuckDBType.Uuid => typeof(Guid),
3✔
171
            DuckDBType.Struct => typeof(Dictionary<string, object>),
3✔
172
            DuckDBType.Bit => typeof(string),
3✔
173
            DuckDBType.TimestampTz => typeof(DuckDBTimestamp),
6✔
174
            DuckDBType.VarInt => typeof(BigInteger),
3✔
UNCOV
175
            _ => throw new ArgumentException($"Unrecognised type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}")
×
176
        };
123✔
177
    }
178

179
    protected unsafe T GetFieldData<T>(ulong offset) where T : unmanaged => *((T*)DataPointer + offset);
16,734,586✔
180

181
    public virtual void Dispose()
182
    {
183
    }
41,727✔
184
}
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