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

Giorgi / DuckDB.NET / 21645923868

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

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%)

566599.28 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)
9✔
20
    {
21
        this.appender = appender;
9✔
22
        var classMap = new TMap();
9✔
23

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

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

33
        var columnTypes = appender.LogicalTypes;
9✔
34
        if (mappings.Count != columnTypes.Count)
9!
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++)
78✔
40
        {
41
            var mapping = mappings[index];
33✔
42

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

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

51
            if (expectedType != columnType)
27✔
52
            {
53
                throw new InvalidOperationException(
3✔
54
                    $"Type mismatch at column index {index}: Mapped type is {mapping.PropertyType.Name} (expected DuckDB type: {expectedType}) but actual column type is {columnType}");
3✔
55
            }
56
        }
57
    }
6✔
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)
6!
66
        {
NEW
67
            throw new ArgumentNullException(nameof(records));
×
68
        }
69

70
        foreach (var record in records)
36✔
71
        {
72
            AppendRecord(record);
12✔
73
        }
74
    }
6✔
75

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

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

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

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

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

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

99
        return duckDBType switch
27!
100
        {
27✔
NEW
101
            DuckDBType.Invalid => throw new NotSupportedException($"Type {type.Name} is not supported for mapping"),
×
102
            _ => duckDBType
27✔
103
        };
27✔
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();
6✔
120
    }
6✔
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