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

Giorgi / DuckDB.NET / 22921736195

10 Mar 2026 07:24PM UTC coverage: 89.526% (+0.08%) from 89.45%
22921736195

push

github

Giorgi
Update global.json

1255 of 1463 branches covered (85.78%)

Branch coverage included in aggregate %.

2651 of 2900 relevant lines covered (91.41%)

447643.55 hits per line

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

90.59
/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)
210✔
21
    {
22
        nativeAppender = appender;
210✔
23
        this.qualifiedTableName = qualifiedTableName;
210✔
24

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

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

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

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

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

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

52
        if (rowCount % DuckDBGlobalData.VectorSize == 0)
430,047✔
53
        {
54
            AppendDataChunk();
297✔
55

56
            InitVectorWriters();
297✔
57

58
            rowCount = 0;
297✔
59
        }
60

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

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

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

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

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

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

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

100
            dataChunk.Dispose();
204✔
101

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

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

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

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

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

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

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

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

152
        throw new DuckDBException(errorMessage);
3✔
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