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

Giorgi / DuckDB.NET / 28126041613

24 Jun 2026 08:00PM UTC coverage: 89.485% (+0.1%) from 89.339%
28126041613

push

github

Giorgi
Use duckdb_appender_error_data for appender error handling

Switch the appender from duckdb_appender_error (plain string) to
duckdb_appender_error_data, which exposes both the message and the
DuckDB error type. Route all appender error sites through the existing
DuckDBErrorData.ThrowOnError extension (message prefix now optional),
so appender exceptions carry ErrorType, consistent with the Arrow paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LWKN1SKSTFDyeqSrA4dfYT

1362 of 1583 branches covered (86.04%)

Branch coverage included in aggregate %.

2 of 6 new or added lines in 4 files covered. (33.33%)

1 existing line in 1 file now uncovered.

2859 of 3134 relevant lines covered (91.23%)

421690.1 hits per line

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

90.36
/DuckDB.NET.Data/DuckDBAppender.cs
1
using DuckDB.NET.Data.Common;
2
using DuckDB.NET.Data.DataChunk.Writer;
3
using DuckDB.NET.Data.Extensions;
4
using System.Diagnostics;
5
using System.Diagnostics.CodeAnalysis;
6

7
namespace DuckDB.NET.Data;
8

9
public class DuckDBAppender : IDisposable
10
{
11
    private bool closed;
12
    private readonly Native.DuckDBAppender nativeAppender;
13
    private readonly string qualifiedTableName;
14

15
    private ulong rowCount;
16

17
    private readonly DuckDBLogicalType[] logicalTypes;
18
    private readonly DuckDBDataChunk dataChunk;
19
    private readonly VectorDataWriterBase[] vectorWriters;
20

21
    internal DuckDBAppender(Native.DuckDBAppender appender, string qualifiedTableName)
216✔
22
    {
23
        nativeAppender = appender;
216✔
24
        this.qualifiedTableName = qualifiedTableName;
216✔
25

26
        var columnCount = NativeMethods.Appender.DuckDBAppenderColumnCount(nativeAppender);
216✔
27

28
        vectorWriters = new VectorDataWriterBase[columnCount];
216✔
29
        logicalTypes = new DuckDBLogicalType[columnCount];
216✔
30
        var logicalTypeHandles = new IntPtr[columnCount];
216✔
31

32
        for (ulong index = 0; index < columnCount; index++)
1,776✔
33
        {
34
            logicalTypes[index] = NativeMethods.Appender.DuckDBAppenderColumnType(nativeAppender, index);
672✔
35
            logicalTypeHandles[index] = logicalTypes[index].DangerousGetHandle();
672✔
36
        }
37

38
        dataChunk = NativeMethods.DataChunks.DuckDBCreateDataChunk(logicalTypeHandles, columnCount);
216✔
39
    }
216✔
40

41
    /// <summary>
42
    /// Gets the logical types of the columns in the appender.
43
    /// </summary>
44
    internal IReadOnlyList<DuckDBLogicalType> LogicalTypes => logicalTypes;
12✔
45

46
    public IDuckDBAppenderRow CreateRow()
47
    {
48
        if (closed)
436,203✔
49
        {
50
            throw new InvalidOperationException("Appender is already closed");
3✔
51
        }
52

53
        if (rowCount % DuckDBGlobalData.VectorSize == 0)
436,200✔
54
        {
55
            AppendDataChunk();
306✔
56

57
            InitVectorWriters();
306✔
58

59
            rowCount = 0;
306✔
60
        }
61

62
        rowCount++;
436,200✔
63
        return new DuckDBAppenderRow(qualifiedTableName, vectorWriters, rowCount - 1, dataChunk, nativeAppender);
436,200✔
64
    }
65

66
    public void Clear()
67
    {
68
        if (closed)
6!
69
        {
70
            throw new InvalidOperationException("Appender is already closed");
×
71
        }
72
        
73
        var state = NativeMethods.Appender.DuckDBAppenderClear(nativeAppender);
6✔
74
        if (!state.IsSuccess())
6!
75
        {
NEW
76
            NativeMethods.Appender.DuckDBAppenderErrorData(nativeAppender).ThrowOnError();
×
77
        }
78

79
        rowCount = 0;
6✔
80
        NativeMethods.DataChunks.DuckDBDataChunkReset(dataChunk);
6✔
81
    }
6✔
82

83
    public void Close()
84
    {
85
        closed = true;
210✔
86

87
        try
88
        {
89
            AppendDataChunk();
210✔
90

91
            foreach (var logicalType in logicalTypes)
1,722✔
92
            {
93
                logicalType.Dispose();
651✔
94
            }
95

96
            foreach (var writer in vectorWriters)
1,722✔
97
            {
98
                writer?.Dispose();
651✔
99
            }
100

101
            dataChunk.Dispose();
210✔
102

103
            var state = NativeMethods.Appender.DuckDBAppenderClose(nativeAppender);
210✔
104
            if (!state.IsSuccess())
210!
105
            {
NEW
106
                NativeMethods.Appender.DuckDBAppenderErrorData(nativeAppender).ThrowOnError();
×
107
            }
108
        }
210✔
109
        finally
110
        {
111
            nativeAppender.Close();
210✔
112
        }
210✔
113
    }
210✔
114

115
    public void Dispose()
116
    {
117
        if (!closed)
207✔
118
        {
119
            Close();
201✔
120
        }
121
    }
207✔
122

123
    private void InitVectorWriters()
124
    {
125
        for (long index = 0; index < vectorWriters.LongLength; index++)
2,364✔
126
        {
127
            var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, index);
876✔
128

129
            vectorWriters[index]?.Dispose();
876✔
130
            vectorWriters[index] = VectorDataWriterFactory.CreateWriter(vector, logicalTypes[index]);
876✔
131
        }
132
    }
306✔
133

134
    private void AppendDataChunk()
135
    {
136
        NativeMethods.DataChunks.DuckDBDataChunkSetSize(dataChunk, rowCount);
516✔
137
        var state = NativeMethods.Appender.DuckDBAppendDataChunk(nativeAppender, dataChunk);
516✔
138

139
        if (!state.IsSuccess())
516!
140
        {
NEW
141
            NativeMethods.Appender.DuckDBAppenderErrorData(nativeAppender).ThrowOnError();
×
142
        }
143

144
        NativeMethods.DataChunks.DuckDBDataChunkReset(dataChunk);
516✔
145
    }
516✔
146
}
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