• 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

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

11
namespace DuckDB.NET.Data;
12

13
partial class DuckDBConnection
14
{
15
    public void RegisterScalarFunction<TResult>(string name, Action<IDuckDBDataWriter, ulong> action, bool isPureFunction = false) => 
16
        RegisterScalarMethod(name, (_, w, index) => action(w, index), TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction);
6✔
17

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

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

25
    public void RegisterScalarFunction<T1, T2, T3, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true) =>
UNCOV
26
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction,
×
NEW
27
            TypeExtensions.GetLogicalType<T1>(), TypeExtensions.GetLogicalType<T2>(), TypeExtensions.GetLogicalType<T3>());
×
28

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

34
    private unsafe void RegisterScalarMethod(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, DuckDBLogicalType returnType,
35
                                             bool varargs, bool @volatile, params DuckDBLogicalType[] parameterTypes)
36
    {
37
        var function = NativeMethods.ScalarFunction.DuckDBCreateScalarFunction();
18✔
38
        using (var handle = name.ToUnmanagedString())
18✔
39
        {
40
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetName(function, handle);
18✔
41
        }
18✔
42

43
        if (varargs)
18✔
44
        {
45
            if (parameterTypes.Length != 1)
3!
46
            {
47
                throw new InvalidOperationException("Cannot use params with multiple parameters");
×
48
            }
49

50
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetVarargs(function, parameterTypes[0]);
3✔
51
        }
52
        else
53
        {
54
            foreach (var type in parameterTypes)
66✔
55
            {
56
                NativeMethods.ScalarFunction.DuckDBScalarFunctionAddParameter(function, type);
18✔
57
                type.Dispose();
18✔
58
            }
59
        }
60

61
        if (@volatile)
18✔
62
        {
63
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetVolatile(function);
9✔
64
        }
65

66
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetReturnType(function, returnType);
18✔
67
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetFunction(function, &ScalarFunctionCallback);
18✔
68

69
        var info = new ScalarFunctionInfo(returnType, action);
18✔
70

71
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetExtraInfo(function, info.ToHandle(), &DestroyExtraInfo);
18✔
72

73
        var state = NativeMethods.ScalarFunction.DuckDBRegisterScalarFunction(NativeConnection, function);
18✔
74

75
        NativeMethods.ScalarFunction.DuckDBDestroyScalarFunction(ref function);
18✔
76

77
        if (!state.IsSuccess())
18!
78
        {
79
            throw new InvalidOperationException($"Error registering user defined scalar function: {name}");
×
80
        }
81
    }
18✔
82

83
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
84
    private static void ScalarFunctionCallback(IntPtr info, IntPtr chunk, IntPtr outputVector)
85
    {
86
        var dataChunk = new DuckDBDataChunk(chunk);
78✔
87

88
        var chunkSize = NativeMethods.DataChunks.DuckDBDataChunkGetSize(dataChunk);
78✔
89
        var handle = GCHandle.FromIntPtr(NativeMethods.ScalarFunction.DuckDBScalarFunctionGetExtraInfo(info));
78✔
90

91
        if (handle.Target is not ScalarFunctionInfo functionInfo)
78!
92
        {
93
            throw new InvalidOperationException("User defined scalar function execution failed. Function extra info is null");
×
94
        }
95

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

98
        for (var index = 0; index < readers.Length; index++)
354✔
99
        {
100
            var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, index);
99✔
101
            readers[index] = VectorDataReaderFactory.CreateReader(vector, NativeMethods.Vectors.DuckDBVectorGetColumnType(vector));
99✔
102
        }
103

104
        var writer = VectorDataWriterFactory.CreateWriter(outputVector, functionInfo.ReturnType);
78✔
105

106
        functionInfo.Action(readers, writer, chunkSize);
78✔
107
    }
78✔
108

109
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
110
    private static void DestroyExtraInfo(IntPtr pointer) => pointer.FreeHandle();
87✔
111
}
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