From fac135d5a51e2cf0111a3faeb6b545c54751adc7 Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Wed, 19 Mar 2025 22:23:57 +0100 Subject: [PATCH] Updated restore database to not use positional arguments --- .../Main/Database/LocalRestoreDatabase.cs | 277 ++++++++---------- 1 file changed, 124 insertions(+), 153 deletions(-) diff --git a/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs b/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs index 56b68dd43..734885498 100644 --- a/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs +++ b/Duplicati/Library/Main/Database/LocalRestoreDatabase.cs @@ -195,10 +195,8 @@ END "); throw; } } - } - public Tuple 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 Blocks { get; } } - public interface IBlockSource { string Path { get; } @@ -595,25 +595,22 @@ END "); public static IEnumerable 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 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 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 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"""); /// A tuple containing the name, size, and hash of the volume. 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 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