diff options
Diffstat (limited to 'lib/AniDB/Datastore.pm')
-rw-r--r-- | lib/AniDB/Datastore.pm | 108 |
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 +); |