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

Giorgi / DuckDB.NET / 13181075586

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

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%)

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

12
namespace DuckDB.NET.Data;
13

14
partial class DuckDBConnection
15
{
16
#if NET8_0_OR_GREATER
17
    [Experimental("DuckDBNET001")]
18
    public void RegisterScalarFunction<TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = false)
19
    {
20
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction);
3✔
21
    }
3✔
22

23
    [Experimental("DuckDBNET001")]
24
    public void RegisterScalarFunction<T, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true, bool @params = false)
25
    {
26
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), @params, !isPureFunction, TypeExtensions.GetLogicalType<T>());
9✔
27
    }
9✔
28

29
    [Experimental("DuckDBNET001")]
30
    public void RegisterScalarFunction<T1, T2, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true)
31
    {
32
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction,
6✔
33
                              TypeExtensions.GetLogicalType<T1>(), 
6✔
34
                              TypeExtensions.GetLogicalType<T2>());
6✔
35
    }
6✔
36

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

46
    [Experimental("DuckDBNET001")]
47
    public void RegisterScalarFunction<T1, T2, T3, T4, TResult>(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, bool isPureFunction = true)
48
    {
NEW
49
        RegisterScalarMethod(name, action, TypeExtensions.GetLogicalType<TResult>(), varargs: false, !isPureFunction,
×
NEW
50
                              TypeExtensions.GetLogicalType<T1>(),
×
NEW
51
                              TypeExtensions.GetLogicalType<T2>(),
×
NEW
52
                              TypeExtensions.GetLogicalType<T3>(),
×
NEW
53
                              TypeExtensions.GetLogicalType<T4>());
×
UNCOV
54
    }
×
55

56
    [Experimental("DuckDBNET001")]
57
    private unsafe void RegisterScalarMethod(string name, Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> action, DuckDBLogicalType returnType,
58
                                             bool varargs, bool @volatile, params DuckDBLogicalType[] parameterTypes)
59
    {
60
        var function = NativeMethods.ScalarFunction.DuckDBCreateScalarFunction();
18✔
61
        using (var handle = name.ToUnmanagedString())
18✔
62
        {
63
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetName(function, handle);
18✔
64
        }
18✔
65

66
        if (varargs)
18✔
67
        {
68
            if (parameterTypes.Length != 1)
3!
69
            {
70
                throw new InvalidOperationException("Cannot use params with multiple parameters");
×
71
            }
72

73
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetVarargs(function, parameterTypes[0]);
3✔
74
        }
75
        else
76
        {
77
            foreach (var type in parameterTypes)
66✔
78
            {
79
                NativeMethods.ScalarFunction.DuckDBScalarFunctionAddParameter(function, type);
18✔
80
                type.Dispose();
18✔
81
            }
82
        }
83

84
        if (@volatile)
18✔
85
        {
86
            NativeMethods.ScalarFunction.DuckDBScalarFunctionSetVolatile(function);
9✔
87
        }
88

89
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetReturnType(function, returnType);
18✔
90
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetFunction(function, &ScalarFunctionCallback);
18✔
91

92
        var info = new ScalarFunctionInfo(returnType, action);
18✔
93

94
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetExtraInfo(function, info.ToHandle(), &DestroyExtraInfo);
18✔
95

96
        var state = NativeMethods.ScalarFunction.DuckDBRegisterScalarFunction(NativeConnection, function);
18✔
97

98
        NativeMethods.ScalarFunction.DuckDBDestroyScalarFunction(out function);
18✔
99

100
        if (!state.IsSuccess())
18!
101
        {
102
            throw new InvalidOperationException($"Error registering user defined scalar function: {name}");
×
103
        }
104
    }
18✔
105

106
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
107
    private static void ScalarFunctionCallback(IntPtr info, IntPtr chunk, IntPtr outputVector)
108
    {
109
        var dataChunk = new DuckDBDataChunk(chunk);
78✔
110

111
        var chunkSize = NativeMethods.DataChunks.DuckDBDataChunkGetSize(dataChunk);
78✔
112
        var handle = GCHandle.FromIntPtr(NativeMethods.ScalarFunction.DuckDBScalarFunctionGetExtraInfo(info));
78✔
113

114
        if (handle.Target is not ScalarFunctionInfo functionInfo)
78!
115
        {
116
            throw new InvalidOperationException("User defined scalar function execution failed. Function extra info is null");
×
117
        }
118

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

121
        for (var index = 0; index < readers.Length; index++)
354✔
122
        {
123
            var vector = NativeMethods.DataChunks.DuckDBDataChunkGetVector(dataChunk, index);
99✔
124
            readers[index] = VectorDataReaderFactory.CreateReader(vector, NativeMethods.Vectors.DuckDBVectorGetColumnType(vector));
99✔
125
        }
126

127
        var writer = VectorDataWriterFactory.CreateWriter(outputVector, functionInfo.ReturnType);
78✔
128

129
        functionInfo.Action(readers, writer, chunkSize);
78✔
130
    }
78✔
131

132
    [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
133
    private static void DestroyExtraInfo(IntPtr pointer) => pointer.FreeHandle();
75✔
134
#endif
135
}
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