Updated restore database to not use positional arguments

This commit is contained in:
Kenneth Skovhede
2025-03-19 22:23:57 +01:00
parent 47afbbbdad
commit fac135d5a5
@@ -195,10 +195,8 @@ END ");
throw;
}
}
}
public Tuple<long, long> PrepareRestoreFilelist(DateTime restoretime, long[] versions, IFilter filter)
{
m_tempfiletable = "Fileset-" + m_temptabsetguid;
@@ -212,7 +210,10 @@ END ");
var filesetId = filesetIds[0];
filesetIds.RemoveAt(0);
m_restoreTime = ParseFromEpochSeconds(cmd.ExecuteScalarInt64(@"SELECT ""Timestamp"" FROM ""Fileset"" WHERE ""ID"" = ?", 0, filesetId));
m_restoreTime = ParseFromEpochSeconds(cmd
.SetCommandAndParameters(@"SELECT ""Timestamp"" FROM ""Fileset"" WHERE ""ID"" = @FilesetId")
.SetParameterValue("@FilesetId", filesetId)
.ExecuteScalarInt64(0));
var ix = FilesetTimes.Select((value, index) => new { value.Key, index })
.Where(n => n.Key == filesetId)
@@ -233,11 +234,11 @@ END ");
if (filter == null || filter.Empty)
{
// Simple case, restore everything
cmd.CommandText = FormatInvariant($@"INSERT INTO ""{m_tempfiletable}"" (""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""DataVerified"") SELECT ""File"".""ID"", ""File"".""Path"", ""File"".""BlocksetID"", ""File"".""MetadataID"", 0 FROM ""File"", ""FilesetEntry"" WHERE ""File"".""ID"" = ""FilesetEntry"".""FileID"" AND ""FilesetEntry"".""FilesetID"" = ? ");
cmd.AddParameter(filesetId);
cmd.ExecuteNonQuery();
cmd.SetCommandAndParameters(FormatInvariant($@"INSERT INTO ""{m_tempfiletable}"" (""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""DataVerified"") SELECT ""File"".""ID"", ""File"".""Path"", ""File"".""BlocksetID"", ""File"".""MetadataID"", 0 FROM ""File"", ""FilesetEntry"" WHERE ""File"".""ID"" = ""FilesetEntry"".""FileID"" AND ""FilesetEntry"".""FilesetID"" = @FilesetId"))
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQuery();
}
else if (Library.Utility.Utility.IsFSCaseSensitive && filter is FilterExpression expression && expression.Type == Duplicati.Library.Utility.FilterType.Simple)
else if (Library.Utility.Utility.IsFSCaseSensitive && filter is FilterExpression expression && expression.Type == FilterType.Simple)
{
// If we get a list of filenames, the lookup table is faster
// unfortunately we cannot do this if the filesystem is case sensitive as
@@ -248,18 +249,17 @@ END ");
var m_filenamestable = "Filenames-" + m_temptabsetguid;
cmd.Transaction = tr;
cmd.ExecuteNonQuery(FormatInvariant($@"CREATE TEMPORARY TABLE ""{m_filenamestable}"" (""Path"" TEXT NOT NULL) "));
cmd.CommandText = FormatInvariant($@"INSERT INTO ""{m_filenamestable}"" (""Path"") VALUES (?)");
cmd.AddParameter();
cmd.SetCommandAndParameters(FormatInvariant($@"INSERT INTO ""{m_filenamestable}"" (""Path"") VALUES (@Path)"));
foreach (var s in p)
{
cmd.SetParameterValue(0, s);
cmd.ExecuteNonQuery();
cmd.SetParameterValue("@Path", s)
.ExecuteNonQuery();
}
cmd.CommandText = FormatInvariant($@"INSERT INTO ""{m_tempfiletable}"" (""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""DataVerified"") SELECT ""File"".""ID"", ""File"".""Path"", ""File"".""BlocksetID"", ""File"".""MetadataID"", 0 FROM ""File"", ""FilesetEntry"" WHERE ""File"".""ID"" = ""FilesetEntry"".""FileID"" AND ""FilesetEntry"".""FilesetID"" = ? AND ""Path"" IN (SELECT DISTINCT ""Path"" FROM ""{m_filenamestable}"") ");
cmd.SetParameterValue(0, filesetId);
var c = cmd.ExecuteNonQuery();
var c = cmd.SetCommandAndParameters(FormatInvariant($@"INSERT INTO ""{m_tempfiletable}"" (""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""DataVerified"") SELECT ""File"".""ID"", ""File"".""Path"", ""File"".""BlocksetID"", ""File"".""MetadataID"", 0 FROM ""File"", ""FilesetEntry"" WHERE ""File"".""ID"" = ""FilesetEntry"".""FileID"" AND ""FilesetEntry"".""FilesetID"" = @FilesetId AND ""Path"" IN (SELECT DISTINCT ""Path"" FROM ""{m_filenamestable}"") "))
.SetParameterValue("@FilesetId", filesetId)
.ExecuteNonQuery();
cmd.Parameters.Clear();
@@ -272,7 +272,11 @@ END ");
while (rd.Read())
sb.AppendLine(rd.GetValue(0).ToString());
var actualrestoretime = ParseFromEpochSeconds(cmd.ExecuteScalarInt64(@"SELECT ""Timestamp"" FROM ""Fileset"" WHERE ""ID"" = ?", 0, filesetId));
var actualrestoretime = ParseFromEpochSeconds(
cmd.SetCommandAndParameters(@"SELECT ""Timestamp"" FROM ""Fileset"" WHERE ""ID"" = @FilesetId")
.SetParameterValue("@FilesetId", filesetId)
.ExecuteScalarInt64(0));
Logging.Log.WriteWarningMessage(LOGTAG, "FilesNotFoundInBackupList", null, "{0} File(s) were not found in list of files for backup at {1}, will not be restored: {2}", p.Length - c, actualrestoretime.ToLocalTime(), sb);
cmd.Parameters.Clear();
}
@@ -287,22 +291,22 @@ END ");
{
// Restore but filter elements based on the filter expression
// If this is too slow, we could add a special handler for wildcard searches too
cmd.CommandText = @"SELECT ""File"".""ID"", ""File"".""Path"", ""File"".""BlocksetID"", ""File"".""MetadataID"" FROM ""File"", ""FilesetEntry"" WHERE ""File"".""ID"" = ""FilesetEntry"".""FileID"" AND ""FilesetID"" = ?";
cmd.AddParameter(filesetId);
cmd.SetCommandAndParameters(@"SELECT ""File"".""ID"", ""File"".""Path"", ""File"".""BlocksetID"", ""File"".""MetadataID"" FROM ""File"", ""FilesetEntry"" WHERE ""File"".""ID"" = ""FilesetEntry"".""FileID"" AND ""FilesetID"" = @FilesetId")
.SetParameterValue("@FilesetId", filesetId);
object[] values = new object[4];
using (var cmd2 = m_connection.CreateCommand(FormatInvariant($@"INSERT INTO ""{m_tempfiletable}"" (""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""DataVerified"") VALUES (?,?,?,?,0)")))
using (var cmd2 = m_connection.CreateCommand(FormatInvariant($@"INSERT INTO ""{m_tempfiletable}"" (""ID"", ""Path"", ""BlocksetID"", ""MetadataID"", ""DataVerified"") VALUES (@ID, @Path, @BlocksetID, @MetadataID, 0)")))
using (var rd = cmd.ExecuteReader())
while (rd.Read())
{
rd.GetValues(values);
if (values[1] != null && values[1] != DBNull.Value && Library.Utility.FilterExpression.Matches(filter, values[1].ToString()))
if (values[1] != null && values[1] != DBNull.Value && FilterExpression.Matches(filter, values[1].ToString()))
{
cmd2.SetParameterValue(0, values[0]);
cmd2.SetParameterValue(1, values[1]);
cmd2.SetParameterValue(2, values[2]);
cmd2.SetParameterValue(3, values[3]);
cmd2.ExecuteNonQuery();
cmd2.SetParameterValue("@ID", values[0])
.SetParameterValue("@Path", values[1])
.SetParameterValue("@BlocksetID", values[2])
.SetParameterValue("@MetadataID", values[3])
.ExecuteNonQuery();
}
}
}
@@ -365,16 +369,14 @@ END ");
var foundfiles = -1L;
//TODO: Handle FS case-sensitive?
cmd.CommandText = FormatInvariant($@"SELECT COUNT(*) FROM ""{m_tempfiletable}"" WHERE SUBSTR(""Path"", 1, ?) = ?");
cmd.AddParameter();
cmd.AddParameter();
cmd.SetCommandAndParameters(FormatInvariant($@"SELECT COUNT(*) FROM ""{m_tempfiletable}"" WHERE SUBSTR(""Path"", 1, @PrefixLength) = @Prefix"));
while (filecount != foundfiles && maxpath.Length > 0)
{
var mp = Util.AppendDirSeparator(maxpath, dirsep);
cmd.SetParameterValue(0, mp.Length);
cmd.SetParameterValue(1, mp);
foundfiles = cmd.ExecuteScalarInt64(-1);
foundfiles = cmd.SetParameterValue("@PrefixLength", mp.Length)
.SetParameterValue("@Prefix", mp)
.ExecuteScalarInt64(-1);
if (filecount != foundfiles)
{
@@ -436,7 +438,9 @@ END ");
else
{
largest_prefix = Util.AppendDirSeparator(largest_prefix, dirsep);
cmd.ExecuteNonQuery(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""TargetPath"" = SUBSTR(""Path"", ?)"), largest_prefix.Length + 1);
cmd.SetCommandAndParameters(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""TargetPath"" = SUBSTR(""Path"", @PrefixLength)"))
.SetParameterValue("@PrefixLength", largest_prefix.Length + 1)
.ExecuteNonQuery();
}
}
@@ -452,11 +456,10 @@ END ");
{
// Paths are now relative with target-os naming system
// so we prefix them with the target path
cmd.ExecuteNonQuery(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""TargetPath"" = ? || ""TargetPath"" "), Util.AppendDirSeparator(destination));
cmd.SetCommandAndParameters(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""TargetPath"" = @Destination || ""TargetPath"" "))
.SetParameterValue("@Destination", Util.AppendDirSeparator(destination))
.ExecuteNonQuery();
}
}
}
@@ -464,22 +467,17 @@ END ");
{
using (var cmd = m_connection.CreateCommand())
{
cmd.CommandText = FormatInvariant($@"INSERT INTO ""{m_tempblocktable}"" (""FileID"", ""Index"", ""Hash"", ""Size"", ""Restored"", ""Metadata"", ""VolumeId"", ""BlockId"") SELECT DISTINCT ""{m_tempfiletable}"".""ID"", ""BlocksetEntry"".""Index"", ""Block"".""Hash"", ""Block"".""Size"", 0, 0, ""Block"".""VolumeID"", ""Block"".""ID"" FROM ""{m_tempfiletable}"", ""BlocksetEntry"", ""Block"" WHERE ""{m_tempfiletable}"".""BlocksetID"" = ""BlocksetEntry"".""BlocksetID"" AND ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" ");
var p1 = cmd.ExecuteNonQuery();
var p1 = cmd.ExecuteNonQuery(FormatInvariant($@"INSERT INTO ""{m_tempblocktable}"" (""FileID"", ""Index"", ""Hash"", ""Size"", ""Restored"", ""Metadata"", ""VolumeId"", ""BlockId"") SELECT DISTINCT ""{m_tempfiletable}"".""ID"", ""BlocksetEntry"".""Index"", ""Block"".""Hash"", ""Block"".""Size"", 0, 0, ""Block"".""VolumeID"", ""Block"".""ID"" FROM ""{m_tempfiletable}"", ""BlocksetEntry"", ""Block"" WHERE ""{m_tempfiletable}"".""BlocksetID"" = ""BlocksetEntry"".""BlocksetID"" AND ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" "));
var p2 = 0;
if (!skipMetadata)
{
cmd.CommandText = FormatInvariant($@"INSERT INTO ""{m_tempblocktable}"" (""FileID"", ""Index"", ""Hash"", ""Size"", ""Restored"", ""Metadata"", ""VolumeId"", ""BlockId"") SELECT DISTINCT ""{m_tempfiletable}"".""ID"", ""BlocksetEntry"".""Index"", ""Block"".""Hash"", ""Block"".""Size"", 0, 1, ""Block"".""VolumeID"", ""Block"".""ID"" FROM ""{m_tempfiletable}"", ""BlocksetEntry"", ""Block"", ""Metadataset"" WHERE ""{m_tempfiletable}"".""MetadataID"" = ""Metadataset"".""ID"" AND ""Metadataset"".""BlocksetID"" = ""BlocksetEntry"".""BlocksetID"" AND ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" ");
p2 = cmd.ExecuteNonQuery();
}
p2 = cmd.ExecuteNonQuery(FormatInvariant($@"INSERT INTO ""{m_tempblocktable}"" (""FileID"", ""Index"", ""Hash"", ""Size"", ""Restored"", ""Metadata"", ""VolumeId"", ""BlockId"") SELECT DISTINCT ""{m_tempfiletable}"".""ID"", ""BlocksetEntry"".""Index"", ""Block"".""Hash"", ""Block"".""Size"", 0, 1, ""Block"".""VolumeID"", ""Block"".""ID"" FROM ""{m_tempfiletable}"", ""BlocksetEntry"", ""Block"", ""Metadataset"" WHERE ""{m_tempfiletable}"".""MetadataID"" = ""Metadataset"".""ID"" AND ""Metadataset"".""BlocksetID"" = ""BlocksetEntry"".""BlocksetID"" AND ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" "));
//creating indexes after insertion is much faster
cmd.ExecuteNonQuery(FormatInvariant($@"CREATE INDEX ""{m_tempblocktable}_HashSizeIndex"" ON ""{m_tempblocktable}"" (""Hash"", ""Size"")"));
// better suited to speed up commit on UpdateBlocks
cmd.ExecuteNonQuery(FormatInvariant($@"CREATE INDEX ""{m_tempblocktable}_FileIdIndexIndex"" ON ""{m_tempblocktable}"" (""FileId"", ""Index"")"));
var size = cmd.ExecuteScalarInt64(FormatInvariant($@"SELECT SUM(""Size"") FROM ""{m_tempblocktable}"" "), 0);
Logging.Log.WriteVerboseMessage(LOGTAG, "RestoreSourceSize", "Restore list contains {0} blocks with a total size of {1}", p1 + p2, Library.Utility.Utility.FormatSizeString(size));
}
@@ -487,8 +485,11 @@ END ");
public void UpdateTargetPath(long ID, string newname)
{
using (var cmd = m_connection.CreateCommand())
cmd.ExecuteNonQuery(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""TargetPath"" = ? WHERE ""ID"" = ?"), newname, ID);
using var cmd = m_connection.CreateCommand(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""TargetPath"" = @TargetPath WHERE ""ID"" = @ID"))
.SetParameterValue("@TargetPath", newname)
.SetParameterValue("@ID", ID);
cmd.ExecuteNonQuery();
}
public interface IExistingFileBlock
@@ -507,7 +508,6 @@ END ");
IEnumerable<IExistingFileBlock> Blocks { get; }
}
public interface IBlockSource
{
string Path { get; }
@@ -595,25 +595,22 @@ END ");
public static IEnumerable<IExistingFile> GetExistingFilesWithBlocks(IDbConnection connection, string tablename)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = FormatInvariant($@"SELECT ""{tablename}"".""TargetPath"", ""Blockset"".""FullHash"", ""{tablename}"".""ID"", ""Blockset"".""Length"", ""Block"".""Hash"", ""BlocksetEntry"".""Index"", ""Block"".""Size"" FROM ""{tablename}"", ""Blockset"", ""BlocksetEntry"", ""Block"" WHERE ""{tablename}"".""BlocksetID"" = ""Blockset"".""ID"" AND ""BlocksetEntry"".""BlocksetID"" = ""{tablename}"".""BlocksetID"" AND ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" ORDER BY ""{tablename}"".""TargetPath"", ""BlocksetEntry"".""Index""");
using (var rd = cmd.ExecuteReader())
if (rd.Read())
using (var cmd = connection.CreateCommand(FormatInvariant($@"SELECT ""{tablename}"".""TargetPath"", ""Blockset"".""FullHash"", ""{tablename}"".""ID"", ""Blockset"".""Length"", ""Block"".""Hash"", ""BlocksetEntry"".""Index"", ""Block"".""Size"" FROM ""{tablename}"", ""Blockset"", ""BlocksetEntry"", ""Block"" WHERE ""{tablename}"".""BlocksetID"" = ""Blockset"".""ID"" AND ""BlocksetEntry"".""BlocksetID"" = ""{tablename}"".""BlocksetID"" AND ""BlocksetEntry"".""BlockID"" = ""Block"".""ID"" ORDER BY ""{tablename}"".""TargetPath"", ""BlocksetEntry"".""Index""")))
using (var rd = cmd.ExecuteReader())
if (rd.Read())
{
var more = true;
while (more)
{
var more = true;
while (more)
{
var f = new ExistingFile(rd);
string current = f.TargetPath;
yield return f;
var f = new ExistingFile(rd);
string current = f.TargetPath;
yield return f;
more = f.HasMore;
while (more && current == f.TargetPath)
more = rd.Read();
}
more = f.HasMore;
while (more && current == f.TargetPath)
more = rd.Read();
}
}
}
}
}
@@ -696,25 +693,22 @@ END ");
public static IEnumerable<ILocalBlockSource> GetFilesAndSourceBlocks(IDbConnection connection, string filetablename, string blocktablename, long blocksize, bool skipMetadata)
{
using (var cmd = connection.CreateCommand())
// TODO: Skip metadata as required
using (var cmd = connection.CreateCommand(FormatInvariant($@"SELECT DISTINCT ""A"".""TargetPath"", ""A"".""ID"", ""B"".""Hash"", (""B"".""Index"" * {blocksize}), ""B"".""Index"", ""B"".""Size"", ""C"".""Path"", (""D"".""Index"" * {blocksize}), ""E"".""Size"", ""B"".""Metadata"" FROM ""{filetablename}"" ""A"", ""{blocktablename}"" ""B"", ""File"" ""C"", ""BlocksetEntry"" ""D"", ""Block"" E WHERE ""A"".""ID"" = ""B"".""FileID"" AND ""C"".""BlocksetID"" = ""D"".""BlocksetID"" AND ""D"".""BlockID"" = ""E"".""ID"" AND ""B"".""Hash"" = ""E"".""Hash"" AND ""B"".""Size"" = ""E"".""Size"" AND ""B"".""Restored"" = 0")))
using (var rd = cmd.ExecuteReader())
{
// TODO: Skip metadata as required
cmd.CommandText = FormatInvariant($@"SELECT DISTINCT ""A"".""TargetPath"", ""A"".""ID"", ""B"".""Hash"", (""B"".""Index"" * {blocksize}), ""B"".""Index"", ""B"".""Size"", ""C"".""Path"", (""D"".""Index"" * {blocksize}), ""E"".""Size"", ""B"".""Metadata"" FROM ""{filetablename}"" ""A"", ""{blocktablename}"" ""B"", ""File"" ""C"", ""BlocksetEntry"" ""D"", ""Block"" E WHERE ""A"".""ID"" = ""B"".""FileID"" AND ""C"".""BlocksetID"" = ""D"".""BlocksetID"" AND ""D"".""BlockID"" = ""E"".""ID"" AND ""B"".""Hash"" = ""E"".""Hash"" AND ""B"".""Size"" = ""E"".""Size"" AND ""B"".""Restored"" = 0");
using (var rd = cmd.ExecuteReader())
if (rd.Read())
{
if (rd.Read())
var more = true;
while (more)
{
var more = true;
while (more)
{
var f = new LocalBlockSource(rd);
string current = f.TargetPath;
yield return f;
var f = new LocalBlockSource(rd);
string current = f.TargetPath;
yield return f;
more = f.HasMore;
while (more && current == f.TargetPath)
more = rd.Read();
}
more = f.HasMore;
while (more && current == f.TargetPath)
more = rd.Read();
}
}
}
@@ -790,21 +784,17 @@ ORDER BY ""BB"".""MaxIndex"" ");
using (var c = m_connection.CreateCommand())
{
m_tmptable = "VolumeFiles-" + Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray());
c.CommandText = FormatInvariant($@"CREATE TEMPORARY TABLE ""{m_tmptable}"" ( ""Hash"" TEXT NOT NULL, ""Size"" INTEGER NOT NULL )");
c.ExecuteNonQuery();
c.ExecuteNonQuery(FormatInvariant($@"CREATE TEMPORARY TABLE ""{m_tmptable}"" ( ""Hash"" TEXT NOT NULL, ""Size"" INTEGER NOT NULL )"));
c.CommandText = FormatInvariant($@"INSERT INTO ""{m_tmptable}"" (""Hash"", ""Size"") VALUES (?,?)");
c.AddParameters(2);
c.SetCommandAndParameters(FormatInvariant($@"INSERT INTO ""{m_tmptable}"" (""Hash"", ""Size"") VALUES (@Hash, @Size)"));
foreach (var s in curvolume.Blocks)
{
c.SetParameterValue(0, s.Key);
c.SetParameterValue(1, s.Value);
c.SetParameterValue("@Hash", s.Key);
c.SetParameterValue("@Size", s.Value);
c.ExecuteNonQuery();
}
// The index _HashSizeIndex is not needed anymore. Index on "Blocks-..." is used on Join in GetMissingBlocks
}
}
@@ -931,7 +921,7 @@ ORDER BY ""A"".""TargetPath"", ""BB"".""Index""");
{
if (!m_connection_pool.TryTake(out var connection))
{
connection = (IDbConnection)Activator.CreateInstance(Duplicati.Library.SQLiteHelper.SQLiteLoader.SQLiteConnectionType);
connection = (IDbConnection)Activator.CreateInstance(SQLiteHelper.SQLiteLoader.SQLiteConnectionType);
connection.ConnectionString = m_connection.ConnectionString + ";Cache=Shared;";
connection.Open();
@@ -992,19 +982,19 @@ ORDER BY ""A"".""TargetPath"", ""BB"".""Index""");
{
using var cmd = Connection.CreateCommand();
using var reader = cmd.ExecuteReader(FormatInvariant($@"
SELECT Block.ID, Block.VolumeID
FROM BlocksetEntry
INNER JOIN ""{m_tempfiletable}"" ON BlocksetEntry.BlocksetID = ""{m_tempfiletable}"".BlocksetID
INNER JOIN Block ON BlocksetEntry.BlockID = Block.ID
SELECT ""Block"".""ID"", ""Block"".""VolumeID""
FROM ""BlocksetEntry""
INNER JOIN ""{m_tempfiletable}"" ON ""BlocksetEntry"".""BlocksetID"" = ""{m_tempfiletable}"".""BlocksetID""
INNER JOIN ""Block"" ON ""BlocksetEntry"".""BlockID"" = ""Block"".""ID""
")
+ (skipMetadata ? "" : FormatInvariant($@"
UNION ALL
SELECT Block.ID, Block.VolumeID
SELECT ""Block"".""ID"", ""Block"".""VolumeID""
FROM ""{m_tempfiletable}""
INNER JOIN Metadataset ON ""{m_tempfiletable}"".MetadataID = Metadataset.ID
INNER JOIN BlocksetEntry ON Metadataset.BlocksetID = BlocksetEntry.BlocksetID
INNER JOIN Block ON BlocksetEntry.BlockID = Block.ID
WHERE ""{m_tempfiletable}"".BlocksetID IS NOT {FOLDER_BLOCKSET_ID}
INNER JOIN ""Metadataset"" ON ""{m_tempfiletable}"".""MetadataID"" = ""Metadataset"".""ID""
INNER JOIN ""BlocksetEntry"" ON ""Metadataset"".""BlocksetID"" = ""BlocksetEntry"".""BlocksetID""
INNER JOIN ""Block"" ON ""BlocksetEntry"".""BlockID"" = ""Block"".""ID""
WHERE ""{m_tempfiletable}"".""BlocksetID"" IS NOT {FOLDER_BLOCKSET_ID}
")));
while (reader.Read())
yield return (reader.ConvertValueToInt64(0), reader.ConvertValueToInt64(1));
@@ -1018,21 +1008,16 @@ ORDER BY ""A"".""TargetPath"", ""BB"".""Index""");
public IEnumerable<BlockRequest> GetBlocksFromFile(long blocksetID)
{
var connection = GetConnectionFromPool();
using var cmd = connection.CreateCommand();
cmd.CommandText = FormatInvariant(@$"
SELECT Block.ID, Block.Hash, Block.Size, Block.VolumeID
FROM BlocksetEntry INNER JOIN Block
ON BlocksetEntry.BlockID = Block.ID
WHERE BlocksetEntry.BlocksetID = ?");
cmd.AddParameter();
cmd.SetParameterValue(0, blocksetID);
using var cmd = connection.CreateCommand(FormatInvariant(@$"
SELECT ""Block"".""ID"", ""Block"".""Hash"", ""Block"".""Size"", ""Block"".""VolumeID""
FROM ""BlocksetEntry"" INNER JOIN ""Block""
ON ""BlocksetEntry"".""BlockID"" = ""Block"".""ID""
WHERE ""BlocksetEntry"".""BlocksetID"" = @BlocksetID"))
.SetParameterValue("@BlocksetID", blocksetID);
using var reader = cmd.ExecuteReader();
for (long i = 0; reader.Read(); i++)
{
yield return new BlockRequest(reader.ConvertValueToInt64(0), i, reader.ConvertValueToString(1), reader.ConvertValueToInt64(2), reader.ConvertValueToInt64(3), false);
}
// Return the connection to the pool
m_connection_pool.Add(connection);
@@ -1046,18 +1031,15 @@ ORDER BY ""A"".""TargetPath"", ""BB"".""Index""");
public IEnumerable<BlockRequest> GetMetadataBlocksFromFile(long fileID)
{
var connection = GetConnectionFromPool();
using var cmd = connection.CreateCommand();
cmd.CommandText = FormatInvariant($@"
SELECT Block.ID, Block.Hash, Block.Size, Block.VolumeID
FROM File
INNER JOIN Metadataset ON File.MetadataID = Metadataset.ID
INNER JOIN BlocksetEntry ON Metadataset.BlocksetID = BlocksetEntry.BlocksetID
INNER JOIN Block ON BlocksetEntry.BlockID = Block.ID
WHERE File.ID = ?
");
cmd.AddParameter();
cmd.SetParameterValue(0, fileID);
using var cmd = connection.CreateCommand(FormatInvariant($@"
SELECT ""Block"".""ID"", ""Block"".""Hash"", ""Block"".""Size"", ""Block"".""VolumeID""
FROM ""File""
INNER JOIN ""Metadataset"" ON ""File"".""MetadataID"" = ""Metadataset"".""ID""
INNER JOIN ""BlocksetEntry"" ON ""Metadataset"".""BlocksetID"" = ""BlocksetEntry"".""BlocksetID""
INNER JOIN ""Block"" ON ""BlocksetEntry"".""BlockID"" = ""Block"".""ID""
WHERE ""File"".""ID"" = @FileID
"))
.SetParameterValue("@FileID", fileID);
using var reader = cmd.ExecuteReader();
for (long i = 0; reader.Read(); i++)
@@ -1076,10 +1058,8 @@ ORDER BY ""A"".""TargetPath"", ""BB"".""Index""");
/// <returns>A tuple containing the name, size, and hash of the volume.</returns>
public IEnumerable<(string, long, string)> GetVolumeInfo(long VolumeID)
{
using var cmd = m_connection.CreateCommand();
cmd.CommandText = "SELECT Name, Size, Hash FROM RemoteVolume WHERE ID = ?";
cmd.AddParameter();
cmd.SetParameterValue(0, VolumeID);
using var cmd = m_connection.CreateCommand("SELECT Name, Size, Hash FROM RemoteVolume WHERE ID = @VolumeID")
.SetParameterValue("@VolumeID", VolumeID);
using var reader = cmd.ExecuteReader();
while (reader.Read())
yield return (reader.ConvertValueToString(0), reader.ConvertValueToInt64(1), reader.ConvertValueToString(2));
@@ -1181,17 +1161,11 @@ ORDER BY ""A"".""TargetPath"", ""BB"".""Index""");
m_filetablename = filetablename;
m_insertblockCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_blocktablename}"" SET ""Restored"" = 1
WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""Metadata"" = ? AND ""Restored"" = 0 "));
m_insertblockCommand.AddParameters(5);
WHERE ""FileID"" = @TargetFileId AND ""Index"" = @Index AND ""Hash"" = @Hash AND ""Size"" = @Size AND ""Metadata"" = @Metadata AND ""Restored"" = 0 "));
m_resetfileCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_blocktablename}"" SET ""Restored"" = 0 WHERE ""FileID"" = ? "));
m_resetfileCommand.AddParameters(1);
m_updateAsRestoredCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_blocktablename}"" SET ""Restored"" = 1 WHERE ""FileID"" = ? AND ""Metadata"" <= ? "));
m_updateAsRestoredCommand.AddParameters(2);
m_updateFileAsDataVerifiedCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_filetablename}"" SET ""DataVerified"" = 1 WHERE ""ID"" = ?"));
m_updateFileAsDataVerifiedCommand.AddParameters(1);
m_resetfileCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_blocktablename}"" SET ""Restored"" = 0 WHERE ""FileID"" = @TargetFileId "));
m_updateAsRestoredCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_blocktablename}"" SET ""Restored"" = 1 WHERE ""FileID"" = @TargetFileId AND ""Metadata"" <= @Metadata "));
m_updateFileAsDataVerifiedCommand = connection.CreateCommand(m_transaction, FormatInvariant($@"UPDATE ""{m_filetablename}"" SET ""DataVerified"" = 1 WHERE ""ID"" = @TargetFileId"));
if (statstablename != null)
{
@@ -1228,8 +1202,8 @@ WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""M
public void SetAllBlocksMissing(long targetfileid)
{
m_hasUpdates = true;
m_resetfileCommand.SetParameterValue(0, targetfileid);
var r = m_resetfileCommand.ExecuteNonQuery();
var r = m_resetfileCommand.SetParameterValue("@TargetFileId", targetfileid)
.ExecuteNonQuery();
if (r <= 0)
throw new Exception("Unexpected reset result");
}
@@ -1237,9 +1211,9 @@ WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""M
public void SetAllBlocksRestored(long targetfileid, bool includeMetadata)
{
m_hasUpdates = true;
m_updateAsRestoredCommand.SetParameterValue(0, targetfileid);
m_updateAsRestoredCommand.SetParameterValue(1, includeMetadata ? 1 : 0);
var r = m_updateAsRestoredCommand.ExecuteNonQuery();
var r = m_updateAsRestoredCommand.SetParameterValue("@TargetFileId", targetfileid)
.SetParameterValue("@Metadata", includeMetadata ? 1 : 0)
.ExecuteNonQuery();
if (r <= 0)
throw new Exception("Unexpected reset result");
}
@@ -1247,8 +1221,8 @@ WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""M
public void SetFileDataVerified(long targetfileid)
{
m_hasUpdates = true;
m_updateFileAsDataVerifiedCommand.SetParameterValue(0, targetfileid);
var r = m_updateFileAsDataVerifiedCommand.ExecuteNonQuery();
var r = m_updateFileAsDataVerifiedCommand.SetParameterValue("@TargetFileId", targetfileid)
.ExecuteNonQuery();
if (r != 1)
throw new Exception("Unexpected result when marking file as verified.");
}
@@ -1256,15 +1230,14 @@ WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""M
public void SetBlockRestored(long targetfileid, long index, string hash, long size, bool metadata)
{
m_hasUpdates = true;
m_insertblockCommand.SetParameterValue(0, targetfileid);
m_insertblockCommand.SetParameterValue(1, index);
m_insertblockCommand.SetParameterValue(2, hash);
m_insertblockCommand.SetParameterValue(3, size);
m_insertblockCommand.SetParameterValue(4, metadata);
var r = m_insertblockCommand.ExecuteNonQuery();
var r = m_insertblockCommand.SetParameterValue("@TargetFileId", targetfileid)
.SetParameterValue("@Index", index)
.SetParameterValue("@Hash", hash)
.SetParameterValue("@Size", size)
.SetParameterValue("@Metadata", metadata)
.ExecuteNonQuery();
if (r != 1)
throw new Exception("Unexpected result when marking block.");
}
public void Commit()
@@ -1307,8 +1280,9 @@ WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""M
public IEnumerable<string> GetTargetFolders()
{
using (var cmd = m_connection.CreateCommand())
using (var rd = cmd.ExecuteReader(FormatInvariant($@"SELECT ""TargetPath"" FROM ""{m_tempfiletable}"" WHERE ""BlocksetID"" == ?"), FOLDER_BLOCKSET_ID))
using var cmd = m_connection.CreateCommand(FormatInvariant($@"SELECT ""TargetPath"" FROM ""{m_tempfiletable}"" WHERE ""BlocksetID"" == @BlocksetID"))
.SetParameterValue("@BlocksetID", FOLDER_BLOCKSET_ID);
using (var rd = cmd.ExecuteReader())
while (rd.Read())
yield return rd.ConvertValueToString(0);
}
@@ -1371,18 +1345,15 @@ WHERE ""FileID"" = ? AND ""Index"" = ? AND ""Hash"" = ? AND ""Size"" = ? AND ""M
using (var cmdReader = m_connection.CreateCommand())
using (var cmd = m_connection.CreateCommand(transaction))
{
cmd.CommandText = FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""LocalSourceExists"" = 1 WHERE Path = ?");
cmd.AddParameters(1);
var fileset = FormatInvariant($@"SELECT DISTINCT ""{m_tempfiletable}"".""Path"" FROM ""{m_tempfiletable}""");
using (var rd = cmdReader.ExecuteReader(fileset))
cmd.SetCommandAndParameters(FormatInvariant($@"UPDATE ""{m_tempfiletable}"" SET ""LocalSourceExists"" = 1 WHERE Path = @Path"));
using (var rd = cmdReader.ExecuteReader(FormatInvariant($@"SELECT DISTINCT ""{m_tempfiletable}"".""Path"" FROM ""{m_tempfiletable}""")))
{
while (rd.Read())
{
var sourcepath = rd.GetValue(0).ToString();
if (SystemIO.IO_OS.FileExists(sourcepath))
{
cmd.SetParameterValue(0, sourcepath);
cmd.SetParameterValue("@Path", sourcepath);
cmd.ExecuteNonQuery();
}
else