should use hashrefinflator
[dbsrgits/DBIx-Class-Journal.git] / lib / DBIx / Class / Schema / Journal.pm
index 46ced86..7d8aa60 100644 (file)
@@ -17,10 +17,12 @@ __PACKAGE__->mk_classdata('_journal_schema'); ## schema object for journal
 __PACKAGE__->mk_classdata('journal_component');
 __PACKAGE__->mk_classdata('journal_components');
 __PACKAGE__->mk_classdata('journal_nested_changesets');
+__PACKAGE__->mk_classdata('journal_prefix');
 
 use strict;
 use warnings;
 
+our $VERSION = '0.01';
 
 sub _journal_schema_prototype {
     my $self = shift;
@@ -39,6 +41,20 @@ sub _journal_schema_prototype {
 
     my $comp = $self->journal_component || "Journal";
 
+    my $prefix = $self->journal_prefix || '';
+    foreach my $audit (qw(ChangeSet ChangeLog)) {
+        my $class = blessed($proto) . "::$audit";
+
+        Class::C3::Componentised->inject_base($class, "DBIx::Class::Schema::Journal::DB::$audit");
+
+        $class->journal_define_table(blessed($proto), $prefix);
+
+        $proto->register_class($audit, $class);
+
+        $self->register_class($audit, $class)
+            if $self->journal_copy_sources;
+    }
+
     ## Create auditlog+history per table
     my %j_sources = map { $_ => 1 } $self->journal_sources
        ? @{$self->journal_sources}
@@ -89,14 +105,6 @@ sub connection {
     return $schema;
 }
 
-sub deploy {
-    my $self = shift;
-
-    $self->next::method(@_);
-
-    $self->journal_schema_deploy(@_);
-}
-
 sub journal_schema_deploy {
     my $self = shift;
 
@@ -114,7 +122,7 @@ sub create_journal_for {
 
         Class::C3::Componentised->inject_base($class, "DBIx::Class::Schema::Journal::DB::$audit");
 
-        $class->journal_define_table($source);
+        $class->journal_define_table($source, blessed($journal_schema));
 
         $journal_schema->register_class($audit_source, $class);
 
@@ -123,6 +131,79 @@ sub create_journal_for {
     }
 }
 
+# XXX FIXME deploy is not idempotent :-(
+sub bootstrap_journal {
+    my $self = shift;
+    $self->journal_schema_deploy;
+    $self->prepopulate_journal;
+}
+
+# copy data from original schema sources into the journal as inserts in one
+# changeset, so that later deletes will not fail to be journalled.
+sub prepopulate_journal {
+    my $self = shift;
+    my $schema = $self;
+
+    # woah, looks like prepopulate has already run?
+    return if $schema->_journal_schema->resultset('ChangeSet')->count != 0;
+
+    # using our own overridden txn_do (see below) will create a changeset
+    $schema->txn_do( sub {
+        my %j_sources = map { $_ => 1 } $self->journal_sources
+        ? @{$self->journal_sources}
+        : $self->sources;
+
+        my $j_schema = $self->_journal_schema;
+        my $changelog_rs = $j_schema->resultset('ChangeLog');
+        my $chs_id = $j_schema->current_changeset;
+
+        foreach my $s_name ($self->sources) {
+            next unless $j_sources{$s_name};
+
+            my $from_rs = $schema->resultset($s_name);
+            my @pks = $from_rs->result_source->primary_columns;
+            $from_rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
+
+            my $to_rs  = $j_schema->resultset("${s_name}AuditHistory");
+            my $log_rs = $j_schema->resultset("${s_name}AuditLog");
+
+            my $page = 1;
+            while (
+                my @x = $from_rs->search(undef, {
+                    rows => 1_000,
+                    page => $page++,
+                    result_class => 'DBIx::Class::ResultClass::HashRefInflator',
+                })
+            ) {
+                # get some number of change log IDs to be generated for this page
+                my @log_ids = map $_->id,
+                   $changelog_rs->populate([
+                       map +{ changeset_id => $chs_id }, (0 .. $#x)
+                   ]);
+
+
+                my @datas;
+                for my $idx (0 .. $#x ) {
+                   push @datas, {
+                       create_id => $log_ids[$idx],
+                       map { $_ => $x[$idx]->{$_} } @pks,
+                   }
+                }
+                # create the audit log entries for the rows in this page
+                $log_rs->populate([@datas]);
+
+                # now populate the audit history
+                $to_rs->populate([
+                    map +{
+                        %{$x[$_]},
+                        audit_change_id => $log_ids[$_],
+                    }, (0 .. $#x)
+                ]);
+            }
+        }
+    });
+}
+
 sub txn_do {
     my ($self, $user_code, @args) = @_;
 
@@ -175,5 +256,4 @@ sub changeset_session {
     $self->_journal_schema->current_session($sessionid);
 }
 
-
 1;