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

Giorgi / DuckDB.NET / 21786556530

07 Feb 2026 08:39PM UTC coverage: 89.155% (-0.07%) from 89.223%
21786556530

push

github

Giorgi
Added support for clearing in-progress adapter

Requires DuckDB 1.5

1199 of 1393 branches covered (86.07%)

Branch coverage included in aggregate %.

6 of 8 new or added lines in 1 file covered. (75.0%)

193 existing lines in 43 files now uncovered.

2336 of 2572 relevant lines covered (90.82%)

557295.56 hits per line

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

75.0
/DuckDB.NET.Data/DuckDBConnection.ScalarFunction.cs
1
using DuckDB.NET.Data.Connection;
2
using DuckDB.NET.Data.DataChunk.Reader;
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
partial class DuckDBConnection
10
{
11
    public void RegisterScalarFunction<TResult>(string name, Action<IDuckDBDataWriter, ulong> action, bool isPureFunction = false)
12
    {
13
        RegisterScalarMethod(name, (_, w, index) => action(w, index), TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction);
6✔
14
    }
3✔
15

16
    public void RegisterScalarFunction<T, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true, bool @params = false)
17
    {
18
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), @params, !isPureFunction, TypeExtensions.GetLogicalType<T>());
9✔
19
    }
9✔
20

21
    public void RegisterScalarFunction<T1, T2, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true)
22
    {
23
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction,
6✔
24
                              TypeExtensions.GetLogicalType<T1>(), 
6✔
25
                              TypeExtensions.GetLogicalType<T2>());
6✔
26
    }
6✔
27

28
    public void RegisterScalarFunction<T1, T2, T3, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true)
29
    {
UNCOV
30
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction,
×
UNCOV
31
                              TypeExtensions.GetLogicalType<T1>(),
×
UNCOV
32
                              TypeExtensions.GetLogicalType<T2>(),
×
UNCOV
33
                              TypeExtensions.GetLogicalType<T3>());
×
34
    }
×
35

36
    public void RegisterScalarFunction<T1, T2, T3, T4, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true)
37
    {
38
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction,
×
UNCOV
39
                              TypeExtensions.GetLogicalType<T1>(),
×
UNCOV
40
                              TypeExtensions.GetLogicalType<T2>(),
×
UNCOV
41
                              TypeExtensions.GetLogicalType<T3>(),
×
42
                              TypeExtensions.GetLogicalType<T4>());
×
43
    }
×
44

45
    private unsafe void RegisterScalarMethod(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, DuckDBLogicalType returnType,
46
                                             bool varargs, bool @volatile, params DuckDBLogicalType[] parameterTypes)
47
    {
48
        var function = NativeMethods.ScalarFunction.DuckDBCreateScalarFunction();
18✔
49
        using (var handle = name.ToUnmanagedString())
18✔
50
        {
51
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetName(function, handle);
18✔
52
        }
18✔
53

54
        if (varargs)
18✔
55
        {
56
            if (parameterTypes.Length != 1)
3!
57
            {
UNCOV
58
                throw new InvalidOperationException("Cannot use params with multiple parameters");
×
59
            }
60

61
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetVarargs(function, parameterTypes[0]);
3✔
62
        }
63
        else
64
        {
65
            foreach (var type in parameterTypes)
66✔
66
            {
67
                NativeMethods.ScalarFunction.DuckDBScalarFunctionAddParameter(function, type);
18✔
68
                type.Dispose();
18✔
69
            }
70
        }
71

72
        if (@volatile)
18✔
73
        {
74
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetVolatile(function);
9✔
75
        }
76

77
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetReturnType(function, returnType);
18✔
78
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetFunction(function, &ScalarFunctionCallback);
18✔
79

80
        var info = new ScalarFunctionInfo(returnType, action);
18✔
81

82
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetExtraInfo(function, info.ToHandle(), &DestroyExtraInfo);
18✔
83

84
        var state = NativeMethods.ScalarFunction.DuckDBRegisterScalarFunction(NativeConnection, function);
18✔
85

86
        NativeMethods.ScalarFunction.DuckDBDestroyScalarFunction(ref function);
18✔
87

88
        if (!state.IsSuccess())
18!
89
        {
UNCOV
90
            throw new InvalidOperationException($"Error registering user defined scalar function: {name}");
×
91
        }
92
    }
18✔
93

94
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
95
    private static void ScalarFunctionCallback(IntPtr info, IntPtr chunk, IntPtr outputVector)
96
    {
97
        var dataChunk = new DuckDBDataChunk(chunk);
78✔
98

99
        var chunkSize = NativeMethods.DataChunks.DuckDBDataChunkGetSize(dataChunk);
78✔
100
        var handle = GCHandle.FromIntPtr(NativeMethods.ScalarFunction.DuckDBScalarFunctionGetExtraInfo(info));
78✔
101

102
        if (handle.Target is not ScalarFunctionInfo functionInfo)
78!
103
        {
UNCOV
104
            throw new InvalidOperationException("User defined scalar function execution failed. Function extra info is null");
×
105
        }
106

107
        var readers = new VectorDataReaderBase[NativeMethods.DataChunks.DuckDBDataChunkGetColumnCount(dataChunk)];
78✔
108

109
        for (var index = 0; index < readers.Length; index++)
354✔
110
        {
111
            var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, index);
99✔
112
            readers[index] = VectorDataReaderFactory.CreateReader(vector, NativeMethods.Vectors.DuckDBVectorGetColumnType(vector));
99✔
113
        }
114

115
        var writer = VectorDataWriterFactory.CreateWriter(outputVector, functionInfo.ReturnType);
78✔
116

117
        functionInfo.Action(readers, writer, chunkSize);
78✔
118
    }
78✔
119

120
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
121
    private static void DestroyExtraInfo(IntPtr pointer) => pointer.FreeHandle();
99✔
122
}
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