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

Giorgi / DuckDB.NET / 11718008911

07 Nov 2024 06:48AM UTC coverage: 89.937% (+0.09%) from 89.848%
11718008911

push

github

Giorgi
Merge branch 'develop'

1063 of 1216 branches covered (87.42%)

Branch coverage included in aggregate %.

256 of 275 new or added lines in 15 files covered. (93.09%)

1 existing line in 1 file now uncovered.

2083 of 2282 relevant lines covered (91.28%)

833852.27 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.Extensions;
2
using DuckDB.NET.Data.Internal;
3
using DuckDB.NET.Data.Internal.Reader;
4
using DuckDB.NET.Data.Internal.Writer;
5
using DuckDB.NET.Data.Reader;
6
using DuckDB.NET.Data.Writer;
7
using DuckDB.NET.Native;
8
using System;
9
using System.Collections.Generic;
10
using System.Diagnostics.CodeAnalysis;
11
using System.Runtime.CompilerServices;
12
using System.Runtime.InteropServices;
13

14
namespace DuckDB.NET.Data;
15

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

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

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

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

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

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

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

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

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

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

94
        var info = new ScalarFunctionInfo(returnType, action);
18✔
95

96
        NativeMethods.ScalarFunction.DuckDBScalarFunctionSetExtraInfo(function, info.ToHandle(), &DestroyExtraInfo);
18✔
97

98
        var state = NativeMethods.ScalarFunction.DuckDBRegisterScalarFunction(NativeConnection, function);
18✔
99

100
        NativeMethods.ScalarFunction.DuckDBDestroyScalarFunction(out function);
18✔
101

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

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

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

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

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

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

129
        var writer = VectorDataWriterFactory.CreateWriter(outputVector, functionInfo.ReturnType);
78✔
130

131
        functionInfo.Action(readers, writer, chunkSize);
78✔
132
    }
78✔
133

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