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

Giorgi / DuckDB.NET / 22550064358

01 Mar 2026 06:46PM UTC coverage: 89.682% (-0.2%) from 89.868%
22550064358

push

github

Giorgi
Skip appender clear tests

1265 of 1467 branches covered (86.23%)

Branch coverage included in aggregate %.

2603 of 2846 relevant lines covered (91.46%)

307607.77 hits per line

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

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

6
namespace DuckDB.NET.Data;
7

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

14
    private ulong rowCount;
15

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

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

25
        var columnCount = NativeMethods.Appender.DuckDBAppenderColumnCount(nativeAppender);
136✔
26

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

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

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

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

45
    public IDuckDBAppenderRow CreateRow()
46
    {
47
        if (closed)
236,700✔
48
        {
49
            throw new InvalidOperationException("Appender is already closed");
2✔
50
        }
51

52
        if (rowCount % DuckDBGlobalData.VectorSize == 0)
236,698✔
53
        {
54
            AppendDataChunk();
172✔
55

56
            InitVectorWriters();
172✔
57

58
            rowCount = 0;
172✔
59
        }
60

61
        rowCount++;
236,698✔
62
        return new DuckDBAppenderRow(qualifiedTableName, vectorWriters, rowCount - 1, dataChunk, nativeAppender);
236,698✔
63
    }
64

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

78
        rowCount = 0;
×
79
        NativeMethods.DataChunks.DuckDBDataChunkReset(dataChunk);
×
80
    }
×
81

82
    public void Close()
83
    {
84
        closed = true;
132✔
85

86
        try
87
        {
88
            AppendDataChunk();
132✔
89

90
            foreach (var logicalType in logicalTypes)
1,092✔
91
            {
92
                logicalType.Dispose();
414✔
93
            }
94

95
            foreach (var writer in vectorWriters)
1,092✔
96
            {
97
                writer?.Dispose();
414✔
98
            }
99

100
            dataChunk.Dispose();
132✔
101

102
            var state = NativeMethods.Appender.DuckDBAppenderClose(nativeAppender);
132✔
103
            if (!state.IsSuccess())
132!
104
            {
105
                ThrowLastError(nativeAppender);
×
106
            }
107
        }
132✔
108
        finally
109
        {
110
            nativeAppender.Close();
132✔
111
        }
132✔
112
    }
132✔
113

114
    public void Dispose()
115
    {
116
        if (!closed)
130✔
117
        {
118
            Close();
126✔
119
        }
120
    }
130✔
121

122
    private void InitVectorWriters()
123
    {
124
        for (long index = 0; index < vectorWriters.LongLength; index++)
1,332✔
125
        {
126
            var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, index);
494✔
127

128
            vectorWriters[index]?.Dispose();
494✔
129
            vectorWriters[index] = VectorDataWriterFactory.CreateWriter(vector, logicalTypes[index]);
494✔
130
        }
131
    }
172✔
132

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

138
        if (!state.IsSuccess())
304!
139
        {
140
            ThrowLastError(nativeAppender);
×
141
        }
142

143
        NativeMethods.DataChunks.DuckDBDataChunkReset(dataChunk);
304✔
144
    }
304✔
145

146
    [DoesNotReturn]
147
    [StackTraceHidden]
148
    internal static void ThrowLastError(Native.DuckDBAppender appender)
149
    {
150
        var errorMessage = NativeMethods.Appender.DuckDBAppenderError(appender);
2✔
151

152
        throw new DuckDBException(errorMessage);
2✔
153
    }
154
}
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