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

Giorgi / DuckDB.NET / 21922970228

11 Feb 2026 09:04PM UTC coverage: 89.265% (+0.02%) from 89.25%
21922970228

push

github

Giorgi
Replace ToManagedString with custom marshallers

Introduce DuckDBOwnedStringMarshaller and
DuckDBCallerOwnedStringMarshaller to handle native string
lifetime semantics at the marshalling layer.

1195 of 1387 branches covered (86.16%)

Branch coverage included in aggregate %.

14 of 17 new or added lines in 10 files covered. (82.35%)

2314 of 2544 relevant lines covered (90.96%)

557359.58 hits per line

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

92.68
/DuckDB.NET.Data/PreparedStatement/PreparedStatement.cs
1
using System.Linq;
2

3
namespace DuckDB.NET.Data.PreparedStatement;
4

5
internal sealed class PreparedStatement : IDisposable
6
{
7
    private readonly DuckDBPreparedStatement statement;
8

9
    private PreparedStatement(DuckDBPreparedStatement statement)
157,869✔
10
    {
11
        this.statement = statement;
157,869✔
12
    }
157,869✔
13

14
    public static IEnumerable<DuckDBResult> PrepareMultiple(DuckDBNativeConnection connection, string query, DuckDBParameterCollection parameters, bool useStreamingMode)
15
    {
16
        var statementCount = NativeMethods.ExtractStatements.DuckDBExtractStatements(connection, query, out var extractedStatements);
157,767✔
17

18
        using (extractedStatements)
157,767✔
19
        {
20
            if (statementCount <= 0)
157,767✔
21
            {
22
                var error = NativeMethods.ExtractStatements.DuckDBExtractStatementsError(extractedStatements);
3✔
23
                throw new DuckDBException(error);
3✔
24
            }
25

26
            for (int index = 0; index < statementCount; index++)
552,546✔
27
            {
28
                var status = NativeMethods.ExtractStatements.DuckDBPrepareExtractedStatement(connection, extractedStatements, index, out var statement);
157,875✔
29

30
                if (status.IsSuccess())
157,875✔
31
                {
32
                    using var preparedStatement = new PreparedStatement(statement);
157,869✔
33
                    yield return preparedStatement.Execute(parameters, useStreamingMode);
157,869✔
34
                }
118,509✔
35
                else
36
                {
37
                    var errorMessage = NativeMethods.PreparedStatements.DuckDBPrepareError(statement);
6✔
38

39
                    throw new DuckDBException(string.IsNullOrEmpty(errorMessage) ? "DuckDBQuery failed" : errorMessage);
6!
40
                }
41
            }
42
        }
118,398✔
43
    }
118,398✔
44

45
    private DuckDBResult Execute(DuckDBParameterCollection parameterCollection, bool useStreamingMode)
46
    {
47
        BindParameters(statement, parameterCollection);
157,869✔
48

49
        var status = useStreamingMode
157,851✔
50
            ? NativeMethods.PreparedStatements.DuckDBExecutePreparedStreaming(statement, out var queryResult)
157,851✔
51
            : NativeMethods.PreparedStatements.DuckDBExecutePrepared(statement, out queryResult);
157,851✔
52

53
        if (!status.IsSuccess())
157,851✔
54
        {
55
            var errorMessage = NativeMethods.Query.DuckDBResultError(ref queryResult);
45✔
56
            var errorType = NativeMethods.Query.DuckDBResultErrorType(ref queryResult);
45✔
57
            queryResult.Close();
45✔
58

59
            if (string.IsNullOrEmpty(errorMessage))
45!
60
            {
61
                errorMessage = "DuckDB execution failed";
×
62
            }
63

64
            if (errorType == DuckDBErrorType.Interrupt)
45✔
65
            {
66
                throw new OperationCanceledException();
12✔
67
            }
68

69
            throw new DuckDBException(errorMessage, errorType);
33✔
70
        }
71

72
        return queryResult;
157,806✔
73
    }
74

75
    private static void BindParameters(DuckDBPreparedStatement preparedStatement, DuckDBParameterCollection parameterCollection)
76
    {
77
        var expectedParameters = NativeMethods.PreparedStatements.DuckDBParams(preparedStatement);
157,869✔
78
        if (parameterCollection.Count < expectedParameters)
157,869✔
79
        {
80
            throw new InvalidOperationException($"Invalid number of parameters. Expected {expectedParameters}, got {parameterCollection.Count}");
18✔
81
        }
82

83
        if (parameterCollection.OfType<DuckDBParameter>().Any(p => !string.IsNullOrEmpty(p.ParameterName)))
159,426✔
84
        {
85
            foreach (DuckDBParameter param in parameterCollection)
672✔
86
            {
87
                var state = NativeMethods.PreparedStatements.DuckDBBindParameterIndex(preparedStatement, out var index, param.ParameterName);
204✔
88
                if (state.IsSuccess())
204✔
89
                {
90
                    BindParameter(preparedStatement, index, param);
174✔
91
                }
92
            }
93
        }
94
        else
95
        {
96
            for (var i = 0; i < expectedParameters; ++i)
317,238✔
97
            {
98
                var param = parameterCollection[i];
900✔
99
                BindParameter(preparedStatement, i + 1, param);
900✔
100
            }
101
        }
102
    }
157,851✔
103

104
    private static void BindParameter(DuckDBPreparedStatement preparedStatement, long index, DuckDBParameter parameter)
105
    {
106
        using var parameterLogicalType = NativeMethods.PreparedStatements.DuckDBParamLogicalType(preparedStatement, index);
1,074✔
107
        var duckDBType = NativeMethods.LogicalType.DuckDBGetTypeId(parameterLogicalType);
1,074✔
108

109
        using var duckDBValue = parameter.Value.ToDuckDBValue(parameterLogicalType, duckDBType, parameter.DbType);
1,074✔
110

111
        var result = NativeMethods.PreparedStatements.DuckDBBindValue(preparedStatement, index, duckDBValue);
1,074✔
112

113
        if (!result.IsSuccess())
1,074!
114
        {
NEW
115
            var errorMessage = NativeMethods.PreparedStatements.DuckDBPrepareError(preparedStatement);
×
116
            throw new InvalidOperationException($"Unable to bind parameter {index}: {errorMessage}");
×
117
        }
118
    }
2,148✔
119

120
    public void Dispose()
121
    {
122
        statement.Dispose();
157,209✔
123
    }
157,209✔
124
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc