summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AniDB/Datastore.pm59
-rw-r--r--t/tests/datastore.t174
2 files changed, 204 insertions, 29 deletions
diff --git a/lib/AniDB/Datastore.pm b/lib/AniDB/Datastore.pm
index 41602e6..d5f61b6 100644
--- a/lib/AniDB/Datastore.pm
+++ b/lib/AniDB/Datastore.pm
@@ -1,18 +1,17 @@
package AniDB::Datastore;
use 5.024;
-use experimental 'signatures';
use Moo;
-use Path::Tiny;
+use experimental 'signatures';
use Try::Tiny;
use JSON::MaybeXS qw(encode_json decode_json);
use namespace::clean;
has database => ( is => 'ro', required => 1 );
-has dbh => ( is => 'ro', lazy => 1 );
+has dbh => ( is => 'lazy' );
sub _build_dbh($self) {
require DBI;
- return DBI->connect(
+ my $dbh = DBI->connect(
'dbi:SQLite:dbname='.$self->database,
'', '',
{
@@ -21,20 +20,20 @@ sub _build_dbh($self) {
PrintError => 0,
},
);
-}
-sub BUILD($self) {
try {
- $self->dbh->selectall_arrayref('SELECT * FROM path_info LIMIT 1');
+ $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;
+ $dbh->do($_) for @sql;
}
else {
die $_;
}
};
+
+ return $dbh;
}
sub has_changed($self,$path,$stat) {
@@ -42,7 +41,7 @@ sub has_changed($self,$path,$stat) {
# if we don't know about the file, it's definitely changed!
return 1 unless $path_info;
- return (
+ return not(
$path_info->{size} == $stat->size
&& $path_info->{mtime} == $stat->mtime
);
@@ -51,7 +50,8 @@ sub has_changed($self,$path,$stat) {
sub rename($self,$path,$new_path) {
$self->dbh->do(
q{UPDATE path_info SET name=? WHERE name=?},
- $path->stringify,$new_path->stringify,
+ {},
+ $new_path->stringify,$path->stringify,
);
}
@@ -72,21 +72,22 @@ sub full_info_for($self,$path) {
sub path_info_for($self,$path) {
my $ret = $self->dbh->selectall_arrayref(
- qr{SELECT * FROM path_info WHERE name=?},
+ q{SELECT * FROM path_info WHERE name=?},
{ Slice => {} },
$path->stringify,
);
+ return unless $ret && $ret->[0];
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=?},
+ return 0+$self->dbh->do(
+ q{UPDATE path_info SET size=?, mtime=?, hash=? WHERE name=?},
{},
@binds,
- ) or $self->dbh->do(
- qr{INSERT INTO path_info(size,mtime,hash,name) VALUES (?,?,?,?)},
+ ) || 0+$self->dbh->do(
+ q{INSERT INTO path_info(size,mtime,hash,name) VALUES (?,?,?,?)},
{},
@binds,
);
@@ -94,7 +95,7 @@ sub update_path_info($self,$path,$path_info) {
sub episode_info_for($self,$args) {
my $ret = $self->dbh->selectall_arrayref(
- qr{SELECT json FROM episode_info WHERE hash=? AND size=?},
+ q{SELECT json FROM episode_info WHERE hash=? AND size=?},
{ },
@{$args}{qw(hash size)},
);
@@ -105,22 +106,22 @@ sub episode_info_for($self,$args) {
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=?},
+ return 0+$self->dbh->do(
+ q{UPDATE episode_info SET json=? WHERE size=? AND hash=?},
{},
@binds,
- ) or $self->dbh->do(
- qr{INSERT INTO episode_info(json,size,hash) VALUES (?,?,?)},
+ ) || 0+$self->dbh->do(
+ q{INSERT INTO episode_info(json,size,hash) VALUES (?,?,?)},
{},
@binds,
);
}
-sub anime_info_for($self,$args) {
+sub anime_info_for($self,$episode_info) {
my $ret = $self->dbh->selectall_arrayref(
- qr{SELECT json FROM anime_info WHERE aid=?},
+ q{SELECT json FROM anime_info WHERE aid=?},
{ },
- @{$args}{qw(aid)},
+ @{$episode_info}{qw(aid)},
);
return unless $ret && $ret->[0];
return decode_json($ret->[0][0]);
@@ -128,13 +129,13 @@ sub anime_info_for($self,$args) {
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=?},
+ my @binds = ($json, $episode_info->{aid});
+ return 0+$self->dbh->do(
+ q{UPDATE anime_info SET json=? WHERE aid=?},
{},
@binds,
- ) or $self->dbh->do(
- qr{INSERT INTO anime_info(json,eid) VALUES (?,?)},
+ ) || 0+$self->dbh->do(
+ q{INSERT INTO anime_info(json,aid) VALUES (?,?)},
{},
@binds,
);
@@ -158,6 +159,6 @@ CREATE TABLE episode_info (
);
CREATE TABLE anime_info (
- eid INT PRIMARY KEY,
+ aid INT PRIMARY KEY,
json TEST NOT NULL
);
diff --git a/t/tests/datastore.t b/t/tests/datastore.t
new file mode 100644
index 0000000..101b125
--- /dev/null
+++ b/t/tests/datastore.t
@@ -0,0 +1,174 @@
+#!perl
+use 5.024;
+use strict;
+use warnings;
+use Test2::Bundle::Extended;
+use experimental 'signatures';
+use Path::Tiny;
+use AniDB::Datastore;
+
+my $tempdir = Path::Tiny->tempdir;
+my $db_file = $tempdir->child('test.db');
+
+my $ds;
+
+subtest 'construction' => sub {
+ try_ok {
+ $ds = AniDB::Datastore->new({database=>$db_file})
+ } 'builds';
+
+ isa_ok(
+ $ds->dbh,
+ ['DBI::db'],
+ 'gets a dbh',
+ );
+};
+
+my $test_file = $tempdir->child('some.video');
+$test_file->spew_raw('data');
+my $stat = $test_file->stat;
+
+subtest 'reading non-existent records' => sub {
+ is(
+ $ds->path_info_for($test_file),
+ undef,
+ 'path record',
+ );
+ is(
+ $ds->episode_info_for({hash=>1,size=>1}),
+ undef,
+ 'episode record',
+ );
+ is(
+ $ds->anime_info_for({aid=>1}),
+ undef,
+ 'anime record',
+ );
+};
+
+subtest 'insert data' => sub {
+ try_ok {
+ ok $ds->update_path_info(
+ $test_file => {
+ size => 1,
+ mtime => 1,
+ hash => 'abc',
+ },
+ );
+ } 'path info';
+
+ try_ok {
+ ok $ds->update_episode_info(
+ {
+ size => 1,
+ hash => 'abc',
+ },
+ { random => 'info', aid => 5 },
+ );
+ } 'episode info';
+
+ try_ok {
+ ok $ds->update_anime_info(
+ { aid => 5 },
+ { more => 'random' },
+ );
+ } 'anime info';
+};
+
+subtest 'update data' => sub {
+ try_ok {
+ ok $ds->update_path_info(
+ $test_file => {
+ size => 3,
+ mtime => 5,
+ hash => 'abc',
+ },
+ );
+ } 'path info';
+
+ try_ok {
+ ok $ds->update_episode_info(
+ {
+ size => 3,
+ hash => 'abc',
+ },
+ { random => 'new-info', aid => 5 },
+ );
+ } 'episode info';
+
+ try_ok {
+ ok $ds->update_anime_info(
+ { aid => 5 },
+ { more => 'new-random' },
+ );
+ } 'anime info';
+};
+
+subtest 'retrieve data' => sub {
+ is(
+ $ds->path_info_for($test_file),
+ my $path_info = {
+ name => $test_file->stringify,
+ size => 3,
+ mtime => 5,
+ hash => 'abc',
+
+ },
+ 'path info',
+ );
+
+ is(
+ $ds->episode_info_for({size=>3,hash=>'abc'}),
+ my $episode_info ={ random => 'new-info', aid => 5 },
+ 'episode info',
+ );
+
+ is(
+ $ds->anime_info_for({ aid => 5 }),
+ my $anime_info = { more => 'new-random' },
+ 'anime info',
+ );
+
+ is(
+ $ds->full_info_for($test_file),
+ {
+ path => $path_info,
+ episode => $episode_info,
+ anime => $anime_info,
+ },
+ 'full info',
+ );
+};
+
+subtest 'changed' => sub {
+ ok $ds->has_changed($test_file,$stat);
+
+ $ds->update_path_info(
+ $test_file => {
+ size => $stat->size,
+ mtime => $stat->mtime,
+ hash => 'abcd',
+ },
+ );
+
+ ok not $ds->has_changed($test_file,$stat);
+};
+
+subtest 'rename' => sub {
+ my $new_name = path('/tmp/another');
+ $ds->rename($test_file,$new_name);
+ is(
+ $ds->path_info_for($new_name),
+ {
+ name => $new_name->stringify,
+ size => $stat->size,
+ mtime => $stat->mtime,
+ hash => 'abcd',
+ },
+ 'path info',
+ );
+};
+
+done_testing;
+
+