示例#1
0
            public IEnumerable <IFileversion> SelectFiles(Library.Utility.IFilter filter)
            {
                using (var tmpnames = new FilteredFilenameTable(m_connection, filter, null))
                    using (var cmd = m_connection.CreateCommand())
                    {
                        //First we trim the filelist to exclude filenames not found in any of the filesets
                        cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));

                        //Then we select the matching results
                        var filesets             = string.Format(@"SELECT ""FilesetID"", ""Timestamp"" FROM ""{0}"" ORDER BY ""Timestamp"" DESC", m_tablename);
                        var cartesianPathFileset = string.Format(@"SELECT ""A"".""Path"", ""B"".""FilesetID"" FROM ""{0}"" A, (" + filesets + @") B ORDER BY ""A"".""Path"" ASC, ""B"".""Timestamp"" DESC", tmpnames.Tablename, m_tablename);
                        var filesWithSizes       = @"SELECT ""Length"", ""FilesetEntry"".""FilesetID"", ""File"".""Path"" FROM ""Blockset"", ""FilesetEntry"", ""File"" WHERE ""File"".""BlocksetID"" = ""Blockset"".""ID"" AND ""FilesetEntry"".""FileID"" = ""File"".""ID"" ";
                        var query = @"SELECT ""C"".""Path"", ""D"".""Length"", ""C"".""FilesetID"" FROM (" + cartesianPathFileset + @") C LEFT OUTER JOIN (" + filesWithSizes + @") D ON ""C"".""FilesetID"" = ""D"".""FilesetID"" AND ""C"".""Path"" = ""D"".""Path""";
                        using (var rd = cmd.ExecuteReader(query))
                            if (rd.Read())
                            {
                                bool more;
                                do
                                {
                                    var f = new Fileversion(rd);
                                    yield return(f);

                                    more = f.More;
                                } while(more);
                            }
                    }
            }
示例#2
0
            public IEnumerable <IFileversion> GetLargestPrefix(Library.Utility.IFilter filter)
            {
                using (var tmpnames = new FilteredFilenameTable(m_connection, filter, null))
                    using (var cmd = m_connection.CreateCommand())
                    {
                        //First we trim the filelist to exclude filenames not found in any of the filesets
                        cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));

                        // Then we recursively find the largest prefix
                        cmd.CommandText = string.Format(@"SELECT ""Path"" FROM ""{0}"" ORDER BY LENGTH(""Path"") DESC LIMIT 1", tmpnames.Tablename);
                        var    v0      = cmd.ExecuteScalar();
                        string maxpath = "";
                        if (v0 != null)
                        {
                            maxpath = v0.ToString();
                        }

                        cmd.CommandText = string.Format(@"SELECT COUNT(*) FROM ""{0}""", tmpnames.Tablename);
                        var  filecount  = cmd.ExecuteScalarInt64(0);
                        long foundfiles = -1;

                        //TODO: Handle FS case-sensitive?
                        cmd.CommandText = string.Format(@"SELECT COUNT(*) FROM ""{0}"" WHERE SUBSTR(""Path"", 1, ?) = ?", tmpnames.Tablename);
                        cmd.AddParameter();
                        cmd.AddParameter();

                        while (filecount != foundfiles && maxpath.Length > 0)
                        {
                            var mp = Library.Utility.Utility.AppendDirSeparator(maxpath);
                            cmd.SetParameterValue(0, mp.Length);
                            cmd.SetParameterValue(1, mp);
                            foundfiles = cmd.ExecuteScalarInt64(0);

                            if (filecount != foundfiles)
                            {
                                var oldlen = maxpath.Length;
                                maxpath = Library.Snapshots.SnapshotUtility.SystemIO.PathGetDirectoryName(maxpath);
                                if (string.IsNullOrWhiteSpace(maxpath) || maxpath.Length == oldlen)
                                {
                                    maxpath = "";
                                }
                            }
                        }

                        return
                            (new IFileversion[] {
                            new FileversionFixed()
                            {
                                Path = maxpath == "" ? "" : Library.Utility.Utility.AppendDirSeparator(maxpath)
                            }
                        });
                    }
            }
示例#3
0
            public IEnumerable <IFileversion> SelectFolderContents(Library.Utility.IFilter filter)
            {
                var tbname = "Filenames-" + Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray());

                try
                {
                    string pathprefix;
                    if (filter == null || filter.Empty)
                    {
                        pathprefix = "";
                    }
                    else if (filter as Library.Utility.FilterExpression == null || ((Library.Utility.FilterExpression)filter).Type != Duplicati.Library.Utility.FilterType.Simple || ((Library.Utility.FilterExpression)filter).GetSimpleList().Length != 1)
                    {
                        throw new ArgumentException("Filter for list-folder-contents must be a path prefix with no wildcards", "filter");
                    }
                    else
                    {
                        pathprefix = ((Library.Utility.FilterExpression)filter).GetSimpleList().First();
                    }

                    var dirsep = Duplicati.Library.Utility.Utility.GuessDirSeparator(pathprefix);

                    if (pathprefix.Length > 0 || dirsep == "/")
                    {
                        pathprefix = Duplicati.Library.Utility.Utility.AppendDirSeparator(pathprefix, dirsep);
                    }

                    using (var tmpnames = new FilteredFilenameTable(m_connection, new Library.Utility.FilterExpression(new string[] { pathprefix + "*" }, true), null))
                        using (var cmd = m_connection.CreateCommand())
                        {
                            //First we trim the filelist to exclude filenames not found in any of the filesets
                            cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));

                            // If we had instr support this would work:

                            /*var distinctPaths = @"SELECT DISTINCT :1 || " +
                             *  @"CASE(INSTR(SUBSTR(""Path"", :2), ""/"")) " +
                             *  @"WHEN 0 THEN SUBSTR(""Path"", :2) " +
                             *  @"ELSE SUBSTR(""Path"", :2,  INSTR(SUBSTR(path, :2), ""/"")) " +
                             *  @"END AS ""Path"", ""FilesetID"" " +
                             *  @" FROM (" + cartesianPathFileset + @")";*/

                            // Instead we manually iterate the paths
                            cmd.ExecuteNonQuery(string.Format(@"CREATE TEMPORARY TABLE ""{0}"" (""Path"" TEXT NOT NULL)", tbname));

                            using (var c2 = m_connection.CreateCommand())
                            {
                                c2.CommandText = string.Format(@"INSERT INTO ""{0}"" (""Path"") VALUES (?)", tbname);
                                c2.AddParameter();

                                foreach (var n in SelectFolderEntries(cmd, pathprefix, tmpnames.Tablename).Distinct())
                                {
                                    c2.SetParameterValue(0, n);
                                    c2.ExecuteNonQuery();
                                }

                                c2.ExecuteNonQuery(string.Format(@"CREATE INDEX ""{0}_PathIndex"" ON ""{0}"" (""Path"")", tbname));
                            }

                            //Then we select the matching results
                            var filesets             = string.Format(@"SELECT ""FilesetID"", ""Timestamp"" FROM ""{0}"" ORDER BY ""Timestamp"" DESC", m_tablename);
                            var cartesianPathFileset = string.Format(@"SELECT ""A"".""Path"", ""B"".""FilesetID"" FROM ""{0}"" A, (" + filesets + @") B ORDER BY ""A"".""Path"" ASC, ""B"".""Timestamp"" DESC", tbname, m_tablename);

                            var filesWithSizes = @"SELECT ""Length"", ""FilesetEntry"".""FilesetID"", ""File"".""Path"" FROM ""Blockset"", ""FilesetEntry"", ""File"" WHERE ""File"".""BlocksetID"" = ""Blockset"".""ID"" AND ""FilesetEntry"".""FileID"" = ""File"".""ID"" ";
                            var query          = @"SELECT ""C"".""Path"", ""D"".""Length"", ""C"".""FilesetID"" FROM (" + cartesianPathFileset + @") C LEFT OUTER JOIN (" + filesWithSizes + @") D ON ""C"".""FilesetID"" = ""D"".""FilesetID"" AND ""C"".""Path"" = ""D"".""Path""";

                            cmd.AddParameter(pathprefix, "1");
                            cmd.AddParameter(pathprefix.Length + 1, "2");

                            using (var rd = cmd.ExecuteReader(query))
                                if (rd.Read())
                                {
                                    bool more;
                                    do
                                    {
                                        var f = new Fileversion(rd);
                                        if (!(string.IsNullOrWhiteSpace(f.Path) || f.Path == pathprefix))
                                        {
                                            yield return(f);

                                            more = f.More;
                                        }
                                        else
                                        {
                                            more = rd.Read();
                                        }
                                    } while(more);
                                }
                        }
                }
                finally
                {
                    try
                    {
                        using (var c = m_connection.CreateCommand())
                            c.ExecuteNonQuery(string.Format(@"DROP TABLE IF EXISTS ""{0}""", tbname));
                    }
                    catch
                    {
                    }
                }
            }
示例#4
0
            private IEnumerable <IFileversion> GetLargestPrefix(Library.Utility.IFilter filter, string prefixrule)
            {
                using (var tmpnames = new FilteredFilenameTable(m_connection, filter, null))
                    using (var cmd = m_connection.CreateCommand())
                    {
                        //First we trim the filelist to exclude filenames not found in any of the filesets
                        cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));

                        //If we have a prefix rule, apply it
                        if (!string.IsNullOrWhiteSpace(prefixrule))
                        {
                            cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE SUBSTR(""Path"", 1, 1) != ?", tmpnames.Tablename), prefixrule);
                        }

                        // Then we recursively find the largest prefix
                        cmd.CommandText = string.Format(@"SELECT ""Path"" FROM ""{0}"" ORDER BY LENGTH(""Path"") DESC LIMIT 1", tmpnames.Tablename);
                        var    v0      = cmd.ExecuteScalar();
                        string maxpath = "";
                        if (v0 != null)
                        {
                            maxpath = v0.ToString();
                        }

                        var dirsep = Duplicati.Library.Utility.Utility.GuessDirSeparator(maxpath);

                        cmd.CommandText = string.Format(@"SELECT COUNT(*) FROM ""{0}""", tmpnames.Tablename);
                        var  filecount  = cmd.ExecuteScalarInt64(0);
                        long foundfiles = -1;

                        //TODO: Handle FS case-sensitive?
                        cmd.CommandText = string.Format(@"SELECT COUNT(*) FROM ""{0}"" WHERE SUBSTR(""Path"", 1, ?) = ?", tmpnames.Tablename);
                        cmd.AddParameter();
                        cmd.AddParameter();

                        while (filecount != foundfiles && maxpath.Length > 0)
                        {
                            var mp = Duplicati.Library.Utility.Utility.AppendDirSeparator(maxpath, dirsep);
                            cmd.SetParameterValue(0, mp.Length);
                            cmd.SetParameterValue(1, mp);
                            foundfiles = cmd.ExecuteScalarInt64(0);

                            if (filecount != foundfiles)
                            {
                                var oldlen = maxpath.Length;
                                var lix    = maxpath.LastIndexOf(dirsep, maxpath.Length - 2, StringComparison.Ordinal);
                                maxpath = maxpath.Substring(0, lix + 1);
                                if (string.IsNullOrWhiteSpace(maxpath) || maxpath.Length == oldlen)
                                {
                                    maxpath = "";
                                }
                            }
                        }

                        // Special handling for Windows and multi-drive backups as they do not have a single common root
                        if (string.IsNullOrWhiteSpace(maxpath) && string.IsNullOrWhiteSpace(prefixrule))
                        {
                            var roots = cmd.ExecuteReaderEnumerable(string.Format(@"SELECT DISTINCT SUBSTR(""Path"", 1, 1) FROM ""{0}""", tmpnames.Tablename)).Select(x => x.ConvertValueToString(0)).ToArray();
                            return(roots.Select(x => GetLargestPrefix(filter, x).First()).Distinct().ToArray());
                        }

                        return
                            (new IFileversion[] {
                            new FileversionFixed()
                            {
                                Path = maxpath == "" ? "" : Duplicati.Library.Utility.Utility.AppendDirSeparator(maxpath, dirsep)
                            }
                        });
                    }
            }
示例#5
0
 public IEnumerable<IFileversion> SelectFiles(Library.Utility.IFilter filter)
 {
     using(var tmpnames = new FilteredFilenameTable(m_connection, filter, null))
     using(var cmd = m_connection.CreateCommand())                
     {
         //First we trim the filelist to exclude filenames not found in any of the filesets
         cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));  
     
         //Then we select the matching results
         var filesets = string.Format(@"SELECT ""FilesetID"", ""Timestamp"" FROM ""{0}"" ORDER BY ""Timestamp"" DESC", m_tablename);
         var cartesianPathFileset = string.Format(@"SELECT ""A"".""Path"", ""B"".""FilesetID"" FROM ""{0}"" A, (" + filesets + @") B ORDER BY ""A"".""Path"" ASC, ""B"".""Timestamp"" DESC", tmpnames.Tablename, m_tablename);
         var filesWithSizes = @"SELECT ""Length"", ""FilesetEntry"".""FilesetID"", ""File"".""Path"" FROM ""Blockset"", ""FilesetEntry"", ""File"" WHERE ""File"".""BlocksetID"" = ""Blockset"".""ID"" AND ""FilesetEntry"".""FileID"" = ""File"".""ID"" ";
         var query = @"SELECT ""C"".""Path"", ""D"".""Length"", ""C"".""FilesetID"" FROM (" + cartesianPathFileset + @") C LEFT OUTER JOIN (" + filesWithSizes + @") D ON ""C"".""FilesetID"" = ""D"".""FilesetID"" AND ""C"".""Path"" = ""D"".""Path""";
         using(var rd = cmd.ExecuteReader(query))
             if(rd.Read())
             {
                 bool more;
                 do
                 {
                     var f = new Fileversion(rd);
                     yield return f;
                     more = f.More;
                 } while(more);
             }
     }
 }
示例#6
0
            public IEnumerable<IFileversion> SelectFolderContents(Library.Utility.IFilter filter)
            {
                var tbname = "Filenames-" + Library.Utility.Utility.ByteArrayAsHexString(Guid.NewGuid().ToByteArray());
                try
                {
                    string pathprefix;
                    if (filter == null || filter.Empty)
                        pathprefix = "";
                    else if (filter as Library.Utility.FilterExpression == null || ((Library.Utility.FilterExpression)filter).Type != Duplicati.Library.Utility.FilterType.Simple || ((Library.Utility.FilterExpression)filter).GetSimpleList().Length != 1)
                        throw new ArgumentException("Filter for list-folder-contents must be a path prefix with no wildcards", "filter");
                    else
                        pathprefix = ((Library.Utility.FilterExpression)filter).GetSimpleList().First();
                    
                    if (pathprefix.Length > 0 || Duplicati.Library.Utility.Utility.IsClientLinux)
                        pathprefix = Duplicati.Library.Utility.Utility.AppendDirSeparator(pathprefix);
                    
                    using(var tmpnames = new FilteredFilenameTable(m_connection, new Library.Utility.FilterExpression(pathprefix + "*", true), null))
                    using(var cmd = m_connection.CreateCommand())
                    {
                        //First we trim the filelist to exclude filenames not found in any of the filesets
                        cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));  
                    
                        // If we had instr support this would work:
                        /*var distinctPaths = @"SELECT DISTINCT :1 || " +
                            @"CASE(INSTR(SUBSTR(""Path"", :2), ""/"")) " +
                            @"WHEN 0 THEN SUBSTR(""Path"", :2) " +
                            @"ELSE SUBSTR(""Path"", :2,  INSTR(SUBSTR(path, :2), ""/"")) " +
                            @"END AS ""Path"", ""FilesetID"" " +
                            @" FROM (" + cartesianPathFileset + @")";*/
                        
                        // Instead we manually iterate the paths
                        cmd.ExecuteNonQuery(string.Format(@"CREATE TEMPORARY TABLE ""{0}"" (""Path"" TEXT NOT NULL)", tbname));
                        
                        using(var c2 = m_connection.CreateCommand())
                        {
                            c2.CommandText = string.Format(@"INSERT INTO ""{0}"" (""Path"") VALUES (?)", tbname);
                            c2.AddParameter();
                        
                            foreach(var n in SelectFolderEntries(cmd, pathprefix, tmpnames.Tablename).Distinct())
                            {
                                c2.SetParameterValue(0, n);
                                c2.ExecuteNonQuery();
                            }

                            c2.ExecuteNonQuery(string.Format(@"CREATE INDEX ""{0}_PathIndex"" ON ""{0}"" (""Path"")", tbname));
                        }
                        
                        //Then we select the matching results
                        var filesets = string.Format(@"SELECT ""FilesetID"", ""Timestamp"" FROM ""{0}"" ORDER BY ""Timestamp"" DESC", m_tablename);
                        var cartesianPathFileset = string.Format(@"SELECT ""A"".""Path"", ""B"".""FilesetID"" FROM ""{0}"" A, (" + filesets + @") B ORDER BY ""A"".""Path"" ASC, ""B"".""Timestamp"" DESC", tbname, m_tablename);
                                                
                        var filesWithSizes = @"SELECT ""Length"", ""FilesetEntry"".""FilesetID"", ""File"".""Path"" FROM ""Blockset"", ""FilesetEntry"", ""File"" WHERE ""File"".""BlocksetID"" = ""Blockset"".""ID"" AND ""FilesetEntry"".""FileID"" = ""File"".""ID"" ";
                        var query = @"SELECT ""C"".""Path"", ""D"".""Length"", ""C"".""FilesetID"" FROM (" + cartesianPathFileset + @") C LEFT OUTER JOIN (" + filesWithSizes + @") D ON ""C"".""FilesetID"" = ""D"".""FilesetID"" AND ""C"".""Path"" = ""D"".""Path""";
                        
                        cmd.AddParameter(pathprefix, "1");                    
                        cmd.AddParameter(pathprefix.Length + 1, "2");
                        
                        using(var rd = cmd.ExecuteReader(query))
                            if (rd.Read())
                            {
                                bool more;
                                do
                                {
                                    var f = new Fileversion(rd);
                                    if (!(string.IsNullOrWhiteSpace(f.Path) || f.Path == pathprefix))
                                    {
                                        yield return f;
                                        more = f.More;
                                    }
                                    else
                                    {
                                        more = rd.Read();
                                    }
                                    
                                } while(more);
                            }
                    }                    
                }
                finally
                {
                    try
                    {
                        using(var c = m_connection.CreateCommand())
                            c.ExecuteNonQuery(string.Format(@"DROP TABLE IF EXISTS ""{0}""", tbname));
                    }
                    catch
                    {
                    }
                }
            }
示例#7
0
         public IEnumerable<IFileversion> GetLargestPrefix(Library.Utility.IFilter filter)
         {
             using(var tmpnames = new FilteredFilenameTable(m_connection, filter, null))
             using(var cmd = m_connection.CreateCommand())                
             {
                 //First we trim the filelist to exclude filenames not found in any of the filesets
                 cmd.ExecuteNonQuery(string.Format(@"DELETE FROM ""{0}"" WHERE ""Path"" NOT IN (SELECT DISTINCT ""Path"" FROM ""File"", ""FilesetEntry"" WHERE ""FilesetEntry"".""FileID"" = ""File"".""ID"" AND ""FilesetEntry"".""FilesetID"" IN (SELECT ""FilesetID"" FROM ""{1}"") ) ", tmpnames.Tablename, m_tablename));
                 
                 // Then we recursively find the largest prefix
                 cmd.CommandText = string.Format(@"SELECT ""Path"" FROM ""{0}"" ORDER BY LENGTH(""Path"") DESC LIMIT 1", tmpnames.Tablename);
                 var v0 = cmd.ExecuteScalar();
                 string maxpath = "";
                 if (v0 != null)
                     maxpath = v0.ToString();
 
                 cmd.CommandText = string.Format(@"SELECT COUNT(*) FROM ""{0}""", tmpnames.Tablename);
                 var filecount = cmd.ExecuteScalarInt64(0);
                 long foundfiles = -1;
 
                 //TODO: Handle FS case-sensitive?
                 cmd.CommandText = string.Format(@"SELECT COUNT(*) FROM ""{0}"" WHERE SUBSTR(""Path"", 1, ?) = ?", tmpnames.Tablename);
                 cmd.AddParameter();
                 cmd.AddParameter();
 
                 while (filecount != foundfiles && maxpath.Length > 0)
                 {
                     var mp = Library.Utility.Utility.AppendDirSeparator(maxpath);
                     cmd.SetParameterValue(0, mp.Length);
                     cmd.SetParameterValue(1, mp);
                     foundfiles = cmd.ExecuteScalarInt64(0);
 
                     if (filecount != foundfiles)
                     {
                         var oldlen = maxpath.Length;
                         maxpath = Library.Snapshots.SnapshotUtility.SystemIO.PathGetDirectoryName(maxpath);
                         if (string.IsNullOrWhiteSpace(maxpath) || maxpath.Length == oldlen)
                             maxpath = "";
                     }
                 }
 
                 return 
                     new IFileversion[] {
                         new FileversionFixed() { Path = maxpath == "" ? "" : Library.Utility.Utility.AppendDirSeparator(maxpath) }
                     };
             }
 
         }