Repository navigation
Expand file tree
/
Copy pathSQLiteUriOptions.cs
More file actions
67 lines (65 loc) · 3.32 KB
/
Copy pathSQLiteUriOptions.cs
File metadata and controls
67 lines (65 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System.Data.Common;
namespace DBAClientX;
/// <summary>Shares native SQLite option semantics between connections and destructive-operation identities.</summary>
internal static class SQLiteUriOptions
{
/// <summary>Applies ordered, case-sensitive options while retaining native options and explicit connection overrides.</summary>
internal static string Apply(DbConnectionStringBuilder builder, string query)
{
// Capture caller overrides once. Earlier URI occurrences are not caller overrides.
bool explicitMode = builder.ShouldSerialize("Mode");
bool explicitCache = builder.ShouldSerialize("Cache");
bool explicitVfs = builder.ShouldSerialize("Vfs");
int access = 3; // SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, before implicit URI mode options.
string? lastVfs = null;
string? lastVfsPart = null;
var native = new List<string>();
foreach (string part in query.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
{
int separator = part.IndexOf('=');
string key = Uri.UnescapeDataString(separator < 0 ? part : part.Substring(0, separator));
string value = Uri.UnescapeDataString(separator < 0 ? string.Empty : part.Substring(separator + 1));
switch (key)
{
case "mode":
string? mode = value switch
{
"ro" => "ReadOnly", "rw" => "ReadWrite", "rwc" => "ReadWriteCreate", "memory" => "Memory", _ => null
};
// Invalid native values must reach SQLite and fail, even if repeated later.
if (mode == null) native.Add(part);
else if (!explicitMode)
{
int nextAccess = value switch { "ro" => 1, "rw" => 2, "rwc" => 3, _ => 0x80 };
// SQLite validates each ordered mode against the preceding access flags.
// A later occurrence cannot escalate a read-only/read-write disk mode.
if (nextAccess != 0x80 && nextAccess > access)
throw new ArgumentException("SQLite URI access mode cannot increase within the option sequence.", nameof(query));
access = nextAccess;
builder["Mode"] = mode;
}
break;
case "cache":
string? cache = value switch { "shared" => "Shared", "private" => "Private", _ => null };
if (cache == null) native.Add(part);
else if (!explicitCache) builder["Cache"] = cache;
break;
case "vfs":
lastVfs = value;
lastVfsPart = part;
break;
default:
native.Add(part);
break;
}
}
if (!explicitVfs && lastVfs != null)
{
// Empty/whitespace final vfs names must remain native options. The managed
// provider treats whitespace builder values as its default VFS instead.
if (string.IsNullOrWhiteSpace(lastVfs)) native.Add(lastVfsPart!);
else builder["Vfs"] = lastVfs;
}
return string.Join("&", native);
}
}