forked from microsoft/winget-cli-restsource
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSqlReader.cs
More file actions
156 lines (131 loc) · 5.6 KB
/
SqlReader.cs
File metadata and controls
156 lines (131 loc) · 5.6 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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// -----------------------------------------------------------------------
// <copyright file="SqlReader.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.WinGet.RestSource.Sql
{
using System;
using System.Collections.Generic;
using Microsoft.Data.Sqlite;
/// <summary>
/// Helper class to read sql database.
/// </summary>
internal class SqlReader : IDisposable
{
private readonly SqliteConnection connection;
/// <summary>
/// Initializes a new instance of the <see cref="SqlReader"/> class.
/// </summary>
/// <param name="dbPath">Database path.</param>
public SqlReader(string dbPath)
{
this.connection = new SqliteConnection($"Data Source={dbPath}");
this.connection.Open();
}
/// <summary>
/// Dispose method.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose method.
/// </summary>
/// <param name="disposing">Bool value indicating if Dispose is being run.</param>
public void Dispose(bool disposing)
{
if (disposing)
{
this.connection?.Dispose();
}
}
/// <summary>
/// Gets a list of packages in the database.
/// </summary>
/// <returns>List of packages.</returns>
public IReadOnlyList<SqlPackage> GetPackages()
{
var packages = new List<SqlPackage>();
// Select name and pathpart.
var getPackagescommand = this.connection.CreateCommand();
getPackagescommand.CommandText = "SELECT rowid, id FROM ids";
using var reader = getPackagescommand.ExecuteReader();
while (reader.Read())
{
string rowId = reader.GetString(0);
string id = reader.GetString(1);
var versions = this.GetVersions(rowId);
packages.Add(new SqlPackage(id, versions));
}
return packages;
}
/// <summary>
/// Get versions of a pacakge.
/// </summary>
/// <param name="idsRowid">ids row id.</param>
/// <returns>Versions of package.</returns>
internal IReadOnlyList<SqlVersion> GetVersions(string idsRowid)
{
var versions = new List<SqlVersion>();
// Get the version and pathpart rowids.
var getVersionAndPathPartIdsCommand = this.connection.CreateCommand();
getVersionAndPathPartIdsCommand.CommandText = "SELECT version, pathpart FROM manifest where id = $idsRowid";
getVersionAndPathPartIdsCommand.Parameters.AddWithValue("$idsRowid", idsRowid);
using var reader = getVersionAndPathPartIdsCommand.ExecuteReader();
while (reader.Read())
{
string versionsRowId = reader.GetString(0);
string version = this.GetVersion(versionsRowId);
string pathPathRowId = reader.GetString(1);
// Get the path parts. This will result in something like manifests\a\a\b\a.b.yaml
string path = this.ReadPathPartFromId(pathPathRowId);
versions.Add(new SqlVersion(version, path));
}
return versions;
}
/// <summary>
/// Get version.
/// </summary>
/// <param name="versionsRowId">Version row id.</param>
/// <returns>Version string.</returns>
internal string GetVersion(string versionsRowId)
{
// Get the string version.
var versionCommand = this.connection.CreateCommand();
versionCommand.CommandText = @"SELECT version FROM versions where rowid = $versionsRowId";
versionCommand.Parameters.AddWithValue("$versionsRowId", versionsRowId);
using var versionCommandReader = versionCommand.ExecuteReader();
// There should only be 1 match for a row id.
if (versionCommandReader.Read())
{
return versionCommandReader.GetString(0);
}
throw new ArgumentException();
}
/// <summary>
/// Gets the path where the manifest is located.
/// </summary>
/// <param name="pathPathRowId">Path path row id.</param>
/// <returns>Path of manifest.</returns>
internal string ReadPathPartFromId(string pathPathRowId)
{
// Get path for that pathrowid
var pathPartCommand = this.connection.CreateCommand();
pathPartCommand.CommandText = @"SELECT parent, pathpart FROM pathparts where rowid = $pathPathRowId";
pathPartCommand.Parameters.AddWithValue("$pathPathRowId", pathPathRowId);
// There should only be 1 match for a row id.
// We just grab the first as we wouldn't know what to do with additional matches anyhow.
using var reader = pathPartCommand.ExecuteReader();
if (reader.Read())
{
var parent = reader.IsDBNull(0) ? string.Empty : reader.GetString(0);
var pathPart = reader.IsDBNull(1) ? string.Empty : reader.GetString(1);
return (string.IsNullOrWhiteSpace(parent) ? string.Empty : this.ReadPathPartFromId(parent) + @"\") + pathPart;
}
return string.Empty;
}
}
}