• 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

97.7
/DuckDB.NET.Data/DataChunk/Reader/StructVectorDataReader.cs
1
using System.Collections.Concurrent;
2
using System.Linq.Expressions;
3
using DuckDB.NET.Data.Common;
4

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

7
internal sealed class StructVectorDataReader : VectorDataReaderBase
8
{
9
    private static readonly ConcurrentDictionary<Type, TypeDetails> TypeCache = new();
3✔
10
    private readonly Dictionary<string, VectorDataReaderBase> structDataReaders;
11

12
    internal unsafe StructVectorDataReader(IntPtr vector, void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
825✔
13
    {
14
        using var logicalType = NativeMethods.Vectors.DuckDBVectorGetColumnType(vector);
825✔
15
        var memberCount = NativeMethods.LogicalType.DuckDBStructTypeChildCount(logicalType);
825✔
16
        structDataReaders = new Dictionary<string, VectorDataReaderBase>(StringComparer.OrdinalIgnoreCase);
825✔
17

18
        for (int index = 0; index < memberCount; index++)
5,058✔
19
        {
20
            var name = NativeMethods.LogicalType.DuckDBStructTypeChildName(logicalType, index).ToManagedString();
1,704✔
21
            var childVector = NativeMethods.Vectors.DuckDBStructVectorGetChild(vector, index);
1,704✔
22
            
23
            using var childType = NativeMethods.LogicalType.DuckDBStructTypeChildType(logicalType, index);
1,704✔
24
            structDataReaders[name] = VectorDataReaderFactory.CreateReader(childVector, childType, columnName);
1,704✔
25
        }
26
    }
1,650✔
27

28
    internal override object GetValue(ulong offset, Type targetType)
29
    {
30
        if (DuckDBType == DuckDBType.Struct)
84!
31
        {
32
            return GetStruct(offset, targetType);
84✔
33
        }
34

UNCOV
35
        return base.GetValue(offset, targetType);
×
36
    }
37

38
    private object GetStruct(ulong offset, Type returnType)
39
    {
40
        var result = Activator.CreateInstance(returnType);
84✔
41

42
        if (result is Dictionary<string, object?> dictionary)
84✔
43
        {
44
            foreach (var reader in structDataReaders)
114✔
45
            {
46
                var value = reader.Value.IsValid(offset) ? reader.Value.GetValue(offset) : null;
42✔
47
                dictionary.Add(reader.Key, value);
42✔
48
            }
49

50
            return result;
15✔
51
        }
52

53
        var typeDetails = TypeCache.GetOrAdd(returnType, type =>
69✔
54
        {
69✔
55
            var propertyInfos = returnType.GetProperties();
18✔
56
            var details = new TypeDetails();
18✔
57

69✔
58
            foreach (var propertyInfo in propertyInfos)
144✔
59
            {
69✔
60
                if (propertyInfo.SetMethod == null)
54✔
61
                {
69✔
62
                    continue;
69✔
63
                }
69✔
64

69✔
65
                var isNullable = propertyInfo.PropertyType.AllowsNullValue(out var isNullableValueType, out var underlyingType);
51✔
66

69✔
67
                var instanceParam = Expression.Parameter(typeof(object));
51✔
68
                var argumentParam = Expression.Parameter(typeof(object));
51✔
69

69✔
70
                var setAction = Expression.Lambda<Action<object, object>>(
51✔
71
                    Expression.Call(Expression.Convert(instanceParam, type), propertyInfo.SetMethod, Expression.Convert(argumentParam, propertyInfo.PropertyType)),
51✔
72
                    instanceParam, argumentParam
51✔
73
                ).Compile();
51✔
74

69✔
75
                details.Properties.Add(propertyInfo.Name, new PropertyDetails(propertyInfo.PropertyType, isNullable, isNullableValueType, underlyingType, setAction));
51✔
76
            }
69✔
77

69✔
78
            return details;
18✔
79
        });
69✔
80

81
        foreach (var property in typeDetails.Properties)
507✔
82
        {
83
            structDataReaders.TryGetValue(property.Key, out var reader);
186✔
84
            var isNullable = property.Value.Nullable;
186✔
85

86
            if (reader == null)
186✔
87
            {
88
                //if (!isNullable)
89
                //{
90
                //    throw new NullReferenceException($"Property '{properties.Key}' not found in struct");
91
                //}
92

93
                continue;
94
            }
95

96
            if (reader.IsValid(offset))
186✔
97
            {
98
                var value = reader.GetValue(offset, property.Value.NullableType ?? property.Value.PropertyType);
138✔
99
                property.Value.Setter(result!, value);
138✔
100
            }
101
            else
102
            {
103
                if (!isNullable)
48✔
104
                {
105
                    throw new InvalidCastException($"Property '{property.Key}' is not nullable but struct contains null value");
3✔
106
                }
107
            }
108
        }
109

110
        return result!;
66✔
111
    }
112

113
    public override void Dispose()
114
    {
115
        foreach (var reader in structDataReaders)
288✔
116
        {
117
            reader.Value.Dispose();
114✔
118
        }
119

120
        base.Dispose();
30✔
121
    }
30✔
122
}
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