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

Giorgi / DuckDB.NET / 21644766496

03 Feb 2026 07:34PM UTC coverage: 89.45%. First build
21644766496

push

github

Giorgi
Merge branch 'develop'

1203 of 1395 branches covered (86.24%)

Branch coverage included in aggregate %.

125 of 154 new or added lines in 7 files covered. (81.17%)

2375 of 2605 relevant lines covered (91.17%)

377965.41 hits per line

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

80.95
/DuckDB.NET.Data/DuckDBMappedAppender.cs
1
using System;
2
using System.Collections.Generic;
3
using DuckDB.NET.Data.Extensions;
4
using DuckDB.NET.Data.Mapping;
5
using DuckDB.NET.Native;
6

7
namespace DuckDB.NET.Data;
8

9
/// <summary>
10
/// A type-safe appender that uses AppenderMap to validate type mappings.
11
/// </summary>
12
/// <typeparam name="T">The type being appended</typeparam>
13
/// <typeparam name="TMap">The AppenderMap type defining the mappings</typeparam>
14
public class DuckDBMappedAppender<T, TMap> : IDisposable where TMap : DuckDBAppenderMap<T>, new()
15
{
16
    private readonly DuckDBAppender appender;
17
    private readonly List<IPropertyMapping<T>> mappings;
18

19
    internal DuckDBMappedAppender(DuckDBAppender appender)
6✔
20
    {
21
        this.appender = appender;
6✔
22
        var classMap = new TMap();
6✔
23

24
        // Get mappings as List<T> to avoid interface enumerator boxing
25
        mappings = classMap.PropertyMappings;
6✔
26

27
        // Validate mappings match the table structure
28
        if (mappings.Count == 0)
6!
29
        {
NEW
30
            throw new InvalidOperationException($"AppenderMap {typeof(TMap).Name} has no property mappings defined");
×
31
        }
32

33
        var columnTypes = appender.LogicalTypes;
6✔
34
        if (mappings.Count != columnTypes.Count)
6!
35
        {
NEW
36
            throw new InvalidOperationException($"AppenderMap {typeof(TMap).Name} has {mappings.Count} mappings but table has {columnTypes.Count} columns");
×
37
        }
38

39
        for (int index = 0; index < mappings.Count; index++)
52✔
40
        {
41
            var mapping = mappings[index];
22✔
42

43
            if (mapping.MappingType != PropertyMappingType.Property)
22✔
44
            {
45
                continue;
46
            }
47

48
            var columnType = NativeMethods.LogicalType.DuckDBGetTypeId(columnTypes[index]);
18✔
49
            var expectedType = GetExpectedDuckDBType(mapping.PropertyType);
18✔
50

51
            if (expectedType != columnType)
18✔
52
            {
53
                throw new InvalidOperationException(
2✔
54
                    $"Type mismatch at column index {index}: Mapped type is {mapping.PropertyType.Name} (expected DuckDB type: {expectedType}) but actual column type is {columnType}");
2✔
55
            }
56
        }
57
    }
4✔
58

59
    /// <summary>
60
    /// Appends multiple records to the table.
61
    /// </summary>
62
    /// <param name="records">The records to append</param>
63
    public void AppendRecords(IEnumerable<T> records)
64
    {
65
        if (records == null)
4!
66
        {
NEW
67
            throw new ArgumentNullException(nameof(records));
×
68
        }
69

70
        foreach (var record in records)
24✔
71
        {
72
            AppendRecord(record);
8✔
73
        }
74
    }
4✔
75

76
    private void AppendRecord(T record)
77
    {
78
        if (record == null)
8!
79
        {
NEW
80
            throw new ArgumentNullException(nameof(record));
×
81
        }
82

83
        var row = appender.CreateRow();
8✔
84

85
        foreach (var mapping in mappings)
80✔
86
        {
87
            row = mapping.AppendToRow(row, record);
32✔
88
        }
89

90
        row.EndRow();
8✔
91
    }
8✔
92

93
    private static DuckDBType GetExpectedDuckDBType(Type type)
94
    {
95
        var underlyingType = Nullable.GetUnderlyingType(type) ?? type;
18✔
96

97
        var duckDBType = underlyingType.GetDuckDBType();
18✔
98

99
        return duckDBType switch
18!
100
        {
18✔
NEW
101
            DuckDBType.Invalid => throw new NotSupportedException($"Type {type.Name} is not supported for mapping"),
×
102
            _ => duckDBType
18✔
103
        };
18✔
104
    }
105

106
    /// <summary>
107
    /// Closes the appender and flushes any remaining data.
108
    /// </summary>
109
    public void Close()
110
    {
NEW
111
        appender.Close();
×
NEW
112
    }
×
113

114
    /// <summary>
115
    /// Disposes the appender.
116
    /// </summary>
117
    public void Dispose()
118
    {
119
        appender.Dispose();
4✔
120
    }
4✔
121
}
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