[Rt-commit] rt branch, 4.2/optimize-cgm-table, updated. rt-4.0.0rc7-269-gc44ea57
Ruslan Zakirov
ruz at bestpractical.com
Wed Mar 21 12:12:24 EDT 2012
The branch, 4.2/optimize-cgm-table has been updated
via c44ea579cb333032708663e0eb3712d47917e4e4 (commit)
via aa2388585f55474fd0ae288396c503a040c97255 (commit)
from df50bf2b38e2cb90537fd43daa73769c17800426 (commit)
Summary of changes:
lib/RT/CachedGroupMember.pm | 74 +++++++++++++++---------
t/api/group_members.t | 133 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 176 insertions(+), 31 deletions(-)
- Log -----------------------------------------------------------------
commit aa2388585f55474fd0ae288396c503a040c97255
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Mar 21 20:10:47 2012 +0400
test Disabled column in CGM table
diff --git a/t/api/group_members.t b/t/api/group_members.t
index 268b864..b85e0dc 100644
--- a/t/api/group_members.t
+++ b/t/api/group_members.t
@@ -1,7 +1,7 @@
use strict;
use warnings;
-use RT::Test nodata => 1, tests => 38;
+use RT::Test nodata => 1, tests => 376;
my %GROUP;
foreach my $name (qw(A B C D)) {
@@ -17,6 +17,8 @@ foreach my $name (qw(a b c d)) {
ok $status, "created an user '$name'" or diag "error: $msg";
}
+my %DISABLED;
+
{
add_members_ok( A => qw(a b c) );
check_membership( A => [qw(a b c)] );
@@ -62,16 +64,73 @@ foreach my $name (qw(a b c d)) {
random_delete( A => [qw(B C)], B => [qw(d)], C => [qw(d)] );
}
-for (1..5) {
+for (1..3) {
random_delete( random_build() );
}
+{
+# variations of ruby:
+# A
+# / | \
+# B | C
+# \ | /
+# D
+ add_members_ok( A => qw(B C) );
+ add_members_ok( B => qw(D) );
+ add_members_ok( C => qw(D) );
+
+ # disable B with A -> C -> D active alternative for A->D
+ disable_group_ok( 'B' );
+ check_cgm_activity( A => [qw(B C)], B => [qw(D)], C => [qw(D)] );
+
+ # disable C, no more active alternative for A->D
+ disable_group_ok( 'C' );
+ check_cgm_activity( A => [qw(B C)], B => [qw(D)], C => [qw(D)] );
+
+ # add direct active (A->D) link
+ add_members_ok( A => qw(D) );
+ check_cgm_activity( A => [qw(B C D)], B => [qw(D)], C => [qw(D)] );
+
+ # delete active (A->D) when all alternative are disabled
+ del_members_ok( A => 'D' );
+ check_cgm_activity( A => [qw(B C)], B => [qw(D)], C => [qw(D)] );
+
+ # enable C that enables A->D
+ enable_group_ok( 'C' );
+ check_cgm_activity( A => [qw(B C)], B => [qw(D)], C => [qw(D)] );
+
+ # delete (A->B) and add back, B is disabled
+ del_members_ok( A => 'B' );
+ add_members_ok( A => qw(B) );
+ check_cgm_activity( A => [qw(B C)], B => [qw(D)], C => [qw(D)] );
+
+ random_delete( A => [qw(B C)], B => [qw(D)], C => [qw(D)] );
+
+ enable_group_ok( 'B' );
+}
+
+{
+# variations of triangle
+# A
+# / \
+# B -> C
+ add_members_ok( A => qw(B C) );
+ disable_group_ok( 'B' );
+
+ # add member to disabled group
+ add_members_ok( B => qw(C) );
+ check_cgm_activity( A => [qw(B C)], B => [qw(C)] );
+
+ random_delete( A => [qw(B C)], B => [qw(C)] );
+ enable_group_ok( 'B' );
+}
+
sub random_build {
my (%GM, %RCGM);
my @groups = keys %GROUP;
- my $i = 12;
+ my $i = 9;
while ( $i-- ) {
REPICK:
my $g = $groups[int rand @groups];
@@ -97,7 +156,6 @@ sub random_build {
push @{ $GM{ $g }||=[] }, $m;
unless ( check_membership( %GM ) ) {
Test::More::diag("were adding $error") unless $ENV{'TEST_VERBOSE'};
- exit 1;
}
%RCGM = reverse_gm( gm_to_cgm(%GM) );
@@ -140,6 +198,7 @@ sub check_membership {
my $res = _check_membership( HasMember => %GM );
my %CGM = gm_to_cgm(%GM);
$res &&= _check_membership( HasMemberRecursively => %CGM );
+ $res &&= check_cgm_activity( %GM );
return $res;
}
@@ -157,6 +216,22 @@ sub gm_to_cgm {
return %CGM;
}
+sub gm_to_activity {
+ my %GM = @_;
+
+ my $flat;
+ $flat = sub {
+ return if $DISABLED{ $_[0] };
+ my @self_ref = $GROUP{$_[0]} && !$DISABLED{$_[0]}? ($_[0]) : ();
+ return @self_ref unless $GM{ $_[0] };
+ return @self_ref, map { $_, $flat->($_) } @{ $GM{ $_[0] } };
+ };
+
+ my %CGM;
+ $CGM{ $_ } = [ $flat->( $_ ) ] foreach keys %GROUP;
+ return %CGM;
+}
+
sub reverse_gm {
my %GM = @_;
my %res = @_;
@@ -167,6 +242,43 @@ sub reverse_gm {
return %res;
}
+sub check_cgm_activity {
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ my %GM = @_;
+
+ my $id_to_name = sub {
+ my $p = RT::Principal->new( RT->SystemUser );
+ $p->Load($_[0]);
+ $p->Object->Name;
+ };
+
+ my $data = $RT::Handle->dbh->selectall_arrayref(
+ "SELECT GroupId, MemberId FROM CachedGroupMembers WHERE Disabled = 0"
+ .' AND GroupId IN ('. join( ', ', map $_->id, values %GROUP, values %USER ) .')'
+ .' AND MemberId IN ('. join( ', ', map $_->id, values %GROUP, values %USER ) .')'
+ );
+
+ my %got;
+ foreach (@$data) {
+ my ($g, $m) = (map $id_to_name->($_), @$_);
+ push @{ $got{$g} ||= []}, $m;
+ }
+
+ my %expected = gm_to_activity( %GM );
+
+ foreach my $hash (\%got, \%expected) {
+ foreach ( values %$hash ) {
+ my %seen;
+ @$_ = sort grep !$seen{$_}++, @$_;
+ }
+ delete $hash->{$_} foreach grep !@{$hash->{$_}}, keys %$hash;
+ }
+ use Data::Dumper;
+ is_deeply(\%got, \%expected, 'activity of the records is correct')
+ or diag Dumper( \%got, \%expected );
+}
+
sub _check_membership {
local $Test::Builder::Level = $Test::Builder::Level + 1;
@@ -258,6 +370,19 @@ sub dump_gm {
$anc_des_pairs->($G, $M);
}
+sub disable_group_ok {
+ my $g = shift;
+ my ($status, $msg) = $GROUP{ $g }->SetDisabled(1);
+ ok $status, "disabled group '$g'" or diag "error: $msg";
+ $DISABLED{$g} = $GROUP{ $g }->Disabled;
+}
+sub enable_group_ok {
+ my $g = shift;
+ my ($status, $msg) = $GROUP{ $g }->SetDisabled(0);
+ ok $status, "enabled group '$g'" or diag "error: $msg";
+ $DISABLED{$g} = $GROUP{ $g }->Disabled;
+}
+
sub substract_list {
my $list = shift;
foreach my $e ( @_ ) {
commit c44ea579cb333032708663e0eb3712d47917e4e4
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Wed Mar 21 20:11:36 2012 +0400
fix Disabled column handling
diff --git a/lib/RT/CachedGroupMember.pm b/lib/RT/CachedGroupMember.pm
index b27cddb..7cefb92 100644
--- a/lib/RT/CachedGroupMember.pm
+++ b/lib/RT/CachedGroupMember.pm
@@ -292,7 +292,7 @@ sub Delete {
);
return $res unless $res;
- if ( $res > 1 && $member_is_group ) {
+ if ( $res > 0 && $member_is_group ) {
$query =
"SELECT main.id
FROM $table main
@@ -311,16 +311,34 @@ sub Delete {
AND main.MemberId = CGMD.MemberId
AND main.Disabled = 1
";
- $RT::Handle->SimpleUpdateFromSelect(
- $table, { Disabled => 0 }, $query,
- $self->GroupId,
- $self->MemberId,
- );
- return $res unless $res;
}
- elsif ( $res > 1 ) {
-
+ elsif ( $res > 0 ) {
+ $query =
+ "SELECT main.id
+ FROM $table main
+ JOIN $table CGMA ON CGMA.MemberId = ?
+
+ JOIN $table CGM3 ON CGM3.GroupId != CGM3.MemberId
+ AND CGM3.GroupId = main.GroupId
+ AND CGM3.Disabled = 0
+ JOIN $table CGM4 ON CGM4.GroupId != CGM4.MemberId
+ AND CGM4.MemberId = main.MemberId
+ AND CGM4.Disabled = 0
+ AND CGM3.MemberId = CGM4.GroupId
+ WHERE
+ main.GroupId = CGMA.GroupId
+ AND main.MemberId = ?
+ AND main.Disabled = 1
+ ";
}
+
+ $res = $RT::Handle->SimpleUpdateFromSelect(
+ $table, { Disabled => 0 }, $query,
+ $self->GroupId,
+ $self->MemberId,
+ ) if $res > 0;
+ return $res unless $res;
+
if ( my $m = $self->can('_FlushKeyCache') ) { $m->($self) };
return 1;
@@ -349,35 +367,36 @@ sub SetDisabled {
}
my $query = "SELECT main.id FROM CachedGroupMembers main
- JOIN CachedGroupMembers CGM1 ON main.GroupId = CGM1.GroupId
- AND CGM1.MemberId = ?
- AND CGM1.Disabled = 0
- JOIN CachedGroupMembers CGM2 ON main.MemberId = CGM2.MemberId
- AND CGM2.GroupId = ?
- WHERE main.Disabled = 0";
+ WHERE main.Disabled = 0 AND main.GroupId = ?";
$RT::Handle->SimpleUpdateFromSelect(
$self->Table, { Disabled => 1 }, $query,
- ($self->GroupId)x2,
+ $self->GroupId,
) or return undef;
$query = "SELECT main.id FROM CachedGroupMembers main
JOIN CachedGroupMembers CGM1 ON main.GroupId = CGM1.GroupId
AND CGM1.MemberId = ?
- AND CGM1.Disabled = 0
JOIN CachedGroupMembers CGM2 ON main.MemberId = CGM2.MemberId
- AND CGM2.GroupId = ?
+ AND CGM2.GroupId = ? AND CGM2.GroupId != CGM2.MemberId
+
+ WHERE main.Disabled = 0
+ AND NOT EXISTS (
+ SELECT CGM3.id
+ FROM CachedGroupMembers CGM3, CachedGroupMembers CGM4
+ WHERE CGM3.Disabled = 0 AND CGM4.Disabled = 0
+ AND CGM3.GroupId = main.GroupId
+ AND CGM3.MemberId = CGM4.GroupId
+ AND CGM4.MemberId = main.MemberId
+ AND CGM3.id != main.id
+ AND CGM4.id != main.id
+ )
+ ";
- JOIN CachedGroupMembers CGM3 ON CGM3.Disabled = 0
- AND main.GroupId = CGM3.GroupID
- JOIN CachedGroupMembers CGM4 ON CGM4.Disabled = 0
- AND main.MemberId = CGM4.MemberId
- AND CGM4.GroupId = CGM3.MemberId
- WHERE main.Disabled = 1";
$RT::Handle->SimpleUpdateFromSelect(
- $self->Table, { Disabled => 0 }, $query,
+ $self->Table, { Disabled => 1 }, $query,
($self->GroupId)x2,
) or return undef;
}
@@ -389,18 +408,19 @@ sub SetDisabled {
);
return $status;
}
+ REDO:
my $query = "SELECT main.id FROM CachedGroupMembers main
JOIN CachedGroupMembers CGM1 ON main.GroupId = CGM1.GroupId
AND CGM1.MemberId = ?
- AND CGM1.Disabled = 0
JOIN CachedGroupMembers CGM2 ON main.MemberId = CGM2.MemberId
AND CGM2.GroupId = ?
WHERE main.Disabled = 1";
- $RT::Handle->SimpleUpdateFromSelect(
+ my $res = $RT::Handle->SimpleUpdateFromSelect(
$self->Table, { Disabled => 0 }, $query,
$self->GroupId, $self->MemberId
) or return undef;
+ goto REDO if $res > 0;
}
if ( my $m = $self->can('_FlushKeyCache') ) { $m->($self) };
return (1);
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list