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

Giorgi / DuckDB.NET / 10762260192

08 Sep 2024 06:40PM UTC coverage: 90.033% (-0.2%) from 90.226%
10762260192

push

github

Giorgi
Merge branch 'nightly-varint' into nightly-build

886 of 1013 branches covered (87.46%)

Branch coverage included in aggregate %.

45 of 48 new or added lines in 2 files covered. (93.75%)

32 existing lines in 5 files now uncovered.

1833 of 2007 relevant lines covered (91.33%)

876732.29 hits per line

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

87.75
/DuckDB.NET.Data/Internal/Reader/VectorDataReaderBase.cs
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Numerics;
5
using DuckDB.NET.Data.Extensions;
6
using DuckDB.NET.Data.Reader;
7
using DuckDB.NET.Native;
8

9
namespace DuckDB.NET.Data.Internal.Reader;
10

11
internal class VectorDataReaderBase : IDisposable
12
#if NET8_0_OR_GREATER
13
#pragma warning disable DuckDBNET001
14
    , IDuckDBDataReader 
15
#pragma warning restore DuckDBNET001
16
#endif
17
{
18
    private readonly unsafe ulong* validityMaskPointer;
19

20
    private Type? clrType;
21
    public Type ClrType => clrType ??= GetColumnType();
210,100✔
22

23
    private Type? providerSpecificClrType;
24
    public Type ProviderSpecificClrType => providerSpecificClrType ??= GetColumnProviderSpecificType();
177✔
25

26

27
    public string ColumnName { get; }
201,750✔
28
    public DuckDBType DuckDBType { get; }
20,181,619✔
29
    private protected unsafe void* DataPointer { get; }
20,098,493✔
30

31
    internal unsafe VectorDataReaderBase(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName)
80,873✔
32
    {
33
        DataPointer = dataPointer;
80,873✔
34
        this.validityMaskPointer = validityMaskPointer;
80,873✔
35

36
        DuckDBType = columnType;
80,873✔
37
        ColumnName = columnName;
80,873✔
38
    }
80,873✔
39

40
    public unsafe bool IsValid(ulong offset)
41
    {
42
        if (validityMaskPointer == default)
29,696,868✔
43
        {
44
            return true;
150,594✔
45
        }
46

47
        var validityMaskEntryIndex = offset / 64;
29,546,274✔
48
        var validityBitIndex = (int)(offset % 64);
29,546,274✔
49

50
        var validityMaskEntryPtr = validityMaskPointer + validityMaskEntryIndex;
29,546,274✔
51
        var validityBit = 1ul << validityBitIndex;
29,546,274✔
52

53
        var isValid = (*validityMaskEntryPtr & validityBit) != 0;
29,546,274✔
54
        return isValid;
29,546,274✔
55
    }
56

57
    public virtual T GetValue<T>(ulong offset)
58
    {
59
        var (isNullableValueType, targetType) = TypeExtensions.IsNullableValueType<T>();
5,576,660✔
60

61
        var isValid = IsValid(offset);
5,576,660✔
62

63
        //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.
64
        if (isNullableValueType)
5,576,660✔
65
        {
66
            return isValid
1,497,407✔
67
                ? (T)GetValue(offset, Nullable.GetUnderlyingType(targetType)!)
1,497,407✔
68
                : default!; //T is Nullable<> and we are returning null so suppress compiler warning.
1,497,407✔
69
        }
70

71
        //If we are here, T isn't Nullable<>. It can be either a value type or a class.
72
        //In both cases if the data is null we should throw.
73
        if (isValid)
4,079,253✔
74
        {
75
            return GetValidValue<T>(offset, targetType);
4,079,076✔
76
        }
77
        
78
        throw new InvalidCastException($"Column '{ColumnName}' value is null");
177✔
79
    }
80

81
    /// <summary>
82
    /// Called when the value at specified <param name="offset">offset</param> is valid (isn't null)
83
    /// </summary>
84
    /// <typeparam name="T">Type of the return value</typeparam>
85
    /// <param name="offset">Position to read the data from</param>
86
    /// <param name="targetType">Type of the return value</param>
87
    /// <returns>Data at the specified offset</returns>
88
    protected virtual T GetValidValue<T>(ulong offset, Type targetType)
89
    {
90
        return (T)GetValue(offset, targetType);
415,527✔
91
    }
92

93
    public object GetValue(ulong offset)
94
    {
95
        return GetValue(offset, ClrType);
178,041✔
96
    }
97

98
    internal virtual object GetValue(ulong offset, Type targetType)
99
    {
UNCOV
100
        return DuckDBType switch
×
UNCOV
101
        {
×
UNCOV
102
            DuckDBType.Invalid => throw new DuckDBException($"Invalid type for column {ColumnName}"),
×
UNCOV
103
            _ => throw new ArgumentException($"Unrecognised type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}")
×
UNCOV
104
        };
×
105
    }
106

107
    internal object GetProviderSpecificValue(ulong offset)
108
    {
109
        return GetValue(offset, ProviderSpecificClrType);
48✔
110
    }
111

112
    protected virtual Type GetColumnType()
113
    {
114
        return DuckDBType switch
63,806!
115
        {
63,806✔
UNCOV
116
            DuckDBType.Invalid => throw new DuckDBException($"Invalid type for column {ColumnName}"),
×
117
            DuckDBType.Boolean => typeof(bool),
30✔
118
            DuckDBType.TinyInt => typeof(sbyte),
36✔
119
            DuckDBType.SmallInt => typeof(short),
36✔
120
            DuckDBType.Integer => typeof(int),
201✔
121
            DuckDBType.BigInt => typeof(long),
207✔
122
            DuckDBType.UnsignedTinyInt => typeof(byte),
36✔
123
            DuckDBType.UnsignedSmallInt => typeof(ushort),
36✔
124
            DuckDBType.UnsignedInteger => typeof(uint),
36✔
125
            DuckDBType.UnsignedBigInt => typeof(ulong),
54✔
126
            DuckDBType.Float => typeof(float),
12✔
127
            DuckDBType.Double => typeof(double),
24✔
128
            DuckDBType.Timestamp => typeof(DateTime),
72✔
129
            DuckDBType.Interval => typeof(TimeSpan),
12✔
130
#if NET6_0_OR_GREATER
63,806✔
131
            DuckDBType.Date => typeof(DateOnly),
36✔
132
#else
63,806✔
133
            DuckDBType.Date => typeof(DateTime),
63,806✔
134
#endif
63,806✔
135
#if NET6_0_OR_GREATER
63,806✔
136
            DuckDBType.Time => typeof(TimeOnly),
57✔
137
#else
63,806✔
138
            DuckDBType.Time => typeof(TimeSpan),
63,806✔
139
#endif
63,806✔
140
            DuckDBType.TimeTz => typeof(DateTimeOffset),
21✔
141
            DuckDBType.HugeInt => typeof(BigInteger),
12✔
142
            DuckDBType.UnsignedHugeInt => typeof(BigInteger),
3✔
143
            DuckDBType.Varchar => typeof(string),
299✔
144
            DuckDBType.Decimal => typeof(decimal),
156✔
145
            DuckDBType.TimestampS => typeof(DateTime),
3✔
146
            DuckDBType.TimestampMs => typeof(DateTime),
3✔
147
            DuckDBType.TimestampNs => typeof(DateTime),
6✔
148
            DuckDBType.Blob => typeof(Stream),
9✔
149
            DuckDBType.Enum => typeof(string),
15✔
150
            DuckDBType.Uuid => typeof(Guid),
30✔
151
            DuckDBType.Struct => typeof(Dictionary<string, object>),
9✔
152
            DuckDBType.Bit => typeof(string),
6✔
153
            DuckDBType.TimestampTz => typeof(DateTime),
3✔
154
            DuckDBType.VarInt => typeof(BigInteger),
62,346✔
UNCOV
155
            _ => throw new ArgumentException($"Unrecognised type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}")
×
156
        };
63,806✔
157
    }
158

159
    protected virtual Type GetColumnProviderSpecificType()
160
    {
161
        return DuckDBType switch
117!
162
        {
117✔
UNCOV
163
            DuckDBType.Invalid => throw new DuckDBException($"Invalid type for column {ColumnName}"),
×
164
            DuckDBType.Boolean => typeof(bool),
3✔
165
            DuckDBType.TinyInt => typeof(sbyte),
3✔
166
            DuckDBType.SmallInt => typeof(short),
3✔
167
            DuckDBType.Integer => typeof(int),
9✔
168
            DuckDBType.BigInt => typeof(long),
3✔
169
            DuckDBType.UnsignedTinyInt => typeof(byte),
3✔
170
            DuckDBType.UnsignedSmallInt => typeof(ushort),
3✔
171
            DuckDBType.UnsignedInteger => typeof(uint),
3✔
172
            DuckDBType.UnsignedBigInt => typeof(ulong),
3✔
173
            DuckDBType.Float => typeof(float),
3✔
174
            DuckDBType.Double => typeof(double),
6✔
175
            DuckDBType.Timestamp => typeof(DuckDBTimestamp),
3✔
176
            DuckDBType.Interval => typeof(DuckDBInterval),
3✔
177
            DuckDBType.Date => typeof(DuckDBDateOnly),
6✔
178
            DuckDBType.Time => typeof(DuckDBTimeOnly),
3✔
179
            DuckDBType.TimeTz => typeof(DuckDBTimeTz),
3✔
180
            DuckDBType.HugeInt => typeof(DuckDBHugeInt),
3✔
181
            DuckDBType.UnsignedHugeInt => typeof(DuckDBUHugeInt),
3✔
182
            DuckDBType.Varchar => typeof(string),
3✔
183
            DuckDBType.Decimal => typeof(decimal),
12✔
184
            DuckDBType.TimestampS => typeof(DuckDBTimestamp),
3✔
185
            DuckDBType.TimestampMs => typeof(DuckDBTimestamp),
3✔
186
            DuckDBType.TimestampNs => typeof(DuckDBTimestamp),
3✔
187
            DuckDBType.Blob => typeof(Stream),
3✔
188
            DuckDBType.Enum => typeof(string),
9✔
189
            DuckDBType.Uuid => typeof(Guid),
3✔
190
            DuckDBType.Struct => typeof(Dictionary<string, object>),
3✔
191
            DuckDBType.Bit => typeof(string),
3✔
192
            DuckDBType.TimestampTz => typeof(DuckDBTimestamp),
3✔
193
            DuckDBType.VarInt => typeof(BigInteger),
3✔
UNCOV
194
            _ => throw new ArgumentException($"Unrecognised type {DuckDBType} ({(int)DuckDBType}) for column {ColumnName}")
×
195
        };
117✔
196
    }
197

198
    protected unsafe T GetFieldData<T>(ulong offset) where T : unmanaged => *((T*)DataPointer + offset);
15,458,330✔
199

200
    public virtual void Dispose()
201
    {
202
    }
34,072✔
203
}
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