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

Giorgi / DuckDB.NET / 22806087371

07 Mar 2026 07:54PM UTC coverage: 89.254% (-0.06%) from 89.313%
22806087371

push

github

Giorgi
Preserve inner exceptions from scalar function errors

Use a bind callback to capture the connection ID, enabling
the UdfExceptionStore to store full exception details for
scalar functions (matching existing table function behavior).

1254 of 1467 branches covered (85.48%)

Branch coverage included in aggregate %.

15 of 19 new or added lines in 3 files covered. (78.95%)

13 existing lines in 3 files now uncovered.

2633 of 2888 relevant lines covered (91.17%)

445065.7 hits per line

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

92.13
/DuckDB.NET.Data/PreparedStatement/PreparedStatement.cs
1
using System.Linq;
2
using DuckDB.NET.Data.Connection;
3

4
namespace DuckDB.NET.Data.PreparedStatement;
5

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

10
    private PreparedStatement(DuckDBPreparedStatement statement)
158,136✔
11
    {
12
        this.statement = statement;
158,136✔
13
    }
158,136✔
14

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

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

27
            for (int index = 0; index < statementCount; index++)
553,428✔
28
            {
29
                var status = NativeMethods.ExtractStatements.DuckDBPrepareExtractedStatement(connection, extractedStatements, index, out var statement);
158,151✔
30

31
                if (status.IsSuccess())
158,151✔
32
                {
33
                    using var preparedStatement = new PreparedStatement(statement);
158,136✔
34
                    yield return preparedStatement.Execute(parameters, useStreamingMode, connection);
158,136✔
35
                }
118,674✔
36
                else
37
                {
38
                    var errorMessage = NativeMethods.PreparedStatements.DuckDBPrepareError(statement);
15✔
39

40
                    if (string.IsNullOrEmpty(errorMessage))
15!
41
                    {
UNCOV
42
                        errorMessage = "DuckDBQuery failed";
×
43
                    }
44

45
                    throw new DuckDBException(errorMessage, UdfExceptionStore.Retrieve(connection));
15✔
46
                }
47
            }
48
        }
118,563✔
49
    }
118,563✔
50

51
    private DuckDBResult Execute(DuckDBParameterCollection parameterCollection, bool useStreamingMode, DuckDBNativeConnection connection)
52
    {
53
        BindParameters(statement, parameterCollection);
158,136✔
54

55
        var status = useStreamingMode
158,118✔
56
            ? NativeMethods.PreparedStatements.DuckDBExecutePreparedStreaming(statement, out var queryResult)
158,118✔
57
            : NativeMethods.PreparedStatements.DuckDBExecutePrepared(statement, out queryResult);
158,118✔
58

59
        if (!status.IsSuccess())
158,118✔
60
        {
61
            var errorMessage = NativeMethods.Query.DuckDBResultError(ref queryResult);
57✔
62
            var errorType = NativeMethods.Query.DuckDBResultErrorType(ref queryResult);
57✔
63
            queryResult.Close();
57✔
64

65
            if (string.IsNullOrEmpty(errorMessage))
57!
66
            {
UNCOV
67
                errorMessage = "DuckDB execution failed";
×
68
            }
69

70
            if (errorType == DuckDBErrorType.Interrupt)
57✔
71
            {
72
                throw new OperationCanceledException();
12✔
73
            }
74

75
            var innerException = UdfExceptionStore.Retrieve(connection);
45✔
76
            throw innerException != null
45✔
77
                ? new DuckDBException(errorMessage, innerException)
45✔
78
                : new DuckDBException(errorMessage, errorType);
45✔
79
        }
80

81
        return queryResult;
158,061✔
82
    }
83

84
    private static void BindParameters(DuckDBPreparedStatement preparedStatement, DuckDBParameterCollection parameterCollection)
85
    {
86
        var expectedParameters = NativeMethods.PreparedStatements.DuckDBParams(preparedStatement);
158,136✔
87
        if (parameterCollection.Count < expectedParameters)
158,136✔
88
        {
89
            throw new InvalidOperationException($"Invalid number of parameters. Expected {expectedParameters}, got {parameterCollection.Count}");
18✔
90
        }
91

92
        if (parameterCollection.OfType<DuckDBParameter>().Any(p => !string.IsNullOrEmpty(p.ParameterName)))
159,693✔
93
        {
94
            foreach (DuckDBParameter param in parameterCollection)
672✔
95
            {
96
                var state = NativeMethods.PreparedStatements.DuckDBBindParameterIndex(preparedStatement, out var index, param.ParameterName);
204✔
97
                if (state.IsSuccess())
204✔
98
                {
99
                    BindParameter(preparedStatement, index, param);
174✔
100
                }
101
            }
102
        }
103
        else
104
        {
105
            for (var i = 0; i < expectedParameters; ++i)
317,772✔
106
            {
107
                var param = parameterCollection[i];
900✔
108
                BindParameter(preparedStatement, i + 1, param);
900✔
109
            }
110
        }
111
    }
158,118✔
112

113
    private static void BindParameter(DuckDBPreparedStatement preparedStatement, long index, DuckDBParameter parameter)
114
    {
115
        using var parameterLogicalType = NativeMethods.PreparedStatements.DuckDBParamLogicalType(preparedStatement, index);
1,074✔
116
        var duckDBType = NativeMethods.LogicalType.DuckDBGetTypeId(parameterLogicalType);
1,074✔
117

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

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

122
        if (!result.IsSuccess())
1,074!
123
        {
UNCOV
124
            var errorMessage = NativeMethods.PreparedStatements.DuckDBPrepareError(preparedStatement);
×
UNCOV
125
            throw new InvalidOperationException($"Unable to bind parameter {index}: {errorMessage}");
×
126
        }
127
    }
2,148✔
128

129
    public void Dispose()
130
    {
131
        statement.Dispose();
157,476✔
132
    }
157,476✔
133
}
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