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

Giorgi / DuckDB.NET / 22323392380

23 Feb 2026 07:25PM UTC coverage: 89.658% (-0.008%) from 89.666%
22323392380

push

github

Giorgi
Throw on invalid enum internal type instead of returning -1

1237 of 1437 branches covered (86.08%)

Branch coverage included in aggregate %.

0 of 1 new or added line in 1 file covered. (0.0%)

6 existing lines in 2 files now uncovered.

2543 of 2779 relevant lines covered (91.51%)

471972.16 hits per line

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

87.6
/DuckDB.NET.Data/DuckDBConnection.TableFunction.cs
1
using DuckDB.NET.Data.Common;
2
using DuckDB.NET.Data.Connection;
3
using DuckDB.NET.Data.DataChunk.Writer;
4
using System.Runtime.CompilerServices;
5
using System.Runtime.InteropServices;
6

7
namespace DuckDB.NET.Data;
8

9
public record ColumnInfo(string Name, Type Type);
600✔
10

11
public record TableFunction(IReadOnlyList<ColumnInfo> Columns, IEnumerable Data);
324✔
12

13
partial class DuckDBConnection
14
{
15
    public void RegisterTableFunction(string name, Func<TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
16
    {
17
        RegisterTableFunctionInternal(name, (_) => resultCallback(), mapperCallback, Array.Empty<Type>());
18✔
18
    }
9✔
19

20
    public void RegisterTableFunction<T>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
21
    {
22
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T));
42✔
23
    }
42✔
24

25
    public void RegisterTableFunction<T1, T2>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
26
    {
27
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2));
12✔
28
    }
12✔
29

30
    public void RegisterTableFunction<T1, T2, T3>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
31
    {
32
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3));
6✔
33
    }
6✔
34

35
    public void RegisterTableFunction<T1, T2, T3, T4>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
36
    {
37
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4));
6✔
38
    }
6✔
39

40
    public void RegisterTableFunction<T1, T2, T3, T4, T5>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
41
    {
42
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
3✔
43
    }
3✔
44

45
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
46
    {
47
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6));
×
48
    }
×
49

50
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6, T7>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
51
    {
52
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7));
×
53
    }
×
54

55
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6, T7, T8>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
56
    {
57
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8));
×
58
    }
×
59

60
    public void RegisterTableFunction(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback, params DuckDBType[] parameterTypes)
61
    {
62
        var logicalTypes = Array.ConvertAll(parameterTypes, NativeMethods.LogicalType.DuckDBCreateLogicalType);
6✔
63
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, logicalTypes);
6✔
64
    }
6✔
65

66
    private void RegisterTableFunctionInternal(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback, params Type[] parameterTypes)
67
    {
68
        var logicalTypes = Array.ConvertAll(parameterTypes, TypeExtensions.GetLogicalType);
78✔
69
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, logicalTypes);
78✔
70
    }
78✔
71

72
    private unsafe void RegisterTableFunctionInternal(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback, DuckDBLogicalType[] parameterLogicalTypes)
73
    {
74
        var function = NativeMethods.TableFunction.DuckDBCreateTableFunction();
84✔
75
        NativeMethods.TableFunction.DuckDBTableFunctionSetName(function, name);
84✔
76

77
        foreach (var logicalType in parameterLogicalTypes)
444✔
78
        {
79
            NativeMethods.TableFunction.DuckDBTableFunctionAddParameter(function, logicalType);
138✔
80
            logicalType.Dispose();
138✔
81
        }
82

83
        var tableFunctionInfo = new TableFunctionInfo(resultCallback, mapperCallback);
84✔
84

85
        NativeMethods.TableFunction.DuckDBTableFunctionSetBind(function, &Bind);
84✔
86
        NativeMethods.TableFunction.DuckDBTableFunctionSetInit(function, &Init);
84✔
87
        NativeMethods.TableFunction.DuckDBTableFunctionSetFunction(function, &TableFunction);
84✔
88
        NativeMethods.TableFunction.DuckDBTableFunctionSetExtraInfo(function, tableFunctionInfo.ToHandle(), &DestroyExtraInfo);
84✔
89

90
        var state = NativeMethods.TableFunction.DuckDBRegisterTableFunction(NativeConnection, function);
84✔
91

92
        NativeMethods.TableFunction.DuckDBDestroyTableFunction(ref function);
84✔
93

94
        if (!state.IsSuccess())
84!
95
        {
96
            throw new InvalidOperationException($"Error registering user defined table function: {name}");
×
97
        }
98
    }
84✔
99

100
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
101
    private static unsafe void Bind(IntPtr info)
102
    {
103
        IDuckDBValueReader[] parameters = [];
87✔
104
        try
105
        {
106
            var handle = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBBindGetExtraInfo(info));
87✔
107

108
            if (handle.Target is not TableFunctionInfo functionInfo)
87!
109
            {
110
                throw new InvalidOperationException("User defined table function bind failed. Bind extra info is null");
×
111
            }
112

113
            parameters = new IDuckDBValueReader[NativeMethods.TableFunction.DuckDBBindGetParameterCount(info)];
87✔
114

115
            for (var i = 0; i < parameters.Length; i++)
456✔
116
            {
117
                var value = NativeMethods.TableFunction.DuckDBBindGetParameter(info, (ulong)i);
141✔
118
                parameters[i] = value;
141✔
119
            }
120

121
            var tableFunctionData = functionInfo.Bind(parameters);
87✔
122

123
            foreach (var columnInfo in tableFunctionData.Columns)
402✔
124
            {
125
                using var logicalType = columnInfo.Type.GetLogicalType();
120✔
126
                NativeMethods.TableFunction.DuckDBBindAddResultColumn(info, columnInfo.Name, logicalType);
120✔
127
            }
128

129
            var bindData = new TableFunctionBindData(tableFunctionData.Columns, tableFunctionData.Data.GetEnumerator());
81✔
130

131
            NativeMethods.TableFunction.DuckDBBindSetBindData(info, bindData.ToHandle(), &DestroyExtraInfo);
81✔
132
        }
81✔
133
        catch (Exception ex)
6✔
134
        {
135
            NativeMethods.TableFunction.DuckDBBindSetError(info, ex.Message);
6✔
136
        }
6✔
137
        finally
138
        {
139
            foreach (var parameter in parameters)
456✔
140
            {
141
                (parameter as IDisposable)?.Dispose();
141!
142
            }
143
        }
87✔
144
    }
87✔
145

146
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
147
    private static void Init(IntPtr info) { }
81✔
148

149
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
150
    private static void TableFunction(IntPtr info, IntPtr chunk)
151
    {
152
        VectorDataWriterBase[] writers = [];
156✔
153
        DuckDBLogicalType[] logicalTypes = [];
156✔
154
        try
155
        {
156
            var bindData = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetBindData(info));
156✔
157
            var extraInfo = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetExtraInfo(info));
156✔
158

159
            if (bindData.Target is not TableFunctionBindData tableFunctionBindData)
156!
160
            {
UNCOV
161
                throw new InvalidOperationException("User defined table function failed. Function bind data is null");
×
162
            }
163

164
            if (extraInfo.Target is not TableFunctionInfo tableFunctionInfo)
156!
165
            {
UNCOV
166
                throw new InvalidOperationException("User defined table function failed. Function extra info is null");
×
167
            }
168

169
            var dataChunk = new DuckDBDataChunk(chunk);
156✔
170

171
            writers = new VectorDataWriterBase[tableFunctionBindData.Columns.Count];
156✔
172
            logicalTypes = new DuckDBLogicalType[tableFunctionBindData.Columns.Count];
156✔
173

174
            for (var columnIndex = 0; columnIndex < tableFunctionBindData.Columns.Count; columnIndex++)
792✔
175
            {
176
                var column = tableFunctionBindData.Columns[columnIndex];
240✔
177
                var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, columnIndex);
240✔
178

179
                logicalTypes[columnIndex] = column.Type.GetLogicalType();
240✔
180
                writers[columnIndex] = VectorDataWriterFactory.CreateWriter(vector, logicalTypes[columnIndex]);
240✔
181
            }
182

183
            ulong size = 0;
156✔
184

185
            for (; size < DuckDBGlobalData.VectorSize; size++)
31,164✔
186
            {
187
                if (tableFunctionBindData.DataEnumerator.MoveNext())
15,654✔
188
                {
189
                    tableFunctionInfo.Mapper(tableFunctionBindData.DataEnumerator.Current, writers, size);
15,507✔
190
                }
191
                else
192
                {
193
                    break;
194
                }
195
            }
196

197
            NativeMethods.DataChunks.DuckDBDataChunkSetSize(dataChunk, size);
153✔
198
        }
153✔
199
        catch (Exception ex)
3✔
200
        {
201
            NativeMethods.TableFunction.DuckDBFunctionSetError(info, ex.Message);
3✔
202
        }
3✔
203
        finally
204
        {
205
            foreach (var writer in writers)
792✔
206
            {
207
                writer.Dispose();
240✔
208
            }
209

210
            foreach (var logicalType in logicalTypes)
792✔
211
            {
212
                logicalType?.Dispose();
240!
213
            }
214
        }
156✔
215
    }
156✔
216
}
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