[Rt-commit] r4500 - in rt/branches/3.5-TESTING/lib: RT

ruz at bestpractical.com ruz at bestpractical.com
Mon Feb 6 14:47:28 EST 2006


Author: ruz
Date: Mon Feb  6 14:47:28 2006
New Revision: 4500

Modified:
   rt/branches/3.5-TESTING/lib/RT/Tickets_Overlay.pm
   rt/branches/3.5-TESTING/lib/t/regression/01ticket_link_searching.t

Log:
* backport from 3.7
* add support for optional OPERATOR argument in LimitLinked(From|To)
* and add this to methods Limit(HasMemeber|DependsOn|...)
* in _LinkLimit:
** support for IS NOT NULL queries ala "has at least one link of defined type"
** operator '!=' didn't work at all, now it works with meanning "has no link with defined ticket"


Modified: rt/branches/3.5-TESTING/lib/RT/Tickets_Overlay.pm
==============================================================================
--- rt/branches/3.5-TESTING/lib/RT/Tickets_Overlay.pm	(original)
+++ rt/branches/3.5-TESTING/lib/RT/Tickets_Overlay.pm	Mon Feb  6 14:47:28 2006
@@ -316,8 +316,8 @@
 Handle fields which deal with links between tickets.  (MemberOf, DependsOn)
 
 Meta Data:
-  1: Direction (From,To)
-  2: Link Type (MemberOf, DependsOn,RefersTo)
+  1: Direction (From, To)
+  2: Link Type (MemberOf, DependsOn, RefersTo)
 
 =cut
 
@@ -325,17 +325,15 @@
     my ( $sb, $field, $op, $value, @rest ) = @_;
 
     my $meta = $FIELD_METADATA{$field};
-    die "Invalid Operator $op for $field" unless $op =~ /^(=|!=|IS)/io;
-
     die "Incorrect Metadata for $field"
-        unless ( defined $meta->[1] and defined $meta->[2] );
+        unless defined $meta->[1] && defined $meta->[2];
+
+    die "Invalid Operator $op for $field" unless $op =~ /^(=|!=|IS|IS NOT)$/io;
 
     my $direction = $meta->[1];
 
     my $matchfield;
     my $linkfield;
-    my $is_local = 1;
-    my $is_null  = 0;
     if ( $direction eq 'To' ) {
         $matchfield = "Target";
         $linkfield  = "Base";
@@ -350,86 +348,83 @@
         die "Invalid link direction '$meta->[1]' for $field\n";
     }
 
-    if ( $op eq '=' || $op =~ /^is/oi ) {
-        if ( $value eq '' || $value =~ /^null$/io ) {
-            $is_null = 1;
-        }
-        elsif ( $value =~ /\D/o ) {
-            $is_local = 0;
-        }
-        else {
-            $is_local = 1;
-        }
+    my ($is_local, $is_null) = (1, 0);
+    if ( !$value || $value =~ /^null$/io ) {
+        $is_null = 1;
+        $op = ($op =~ /^(=|IS)$/)? 'IS': 'IS NOT';
+    }
+    elsif ( $value =~ /\D/o ) {
+        $is_local = 0;
+    }
+    $matchfield = "Local$matchfield" if $is_local;
+
+    my $is_negative = 0;
+    if ( $op eq '!=' ) {
+        $is_negative = 1;
+        $op = '=';
     }
 
 #For doing a left join to find "unlinked tickets" we want to generate a query that looks like this
 #    SELECT main.* FROM Tickets main
 #        LEFT JOIN Links Links_1 ON (     (Links_1.Type = 'MemberOf')
 #                                      AND(main.id = Links_1.LocalTarget))
-#        WHERE   ((main.EffectiveId = main.id))
-#            AND ((main.Status != 'deleted'))
-#            AND (Links_1.LocalBase IS NULL);
+#        WHERE Links_1.LocalBase IS NULL;
 
+    my $linkalias = $sb->Join(
+        TYPE   => ($is_null || $is_negative)? 'LEFT': 'NORMAL',
+        ALIAS1 => 'main',
+        FIELD1 => 'id',
+        TABLE2 => 'Links',
+        FIELD2 => 'Local' . $linkfield
+    );
+    $sb->_OpenParen();
+    $sb->SUPER::Limit(
+        @rest,
+        ($is_null || $is_negative)? (LEFTJOIN => $linkalias): (),
+        FIELD    => 'Type',
+        OPERATOR => '=',
+        VALUE    => $meta->[2],
+    );
     if ($is_null) {
-        my $linkalias = $sb->Join(
-            TYPE   => 'left',
-            ALIAS1 => 'main',
-            FIELD1 => 'id',
-            TABLE2 => 'Links',
-            FIELD2 => 'Local' . $linkfield
-        );
 
+        $sb->_SQLLimit(
+            ALIAS           => $linkalias,
+            ENTRYAGGREGATOR => 'AND',
+            FIELD           => $matchfield,
+            OPERATOR        => $op,
+            VALUE           => 'NULL',
+            QUOTEVALUE      => 0,
+        );
+    }
+    elsif ( $is_negative ) {
         $sb->SUPER::Limit(
             LEFTJOIN => $linkalias,
-            FIELD    => 'Type',
-            OPERATOR => '=',
-            VALUE    => $meta->[2],
-            @rest,
+            FIELD    => $matchfield,
+            OPERATOR => $op,
+            VALUE    => $value,
         );
-
         $sb->_SQLLimit(
             ALIAS           => $linkalias,
             ENTRYAGGREGATOR => 'AND',
-            FIELD      => ( $is_local ? "Local$matchfield" : $matchfield ),
-            OPERATOR   => 'IS',
-            VALUE      => 'NULL',
-            QUOTEVALUE => '0',
+            FIELD           => $matchfield,
+            OPERATOR        => 'IS',
+            VALUE           => 'NULL',
+            QUOTEVALUE      => 0,
         );
-
     }
     else {
 
-        $sb->{_sql_linkalias} = $sb->NewAlias('Links')
-            unless defined $sb->{_sql_linkalias};
-
-        $sb->_OpenParen();
 
         $sb->_SQLLimit(
-            ALIAS    => $sb->{_sql_linkalias},
-            FIELD    => 'Type',
-            OPERATOR => '=',
-            VALUE    => $meta->[2],
-            @rest,
-        );
-
-        $sb->_SQLLimit(
-            ALIAS           => $sb->{_sql_linkalias},
+            ALIAS           => $linkalias,
             ENTRYAGGREGATOR => 'AND',
-            FIELD    => ( $is_local ? "Local$matchfield" : $matchfield ),
-            OPERATOR => '=',
+            FIELD    => $matchfield,
+            OPERATOR => $op,
             VALUE    => $value,
         );
 
-        #If we're searching on target, join the base to ticket.id
-        $sb->_SQLJoin(
-            ALIAS1 => 'main',
-            FIELD1 => $sb->{'primary_key'},
-            ALIAS2 => $sb->{_sql_linkalias},
-            FIELD2 => 'Local' . $linkfield
-        );
-
-        $sb->_CloseParen();
     }
+    $sb->_CloseParen();
 }
 
 =head2 _DateLimit
@@ -2052,9 +2047,10 @@
 sub LimitLinkedTo {
     my $self = shift;
     my %args = (
-        TICKET => undef,
-        TARGET => undef,
-        TYPE   => undef,
+        TICKET   => undef,
+        TARGET   => undef,
+        TYPE     => undef,
+        OPERATOR => '=',
         @_
     );
 
@@ -2068,6 +2064,7 @@
             $self->loc( $args{'TYPE'} ),
             ( $args{'TARGET'} || $args{'TICKET'} )
         ),
+        OPERATOR    => $args{'OPERATOR'},
     );
 }
 
@@ -2090,9 +2087,10 @@
 sub LimitLinkedFrom {
     my $self = shift;
     my %args = (
-        BASE   => undef,
-        TICKET => undef,
-        TYPE   => undef,
+        BASE     => undef,
+        TICKET   => undef,
+        TYPE     => undef,
+        OPERATOR => '=',
         @_
     );
 
@@ -2114,6 +2112,7 @@
             $self->loc( $args{'TYPE'} ),
             ( $args{'BASE'} || $args{'TICKET'} )
         ),
+        OPERATOR    => $args{'OPERATOR'},
     );
 }
 
@@ -2123,11 +2122,11 @@
 sub LimitMemberOf {
     my $self      = shift;
     my $ticket_id = shift;
-    $self->LimitLinkedTo(
-        TARGET => "$ticket_id",
+    return $self->LimitLinkedTo(
+        @_,
+        TARGET => $ticket_id,
         TYPE   => 'MemberOf',
     );
-
 }
 
 # }}}
@@ -2136,7 +2135,8 @@
 sub LimitHasMember {
     my $self      = shift;
     my $ticket_id = shift;
-    $self->LimitLinkedFrom(
+    return $self->LimitLinkedFrom(
+        @_,
         BASE => "$ticket_id",
         TYPE => 'HasMember',
     );
@@ -2150,8 +2150,9 @@
 sub LimitDependsOn {
     my $self      = shift;
     my $ticket_id = shift;
-    $self->LimitLinkedTo(
-        TARGET => "$ticket_id",
+    return $self->LimitLinkedTo(
+        @_,
+        TARGET => $ticket_id,
         TYPE   => 'DependsOn',
     );
 
@@ -2164,8 +2165,9 @@
 sub LimitDependedOnBy {
     my $self      = shift;
     my $ticket_id = shift;
-    $self->LimitLinkedFrom(
-        BASE => "$ticket_id",
+    return $self->LimitLinkedFrom(
+        @_,
+        BASE => $ticket_id,
         TYPE => 'DependentOn',
     );
 
@@ -2178,8 +2180,9 @@
 sub LimitRefersTo {
     my $self      = shift;
     my $ticket_id = shift;
-    $self->LimitLinkedTo(
-        TARGET => "$ticket_id",
+    return $self->LimitLinkedTo(
+        @_,
+        TARGET => $ticket_id,
         TYPE   => 'RefersTo',
     );
 
@@ -2192,11 +2195,11 @@
 sub LimitReferredToBy {
     my $self      = shift;
     my $ticket_id = shift;
-    $self->LimitLinkedFrom(
-        BASE => "$ticket_id",
+    return $self->LimitLinkedFrom(
+        @_,
+        BASE => $ticket_id,
         TYPE => 'ReferredToBy',
     );
-
 }
 
 # }}}

Modified: rt/branches/3.5-TESTING/lib/t/regression/01ticket_link_searching.t
==============================================================================
--- rt/branches/3.5-TESTING/lib/t/regression/01ticket_link_searching.t	(original)
+++ rt/branches/3.5-TESTING/lib/t/regression/01ticket_link_searching.t	Mon Feb  6 14:47:28 2006
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 
-use Test::More tests => 25;
+use Test::More tests => 30;
 use strict;
 use RT;
 
@@ -17,54 +17,46 @@
 $queue->Load('General') || Abort(loc("Queue could not be loaded."));
 
 my $child_ticket = new RT::Ticket( $CurrentUser );
-
-my ( $childid ) = $child_ticket->Create
-    ( Subject => 'test child',
-      Queue => $queue->Id);
-
-ok($childid != 0);
+my ($childid) = $child_ticket->Create(
+    Subject => 'test child',
+    Queue => $queue->Id,
+);
+ok($childid, "We created a child ticket");
 
 my $parent_ticket = new RT::Ticket( $CurrentUser );
+my ($parentid) = $parent_ticket->Create(
+    Subject => 'test parent',
+    Children => [ $childid ],
+    Queue => $queue->Id,
+);
+ok($parentid, "We created a parent ticket");
 
-my ( $parentid ) = $parent_ticket->Create
-    ( Subject => 'test parent',
-      Children => [$childid],
-      Queue => $queue->Id);
-
-ok($parentid != 0, "We created a parent ticket");
 
 my $Collection = RT::Tickets->new($CurrentUser);
-$Collection->LimitMemberOf ($parentid);
-
-ok ($Collection->First);
-is ($Collection->First->id, $childid, "We found the collection of all children of $parentid with Limit");
+$Collection->LimitMemberOf( $parentid );
 is($Collection->Count,1, "We found only one result");
+ok($Collection->First);
+is($Collection->First->id, $childid, "We found the collection of all children of $parentid with Limit");
 
 $Collection = RT::Tickets->new($CurrentUser);
-$Collection->FromSQL( "MemberOf =  $parentid");
-is ($Collection->First->id, $childid, "We found the collection of all children of $parentid with TicketSQL");
-is($Collection->Count,1, "We found only one result");
-
-
-
+$Collection->FromSQL("MemberOf = $parentid");
+is($Collection->Count, 1, "We found only one result");
+ok($Collection->First);
+is($Collection->First->id, $childid, "We found the collection of all children of $parentid with TicketSQL");
 
 
 $Collection = RT::Tickets->new($CurrentUser);
 $Collection->LimitHasMember ($childid);
-
-ok ($Collection->First);
-is ($Collection->First->id, $parentid, "We found the collection of all parents of $childid with Limit");
 is($Collection->Count,1, "We found only one result");
-
+ok($Collection->First);
+is($Collection->First->id, $parentid, "We found the collection of all parents of $childid with Limit");
 
 
 $Collection = RT::Tickets->new($CurrentUser);
 $Collection->FromSQL("HasMember = $childid");
-
-ok ($Collection->First);
-is ($Collection->First->id, $parentid, "We found the collection of all parents of $childid with TicketSQL");
 is($Collection->Count,1, "We found only one result");
-
+ok($Collection->First);
+is($Collection->First->id, $parentid, "We found the collection of all parents of $childid with TicketSQL");
 
 
 # Now we find a collection of all the tickets which have no members. they should have no children.
@@ -75,12 +67,10 @@
 while (my $t = $Collection->Next) {
     ++$has{$t->id};
 }
-ok ($has{$childid} , "The collection has our child - $childid");
+ok( $has{$childid}, "The collection has our child - $childid");
 ok( !$has{$parentid}, "The collection doesn't have our parent - $parentid");
 
 
-
-
 # Now we find a collection of all the tickets which are not members of anything. they should have no parents.
 $Collection = RT::Tickets->new($CurrentUser);
 $Collection->LimitMemberOf('');
@@ -102,28 +92,27 @@
 $Collection = RT::Tickets->new($CurrentUser);
 $Collection->FromSQL ("HasMember IS NULL");
 # must contain parent; must not contain child
- %has = ();
+%has = ();
 while (my $t = $Collection->Next) {
     ++$has{$t->id};
 }
-ok (!$has{$parentid} , "The collection doesn't have our parent - $parentid");
+ok( !$has{$parentid}, "The collection doesn't have our parent - $parentid");
 ok( $has{$childid}, "The collection has our child - $childid");
 
 
 # Now we find a collection of all the tickets which have no members. they should have no children.
 # Alternate syntax
 $Collection = RT::Tickets->new($CurrentUser);
-$Collection->FromSQL ("HasMember = ''");
+$Collection->FromSQL("HasMember = ''");
 # must contain parent; must not contain child
- %has = ();
+%has = ();
 while (my $t = $Collection->Next) {
     ++$has{$t->id};
 }
-ok (!$has{$parentid} , "The collection doesn't have our parent - $parentid");
+ok( !$has{$parentid}, "The collection doesn't have our parent - $parentid");
 ok( $has{$childid}, "The collection has our child - $childid");
 
 
-
 # Now we find a collection of all the tickets which are not members of anything. they should have no parents.
 $Collection = RT::Tickets->new($CurrentUser);
 $Collection->FromSQL("MemberOf IS NULL");
@@ -132,8 +121,8 @@
 while (my $t = $Collection->Next) {
     ++$has{$t->id};
 }
-ok ($has{$parentid} , "The collection has our parent - $parentid");
-ok(!$has{$childid}, "The collection doesn't have our child - $childid");
+ok( $has{$parentid}, "The collection has our parent - $parentid");
+ok( !$has{$childid}, "The collection doesn't have our child - $childid");
 
 
 # Now we find a collection of all the tickets which are not members of anything. they should have no parents.
@@ -144,12 +133,27 @@
 while (my $t = $Collection->Next) {
     ++$has{$t->id};
 }
-ok ($has{$parentid} , "The collection has our parent - $parentid");
-ok(!$has{$childid}, "The collection doesn't have our child - $childid");
+ok( $has{$parentid}, "The collection has our parent - $parentid");
+ok( !$has{$childid}, "The collection doesn't have our child - $childid");
 
 
+# Now we find a collection of all the tickets which are not members of the parent ticket
+$Collection = RT::Tickets->new($CurrentUser);
+$Collection->FromSQL("MemberOf != $parentid");
+%has = ();
+while (my $t = $Collection->Next) {
+    ++$has{$t->id};
+}
+ok( $has{$parentid}, "The collection has our parent - $parentid");
+ok( !$has{$childid}, "The collection doesn't have our child - $childid");
 
+$Collection = RT::Tickets->new($CurrentUser);
+$Collection->LimitMemberOf($parentid, OPERATOR => '!=');
+%has = ();
+while (my $t = $Collection->Next) {
+    ++$has{$t->id};
+}
+ok( $has{$parentid}, "The collection has our parent - $parentid");
+ok( !$has{$childid}, "The collection doesn't have our child - $childid");
 
 1;
-
-


More information about the Rt-commit mailing list