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

Giorgi / DuckDB.NET / 13181745983

06 Feb 2025 02:31PM UTC coverage: 89.958% (+0.02%) from 89.937%
13181745983

push

github

Giorgi
Merge branch 'develop'

1081 of 1235 branches covered (87.53%)

Branch coverage included in aggregate %.

322 of 345 new or added lines in 20 files covered. (93.33%)

2 existing lines in 1 file now uncovered.

2108 of 2310 relevant lines covered (91.26%)

760472.2 hits per line

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

85.71
/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.Diagnostics.CodeAnalysis;
10
using System.Runtime.CompilerServices;
11
using System.Runtime.InteropServices;
12

13
namespace DuckDB.NET.Data;
14

15
public record ColumnInfo(string Name, Type Type);
141✔
16

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

19
partial class DuckDBConnection
20
{
21
#if NET8_0_OR_GREATER
22
    [Experimental("DuckDBNET001")]
23
    public void RegisterTableFunction<T>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
24
    {
25
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T));
12✔
26
    }
12✔
27

28
    [Experimental("DuckDBNET001")]
29
    public void RegisterTableFunction<T1, T2>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
30
    {
31
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2));
9✔
32
    }
9✔
33

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

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

46
    [Experimental("DuckDBNET001")]
47
    public void RegisterTableFunction<T1, T2, T3, T4, T5>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
48
    {
49
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5));
3✔
50
    }
3✔
51

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

58
    [Experimental("DuckDBNET001")]
59
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6, T7>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
60
    {
61
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7));
×
62
    }
×
63

64
    [Experimental("DuckDBNET001")]
65
    public void RegisterTableFunction<T1, T2, T3, T4, T5, T6, T7, T8>(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback)
66
    {
67
        RegisterTableFunctionInternal(name, resultCallback, mapperCallback, typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8));
×
68
    }
×
69

70
    [Experimental("DuckDBNET001")]
71
    private unsafe void RegisterTableFunctionInternal(string name, Func<IReadOnlyList<IDuckDBValueReader>, TableFunction> resultCallback, Action<object?, IDuckDBDataWriter[], ulong> mapperCallback, params Type[] parameterTypes)
72
    {
73
        var function = NativeMethods.TableFunction.DuckDBCreateTableFunction();
30✔
74
        using (var handle = name.ToUnmanagedString())
30✔
75
        {
76
            NativeMethods.TableFunction.DuckDBTableFunctionSetName(function, handle);
30✔
77
        }
30✔
78

79
        foreach (var type in parameterTypes)
192✔
80
        {
81
            using var logicalType = type.GetLogicalType();
66✔
82
            NativeMethods.TableFunction.DuckDBTableFunctionAddParameter(function, logicalType);
66✔
83
        }
84

85
        var tableFunctionInfo = new TableFunctionInfo(resultCallback, mapperCallback);
30✔
86

87
        NativeMethods.TableFunction.DuckDBTableFunctionSetBind(function, &Bind);
30✔
88
        NativeMethods.TableFunction.DuckDBTableFunctionSetInit(function, &Init);
30✔
89
        NativeMethods.TableFunction.DuckDBTableFunctionSetFunction(function, &TableFunction);
30✔
90
        NativeMethods.TableFunction.DuckDBTableFunctionSetExtraInfo(function, tableFunctionInfo.ToHandle(), &DestroyExtraInfo);
30✔
91

92
        var state = NativeMethods.TableFunction.DuckDBRegisterTableFunction(NativeConnection, function);
30✔
93

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

99
        NativeMethods.TableFunction.DuckDBDestroyTableFunction(out function);
30✔
100
    }
30✔
101

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

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

115
            parameters = new IDuckDBValueReader[NativeMethods.TableFunction.DuckDBBindGetParameterCount(info)];
30✔
116

117
            for (var i = 0; i < parameters.Length; i++)
192✔
118
            {
119
                var value = NativeMethods.TableFunction.DuckDBBindGetParameter(info, (ulong)i);
66✔
120
                parameters[i] = value;
66✔
121
            }
122

123
            var tableFunctionData = functionInfo.Bind(parameters);
30✔
124

125
            foreach (var columnInfo in tableFunctionData.Columns)
114✔
126
            {
127
                using var logicalType = columnInfo.Type.GetLogicalType();
30✔
128
                NativeMethods.TableFunction.DuckDBBindAddResultColumn(info, columnInfo.Name.ToUnmanagedString(), logicalType);
30✔
129
            }
130

131
            var bindData = new TableFunctionBindData(tableFunctionData.Columns, tableFunctionData.Data.GetEnumerator());
27✔
132

133
            NativeMethods.TableFunction.DuckDBBindSetBindData(info, bindData.ToHandle(), &DestroyExtraInfo);
27✔
134
        }
27✔
135
        catch (Exception ex)
136
        {
137
            using var errorMessage = ex.Message.ToUnmanagedString();
3✔
138
            NativeMethods.TableFunction.DuckDBBindSetError(info, errorMessage);
3✔
139
        }
3✔
140
        finally
141
        {
142
            foreach (var parameter in parameters)
192✔
143
            {
144
                (parameter as IDisposable)?.Dispose();
66!
145
            }
146
        }
30✔
147
    }
30✔
148

149
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
150
    public static void Init(IntPtr info) { }
27✔
151

152
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
153
    public static void TableFunction(IntPtr info, IntPtr chunk)
154
    {
155
        try
156
        {
157
            var bindData = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetBindData(info));
45✔
158
            var extraInfo = GCHandle.FromIntPtr(NativeMethods.TableFunction.DuckDBFunctionGetExtraInfo(info));
45✔
159

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

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

170
            var dataChunk = new DuckDBDataChunk(chunk);
45✔
171

172
            var writers = new VectorDataWriterBase[tableFunctionBindData.Columns.Count];
45✔
173
            for (var columnIndex = 0; columnIndex < tableFunctionBindData.Columns.Count; columnIndex++)
192✔
174
            {
175
                var column = tableFunctionBindData.Columns[columnIndex];
51✔
176
                var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, columnIndex);
51✔
177

178
                using var logicalType = column.Type.GetLogicalType();
51✔
179
                writers[columnIndex] = VectorDataWriterFactory.CreateWriter(vector, logicalType);
51✔
180
            }
181

182
            ulong size = 0;
45✔
183

184
            for (; size < DuckDBGlobalData.VectorSize; size++)
861✔
185
            {
186
                if (tableFunctionBindData.DataEnumerator.MoveNext())
453✔
187
                {
188
                    tableFunctionInfo.Mapper(tableFunctionBindData.DataEnumerator.Current, writers, size);
411✔
189
                }
190
                else
191
                {
192
                    break;
193
                }
194
            }
195

196
            NativeMethods.DataChunks.DuckDBDataChunkSetSize(dataChunk, size);
42✔
197
        }
42✔
198
        catch (Exception ex)
199
        {
200
            using var errorMessage = ex.Message.ToUnmanagedString();
3✔
201
            NativeMethods.TableFunction.DuckDBFunctionSetError(info, errorMessage);
3✔
202
        }
3✔
203
    }
45✔
204
#endif
205
}
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