__PACKAGE__->mk_classdata('__journal_schema_prototype');
__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;
my $c = blessed($self)||$self;
my $journal_schema_class = "${c}::_JOURNAL";
Class::C3::Componentised->inject_base($journal_schema_class, 'DBIx::Class::Schema::Journal::DB');
+ $journal_schema_class->load_components($self->journal_components)
+ if $self->journal_components;
my $proto = $self->__journal_schema_prototype (
$journal_schema_class->compose_namespace( $c.'::Journal')
);
+
+
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}
return $schema;
}
-sub deploy {
- my $self = shift;
-
- $self->next::method(@_);
-
- $self->journal_schema_deploy(@_);
-}
-
sub journal_schema_deploy {
my $self = shift;
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);
}
}
+# 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++,
+ })
+ ) {
+ # 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) = @_;
$self->_journal_schema->current_session($sessionid);
}
-
1;