[Rt-commit] rt branch, 4.2/who-have-right-optimization, created. rt-4.2.11-5-g9f96a81

Alex Vandiver alexmv at bestpractical.com
Fri May 8 16:30:49 EDT 2015


The branch, 4.2/who-have-right-optimization has been created
        at  9f96a81abd067c8630cc4c887abfb03696bf69fe (commit)

- Log -----------------------------------------------------------------
commit 8cb2dc576e6798512dae9414045b9707c21659d8
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Oct 28 18:48:49 2014 -0400

    Only add limits for types that explicitly are rights targets
    
    This skips adding an ObjectType = 'RT::Ticket' limit, which will never
    be necessary.
    
    XXX: This causes tests to fail, but the tests are horrible and old and wrong.

diff --git a/lib/RT/Users.pm b/lib/RT/Users.pm
index a8e81eb..1d6c689 100644
--- a/lib/RT/Users.pm
+++ b/lib/RT/Users.pm
@@ -512,6 +512,7 @@ sub WhoHaveGroupRight
             my $id = 0;
             $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
             next if $seen{"$type-$id"}++;
+            next unless $type->DOES("RT::Record::Role::Rights");
 
             my $object_clause = "$acl.ObjectType = '$type'";
             $object_clause   .= " AND $acl.ObjectId   = $id" if $id;
@@ -524,6 +525,7 @@ sub WhoHaveGroupRight
             $check_objects = "($acl.ObjectType != 'RT::System')";
         }
     }
+    $check_objects ||= "$acl.id = 0";
     $self->_AddSubClause( "WhichObject", "($check_objects)" );
     
     my $group_members = $self->_JoinGroupMembersForGroupRights( %args, ACLAlias => $acl );

commit 9f96a81abd067c8630cc4c887abfb03696bf69fe
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Oct 28 18:50:58 2014 -0400

    Simplify WhoHaveRoleRight and WhoHaveGroupRight queries before unioning
    
    Perform a true union in SQL, via a separate 'in' query.  This
    effectively prevents duplicates in the resultset (which
    DBIx::SearchBuilder::Union makes no attempt to do), orders the set as a
    whole, and allows the individual queries to be simpler.  In particular,
    the lack of "DISTINCT" and "ORDER BY" on the WhoHaveGroupRight query on
    MySQL causes it to generate a query plan which no longer includes "with
    temporary table" (due to the DISTINCT) or "with filesort" (due to the
    ORDER BY), and makes better use of indexes (due to the limited number of
    columns returned).
    
    This does come at the assumption that duplicates within each of the two
    queries are not common -- that is, that users will not have the relevant
    right by way of a large number of membership paths.

diff --git a/lib/RT/Groups.pm b/lib/RT/Groups.pm
index 4d06528..aeb80e6 100644
--- a/lib/RT/Groups.pm
+++ b/lib/RT/Groups.pm
@@ -339,19 +339,34 @@ sub WithRight {
                  EquivObjects           => [ ],
                  @_ );
 
+    my @ids = (0);
+
     my $from_role = $self->Clone;
     $from_role->WithRoleRight( %args );
+    $from_role->Columns( 'id' );
+    $from_role->OrderBy();
+    $from_role->{'joins_are_distinct'} = 1;
+    while (my $row = $from_role->Next) {
+        push @ids, $row->id;
+    }
 
     my $from_group = $self->Clone;
     $from_group->WithGroupRight( %args );
+    $from_group->Columns( 'id' );
+    $from_group->OrderBy();
+    $from_group->{'joins_are_distinct'} = 1;
+    while (my $row = $from_group->Next) {
+        push @ids, $row->id;
+    }
 
-    #XXX: DIRTY HACK
-    use DBIx::SearchBuilder::Union;
-    my $union = DBIx::SearchBuilder::Union->new();
-    $union->add($from_role);
-    $union->add($from_group);
+    my $union = RT::Groups->new( $self->CurrentUser );
+    while ( @ids > 1000 ) {
+        my @batch = splice( @ids, 0, 1000 );
+        $union->Limit( FIELD => 'id', OPERATOR => 'IN', VALUE => \@batch );
+    }
+    $union->Limit( FIELD => 'id', OPERATOR => 'IN', VALUE => \@ids );
+    $union->{'handled_disabled_column'} = 1;
     %$self = %$union;
-    bless $self, ref($union);
 
     return;
 }
diff --git a/lib/RT/Users.pm b/lib/RT/Users.pm
index 1d6c689..86cda82 100644
--- a/lib/RT/Users.pm
+++ b/lib/RT/Users.pm
@@ -386,19 +386,34 @@ sub WhoHaveRight {
         return (undef);
     }
 
+    my @ids = (0);
+
     my $from_role = $self->Clone;
     $from_role->WhoHaveRoleRight( %args );
+    $from_role->Columns( 'id' );
+    $from_role->OrderBy();
+    $from_role->{'joins_are_distinct'} = 1;
+    while (my $row = $from_role->Next) {
+        push @ids, $row->id;
+    }
 
     my $from_group = $self->Clone;
     $from_group->WhoHaveGroupRight( %args );
+    $from_group->Columns( 'id' );
+    $from_group->OrderBy();
+    $from_group->{'joins_are_distinct'} = 1;
+    while (my $row = $from_group->Next) {
+        push @ids, $row->id;
+    }
 
-    #XXX: DIRTY HACK
-    use DBIx::SearchBuilder::Union;
-    my $union = DBIx::SearchBuilder::Union->new();
-    $union->add( $from_group );
-    $union->add( $from_role );
+    my $union = RT::Users->new( $self->CurrentUser );
+    while ( @ids > 1000 ) {
+        my @batch = splice( @ids, 0, 1000 );
+        $union->Limit( FIELD => 'id', OPERATOR => 'IN', VALUE => \@batch );
+    }
+    $union->Limit( FIELD => 'id', OPERATOR => 'IN', VALUE => \@ids );
+    $union->{'handled_disabled_column'} = 1;
     %$self = %$union;
-    bless $self, ref($union);
 
     return;
 }

-----------------------------------------------------------------------


More information about the rt-commit mailing list