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

Giorgi / DuckDB.NET / 21786556530

07 Feb 2026 08:39PM UTC coverage: 89.155% (-0.07%) from 89.223%
21786556530

push

github

Giorgi
Added support for clearing in-progress adapter

Requires DuckDB 1.5

1199 of 1393 branches covered (86.07%)

Branch coverage included in aggregate %.

6 of 8 new or added lines in 1 file covered. (75.0%)

193 existing lines in 43 files now uncovered.

2336 of 2572 relevant lines covered (90.82%)

557295.56 hits per line

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

86.87
/DuckDB.NET.Data/Connection/ConnectionManager.cs
1
using System.Collections.Concurrent;
2
using System.Threading;
3

4
namespace DuckDB.NET.Data.Connection;
5

6
/// <summary>
7
/// Creates, caches, and disconnects ConnectionReferences.
8
/// </summary>
9
internal class ConnectionManager
10
{
11
    public static readonly ConnectionManager Default = new();
3✔
12

13
    private static readonly ConcurrentDictionary<string, FileReference> ConnectionCache = new(StringComparer.OrdinalIgnoreCase);
3✔
14

15
    internal ConnectionReference GetConnectionReference(DuckDBConnectionString connectionString)
16
    {
17
        var filename = connectionString.DataSource;
64,941✔
18

19
        var fileRef = connectionString.InMemory && !connectionString.Shared ? new FileReference("") : null;
64,941✔
20

21
        //need to loop until we have a locked fileRef
22
        //that is also in the cache
23
        while (fileRef == null)
65,168✔
24
        {
25
            fileRef = ConnectionCache.GetOrAdd(filename, fn =>
64,946✔
26
            {
64,946✔
27
                fileRef = new FileReference(filename);
46,393✔
28
                return fileRef;
46,393✔
29
            });
64,946✔
30

31
            Monitor.Enter(fileRef);
64,946✔
32

33
            //Need to make sure what we have locked is still in the cache
34
            var existingFileRef = ConnectionCache.GetOrAdd(filename, fileRef);
64,946✔
35

36
            if (existingFileRef == fileRef)
64,946✔
37
            {
38
                //file in the cache matches what is locked, we are good!
39
                break;
40
            }
41

42
            //exit lock and try the whole thing again
43
            Monitor.Exit(fileRef);
227✔
44
            fileRef = null;
227✔
45
        }
46

47
        //now connect what needs to be connected
48
        try
49
        {
50
            if (fileRef.Database == null)
64,941✔
51
            {
52
                var path = connectionString.InMemory ? null : filename;
51,607✔
53

54
                NativeMethods.Configuration.DuckDBCreateConfig(out var config);
51,607✔
55
                using (config)
51,607✔
56
                {
57
                    foreach (var (option, value) in connectionString.Configuration)
206,500✔
58
                    {
59
                        var state = NativeMethods.Configuration.DuckDBSetConfig(config, option, value);
51,646✔
60

61
                        if (!state.IsSuccess())
51,646✔
62
                        {
63
                            throw new DuckDBException($"Error setting '{option}' to '{value}'");
6✔
64
                        }
65
                    }
66

67
                    using var pathUnmanaged = path.ToUnmanagedString();
51,601✔
68

69
                    var resultOpen = NativeMethods.Startup.DuckDBOpen(pathUnmanaged, out var db, config, out var error);
51,601✔
70

71
                    if (!resultOpen.IsSuccess())
51,601!
72
                    {
UNCOV
73
                        throw new DuckDBException($"DuckDBOpen failed: {error.ToManagedString()}");
×
74
                    }
75
                    fileRef.Database = db;
51,601✔
76
                }
77
            }
78

79
            var resultConnect = NativeMethods.Startup.DuckDBConnect(fileRef.Database, out var nativeConnection);
64,935✔
80

81
            if (resultConnect.IsSuccess())
64,935!
82
            {
83
                fileRef.Increment();
64,935✔
84
            }
85
            else
86
            {
UNCOV
87
                throw new DuckDBException("DuckDBConnect failed");
×
88
            }
89

90
            return new ConnectionReference(fileRef, nativeConnection);
64,935✔
91
        }
92
        finally
93
        {
94
            if (Monitor.IsEntered(fileRef))
64,941✔
95
            {
96
                Monitor.Exit(fileRef);
64,719✔
97
            }
98
        }
64,941✔
99
    }
64,935✔
100

101
    internal void ReturnConnectionReference(ConnectionReference connectionReference)
102
    {
103
        var fileRef = connectionReference.FileReferenceCounter;
64,932✔
104

105
        lock (fileRef)
64,932✔
106
        {
107
            var nativeConnection = connectionReference.NativeConnection;
64,932✔
108

109
            nativeConnection.Dispose();
64,932✔
110

111
            var current = fileRef.Decrement();
64,932✔
112

113
            if (current < 0)
64,932!
114
            {
UNCOV
115
                throw new InvalidOperationException($"{fileRef.FileName} has been returned too many times");
×
116
            }
117

118
            if (current == 0)
64,932✔
119
            {
120
                fileRef.Database?.Dispose();
51,595!
121
                fileRef.Database = null;
51,595✔
122

123
                if (!string.IsNullOrEmpty(fileRef.FileName) && !ConnectionCache.TryRemove(fileRef.FileName, out _))
51,595!
124
                {
UNCOV
125
                    throw new InvalidOperationException($"Internal Error: tried to remove {fileRef.FileName} from cache but it wasn't there!");
×
126
                }
127
            }
128
        }
64,932✔
129
    }
64,932✔
130

131
    internal ConnectionReference DuplicateConnectionReference(ConnectionReference connectionReference)
132
    {
133
        var fileRef = connectionReference.FileReferenceCounter;
3✔
134

135
        if (fileRef.Database is null)
3!
UNCOV
136
            throw new InvalidOperationException(); //shouldn't happen if we already have a connection reference
×
137

138
        lock (fileRef)
3✔
139
        {
140
            var resultConnect = NativeMethods.Startup.DuckDBConnect(fileRef.Database, out var duplicatedNativeConnection);
3✔
141
            if (resultConnect.IsSuccess())
3!
142
            {
143
                fileRef.Increment();
3✔
144
            }
145
            else
146
            {
UNCOV
147
                throw new DuckDBException("DuckDBConnect failed");
×
148
            }
149
            return new ConnectionReference(fileRef, duplicatedNativeConnection);
3✔
150
        }
151
    }
3✔
152
}
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