Seperate DBIC Storage Engine
Mugen Kenichi [Tue, 27 Sep 2011 11:11:40 +0000 (13:11 +0200)]
lib/Email/Archive/Storage/DBI.pm
lib/Email/Archive/Storage/DBIC.pm [new file with mode: 0644]
lib/Email/Archive/Storage/DBIC/Schema.pm [moved from lib/Email/Archive/Schema.pm with 100% similarity]
lib/Email/Archive/Storage/DBIC/Schema/Result/Messages.pm [moved from lib/Email/Archive/Schema/Result/Messages.pm with 100% similarity]
lib/Email/Archive/Storage/DBIC/Schema/Result/Metadata.pm [moved from lib/Email/Archive/Schema/Result/Metadata.pm with 100% similarity]

index 1dcf8a7..3ee81f6 100644 (file)
 package Email::Archive::Storage::DBI;
 use Moo;
 use Carp;
+use DBI;
+use File::ShareDir 'module_file';
+use File::Slurp 'read_file';
 use Email::MIME;
 use Email::Abstract;
-use Email::Archive::Schema;
+use SQL::Abstract;
+use Scalar::Util qw(looks_like_number);
 use autodie;
-use Try::Tiny;
 with q/Email::Archive::Storage/;
 
-has schema => (
-  is => 'rw',
+has sqla => (
+  is   => 'ro',
+  isa  => sub { 
+    ref $_[0] eq 'SQL::Abstract' or die "sqla must be a SQL::Abstract object" 
+  },
+  lazy => 1,
+  default => sub { SQL::Abstract->new },
+  handles => [qw/
+    select
+    insert
+  /],
+);
+
+has dbh => (
+  is   => 'rw',
+  isa  => sub { 
+    ref $_[0] eq 'DBI::db' or die "dbh must be a DBI handle",
+  },
+  handles => [qw/
+    prepare
+    do
+  /],
+);
+
+has deployed_schema_version => (
+  is  => 'rw',
   isa => sub {
-    ref $_[0] eq 'Email::Archive::Schema' or die "schema must be a Email::Archive schema",
+    looks_like_number($_[0]) or die "deployed_schema_version must be integer"
   },
+  default => 0,
 );
 
+
+my $SCHEMA_VERSION = 1;
+
 sub store {
   my ($self, $email) = @_;
+  # passing an E::A to E::A->new is perfectly valid
   $email = Email::Abstract->new($email);
-  $self->schema->resultset('Messages')->update_or_create({
-    message_id => $email->get_header('Message-ID'),
-    from_addr  => $email->get_header('From'),
-    to_addr    => $email->get_header('To'),
-    date       => $email->get_header('Date'),
-    subject    => $email->get_header('Subject'),
-    body       => $email->get_body,
-  });
+  my $fields = {
+    from_addr   => $email->get_header('From'),
+    to_addr     => $email->get_header('To'),
+    date        => $email->get_header('Date'),
+    subject     => $email->get_header('Subject'),
+    message_id  => $email->get_header('Message-ID'),
+    body        => $email->get_body,
+  };
+  my ($sql, @bind) = $self->insert('messages', $fields);
+  my $sth = $self->prepare($sql);
+  $sth->execute(@bind);
 }
 
 sub search {
-  my ($self, $attribs) = @_;
-  my $message = $self->schema
-                  ->resultset('Messages')
-                  ->find($attribs);
+  my ($self, $attribs) = shift;
+  my ($sql, @bind) = $self->select('messages', [qw/message_id from_addr to_addr date subject body/], $attribs);
+  my $sth = $self->prepare($sql);
+  $sth->execute(@bind);
+  my ($message) = $sth->fetchrow_hashref;
   return Email::MIME->create(
     header => [
-      From    => $message->from_addr,
-      To      => $message->to_addr,
-      Subject => $message->subject,
+      From    => $message->{from_addr},
+      To      => $message->{to_addr},
+      Subject => $message->{subject},
     ],
-    body => $message->body,
+    body => $message->{body},
   );
 }
 
 sub retrieve {
-  my ($self, $message_id) = @_;
-  $self->search({ message_id => $message_id });
+  my ($self, $message_id) = shift;
+  $self->search({message_id => $message_id});
 }
 
 sub _deploy {
   my ($self) = @_;
-  $self->schema->deploy;
+  my $schema = module_file('Email::Archive::Storage::DBI', 'latest_schema.txt');
+  my $sql = read_file($schema);
+  $self->do($sql);
 }
 
 sub _deployed {
   my ($self) = @_;
-  my $deployed = 1;
-  try {
-      # naive check if table metadata exists
-      $self->schema->resultset('Metadata')->all;
+  my $schema_version = eval { $self->selectcol_array('SELECT schema_version FROM metadata') };
+  if(defined $schema_version and $schema_version =~ /^\d+$/) {
+    $self->deployed_schema_version($schema_version);
+    return $schema_version =~ /^\d+$/;
   }
-  catch {
-      $deployed = 0;
-  };
-
-  return $deployed;
 }
 
-sub storage_connect_dbic {
+sub storage_connect {
   my ($self, $dsn) = @_;
-  $self->schema(Email::Archive::Schema->connect($dsn));
-  my $deployed = $self->_deployed;
-  $self->_deploy unless $deployed;
+  $self->dbh(DBI->connect($dsn));
+  if(!$self->_deployed) {
+    $self->_deploy;
+  }
+  elsif(!$self->_is_latest_schema) {
+    croak sprintf "Schema version %d not supported; we support version " .
+                  "$SCHEMA_VERSION. Please upgrade your schema before "  .
+                  "continuing.", $self->_deployed_schema_version;
+  }
 }
 
 1;
-
diff --git a/lib/Email/Archive/Storage/DBIC.pm b/lib/Email/Archive/Storage/DBIC.pm
new file mode 100644 (file)
index 0000000..1dcf8a7
--- /dev/null
@@ -0,0 +1,78 @@
+package Email::Archive::Storage::DBI;
+use Moo;
+use Carp;
+use Email::MIME;
+use Email::Abstract;
+use Email::Archive::Schema;
+use autodie;
+use Try::Tiny;
+with q/Email::Archive::Storage/;
+
+has schema => (
+  is => 'rw',
+  isa => sub {
+    ref $_[0] eq 'Email::Archive::Schema' or die "schema must be a Email::Archive schema",
+  },
+);
+
+sub store {
+  my ($self, $email) = @_;
+  $email = Email::Abstract->new($email);
+  $self->schema->resultset('Messages')->update_or_create({
+    message_id => $email->get_header('Message-ID'),
+    from_addr  => $email->get_header('From'),
+    to_addr    => $email->get_header('To'),
+    date       => $email->get_header('Date'),
+    subject    => $email->get_header('Subject'),
+    body       => $email->get_body,
+  });
+}
+
+sub search {
+  my ($self, $attribs) = @_;
+  my $message = $self->schema
+                  ->resultset('Messages')
+                  ->find($attribs);
+  return Email::MIME->create(
+    header => [
+      From    => $message->from_addr,
+      To      => $message->to_addr,
+      Subject => $message->subject,
+    ],
+    body => $message->body,
+  );
+}
+
+sub retrieve {
+  my ($self, $message_id) = @_;
+  $self->search({ message_id => $message_id });
+}
+
+sub _deploy {
+  my ($self) = @_;
+  $self->schema->deploy;
+}
+
+sub _deployed {
+  my ($self) = @_;
+  my $deployed = 1;
+  try {
+      # naive check if table metadata exists
+      $self->schema->resultset('Metadata')->all;
+  }
+  catch {
+      $deployed = 0;
+  };
+
+  return $deployed;
+}
+
+sub storage_connect_dbic {
+  my ($self, $dsn) = @_;
+  $self->schema(Email::Archive::Schema->connect($dsn));
+  my $deployed = $self->_deployed;
+  $self->_deploy unless $deployed;
+}
+
+1;
+