package AniDB::Datastore; use 5.024; use experimental 'signatures'; use Moo; use Path::Tiny; use AniDB::Hashing; use namespace::clean; has database => ( is => 'ro', required => 1 ); has dbh => ( is => 'ro', lazy => 1 ); sub _build_dbh($self) { require DBI; return DBI->connect( 'dbi:SQLite:dbname='.$self->database, '', '', { AutoCommit => 1, RaiseError => 1, PrintError => 0, }, ); } 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 _has_changed($self,$path,$stat) { my $path_info = $self->path_info_for($path); return ( $path_info->{size} == $stat->size && $path_info->{mtime} == $stat->mtime ); } sub rename($self,$path,$new_path) { $self->dbh->do( q{UPDATE path_info SET name=? WHERE name=?}, $path->stringify,$new_path->stringify, ); } sub full_info_for($self,$path) { my $path_info = $self->path_info_for($path); my $episode_info = $self->episode_info_for( $path_info, ); my $anime_info = $self->anime_info_for( $episode_info, ); return { path => $path_info, episode => $episode_info, anime => $anime_info, }; } sub path_info_for($self,$path) { my $ret = $self->dbh->selectall_arrayref( qr{SELECT * FROM path_info WHERE name=?}, { Slice => {} }, $path->stringify, ); return $ret->[0]; } sub episode_info_for($self,$args) { my $ret = $self->dbh->selectall_arrayref( qr{SELECT * FROM episode_info WHERE hash=? AND size=?}, { Slice => {} }, @{$args}{qw(hash size)}, ); return $ret->[0]; } sub anime_info_for($self,$args) { my $ret = $self->dbh->selectall_arrayref( qr{SELECT * FROM anime_info WHERE aid=?}, { Slice => {} }, @{$args}{qw(aid)}, ); return $ret->[0]; } 1;