[Rt-commit] rt branch, 4.2/use-in-operator, created. rt-4.2.7-16-g47d8762

Alex Vandiver alexmv at bestpractical.com
Tue Sep 30 17:23:43 EDT 2014


The branch, 4.2/use-in-operator has been created
        at  47d876236b6a3cb7dc5b7e6cffb68a8ef18f8c87 (commit)

- Log -----------------------------------------------------------------
commit 3ed8f4b3954bd87fdaa686e69230f1a348eece7a
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Apr 18 13:00:09 2014 -0400

    When possible, switch to IN or NOT IN rather than multiple OR'd clauses
    
    DBIx::SearchBuilder 1.63 began allowing the IN and NOT IN operators; RT
    4.0 could not immediately make use of them because it did depend on a
    high enough version of DBIx::SearchBuilder.  RT 4.2, however, depends on
    DBIx::SearchBuilder 1.65, and thus can use IN freely.  Do so, as query
    optimizers are likely to be able to make better plans based on IN
    queries, rather than multiple OR's.
    
    This also rewrites two queries in GetForwardAttachments into one, using
    a simple JOIN.

diff --git a/lib/RT/Action/SendForward.pm b/lib/RT/Action/SendForward.pm
index 914e748..52937ff 100644
--- a/lib/RT/Action/SendForward.pm
+++ b/lib/RT/Action/SendForward.pm
@@ -92,9 +92,10 @@ sub Prepare {
     else {
         my $txns = $self->TicketObj->Transactions;
         $txns->Limit(
-            FIELD => 'Type',
-            VALUE => $_,
-        ) for qw(Create Correspond);
+            FIELD    => 'Type',
+            OPERATOR => 'IN',
+            VALUE    => [qw(Create Correspond)],
+        );
 
         $entity = MIME::Entity->build(
             Type        => 'multipart/mixed',
diff --git a/lib/RT/Articles.pm b/lib/RT/Articles.pm
index 97a4708..ea82827 100644
--- a/lib/RT/Articles.pm
+++ b/lib/RT/Articles.pm
@@ -406,12 +406,11 @@ sub LimitTopics {
 
     my $topics = $self->NewAlias('ObjectTopics');
     $self->Limit(
-        ALIAS           => $topics,
-        FIELD           => 'Topic',
-        VALUE           => $_,
-        ENTRYAGGREGATOR => 'OR'
-      )
-      for @topics;
+        ALIAS    => $topics,
+        FIELD    => 'Topic',
+        OPERATOR => 'IN',
+        VALUE    => [ @topics ],
+    );
 
     $self->Limit(
         ALIAS => $topics,
diff --git a/lib/RT/CustomFields.pm b/lib/RT/CustomFields.pm
index 14b0e8f..9a24215 100644
--- a/lib/RT/CustomFields.pm
+++ b/lib/RT/CustomFields.pm
@@ -130,24 +130,24 @@ sub LimitToGrouping {
         unless ( $list and ref($list) eq 'ARRAY' and @$list ) {
             return $self->Limit( FIELD => 'id', VALUE => 0, ENTRYAGGREGATOR => 'AND' );
         }
-        foreach ( @$list ) {
-            $self->Limit( FIELD => 'Name', VALUE => $_, CASESENSITIVE => 0 );
-        }
+        $self->Limit(
+            FIELD         => 'Name',
+            OPERATOR      => 'IN',
+            VALUE         => $list,
+            CASESENSITIVE => 0,
+        );
     } else {
         my @list = map {@$_} grep defined && ref($_) eq 'ARRAY',
             values %h;
 
         return unless @list;
-        foreach ( @list ) {
-            $self->Limit(
-                FIELD => 'Name',
-                OPERATOR => '!=',
-                VALUE => $_,
-                ENTRYAGGREGATOR => 'AND',
-                CASESENSITIVE => 0,
-            );
-        }
 
+        $self->Limit(
+            FIELD         => 'Name',
+            OPERATOR      => 'NOT IN',
+            VALUE         => [ @list ],
+            CASESENSITIVE => 0,
+        );
     }
     return;
 }
diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index ef939cf..b765a25 100644
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -636,15 +636,14 @@ sub GetForwardAttachments {
         $attachments->Limit( FIELD => 'TransactionId', VALUE => $txn->id );
     }
     else {
-        my $txns = $ticket->Transactions;
-        $txns->Limit(
-            FIELD => 'Type',
-            VALUE => $_,
-        ) for qw(Create Correspond);
-
-        while ( my $txn = $txns->Next ) {
-            $attachments->Limit( FIELD => 'TransactionId', VALUE => $txn->id );
-        }
+        $attachments->LimitByTicket( $ticket->id );
+        $attachments->Limit(
+            ALIAS         => $attachments->TransactionAlias,
+            FIELD         => 'Type',
+            OPERATOR      => 'IN',
+            VALUE         => [ qw(Create Correspond) ],
+            CASESENSITIVE => 1,
+        );
     }
     return $attachments;
 }
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index a2fa00f..822bcac 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -3796,8 +3796,12 @@ sub GetPrincipalsMap {
                 my $class = $object->RecordClassFromLookupType;
                 if ($class and $class->DOES("RT::Record::Role::Roles")) {
                     $roles->LimitToRolesForObject(RT->System);
-                    $roles->Limit( FIELD => "Name", VALUE => $_, CASESENSITIVE => 0 )
-                        for $class->Roles;
+                    $roles->Limit(
+                        FIELD         => "Name",
+                        OPERATOR      => "IN",
+                        VALUE         => [ $class->Roles ],
+                        CASESENSITIVE => 0
+                    );
                 } else {
                     # No roles to show; so show nothing
                     undef $roles;
diff --git a/lib/RT/Migrate/Serializer.pm b/lib/RT/Migrate/Serializer.pm
index 2c23833..4c1d9eb 100644
--- a/lib/RT/Migrate/Serializer.pm
+++ b/lib/RT/Migrate/Serializer.pm
@@ -248,8 +248,9 @@ sub PushBasics {
     my $cfs = RT::CustomFields->new( RT->SystemUser );
     $cfs->Limit(
         FIELD => 'LookupType',
-        VALUE => $_
-    ) for qw/RT::User RT::Group RT::Queue/;
+        OPERATOR => 'IN',
+        VALUE => [ qw/RT::User RT::Group RT::Queue/ ],
+    );
     $self->PushObj( $cfs );
 
     # Global attributes
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 50a2ba1..6d2b0f7 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -1007,16 +1007,13 @@ sub TransactionAddresses {
     $attachments->LimitByTicket( $self->id );
     $attachments->Columns( qw( id Headers TransactionId));
 
-
-    foreach my $type (qw(Create Comment Correspond)) {
-        $attachments->Limit( ALIAS    => $attachments->TransactionAlias,
-                             FIELD    => 'Type',
-                             OPERATOR => '=',
-                             VALUE    => $type,
-                             ENTRYAGGREGATOR => 'OR',
-                             CASESENSITIVE   => 1
-                           );
-    }
+    $attachments->Limit(
+        ALIAS         => $attachments->TransactionAlias,
+        FIELD         => 'Type',
+        OPERATOR      => 'IN',
+        VALUE         => [ qw(Create Comment Correspond) ],
+        CASESENSITIVE => 1,
+    );
 
     while ( my $att = $attachments->Next ) {
         foreach my $addrlist ( values %{$att->Addresses } ) {
@@ -1746,15 +1743,10 @@ sub _Links {
     # at least to myself
     $links->Limit(
         FIELD           => $limit_on,
-        VALUE           => $self->id,
-        ENTRYAGGREGATOR => 'OR',
+        OPERATOR        => 'IN',
+        VALUE           => [ $self->id, $self->Merged ],
     );
     $links->Limit(
-        FIELD           => $limit_on,
-        VALUE           => $_,
-        ENTRYAGGREGATOR => 'OR',
-    ) foreach $self->Merged;
-    $links->Limit(
         FIELD => 'Type',
         VALUE => $type,
     ) if $type;
diff --git a/lib/RT/Tickets.pm b/lib/RT/Tickets.pm
index 79d5e15..34594ae 100644
--- a/lib/RT/Tickets.pm
+++ b/lib/RT/Tickets.pm
@@ -329,20 +329,15 @@ sub _BookmarkLimit {
         TABLE2 => 'Tickets',
         FIELD2 => 'EffectiveId',
     );
-    $sb->_OpenParen;
-    my $first = 1;
-    my $ea = $op eq '='? 'OR': 'AND';
-    foreach my $id ( sort @bookmarks ) {
-        $sb->Limit(
-            ALIAS    => $tickets_alias,
-            FIELD    => 'id',
-            OPERATOR => $op,
-            VALUE    => $id,
-            $first? (@rest): ( ENTRYAGGREGATOR => $ea )
-        );
-        $first = 0 if $first;
-    }
-    $sb->_CloseParen;
+
+    $op = $op eq '='? 'IN': 'NOT IN';
+    $sb->Limit(
+        ALIAS    => $tickets_alias,
+        FIELD    => 'id',
+        OPERATOR => $op,
+        VALUE    => [ @bookmarks ],
+        @rest,
+    );
 }
 
 =head2 _EnumLimit
@@ -2511,9 +2506,12 @@ sub CurrentUserCanSee {
 
         my $groups = RT::Groups->new( RT->SystemUser );
         $groups->Limit( FIELD => 'Domain', VALUE => 'RT::Queue-Role', CASESENSITIVE => 0 );
-        foreach ( @tmp ) {
-            $groups->Limit( FIELD => 'Name', VALUE => $_, CASESENSITIVE => 0 );
-        }
+        $groups->Limit(
+            FIELD         => 'Name',
+            OPERATOR      => 'IN',
+            VALUE         => [ @tmp ],
+            CASESENSITIVE => 0
+        );
         my $principal_alias = $groups->Join(
             ALIAS1 => 'main',
             FIELD1 => 'id',
@@ -2564,28 +2562,14 @@ sub CurrentUserCanSee {
             my @queues = @_;
 
             return unless @queues;
-            if ( @queues == 1 ) {
-                $self->Limit(
-                    SUBCLAUSE => 'ACL',
-                    ALIAS => 'main',
-                    FIELD => 'Queue',
-                    VALUE => $_[0],
-                    ENTRYAGGREGATOR => $ea,
-                );
-            } else {
-                $self->SUPER::_OpenParen('ACL');
-                foreach my $q ( @queues ) {
-                    $self->Limit(
-                        SUBCLAUSE => 'ACL',
-                        ALIAS => 'main',
-                        FIELD => 'Queue',
-                        VALUE => $q,
-                        ENTRYAGGREGATOR => $ea,
-                    );
-                    $ea = 'OR';
-                }
-                $self->SUPER::_CloseParen('ACL');
-            }
+            $self->Limit(
+                SUBCLAUSE       => 'ACL',
+                ALIAS           => 'main',
+                FIELD           => 'Queue',
+                OPERATOR        => 'IN',
+                VALUE           => [ @queues ],
+                ENTRYAGGREGATOR => $ea,
+            );
             return 1;
         };
 
diff --git a/lib/RT/Users.pm b/lib/RT/Users.pm
index 0aec195..dbaa33c 100644
--- a/lib/RT/Users.pm
+++ b/lib/RT/Users.pm
@@ -570,14 +570,13 @@ sub WhoBelongToGroups {
     }
     my $group_members = $self->_JoinGroupMembers( %args );
 
-    foreach my $groupid (@{$args{'Groups'}}) {
-        $self->Limit( ALIAS           => $group_members,
-                      FIELD           => 'GroupId',
-                      VALUE           => $groupid,
-                      QUOTEVALUE      => 0,
-                      ENTRYAGGREGATOR => 'OR',
-                    );
-    }
+    $self->Limit(
+        ALIAS      => $group_members,
+        FIELD      => 'GroupId',
+        OPERATOR   => 'IN',
+        VALUE      => $args{'Groups'},
+        QUOTEVALUE => 0,
+    );
 }
 
 =head2 SimpleSearch
@@ -645,9 +644,8 @@ sub SimpleSearch {
     }
 
     # Exclude users we don't want
-    foreach (@{$args{Exclude}}) {
-        $self->Limit(FIELD => 'id', VALUE => $_, OPERATOR => '!=', ENTRYAGGREGATOR => 'AND');
-    }
+    $self->Limit(FIELD => 'id', OPERATOR => 'NOT IN', VALUE => $args{Exclude} )
+        if @{$args{Exclude}};
 
     if ( RT->Config->Get('DatabaseType') eq 'Oracle' ) {
         $self->Limit(

commit 47d876236b6a3cb7dc5b7e6cffb68a8ef18f8c87
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Tue Sep 30 17:20:41 2014 -0400

    TODO: Fix CASESENSITIVE => 0 with OPERATOR => 'IN'
    
    OPERATOR => 'IN' is implemented by rewriting the arrayref to a complex
    VALUE and setting QUOTEVALUE => 0 -- which disables the CASESENSITIVE =>
    0 adjustment.  Even if DBIx::SearchBuilder fixes this, it still prevents
    merging of this branch because not all 4.2 installs will have the latest
    DBIx::SearchBuilder.
    
    Merging this would thus require an RT-level implementation of
    CASESENSITIVE => 0 for OPERATOR => 'IN'

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


More information about the rt-commit mailing list