Cleaned up some nullability issues
This commit is contained in:
@@ -211,7 +211,7 @@ public static class ExtensionMethods
|
||||
/// <param name="self">The command instance to execute on</param>
|
||||
/// <param name="transaction">The transaction to use for the command</param>
|
||||
/// <returns>The number of rows affected</returns>
|
||||
public static int ExecuteNonQuery(this IDbCommand self, IDbTransaction transaction)
|
||||
public static int ExecuteNonQuery(this IDbCommand self, IDbTransaction? transaction)
|
||||
{
|
||||
self.Transaction = transaction;
|
||||
return self.ExecuteNonQuery();
|
||||
@@ -274,7 +274,7 @@ public static class ExtensionMethods
|
||||
/// <param name="transaction">The transaction to use for the command</param>
|
||||
/// <param name="defaultvalue">The default value to return if no value is found</param>
|
||||
/// <returns>The scalar int64 value of the first row as a string</returns>
|
||||
public static long ExecuteScalarInt64(this IDbCommand self, IDbTransaction transaction, long defaultvalue = -1)
|
||||
public static long ExecuteScalarInt64(this IDbCommand self, IDbTransaction? transaction, long defaultvalue = -1)
|
||||
{
|
||||
self.Transaction = transaction;
|
||||
return ExecuteScalarInt64(self, true, null, defaultvalue);
|
||||
@@ -320,7 +320,7 @@ public static class ExtensionMethods
|
||||
/// <param name="cmd">The command string to execute</param>
|
||||
/// <param name="values">The values to use as parameters. The parameters must already be added.</param>
|
||||
/// <returns>A <see cref="IDataReader"/> instance</returns>
|
||||
public static IDataReader ExecuteReader(this IDbCommand self, string cmd, Dictionary<string, object?> values)
|
||||
public static IDataReader ExecuteReader(this IDbCommand self, string cmd, Dictionary<string, object?>? values)
|
||||
{
|
||||
return ExecuteReader(self, true, cmd, values);
|
||||
}
|
||||
@@ -361,7 +361,7 @@ public static class ExtensionMethods
|
||||
/// <param name="cmd">The command string to execute</param>
|
||||
/// <param name="values">The values to use as parameters. The parameters must already be added.</param>
|
||||
/// <returns>A <see cref="IDataReader"/> instance</returns>
|
||||
public static IDataReader ExecuteReader(this IDbCommand self, bool writeLog, string? cmd, Dictionary<string, object?> values)
|
||||
public static IDataReader ExecuteReader(this IDbCommand self, bool writeLog, string? cmd, Dictionary<string, object?>? values)
|
||||
{
|
||||
if (cmd != null)
|
||||
self.SetCommandAndParameters(cmd);
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
@@ -83,7 +86,7 @@ namespace Duplicati.Library.Main.Database
|
||||
{
|
||||
path = Path.GetFullPath(path);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(path)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path) ?? throw new DirectoryNotFoundException("Path was a root folder."));
|
||||
|
||||
var c = SQLiteHelper.SQLiteLoader.LoadConnection(path);
|
||||
|
||||
@@ -174,6 +177,7 @@ namespace Duplicati.Library.Main.Database
|
||||
|
||||
private LocalDatabase(IDbConnection connection)
|
||||
{
|
||||
m_connection = connection;
|
||||
m_insertlogCommand = connection.CreateCommand(@"INSERT INTO ""LogData"" (""OperationID"", ""Timestamp"", ""Type"", ""Message"", ""Exception"") VALUES (@OperationID, @Timestamp, @Type, @Message, @Exception)");
|
||||
m_insertremotelogCommand = connection.CreateCommand(@"INSERT INTO ""RemoteOperation"" (""OperationID"", ""Timestamp"", ""Operation"", ""Path"", ""Data"") VALUES (@OperationID, @Timestamp, @Operation, @Path, @Data)");
|
||||
m_updateremotevolumeCommand = connection.CreateCommand(@"UPDATE ""Remotevolume"" SET ""OperationID"" = @OperationID, ""State"" = @State, ""Hash"" = @Hash, ""Size"" = @Size WHERE ""Name"" = @Name");
|
||||
@@ -197,17 +201,17 @@ namespace Duplicati.Library.Main.Database
|
||||
return Library.Utility.Utility.EPOCH.AddSeconds(seconds);
|
||||
}
|
||||
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, IDbTransaction transaction = null)
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, IDbTransaction? transaction = null)
|
||||
{
|
||||
UpdateRemoteVolume(name, state, size, hash, false, transaction);
|
||||
}
|
||||
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, IDbTransaction transaction = null)
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, IDbTransaction? transaction = null)
|
||||
{
|
||||
UpdateRemoteVolume(name, state, size, hash, suppressCleanup, new TimeSpan(0), transaction);
|
||||
}
|
||||
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, TimeSpan deleteGraceTime, IDbTransaction transaction = null)
|
||||
public void UpdateRemoteVolume(string name, RemoteVolumeState state, long size, string hash, bool suppressCleanup, TimeSpan deleteGraceTime, IDbTransaction? transaction = null)
|
||||
{
|
||||
m_updateremotevolumeCommand.Transaction = transaction;
|
||||
var c = m_updateremotevolumeCommand.SetParameterValue("@OperationID", m_operationid)
|
||||
@@ -253,11 +257,11 @@ namespace Duplicati.Library.Main.Database
|
||||
}
|
||||
}
|
||||
|
||||
public (string Query, Dictionary<string, object> Values) GetFilelistWhereClause(DateTime time, long[] versions, IEnumerable<KeyValuePair<long, DateTime>> filesetslist = null, bool singleTimeMatch = false)
|
||||
public (string Query, Dictionary<string, object?> Values) GetFilelistWhereClause(DateTime time, long[] versions, IEnumerable<KeyValuePair<long, DateTime>>? filesetslist = null, bool singleTimeMatch = false)
|
||||
{
|
||||
var filesets = (filesetslist ?? FilesetTimes).ToArray();
|
||||
var query = new StringBuilder();
|
||||
var args = new Dictionary<string, object>();
|
||||
var args = new Dictionary<string, object?>();
|
||||
if (time.Ticks > 0 || (versions != null && versions.Length > 0))
|
||||
{
|
||||
var hasTime = false;
|
||||
@@ -306,13 +310,13 @@ namespace Duplicati.Library.Main.Database
|
||||
return (query.ToString(), args);
|
||||
}
|
||||
|
||||
public long GetRemoteVolumeID(string file, IDbTransaction transaction = null)
|
||||
public long GetRemoteVolumeID(string file, IDbTransaction? transaction = null)
|
||||
{
|
||||
m_selectremotevolumeIdCommand.Transaction = transaction;
|
||||
return m_selectremotevolumeIdCommand.SetParameterValue("@Name", file).ExecuteScalarInt64(-1);
|
||||
}
|
||||
|
||||
public IEnumerable<KeyValuePair<string, long>> GetRemoteVolumeIDs(IEnumerable<string> files, IDbTransaction transaction = null)
|
||||
public IEnumerable<KeyValuePair<string, long>> GetRemoteVolumeIDs(IEnumerable<string> files, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var cmd = m_connection.CreateCommand(transaction))
|
||||
{
|
||||
@@ -326,7 +330,7 @@ namespace Duplicati.Library.Main.Database
|
||||
}
|
||||
}
|
||||
|
||||
public RemoteVolumeEntry GetRemoteVolume(string file, IDbTransaction transaction = null)
|
||||
public RemoteVolumeEntry GetRemoteVolume(string file, IDbTransaction? transaction = null)
|
||||
{
|
||||
m_selectremotevolumeCommand.Transaction = transaction;
|
||||
m_selectremotevolumeCommand.SetParameterValue("@Name", file);
|
||||
@@ -334,11 +338,11 @@ namespace Duplicati.Library.Main.Database
|
||||
if (rd.Read())
|
||||
return new RemoteVolumeEntry(
|
||||
rd.ConvertValueToInt64(0),
|
||||
rd.GetValue(1).ToString(),
|
||||
(rd.GetValue(4) == null || rd.GetValue(4) == DBNull.Value) ? null : rd.GetValue(4).ToString(),
|
||||
rd.ConvertValueToString(1),
|
||||
rd.ConvertValueToString(4),
|
||||
rd.ConvertValueToInt64(3, -1),
|
||||
(RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), rd.GetValue(2).ToString()),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.GetValue(5).ToString()),
|
||||
(RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), rd.ConvertValueToString(2) ?? ""),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.ConvertValueToString(5) ?? ""),
|
||||
ParseFromEpochSeconds(rd.ConvertValueToInt64(6, 0))
|
||||
);
|
||||
|
||||
@@ -347,16 +351,16 @@ namespace Duplicati.Library.Main.Database
|
||||
|
||||
public IEnumerable<KeyValuePair<string, RemoteVolumeState>> DuplicateRemoteVolumes()
|
||||
{
|
||||
foreach (var rd in m_selectduplicateRemoteVolumesCommand.ExecuteReaderEnumerable(null))
|
||||
foreach (var rd in m_selectduplicateRemoteVolumesCommand.ExecuteReaderEnumerable())
|
||||
{
|
||||
yield return new KeyValuePair<string, RemoteVolumeState>(
|
||||
rd.GetValue(0).ToString(),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.GetValue(1).ToString())
|
||||
rd.ConvertValueToString(0) ?? throw new Exception("Name was null"),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.ConvertValueToString(1) ?? "")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<RemoteVolumeEntry> GetRemoteVolumes(IDbTransaction transaction = null)
|
||||
public IEnumerable<RemoteVolumeEntry> GetRemoteVolumes(IDbTransaction? transaction = null)
|
||||
{
|
||||
m_selectremotevolumesCommand.Transaction = transaction;
|
||||
using (var rd = m_selectremotevolumesCommand.ExecuteReader())
|
||||
@@ -365,11 +369,11 @@ namespace Duplicati.Library.Main.Database
|
||||
{
|
||||
yield return new RemoteVolumeEntry(
|
||||
rd.ConvertValueToInt64(0),
|
||||
rd.GetValue(1).ToString(),
|
||||
(rd.GetValue(4) == null || rd.GetValue(4) == DBNull.Value) ? null : rd.GetValue(4).ToString(),
|
||||
rd.ConvertValueToString(1),
|
||||
rd.ConvertValueToString(4),
|
||||
rd.ConvertValueToInt64(3, -1),
|
||||
(RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), rd.GetValue(2).ToString()),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.GetValue(5).ToString()),
|
||||
(RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), rd.ConvertValueToString(2) ?? ""),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.ConvertValueToString(5) ?? ""),
|
||||
ParseFromEpochSeconds(rd.ConvertValueToInt64(6, 0))
|
||||
);
|
||||
}
|
||||
@@ -399,7 +403,7 @@ namespace Duplicati.Library.Main.Database
|
||||
/// <param name="type">The message type</param>
|
||||
/// <param name="message">The message</param>
|
||||
/// <param name="exception">An optional exception</param>
|
||||
public void LogMessage(string type, string message, Exception exception, IDbTransaction transaction)
|
||||
public void LogMessage(string type, string message, Exception? exception, IDbTransaction? transaction)
|
||||
{
|
||||
m_insertlogCommand.SetParameterValue("@OperationID", m_operationid)
|
||||
.SetParameterValue("@Timestamp", Library.Utility.Utility.NormalizeDateTimeToEpochSeconds(DateTime.UtcNow))
|
||||
@@ -409,7 +413,7 @@ namespace Duplicati.Library.Main.Database
|
||||
.ExecuteNonQuery(transaction);
|
||||
}
|
||||
|
||||
public void UnlinkRemoteVolume(string name, RemoteVolumeState state, IDbTransaction transaction = null)
|
||||
public void UnlinkRemoteVolume(string name, RemoteVolumeState state, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
|
||||
using (var cmd = m_connection.CreateCommand(tr.Parent))
|
||||
@@ -426,12 +430,12 @@ namespace Duplicati.Library.Main.Database
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveRemoteVolume(string name, IDbTransaction transaction = null)
|
||||
public void RemoveRemoteVolume(string name, IDbTransaction? transaction = null)
|
||||
{
|
||||
RemoveRemoteVolumes([name], transaction);
|
||||
}
|
||||
|
||||
public void RemoveRemoteVolumes(IEnumerable<string> names, IDbTransaction transaction = null)
|
||||
public void RemoveRemoteVolumes(IEnumerable<string> names, IDbTransaction? transaction = null)
|
||||
{
|
||||
if (names == null || !names.Any()) return;
|
||||
|
||||
@@ -559,17 +563,17 @@ AND Fileset.ID NOT IN
|
||||
return RegisterRemoteVolume(name, type, state, size, new TimeSpan(0), null);
|
||||
}
|
||||
|
||||
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, IDbTransaction transaction)
|
||||
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, IDbTransaction? transaction)
|
||||
{
|
||||
return RegisterRemoteVolume(name, type, state, new TimeSpan(0), transaction);
|
||||
}
|
||||
|
||||
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, TimeSpan deleteGraceTime, IDbTransaction transaction)
|
||||
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, TimeSpan deleteGraceTime, IDbTransaction? transaction)
|
||||
{
|
||||
return RegisterRemoteVolume(name, type, state, -1, deleteGraceTime, transaction);
|
||||
}
|
||||
|
||||
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, long size, TimeSpan deleteGraceTime, IDbTransaction transaction)
|
||||
public long RegisterRemoteVolume(string name, RemoteVolumeType type, RemoteVolumeState state, long size, TimeSpan deleteGraceTime, IDbTransaction? transaction)
|
||||
{
|
||||
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
|
||||
{
|
||||
@@ -592,14 +596,11 @@ AND Fileset.ID NOT IN
|
||||
if (restoretime.Kind == DateTimeKind.Unspecified)
|
||||
throw new Exception("Invalid DateTime given, must be either local or UTC");
|
||||
|
||||
var tmp = GetFilelistWhereClause(restoretime, versions);
|
||||
string query = tmp.Item1;
|
||||
var args = tmp.Item2;
|
||||
|
||||
(var query, var values) = GetFilelistWhereClause(restoretime, versions);
|
||||
var res = new List<long>();
|
||||
using (var cmd = m_connection.CreateCommand())
|
||||
{
|
||||
using (var rd = cmd.ExecuteReader($@"SELECT ""ID"" FROM ""Fileset"" {query} ORDER BY ""Timestamp"" DESC", args))
|
||||
using (var rd = cmd.ExecuteReader($@"SELECT ""ID"" FROM ""Fileset"" {query} ORDER BY ""Timestamp"" DESC", values))
|
||||
while (rd.Read())
|
||||
res.Add(rd.GetInt64(0));
|
||||
|
||||
@@ -661,7 +662,7 @@ AND Fileset.ID NOT IN
|
||||
private readonly IDbTransaction m_parent;
|
||||
private readonly bool m_isTemporary;
|
||||
|
||||
public TemporaryTransactionWrapper(IDbConnection connection, IDbTransaction transaction)
|
||||
public TemporaryTransactionWrapper(IDbConnection connection, IDbTransaction? transaction)
|
||||
{
|
||||
if (transaction != null)
|
||||
{
|
||||
@@ -690,15 +691,15 @@ AND Fileset.ID NOT IN
|
||||
public IDbTransaction Parent { get { return m_parent; } }
|
||||
}
|
||||
|
||||
private IEnumerable<KeyValuePair<string, string>> GetDbOptionList(IDbTransaction transaction = null)
|
||||
private IEnumerable<KeyValuePair<string, string>> GetDbOptionList(IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var cmd = m_connection.CreateCommand(transaction))
|
||||
using (var rd = cmd.ExecuteReader(@"SELECT ""Key"", ""Value"" FROM ""Configuration"" "))
|
||||
while (rd.Read())
|
||||
yield return new KeyValuePair<string, string>(rd.GetValue(0).ToString(), rd.GetValue(1).ToString());
|
||||
yield return new KeyValuePair<string, string>(rd.ConvertValueToString(0) ?? "", rd.ConvertValueToString(1) ?? "");
|
||||
}
|
||||
|
||||
public IDictionary<string, string> GetDbOptions(IDbTransaction transaction = null)
|
||||
public IDictionary<string, string> GetDbOptions(IDbTransaction? transaction = null)
|
||||
{
|
||||
return GetDbOptionList(transaction).ToDictionary(x => x.Key, x => x.Value);
|
||||
}
|
||||
@@ -752,7 +753,7 @@ AND Fileset.ID NOT IN
|
||||
/// </summary>
|
||||
/// <param name="options">The options to set</param>
|
||||
/// <param name="transaction">An optional transaction</param>
|
||||
public void SetDbOptions(IDictionary<string, string> options, IDbTransaction transaction = null)
|
||||
public void SetDbOptions(IDictionary<string, string> options, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
|
||||
using (var cmd = m_connection.CreateCommand(tr.Parent))
|
||||
@@ -1001,25 +1002,26 @@ ON
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IBlock> GetBlocks(long volumeid, IDbTransaction transaction = null)
|
||||
public IEnumerable<IBlock> GetBlocks(long volumeid, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var cmd = m_connection.CreateCommand(transaction))
|
||||
using (var rd = cmd.SetCommandAndParameters(@"SELECT DISTINCT ""Hash"", ""Size"" FROM ""Block"" WHERE ""VolumeID"" = @VolumeId")
|
||||
.SetParameterValue("@VolumeId", volumeid)
|
||||
.ExecuteReader())
|
||||
using var cmd = m_connection.CreateCommand(transaction)
|
||||
.SetCommandAndParameters(@"SELECT DISTINCT ""Hash"", ""Size"" FROM ""Block"" WHERE ""VolumeID"" = @VolumeId")
|
||||
.SetParameterValue("@VolumeId", volumeid);
|
||||
using (var rd = cmd.ExecuteReader())
|
||||
while (rd.Read())
|
||||
yield return new Block(rd.GetValue(0).ToString(), rd.GetInt64(1));
|
||||
yield return new Block(rd.ConvertValueToString(0) ?? throw new Exception("Hash is null"), rd.ConvertValueToInt64(1));
|
||||
}
|
||||
|
||||
// TODO: Replace this with an enumerable method
|
||||
private class BlocklistHashEnumerable : IEnumerable<string>
|
||||
{
|
||||
private class BlocklistHashEnumerator : IEnumerator<string>
|
||||
{
|
||||
private readonly IDataReader m_reader;
|
||||
private readonly BlocklistHashEnumerable m_parent;
|
||||
private string m_path = null;
|
||||
private string? m_path = null;
|
||||
private bool m_first = true;
|
||||
private string m_current = null;
|
||||
private string? m_current = null;
|
||||
|
||||
public BlocklistHashEnumerator(BlocklistHashEnumerable parent, IDataReader reader)
|
||||
{
|
||||
@@ -1027,7 +1029,7 @@ ON
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
public string Current { get { return m_current; } }
|
||||
public string Current { get { return m_current!; } }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
@@ -1041,8 +1043,8 @@ ON
|
||||
|
||||
if (m_path == null)
|
||||
{
|
||||
m_path = m_reader.GetValue(0).ToString();
|
||||
m_current = m_reader.GetValue(6).ToString();
|
||||
m_path = m_reader.ConvertValueToString(0);
|
||||
m_current = m_reader.ConvertValueToString(6);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -1057,14 +1059,14 @@ ON
|
||||
return false;
|
||||
}
|
||||
|
||||
var np = m_reader.GetValue(0).ToString();
|
||||
var np = m_reader.ConvertValueToString(0);
|
||||
if (m_path != np)
|
||||
{
|
||||
m_current = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_current = m_reader.GetValue(6).ToString();
|
||||
m_current = m_reader.ConvertValueToString(6);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1236,7 +1238,7 @@ ORDER BY
|
||||
.SetParameterValue("@FolderBlocksetId", FOLDER_BLOCKSET_ID)
|
||||
.SetParameterValue("@SymlinkBlocksetId", SYMLINK_BLOCKSET_ID);
|
||||
|
||||
string lastpath = null;
|
||||
string? lastpath = null;
|
||||
using (var rd = cmd.ExecuteReader())
|
||||
while (rd.Read())
|
||||
{
|
||||
@@ -1269,19 +1271,19 @@ ORDER BY
|
||||
var more = false;
|
||||
do
|
||||
{
|
||||
var path = rd.GetValue(0).ToString();
|
||||
var filehash = rd.GetValue(3).ToString();
|
||||
var path = rd.ConvertValueToString(0);
|
||||
var filehash = rd.ConvertValueToString(3);
|
||||
var size = rd.ConvertValueToInt64(2);
|
||||
var lastmodified = new DateTime(rd.ConvertValueToInt64(1, 0), DateTimeKind.Utc);
|
||||
var metahash = rd.GetValue(4).ToString();
|
||||
var metahash = rd.ConvertValueToString(4);
|
||||
var metasize = rd.ConvertValueToInt64(5, -1);
|
||||
var p = rd.GetValue(6);
|
||||
var blrd = (p == null || p == DBNull.Value) ? null : new BlocklistHashEnumerable(rd);
|
||||
var blockhash = rd.GetValue(7).ToString();
|
||||
var blockhash = rd.ConvertValueToString(7);
|
||||
var blocksize = rd.ConvertValueToInt64(8, -1);
|
||||
var metablockhash = rd.GetValue(9).ToString();
|
||||
var metablockhash = rd.ConvertValueToString(9);
|
||||
//var metablocksize = rd.ConvertValueToInt64(10, -1);
|
||||
var metablocklisthash = rd.GetValue(11).ToString();
|
||||
var metablocklisthash = rd.ConvertValueToString(11);
|
||||
|
||||
if (blockhash == filehash)
|
||||
blockhash = null;
|
||||
@@ -1346,7 +1348,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
type = expression.Type;
|
||||
|
||||
// Bugfix: SQLite does not handle case-insensitive LIKE with non-ascii characters
|
||||
if (type != FilterType.Regexp && !Library.Utility.Utility.IsFSCaseSensitive && filter.ToString().Any(x => x > 127))
|
||||
if (type != FilterType.Regexp && !Library.Utility.Utility.IsFSCaseSensitive && filter.ToString()!.Any(x => x > 127))
|
||||
type = FilterType.Regexp;
|
||||
|
||||
if (filter.Empty)
|
||||
@@ -1385,7 +1387,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
else
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var args = new Dictionary<string, object>();
|
||||
var args = new Dictionary<string, object?>();
|
||||
foreach (var f in ((FilterExpression)filter).GetSimpleList())
|
||||
{
|
||||
if (sb.Length != 0)
|
||||
@@ -1423,7 +1425,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
cmd.ExecuteNonQuery(FormatInvariant(@$"DROP TABLE IF EXISTS ""{Tablename}"" "));
|
||||
}
|
||||
catch { }
|
||||
finally { Tablename = null; }
|
||||
finally { Tablename = null!; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1447,7 +1449,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
cmd.SetCommandAndParameters(@"SELECT ""Type"" FROM ""Remotevolume"" WHERE ""Name"" = @Name")
|
||||
.SetParameterValue("@Name", newname)
|
||||
.ExecuteScalar()
|
||||
.ToString(),
|
||||
?.ToString() ?? "",
|
||||
true);
|
||||
|
||||
//Create a fake new entry with the old name and mark as deleting
|
||||
@@ -1464,7 +1466,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
/// <param name="volumeid">The ID of the fileset volume to update</param>
|
||||
/// <param name="timestamp">The timestamp of the operation to create</param>
|
||||
/// <param name="transaction">An optional external transaction</param>
|
||||
public virtual long CreateFileset(long volumeid, DateTime timestamp, IDbTransaction transaction = null)
|
||||
public virtual long CreateFileset(long volumeid, DateTime timestamp, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
|
||||
using (var cmd = m_connection.CreateCommand(tr.Parent))
|
||||
@@ -1495,7 +1497,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
/// <param name="hashsize">The size of the hash</param>
|
||||
/// <param name="transaction">An optional external transaction</param>
|
||||
/// <returns>An enumerable of tuples containing the blocklist hash, the blocklist data and the length of the data</returns>
|
||||
public IEnumerable<Tuple<string, byte[], int>> GetBlocklists(long volumeid, long blocksize, int hashsize, IDbTransaction transaction = null)
|
||||
public IEnumerable<Tuple<string, byte[], int>> GetBlocklists(long volumeid, long blocksize, int hashsize, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var cmd = m_connection.CreateCommand(transaction))
|
||||
{
|
||||
@@ -1506,9 +1508,9 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
""B"".""Index"" >= (""A"".""Index"" * {blocksize / hashsize}) AND ""B"".""Index"" < ((""A"".""Index"" + 1) * {blocksize / hashsize}) AND ""C"".""ID"" = ""B"".""BlockID""
|
||||
ORDER BY ""A"".""BlocksetID"", ""B"".""Index""");
|
||||
|
||||
string curHash = null;
|
||||
int count = 0;
|
||||
byte[] buffer = new byte[blocksize];
|
||||
string? curHash = null;
|
||||
var count = 0;
|
||||
var buffer = new byte[blocksize];
|
||||
|
||||
using (var rd = cmd.SetCommandAndParameters(sql).SetParameterValue("@VolumeId", volumeid).ExecuteReader())
|
||||
while (rd.Read())
|
||||
@@ -1516,12 +1518,12 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
var blockhash = rd.GetValue(0).ToString();
|
||||
if ((blockhash != curHash && curHash != null) || count + hashsize > buffer.Length)
|
||||
{
|
||||
yield return new Tuple<string, byte[], int>(curHash, buffer, count);
|
||||
yield return new Tuple<string, byte[], int>(curHash!, buffer, count);
|
||||
buffer = new byte[blocksize];
|
||||
count = 0;
|
||||
}
|
||||
|
||||
var hash = Convert.FromBase64String(rd.GetValue(1).ToString());
|
||||
var hash = Convert.FromBase64String(rd.ConvertValueToString(1) ?? throw new Exception("Hash is null"));
|
||||
Array.Copy(hash, 0, buffer, count, hashsize);
|
||||
curHash = blockhash;
|
||||
count += hashsize;
|
||||
@@ -1538,7 +1540,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
/// <param name="fileSetId">Existing file set to update</param>
|
||||
/// <param name="isFullBackup">Full backup state</param>
|
||||
/// <param name="transaction">An optional external transaction</param>
|
||||
public void UpdateFullBackupStateInFileset(long fileSetId, bool isFullBackup, IDbTransaction transaction = null)
|
||||
public void UpdateFullBackupStateInFileset(long fileSetId, bool isFullBackup, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var tr = new TemporaryTransactionWrapper(m_connection, transaction))
|
||||
using (var cmd = m_connection.CreateCommand(tr.Parent))
|
||||
@@ -1589,7 +1591,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
/// <param name="filesetID">The fileset ID</param>
|
||||
/// <param name="transaction">An optional transaction</param>
|
||||
/// <returns>The remote volume entry or default</returns>
|
||||
public RemoteVolumeEntry GetRemoteVolumeFromFilesetID(long filesetID, IDbTransaction transaction = null)
|
||||
public RemoteVolumeEntry GetRemoteVolumeFromFilesetID(long filesetID, IDbTransaction? transaction = null)
|
||||
{
|
||||
using (var cmd = m_connection.CreateCommand(transaction))
|
||||
using (var rd = cmd.SetCommandAndParameters(@"SELECT ""RemoteVolume"".""ID"", ""Name"", ""Type"", ""Size"", ""Hash"", ""State"", ""DeleteGraceTime"" FROM ""RemoteVolume"", ""Fileset"" WHERE ""Fileset"".""VolumeID"" = ""RemoteVolume"".""ID"" AND ""Fileset"".""ID"" = @FilesetId")
|
||||
@@ -1598,12 +1600,12 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
if (rd.Read())
|
||||
return new RemoteVolumeEntry(
|
||||
rd.ConvertValueToInt64(0, -1),
|
||||
rd.GetValue(1).ToString(),
|
||||
(rd.GetValue(4) == null || rd.GetValue(4) == DBNull.Value) ? null : rd.GetValue(4).ToString(),
|
||||
rd.ConvertValueToString(1),
|
||||
rd.ConvertValueToString(4),
|
||||
rd.ConvertValueToInt64(3, -1),
|
||||
(RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), rd.GetValue(2).ToString()),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.GetValue(5).ToString()),
|
||||
ParseFromEpochSeconds(rd.GetInt64(6)).ToLocalTime()
|
||||
(RemoteVolumeType)Enum.Parse(typeof(RemoteVolumeType), rd.ConvertValueToString(2) ?? ""),
|
||||
(RemoteVolumeState)Enum.Parse(typeof(RemoteVolumeState), rd.ConvertValueToString(5) ?? ""),
|
||||
ParseFromEpochSeconds(rd.ConvertValueToInt64(6)).ToLocalTime()
|
||||
);
|
||||
else
|
||||
return default;
|
||||
@@ -1752,7 +1754,7 @@ AND oldVersion.FilesetID = (SELECT ID FROM Fileset WHERE ID != @FilesetId ORDER
|
||||
/// <returns>The path prefix ID.</returns>
|
||||
/// <param name="prefix">The path to get the prefix for.</param>
|
||||
/// <param name="transaction">The transaction to use for insertion, or null for no transaction</param>
|
||||
public long GetOrCreatePathPrefix(string prefix, IDbTransaction transaction)
|
||||
public long GetOrCreatePathPrefix(string prefix, IDbTransaction? transaction)
|
||||
{
|
||||
// Ring-buffer style lookup
|
||||
for (var i = 0; i < m_pathPrefixLookup.Length; i++)
|
||||
|
||||
Reference in New Issue
Block a user