summaryrefslogtreecommitdiff
path: root/lib/AniDB/Datastore.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AniDB/Datastore.pm')
-rw-r--r--lib/AniDB/Datastore.pm108
1 files changed, 87 insertions, 21 deletions
diff --git a/lib/AniDB/Datastore.pm b/lib/AniDB/Datastore.pm
index 8db4e16..41602e6 100644
--- a/lib/AniDB/Datastore.pm
+++ b/lib/AniDB/Datastore.pm
@@ -3,7 +3,8 @@ use 5.024;
use experimental 'signatures';
use Moo;
use Path::Tiny;
-use AniDB::Hashing;
+use Try::Tiny;
+use JSON::MaybeXS qw(encode_json decode_json);
use namespace::clean;
has database => ( is => 'ro', required => 1 );
@@ -22,23 +23,25 @@ sub _build_dbh($self) {
);
}
-sub update($self,$path) {
- my $stat = $path->stat;
-
- return 0 unless $self->_has_changed($path,$stat);
- my $hash = AniDB::Hashing::hash_fd($path->openr_raw);
- $self->_update_path_info(
- $path => {
- size => $stat->size,
- mtime => $stat->mtime,
- hash => $hash,
- },
- );
- return 1;
+sub BUILD($self) {
+ try {
+ $self->dbh->selectall_arrayref('SELECT * FROM path_info LIMIT 1');
+ } catch {
+ if (/\bno such table\b/) {
+ my @sql = do { local $/ = ";\n\n"; <DATA> };
+ $self->dbh->do($_) for @sql;
+ }
+ else {
+ die $_;
+ }
+ };
}
-sub _has_changed($self,$path,$stat) {
+sub has_changed($self,$path,$stat) {
my $path_info = $self->path_info_for($path);
+ # if we don't know about the file, it's definitely changed!
+ return 1 unless $path_info;
+
return (
$path_info->{size} == $stat->size
&& $path_info->{mtime} == $stat->mtime
@@ -76,22 +79,85 @@ sub path_info_for($self,$path) {
return $ret->[0];
}
+sub update_path_info($self,$path,$path_info) {
+ my @binds = (@{$path_info}{qw(size mtime hash)}, $path->stringify);
+ return $self->dbh->do(
+ qr{UPDATE path_info SET size=?, mtime=?, hash=? WHERE name=?},
+ {},
+ @binds,
+ ) or $self->dbh->do(
+ qr{INSERT INTO path_info(size,mtime,hash,name) VALUES (?,?,?,?)},
+ {},
+ @binds,
+ );
+}
+
sub episode_info_for($self,$args) {
my $ret = $self->dbh->selectall_arrayref(
- qr{SELECT * FROM episode_info WHERE hash=? AND size=?},
- { Slice => {} },
+ qr{SELECT json FROM episode_info WHERE hash=? AND size=?},
+ { },
@{$args}{qw(hash size)},
);
- return $ret->[0];
+ return unless $ret && $ret->[0];
+ return decode_json($ret->[0][0]);
+}
+
+sub update_episode_info($self,$path_info, $episode_info) {
+ my $json = encode_json($episode_info);
+ my @binds = ($json, @{$path_info}{qw(size hash)});
+ return $self->dbh->do(
+ qr{UPDATE episode_info SET json=? WHERE size=? AND hash=?},
+ {},
+ @binds,
+ ) or $self->dbh->do(
+ qr{INSERT INTO episode_info(json,size,hash) VALUES (?,?,?)},
+ {},
+ @binds,
+ );
}
sub anime_info_for($self,$args) {
my $ret = $self->dbh->selectall_arrayref(
- qr{SELECT * FROM anime_info WHERE aid=?},
- { Slice => {} },
+ qr{SELECT json FROM anime_info WHERE aid=?},
+ { },
@{$args}{qw(aid)},
);
- return $ret->[0];
+ return unless $ret && $ret->[0];
+ return decode_json($ret->[0][0]);
+}
+
+sub update_anime_info($self,$episode_info, $anime_info) {
+ my $json = encode_json($anime_info);
+ my @binds = ($json, $episode_info->{eid});
+ return $self->dbh->do(
+ qr{UPDATE anime_info SET json=? WHERE eid=?},
+ {},
+ @binds,
+ ) or $self->dbh->do(
+ qr{INSERT INTO anime_info(json,eid) VALUES (?,?)},
+ {},
+ @binds,
+ );
}
1;
+
+__DATA__
+CREATE TABLE path_info (
+ name TEXT PRIMARY KEY,
+ mtime INT NOT NULL,
+ size INT NOT NULL,
+ hash TEXT NOT NULL
+);
+
+CREATE TABLE episode_info (
+ size INT NOT NULL,
+ hash TEXT NOT NULL,
+ json TEST NOT NULL,
+ PRIMARY KEY (size,hash)
+);
+
+CREATE TABLE anime_info (
+ eid INT PRIMARY KEY,
+ json TEST NOT NULL
+);