summaryrefslogtreecommitdiffstats
path: root/lib/App/BorgRestore/DB.pm
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2017-02-27 00:05:30 +0100
committerFlorian Pritz <bluewind@xinu.at>2017-02-27 09:56:32 +0100
commit82bdef1a323fc46ad8499ccd17d3c255200696d4 (patch)
treeaec53709686cb45c57a3c752b0a1dc3bba12c2b9 /lib/App/BorgRestore/DB.pm
parent0265a0785a266f88ae17217872badb9a53c2bea6 (diff)
downloadApp-BorgRestore-82bdef1a323fc46ad8499ccd17d3c255200696d4.tar.gz
App-BorgRestore-82bdef1a323fc46ad8499ccd17d3c255200696d4.tar.xz
Move packages to dedicated files
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'lib/App/BorgRestore/DB.pm')
-rw-r--r--lib/App/BorgRestore/DB.pm185
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/App/BorgRestore/DB.pm b/lib/App/BorgRestore/DB.pm
new file mode 100644
index 0000000..d4e61df
--- /dev/null
+++ b/lib/App/BorgRestore/DB.pm
@@ -0,0 +1,185 @@
+package App::BorgRestore::DB;
+use v5.10;
+use strict;
+use warnings;
+
+use App::BorgRestore::Helper;
+
+use Data::Dumper;
+use DBI;
+
+sub new {
+ my $class = shift;
+ my $db_path = shift;
+
+ my $self = {};
+ bless $self, $class;
+
+ $self->_open_db($db_path);
+
+ return $self;
+}
+
+sub _open_db {
+ my $self = shift;
+ my $dbfile = shift;
+
+ $self->{dbh} = DBI->connect("dbi:SQLite:dbname=$dbfile","","", {RaiseError => 1, Taint => 1});
+ $self->{dbh}->do("PRAGMA cache_size=-1024000");
+ $self->{dbh}->do("PRAGMA strict=ON");
+}
+
+sub initialize_db {
+ my $self = shift;
+
+ $self->{dbh}->do('create table `files` (`path` text, primary key (`path`)) without rowid;');
+ $self->{dbh}->do('create table `archives` (`archive_name` text unique);');
+}
+
+sub get_archive_names {
+ my $self = shift;
+
+ my @ret;
+
+ my $st = $self->{dbh}->prepare("select `archive_name` from `archives`;");
+ $st->execute();
+ while (my $result = $st->fetchrow_hashref) {
+ push @ret, $result->{archive_name};
+ }
+ return \@ret;
+}
+
+sub get_archive_row_count {
+ my $self = shift;
+
+ my $st = $self->{dbh}->prepare("select count(*) count from `files`;");
+ $st->execute();
+ my $result = $st->fetchrow_hashref;
+ return $result->{count};
+}
+
+sub add_archive_name {
+ my $self = shift;
+ my $archive = shift;
+
+ $archive = App::BorgRestore::Helper::untaint_archive_name($archive);
+
+ my $st = $self->{dbh}->prepare('insert into `archives` (`archive_name`) values (?);');
+ $st->execute($archive);
+
+ $self->_add_column_to_table("files", $archive);
+}
+
+sub _add_column_to_table {
+ my $self = shift;
+ my $table = shift;
+ my $column = shift;
+
+ my $st = $self->{dbh}->prepare('alter table `'.$table.'` add column `'._prefix_archive_id($column).'` integer;');
+ $st->execute();
+}
+
+sub remove_archive {
+ my $self = shift;
+ my $archive = shift;
+
+ $archive = App::BorgRestore::Helper::untaint_archive_name($archive);
+
+ my $archive_id = $self->get_archive_id($archive);
+
+ my @keep_archives = grep {$_ ne $archive;} @{$self->get_archive_names()};
+
+ $self->{dbh}->do('create table `files_new` (`path` text, primary key (`path`)) without rowid;');
+ for my $archive (@keep_archives) {
+ $self->_add_column_to_table("files_new", $archive);
+ }
+
+ my @columns_to_copy = map {'`'._prefix_archive_id($_).'`'} @keep_archives;
+ @columns_to_copy = ('`path`', @columns_to_copy);
+ $self->{dbh}->do('insert into `files_new` select '.join(',', @columns_to_copy).' from files');
+
+ $self->{dbh}->do('drop table `files`');
+
+ $self->{dbh}->do('alter table `files_new` rename to `files`');
+
+ my $st = $self->{dbh}->prepare('delete from `archives` where `archive_name` = ?;');
+ $st->execute($archive);
+}
+
+sub _prefix_archive_id {
+ my $archive = shift;
+
+ $archive = App::BorgRestore::Helper::untaint_archive_name($archive);
+
+ return 'timestamp-'.$archive;
+}
+
+sub get_archive_id {
+ my $self = shift;
+ my $archive = shift;
+
+ return _prefix_archive_id($archive);
+}
+
+sub get_archives_for_path {
+ my $self = shift;
+ my $path = shift;
+
+ my $st = $self->{dbh}->prepare('select * from `files` where `path` = ?;');
+ $st->execute(App::BorgRestore::Helper::untaint($path, qr(.*)));
+
+ my @ret;
+
+ my $result = $st->fetchrow_hashref;
+ my $archives = $self->get_archive_names();
+
+ for my $archive (@$archives) {
+ my $archive_id = $self->get_archive_id($archive);
+ my $timestamp = $result->{$archive_id};
+
+ push @ret, {
+ modification_time => $timestamp,
+ archive => $archive,
+ };
+ }
+
+ return \@ret;
+}
+
+
+sub add_path {
+ my $self = shift;
+ my $archive_id = shift;
+ my $path = shift;
+ my $time = shift;
+
+ my $st = $self->{dbh}->prepare_cached('insert or ignore into `files` (`path`, `'.$archive_id.'`)
+ values(?, ?)');
+ $st->execute($path, $time);
+
+ $st = $self->{dbh}->prepare_cached('update files set `'.$archive_id.'` = ? where `path` = ?');
+ $st->execute($time, $path);
+}
+
+sub begin_work {
+ my $self = shift;
+
+ $self->{dbh}->begin_work();
+}
+
+sub commit {
+ my $self = shift;
+
+ $self->{dbh}->commit();
+}
+
+sub vacuum {
+ my $self = shift;
+
+ $self->{dbh}->do("vacuum");
+}
+
+
+1;
+
+__END__