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

Giorgi / DuckDB.NET / 22500794591

27 Feb 2026 07:31PM UTC coverage: 89.868% (+0.2%) from 89.658%
22500794591

push

github

Giorgi
Add `object` type support for simplified scalar functions

Extract `ReadValue<T>` helper that dispatches to non-generic
`GetValue` when T is `object`, enabling dynamic type resolution
at runtime.

1267 of 1467 branches covered (86.37%)

Branch coverage included in aggregate %.

5 of 7 new or added lines in 1 file covered. (71.43%)

9 existing lines in 3 files now uncovered.

2609 of 2846 relevant lines covered (91.67%)

462743.29 hits per line

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

92.98
/DuckDB.NET.Data/DuckDBConnection.ScalarFunction.Extensions.cs
1
using DuckDB.NET.Data.DataChunk.Reader;
2
using DuckDB.NET.Data.DataChunk.Writer;
3
using System.Runtime.CompilerServices;
4

5
namespace DuckDB.NET.Data;
6

7
public static class DuckDBConnectionScalarFunctionExtensions
8
{
9
    extension(DuckDBConnection connection)
10
    {
11
        public void RegisterScalarFunction<TResult>(string name, Func<TResult> func, bool isPureFunction = false)
12
        {
13
            connection.RegisterScalarFunction<TResult>(name, (writer, rowCount) =>
3✔
14
            {
3✔
15
                for (ulong index = 0; index < rowCount; index++)
36✔
16
                {
3✔
17
                    writer.WriteValue(func(), index);
15✔
18
                }
3✔
19
            }, isPureFunction);
6✔
20
        }
3✔
21

22
        public void RegisterScalarFunction<T, TResult>(string name, Func<T, TResult> func, bool isPureFunction = true)
23
        {
24
            connection.RegisterScalarFunction<T, TResult>(name, WrapScalarFunction<TResult>((readers, index) =>
15✔
25
                func(ReadValue<T>(readers[0], index))), isPureFunction);
348✔
26
        }
15✔
27

28
        public void RegisterScalarFunction<T, TResult>(string name, Func<T[], TResult> func, bool isPureFunction = true)
29
        {
30
            connection.RegisterScalarFunction<T, TResult>(name, WrapVarargsScalarFunction(func), isPureFunction, @params: true);
18✔
31
        }
18✔
32

33
        public void RegisterScalarFunction<T1, T2, TResult>(string name, Func<T1, T2, TResult> func, bool isPureFunction = true)
34
        {
35
            connection.RegisterScalarFunction<T1, T2, TResult>(name, WrapScalarFunction<TResult>((readers, index) =>
9✔
36
                func(ReadValue<T1>(readers[0], index), ReadValue<T2>(readers[1], index))), isPureFunction);
21✔
37
        }
9✔
38

39
        public void RegisterScalarFunction<T1, T2, T3, TResult>(string name, Func<T1, T2, T3, TResult> func, bool isPureFunction = true)
40
        {
41
            connection.RegisterScalarFunction<T1, T2, T3, TResult>(name, WrapScalarFunction<TResult>((readers, index) =>
6✔
42
                func(ReadValue<T1>(readers[0], index), ReadValue<T2>(readers[1], index), ReadValue<T3>(readers[2], index))), isPureFunction);
42✔
43
        }
6✔
44

45
        public void RegisterScalarFunction<T1, T2, T3, T4, TResult>(string name, Func<T1, T2, T3, T4, TResult> func, bool isPureFunction = true)
46
        {
UNCOV
47
            connection.RegisterScalarFunction<T1, T2, T3, T4, TResult>(name, WrapScalarFunction<TResult>((readers, index) =>
×
NEW
48
                func(ReadValue<T1>(readers[0], index), ReadValue<T2>(readers[1], index),
×
NEW
49
                    ReadValue<T3>(readers[2], index), ReadValue<T4>(readers[3], index))), isPureFunction);
×
UNCOV
50
        }
×
51
    }
52

53
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
54
    private static T ReadValue<T>(IDuckDBDataReader reader, ulong index)
55
        => typeof(T) == typeof(object) ? (T)reader.GetValue(index) : reader.GetValue<T>(index);
120,522✔
56

57
    private static Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> WrapScalarFunction<TResult>(Func<IReadOnlyList<IDuckDBDataReader>, ulong, TResult> perRowFunc)
58
    {
59
        return (readers, writer, rowCount) =>
30✔
60
        {
30✔
61
            for (ulong index = 0; index < rowCount; index++)
846✔
62
            {
30✔
63
                var result = perRowFunc(readers, index);
381✔
64

30✔
65
                writer.WriteValue(result, index);
381✔
66
            }
30✔
67
        };
72✔
68
    }
69

70
    private static Action<IReadOnlyList<IDuckDBDataReader>, IDuckDBDataWriter, ulong> WrapVarargsScalarFunction<T, TResult>(Func<T[], TResult> func)
71
    {
72
        return (readers, writer, rowCount) =>
18✔
73
        {
18✔
74
            var args = new T[readers.Count];
81✔
75

18✔
76
            for (ulong index = 0; index < rowCount; index++)
210,216✔
77
            {
18✔
78
                for (int r = 0; r < readers.Count; r++)
450,168✔
79
                {
18✔
80
                    args[r] = ReadValue<T>(readers[r], index);
120,057✔
81
                }
18✔
82

18✔
83
                writer.WriteValue(func(args), index);
105,027✔
84
            }
18✔
85
        };
99✔
86
    }
87
}
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