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

Giorgi / DuckDB.NET / 22870989532

09 Mar 2026 07:28PM UTC coverage: 89.342% (+0.09%) from 89.254%
22870989532

push

github

Giorgi
Infer scalar function null handling from parameter nullability

Use NullabilityInfoContext to detect nullable parameters and
automatically set HandlesNulls, removing the need for callers
to pass ScalarFunctionOptions. Add strict/non-strict GetValue
modes so reference types return null instead of throwing in
non-strict contexts (e.g. scalar function callbacks).

1253 of 1463 branches covered (85.65%)

Branch coverage included in aggregate %.

43 of 48 new or added lines in 6 files covered. (89.58%)

1 existing line in 1 file now uncovered.

2645 of 2900 relevant lines covered (91.21%)

445447.62 hits per line

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

91.43
/DuckDB.NET.Data/DataChunk/Reader/StringVectorDataReader.cs
1
using System.IO;
2
using System.Text;
3

4
namespace DuckDB.NET.Data.DataChunk.Reader;
5

6
internal sealed class StringVectorDataReader : VectorDataReaderBase
7
{
8
    internal unsafe StringVectorDataReader(void* dataPointer, ulong* validityMaskPointer, DuckDBType columnType, string columnName) : base(dataPointer, validityMaskPointer, columnType, columnName)
2,730✔
9
    {
10
    }
2,730✔
11

12
    protected override T GetValidValue<T>(ulong offset, Type targetType)
13
    {
14
        return DuckDBType switch
30,324!
15
        {
30,324✔
16
            DuckDBType.Bit => GetBitString<T>(offset),
12✔
17
            DuckDBType.Blob => (T)(object)GetStream(offset),
24✔
18
            DuckDBType.Varchar => (T)(object)GetString(offset),
30,288✔
19
            _ => base.GetValidValue<T>(offset, targetType)
×
20
        };
30,324✔
21
    }
22

23
    internal override object GetValue(ulong offset, Type targetType)
24
    {
25
        return DuckDBType switch
834,601!
26
        {
834,601✔
27
            DuckDBType.Bit => GetBitString(offset),
9✔
28
            DuckDBType.Blob => GetStream(offset),
3✔
29
            DuckDBType.Varchar => GetString(offset),
834,589✔
30
            _ => base.GetValue(offset, targetType)
×
31
        };
834,601✔
32
    }
33

34
    private T GetBitString<T>(ulong offset)
35
    {
36
        if (typeof(T) == typeof(string))
12✔
37
        {
38
            return (T)(object)GetBitString(offset);
9✔
39
        }
40

41
        if (typeof(T) == typeof(BitArray))
3!
42
        {
43
            return (T)(object)GetBitStringAsBitArray(offset);
3✔
44
        }
45

NEW
46
        return GetValueStrict<T>(offset);
×
47
    }
48

49
    private string GetBitString(ulong offset)
50
    {
51
        var bitArray = GetBitStringAsBitArray(offset);
18✔
52

53
        return string.Create(bitArray.Length, bitArray, (chars, array) =>
18✔
54
        {
18✔
55
            for (int index = 0; index < array.Length; index++)
612✔
56
            {
18✔
57
                chars[index] = array[index] ? '1' : '0';
288✔
58
            }
18✔
59
        });
36✔
60
    }
61

62
    //Copied from https://github.com/duckdb/duckdb/blob/8a17511028d306561d88da9425f9e0e88dedd70c/src/common/types/bit.cpp#L63
63
    private unsafe BitArray GetBitStringAsBitArray(ulong offset)
64
    {
65
        var bits = (DuckDBString*)DataPointer + offset;
21✔
66
        var data = bits->Data;
21✔
67

68
        var bitLength = (bits->Length - 1) * 8 - *data;
21✔
69

70
        var output = new BitArray(bitLength);
21✔
71
        var outputIndex = 0;
21✔
72

73
        for (var bitIndex = *data; bitIndex < 8; bitIndex++)
258✔
74
        {
75
            output[outputIndex++] = (*(data + 1) & (1 << (7 - bitIndex))) > 0;
108✔
76
        }
77

78
        for (var byteIndex = 2; byteIndex < bits->Length; byteIndex++)
96✔
79
        {
80
            for (var bitIndex = 0; bitIndex < 8; bitIndex++)
486✔
81
            {
82
                output[outputIndex++] = (*(data + byteIndex) & (1 << (7 - bitIndex))) > 0;
216✔
83
            }
84
        }
85

86
        return output;
21✔
87
    }
88

89
    private unsafe string GetString(ulong offset)
90
    {
91
        var data = (DuckDBString*)DataPointer + offset;
864,877✔
92

93
        return new string(data->Data, 0, data->Length, Encoding.UTF8);
864,877✔
94
    }
95

96
    private unsafe Stream GetStream(ulong offset)
97
    {
98
        var data = (DuckDBString*)DataPointer + offset;
27✔
99

100
        return new UnmanagedMemoryStream((byte*)data->Data, data->Length, data->Length, FileAccess.Read);
27✔
101
    }
102
}
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