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

Giorgi / DuckDB.NET / 20383681089

19 Dec 2025 10:02PM UTC coverage: 89.294% (+0.03%) from 89.262%
20383681089

push

github

Giorgi
Drop .Net Standard support

1183 of 1379 branches covered (85.79%)

Branch coverage included in aggregate %.

19 of 22 new or added lines in 13 files covered. (86.36%)

16 existing lines in 9 files now uncovered.

2295 of 2516 relevant lines covered (91.22%)

567948.85 hits per line

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

87.76
/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 DuckDB.NET.Data.Extensions;
5
using DuckDB.NET.Native;
6
using System;
7
using System.Collections;
8
using System.Collections.Generic;
9
using System.Runtime.CompilerServices;
10
using System.Runtime.InteropServices;
11

12
namespace DuckDB.NET.Data;
13

14
public record ColumnInfo(string Name, Type Type);
171✔
15

16
public record TableFunction(IReadOnlyList<ColumnInfo> Columns, IEnumerable Data);
132✔
17

18
partial class DuckDBConnection
19
{
20
    public void RegisterTableFunction(string name, Func<TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback) => 
21
        RegisterTableFunctionInternal(name, _ => resultCallback(), mapperCallback);
6✔
22

23
    public void RegisterTableFunction<T>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback) => 
24
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T));
15✔
25

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

29
    public void RegisterTableFunction<T1, T2, T3>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback) => 
30
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3));
3✔
31

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

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

38
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback) => 
UNCOV
39
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6));
×
40

41
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6, T7>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback) => 
UNCOV
42
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7));
×
43

44
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6, T7, T8>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback) => 
UNCOV
45
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8));
×
46

47
    private unsafe void RegisterTableFunctionInternal(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback, params Type[] parameterTypes)
48
    {
49
        var function = NativeMethods.TableFunction.DuckDBCreateTableFunction();
36✔
50
        using (var handle = name.ToUnmanagedString())
36✔
51
        {
52
            NativeMethods.TableFunction.DuckDBTableFunctionSetName(function, handle);
36✔
53
        }
36✔
54

55
        foreach (var type in parameterTypes)
210✔
56
        {
57
            using var logicalType = type.GetLogicalType();
69✔
58
            NativeMethods.TableFunction.DuckDBTableFunctionAddParameter(function, logicalType);
69✔
59
        }
60

61
        var tableFunctionInfo = new TableFunctionInfo(resultCallback, mapperCallback);
36✔
62

63
        NativeMethods.TableFunction.DuckDBTableFunctionSetBind(function, &Bind);
36✔
64
        NativeMethods.TableFunction.DuckDBTableFunctionSetInit(function, &Init);
36✔
65
        NativeMethods.TableFunction.DuckDBTableFunctionSetFunction(function, &TableFunction);
36✔
66
        NativeMethods.TableFunction.DuckDBTableFunctionSetExtraInfo(function, tableFunctionInfo.ToHandle(), &DestroyExtraInfo);
36✔
67

68
        var state = NativeMethods.TableFunction.DuckDBRegisterTableFunction(NativeConnection, function);
36✔
69

70
        if (!state.IsSuccess())
36!
71
        {
72
            throw new InvalidOperationException($"Error registering user defined table function: {name}");
×
73
        }
74

75
        NativeMethods.TableFunction.DuckDBDestroyTableFunction(ref function);
36✔
76
    }
36✔
77

78
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
79
    public static unsafe void Bind(IntPtr info)
80
    {
81
        IDuckDBValueReader[] parameters = [];
36✔
82
        try
83
        {
84
            var handle = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBBindGetExtraInfo(info));
36✔
85

86
            if (handle.Target is not TableFunctionInfo functionInfo)
36!
87
            {
88
                throw new InvalidOperationException("User defined table function bind failed. Bind extra info is null");
×
89
            }
90

91
            parameters = new IDuckDBValueReader[NativeMethods.TableFunction.DuckDBBindGetParameterCount(info)];
36✔
92

93
            for (var i = 0; i < parameters.Length; i++)
210✔
94
            {
95
                var value = NativeMethods.TableFunction.DuckDBBindGetParameter(info, (ulong)i);
69✔
96
                parameters[i] = value;
69✔
97
            }
98

99
            var tableFunctionData = functionInfo.Bind(parameters);
36✔
100

101
            foreach (var columnInfo in tableFunctionData.Columns)
138✔
102
            {
103
                using var logicalType = columnInfo.Type.GetLogicalType();
36✔
104
                NativeMethods.TableFunction.DuckDBBindAddResultColumn(info, columnInfo.Name.ToUnmanagedString(), logicalType);
36✔
105
            }
106

107
            var bindData = new TableFunctionBindData(tableFunctionData.Columns, tableFunctionData.Data.GetEnumerator());
33✔
108

109
            NativeMethods.TableFunction.DuckDBBindSetBindData(info, bindData.ToHandle(), &DestroyExtraInfo);
33✔
110
        }
33✔
111
        catch (Exception ex)
112
        {
113
            using var errorMessage = ex.Message.ToUnmanagedString();
3✔
114
            NativeMethods.TableFunction.DuckDBBindSetError(info, errorMessage);
3✔
115
        }
3✔
116
        finally
117
        {
118
            foreach (var parameter in parameters)
210✔
119
            {
120
                (parameter as IDisposable)?.Dispose();
69!
121
            }
122
        }
36✔
123
    }
36✔
124

125
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
126
    public static void Init(IntPtr info) { }
33✔
127

128
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
129
    public static void TableFunction(IntPtr info, IntPtr chunk)
130
    {
131
        try
132
        {
133
            var bindData = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetBindData(info));
57✔
134
            var extraInfo = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetExtraInfo(info));
57✔
135

136
            if (bindData.Target is not TableFunctionBindData tableFunctionBindData)
57!
137
            {
138
                throw new InvalidOperationException("User defined table function failed. Function bind data is null");
×
139
            }
140

141
            if (extraInfo.Target is not TableFunctionInfo tableFunctionInfo)
57!
142
            {
143
                throw new InvalidOperationException("User defined table function failed. Function extra info is null");
×
144
            }
145

146
            var dataChunk = new DuckDBDataChunk(chunk);
57✔
147

148
            var writers = new VectorDataWriterBase[tableFunctionBindData.Columns.Count];
57✔
149
            for (var columnIndex = 0; columnIndex < tableFunctionBindData.Columns.Count; columnIndex++)
240✔
150
            {
151
                var column = tableFunctionBindData.Columns[columnIndex];
63✔
152
                var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, columnIndex);
63✔
153

154
                using var logicalType = column.Type.GetLogicalType();
63✔
155
                writers[columnIndex] = VectorDataWriterFactory.CreateWriter(vector, logicalType);
63✔
156
            }
157

158
            ulong size = 0;
57✔
159

160
            for (; size < DuckDBGlobalData.VectorSize; size++)
885✔
161
            {
162
                if (tableFunctionBindData.DataEnumerator.MoveNext())
471✔
163
                {
164
                    tableFunctionInfo.Mapper(tableFunctionBindData.DataEnumerator.Current, writers, size);
417✔
165
                }
166
                else
167
                {
168
                    break;
169
                }
170
            }
171

172
            NativeMethods.DataChunks.DuckDBDataChunkSetSize(dataChunk, size);
54✔
173
        }
54✔
174
        catch (Exception ex)
175
        {
176
            using var errorMessage = ex.Message.ToUnmanagedString();
3✔
177
            NativeMethods.TableFunction.DuckDBFunctionSetError(info, errorMessage);
3✔
178
        }
3✔
179
    }
57✔
180
}
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

© 2025 Coveralls, Inc