[Bast-commits] r3936 - in DBIx-Class-Partitioned/1.000/trunk: lib/DBIx/Class t t/lib/My/Schema

edenc at dev.catalyst.perl.org edenc at dev.catalyst.perl.org
Tue Jan 15 14:48:39 GMT 2008


Author: edenc
Date: 2008-01-15 14:48:39 +0000 (Tue, 15 Jan 2008)
New Revision: 3936

Removed:
   DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/InactiveUser.pm
Modified:
   DBIx-Class-Partitioned/1.000/trunk/lib/DBIx/Class/Partitioned.pm
   DBIx-Class-Partitioned/1.000/trunk/t/01-basic.t
   DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/User.pm
   DBIx-Class-Partitioned/1.000/trunk/t/test.db
Log:
partitions simulating materialized view

Modified: DBIx-Class-Partitioned/1.000/trunk/lib/DBIx/Class/Partitioned.pm
===================================================================
--- DBIx-Class-Partitioned/1.000/trunk/lib/DBIx/Class/Partitioned.pm	2008-01-14 13:25:00 UTC (rev 3935)
+++ DBIx-Class-Partitioned/1.000/trunk/lib/DBIx/Class/Partitioned.pm	2008-01-15 14:48:39 UTC (rev 3936)
@@ -3,7 +3,6 @@
 use warnings;
 use strict;
 use base qw/DBIx::Class/;
-use Data::Dump;
 
 =head1 NAME
 
@@ -24,31 +23,29 @@
     use base qw/DBIx::Class/;
 
     __PACKAGE__->load_components(qw/Partitioned Core/);
-    __PACKAGE__->partitions(qw/active_user inactive_user/);
+    __PACKAGE__->table('user');
+    __PACKAGE__->partitions(qw/active_user/);
     __PACKAGE__->add_columns(qw/id foo is_expired/);
-    __PACKAGE__->select_partition_via('is_active');
 
-    sub is_active { shift->is_expired ? 'active_user' : 'inactive_user' }
+    sub is_active { return 'active_user' if !shift->is_expired; return }
 
     # meanwhile in a nearby piece of code...
 
     my $user_rs = $schema->resultset('User');
-    my @rows = $user_rs->all; # selects rows from active_user and inactive_user
-    $user_rs->create({ foo => 'bar', is_active => 1 }); # inserts to active_user
-    $user_rs->create({ foo => 'baz', is_active => 0 }); # inserts to inactive_user
+    $user_rs->search_partition('active_user');
+    my @rows = $user_rs->all; # selects rows from active_user
+    $user_rs->create({ foo => 'bar', is_active => 1 }); # inserts to active_user and user
 
 =cut
 
 __PACKAGE__->mk_classdata('_partitions');
-__PACKAGE__->mk_classdata('ident_rel');
+__PACKAGE__->mk_group_accessors(
+    'simple' => qw/_current_partition is_partition_row/ );
 
 sub partitions {
     my ( $class, @parts ) = @_;
     $class->_partitions( {} );
-    my $union =
-      '(' . join( ' UNION ALL ', map { "SELECT * FROM $_" } @parts ) . ')';
     my $source = $class->result_source_instance;
-    $source->name( \$union );
     foreach my $partition (@parts) {
         my $new_source = $source->new($source);
         my $new_source_name = join '::', map { ucfirst } split '_', $partition;
@@ -56,6 +53,7 @@
         $new_source->name($partition);
         foreach my $rel_name ( $source->relationships ) {
             my $rel_info = $source->relationship_info($rel_name);
+            $rel_info->{attrs}{cascade_delete} = 0;
             $new_source->add_relationship( $rel_name,
                 @{$rel_info}{qw/source cond attrs/} );
         }
@@ -81,51 +79,92 @@
     return;
 }
 
-sub set_partition_source {
-    my ($self) = @_;
-    my $partition_name = $self->_partition_name;
-    $self->result_source( $self->partition($partition_name) );
-}
-
 sub new {
     my $class = shift;
     my $self  = $class->next::method(@_);
-    my $ident_source_name =
-      $self->relationship_info( $self->ident_rel )->{source};
-    my $ident_source = $self->result_source->schema->source($ident_source_name);
-    my $ident_row =
-      $self->create_related( $self->ident_rel,
-        { map { $_ => undef } $ident_source->columns } );
-    $ident_row->discard_changes;
-    my %pks = $ident_row->get_columns;
-    $self->$_( $pks{$_} ) for keys %pks;
-    $self->set_partition_source;
+    if ( my $partition_name = $self->_partition_name ) {
+        $self->_current_partition($partition_name);
+    }
     return $self;
 }
 
 sub inflate_result {
-    my $self = shift->next::method(@_);
-    $self->set_partition_source;
+    my $class = shift;
+    my $self  = $class->next::method(@_);
+    if ( my $partition_name = $self->_partition_name ) {
+        $self->_current_partition($partition_name);
+    }
     return $self;
 }
 
+sub insert {
+    my $self = shift;
+    if (   !$self->in_storage
+        && !$self->is_partition_row
+        && ( my $part = $self->_partition_name ) )
+    {
+        my $partition = $self->partition($part)
+          or confess("couldn't find partition '${part}'");
+        my $row = $partition->resultset->new_result( { $self->get_columns } );
+        $row->is_partition_row(1);
+        $row->insert;
+        $self->_current_partition($part);
+    }
+    return $self->next::method(@_);
+}
+
 sub update {
-    my $self          = shift;
-    my $old_partition = $self->result_source;
-    $self->set_partition_source;
-    my $new_partition = $self->result_source;
-    if ( $new_partition->source_name ne $old_partition->source_name ) {
-        $self->result_source($old_partition);
-        $self->delete;
-        $self->result_source($new_partition);
-        $self->insert;
+    my $self = shift;
+    $self->next::method(@_);
+    my $old_part = $self->_current_partition;
+    my $new_part = $self->_partition_name;
+
+    if ( $old_part && $new_part ) {
+        my $part_row =
+          $self->partition($old_part)
+          ->resultset->find( { $self->get_columns } );
+        if ( $old_part ne $new_part ) {
+            $part_row->delete;
+            my $row =
+              $self->partition($new_part)
+              ->resultset->new_result( { $self->get_columns } );
+            $row->is_partition_row(1);
+            $row->insert;
+            $self->_current_partition($new_part);
+        }
+        else {
+            $part_row->set_columns( { $self->get_columns } );
+            $part_row->update;
+        }
     }
-    else {
-        $self->next::method(@_);
+    elsif ( !$old_part && $new_part ) {
+        my $row =
+          $self->partition($new_part)
+          ->resultset->new_result( { $self->get_columns } );
+        $row->is_partition_row(1);
+        $row->insert;
+        $self->_current_partition($new_part);
     }
+    elsif ( $old_part && !$new_part ) {
+        my $row = $self->partition($old_part)->resultset->find( { $self->get_columns } );
+        $row->is_partition_row(1);
+        $row->delete;
+        $self->_current_partition('');
+    }
     return $self;
 }
 
+sub delete {
+    my $self = shift;
+    $self->next::method(@_);
+    if ( my $part = $self->_current_partition && !$self->is_partition_row) {
+        $self->partition($part)->resultset->find( { $self->get_columns } )
+          ->delete;
+        $self->_current_partition('');
+    }
+    return $self;
+}
+
 =head1 AUTHOR
 
 Eden Cardim, C<< <edenc at shadowcatsystems.co.uk> >>

Modified: DBIx-Class-Partitioned/1.000/trunk/t/01-basic.t
===================================================================
--- DBIx-Class-Partitioned/1.000/trunk/t/01-basic.t	2008-01-14 13:25:00 UTC (rev 3935)
+++ DBIx-Class-Partitioned/1.000/trunk/t/01-basic.t	2008-01-15 14:48:39 UTC (rev 3936)
@@ -7,6 +7,7 @@
 my $schema = My::Schema->connect('dbi:SQLite:dbname=t/test.db');
 my $test   = sub {
     my $user_rs = $schema->resultset('User');
+    $user_rs->partition( 'active_user' );
     my $data = { foo => 'bar', is_expired => 0 };
     isa_ok( my $user = $user_rs->create($data), 'My::Schema::User' );
     $user->add_to_affiliations( { name => 'foo' } );
@@ -24,12 +25,9 @@
     is( $user->posts->first->content,      'bar' );
 
     $data->{is_expired} = 1;
-    isa_ok( $user_rs->create($data), 'My::Schema::User' );
-    row_fields_equal(
-        $user = $user_rs->search($data)->single,
-        $schema->resultset('InactiveUser')->search($data)->single,
-        [qw/id foo is_expired/]
-    );
+    isa_ok( $user = $user_rs->create($data), 'My::Schema::User' );
+    ok( !$schema->resultset('ActiveUser')->search( { $user->get_columns } )
+          ->count );
     $user->add_to_affiliations( $schema->resultset('Affiliation')->first );
     $user->add_to_posts( { title => 'foo', content => 'bar' } );
     is( $user->affiliations->first->name, 'foo' );
@@ -39,11 +37,13 @@
     $user->update;
     ok( $schema->resultset('ActiveUser')->search( { $user->get_columns } )
           ->count );
-    ok( !$schema->resultset('InactiveUser')->search( { $user->get_columns } )
-          ->count );
     is( $user->affiliations->first->name, 'foo' );
     is( $user->posts->first->title,       'foo' );
     is( $user->posts->first->content,     'bar' );
+    $user->is_expired(1);
+    $user->update;
+    ok( !$schema->resultset('ActiveUser')->search( { $user->get_columns } )
+          ->count );
     die 'rollback';
 };
 eval { $schema->txn_do($test) };
@@ -54,6 +54,6 @@
     ok($row1);
     ok($row2);
     foreach my $field (@$fields) {
-        is( $row1->$field, $row2->$field );
+        is( $row1->$field, $row2->$field, "$field: " . $row1->$field );
     }
 }

Deleted: DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/InactiveUser.pm
===================================================================
--- DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/InactiveUser.pm	2008-01-14 13:25:00 UTC (rev 3935)
+++ DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/InactiveUser.pm	2008-01-15 14:48:39 UTC (rev 3936)
@@ -1,23 +0,0 @@
-package My::Schema::InactiveUser;
-
-use warnings;
-use strict;
-
-use base qw/DBIx::Class/;
-
-__PACKAGE__->load_components(qw/Core/);
-__PACKAGE__->table('inactive_user');
-
-__PACKAGE__->add_column(
-    id => { is_auto_increment => 1, data_type => 'integer' } );
-__PACKAGE__->add_columns(qw/foo is_expired/);
-__PACKAGE__->set_primary_key('id');
-
-__PACKAGE__->has_many( 'posts', 'Post', { 'foreign.user_id' => 'self.id' } );
-
-__PACKAGE__->has_many( 'user_affiliations',
-    'UserAffiliation' => { 'foreign.user_id' => 'self.id' } );
-
-__PACKAGE__->many_to_many( 'affiliations', 'user_affiliations', 'affiliation' );
-
-1;

Modified: DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/User.pm
===================================================================
--- DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/User.pm	2008-01-14 13:25:00 UTC (rev 3935)
+++ DBIx-Class-Partitioned/1.000/trunk/t/lib/My/Schema/User.pm	2008-01-15 14:48:39 UTC (rev 3936)
@@ -12,31 +12,49 @@
 __PACKAGE__->add_columns(qw/foo is_expired/);
 __PACKAGE__->set_primary_key('id');
 
-__PACKAGE__->has_one(
-    'user_ident',
-    'UserIdent' => { 'foreign.id' => 'self.id' },
-    { cascade_delete => 0 }
-);
+__PACKAGE__->has_many( 'posts', 'Post' => { 'foreign.user_id' => 'self.id' } );
 
-__PACKAGE__->has_many(
-    'posts',
-    'Post' => { 'foreign.user_id' => 'self.id' },
-    { cascade_delete => 0 }
-);
+__PACKAGE__->has_many( 'user_affiliations',
+    'UserAffiliation' => { 'foreign.user_id' => 'self.id' } );
 
-__PACKAGE__->has_many(
-    'user_affiliations',
-    'UserAffiliation' => { 'foreign.user_id' => 'self.id' },
-    { cascade_delete => 0 }
-);
-
 __PACKAGE__->many_to_many( 'affiliations', 'user_affiliations', 'affiliation' );
 
-__PACKAGE__->partitions(qw/inactive_user active_user/);
-__PACKAGE__->ident_rel('user_ident');
+__PACKAGE__->partitions(qw/active_user/);
 
 sub _partition_name {
-    return shift->is_expired ? 'inactive_user' : 'active_user';
+    return 'active_user' if !shift->is_expired;
+    return;
 }
 
+__PACKAGE__->resultset_class('My::ResultSet::User');
+
+package My::ResultSet::User;
+
+use warnings;
+use strict;
+
+use base qw/DBIx::Class::ResultSet/;
+
+__PACKAGE__->mk_group_accessors( 'simple' => qw/partition/ );
+
+sub search_rs {
+    my $self = shift;
+    my $new  = $self->next::method(@_);
+    $new->partition( $self->partition );
+    return $new;
+}
+
+sub cursor {
+    my $self = shift;
+    if ( $self->partition ) {
+        my $source = $self->result_source;
+        $self->result_source(
+            $self->result_class->partition( $self->partition ) );
+        my $cursor = $self->next::method(@_);
+        $self->result_source($source);
+        return $cursor;
+    }
+    return $self->next::method(@_);
+}
+
 1;

Modified: DBIx-Class-Partitioned/1.000/trunk/t/test.db
===================================================================
(Binary files differ)




More information about the Bast-commits mailing list