[Rt-commit] r1992 - in rt/branches/3.3-TESTING: . lib/RT

jesse at bestpractical.com jesse at bestpractical.com
Thu Dec 16 14:47:58 EST 2004


Author: jesse
Date: Tue Dec 14 02:25:03 2004
New Revision: 1992

Modified:
   rt/branches/3.3-TESTING/   (props changed)
   rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay.pm
   rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay_SQL.pm
Log:
 r2428 at hualien:  jesse | 2004-12-14T07:21:15.616305Z
 Adding support for searching on tickets which have no relationships of a given type  (Such as "HasMember IS NULL") for clkao


Modified: rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay.pm
==============================================================================
--- rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay.pm	(original)
+++ rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay.pm	Tue Dec 14 02:25:03 2004
@@ -308,64 +308,118 @@
 =cut
 
 sub _LinkLimit {
-  my ($sb,$field,$op,$value, at rest) = @_;
-
-  die "Op must be ="
-    unless $op eq "=";
+    my ( $sb, $field, $op, $value, @rest ) = @_;
 
-  my $meta = $FIELDS{$field};
-  die "Incorrect Meta Data for $field"
-    unless (defined $meta->[1] and defined $meta->[2]);
+    my $meta = $FIELDS{$field};
+    die "Invalid Operator $op for $field" unless $op =~ /^(=|!=|IS)/io;
 
-  $sb->{_sql_linkalias} = $sb->NewAlias ('Links')
-    unless defined $sb->{_sql_linkalias};
+    die "Incorrect Metadata for $field"
+      unless ( defined $meta->[1] and defined $meta->[2] );
 
-  $sb->_OpenParen();
+    my $direction = $meta->[1];
 
-  $sb->_SQLLimit(
-	     ALIAS => $sb->{_sql_linkalias},
-	     FIELD =>   'Type',
-	     OPERATOR => '=',
-	     VALUE => $meta->[2],
-	     @rest,
-	    );
+    my $matchfield;
+    my $linkfield;
+    my $is_local = 1;
+    my $is_null  = 0;
+    if ( $direction eq 'To' ) {
+        $matchfield = "Target";
+        $linkfield  = "Base";
 
-  if ($meta->[1] eq "To") {
-    my $matchfield = ( $value  =~ /^(\d+)$/ ? "LocalTarget" : "Target" );
+    }
+    elsif ( $direction eq 'From' ) {
+        $linkfield  = "Target";
+        $matchfield = "Base";
 
-    $sb->_SQLLimit(
-	       ALIAS => $sb->{_sql_linkalias},
-	       ENTRYAGGREGATOR => 'AND',
-	       FIELD =>   $matchfield,
-	       OPERATOR => '=',
-	       VALUE => $value ,
-	      );
+    }
+    else {
+        die "Invalid link direction '$meta->[1]' for $field\n";
+    }
 
-    #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 => 'LocalBase');
+    if ( $op eq '=' || $op =~ /^is/oi ) {
+        if ( $value eq '' || $value =~ /^null$/io ) {
+            $is_null = 1;
+            # When doing null searches, we need to turn everything around. WHY?
+            my $tmp = $linkfield;
+            $linkfield = $matchfield;
+            $matchfield = $tmp;
+        }
+        elsif ( $value =~ /\D/o ) {
+            $is_local = 0;
+        }
+        else {
+            $is_local = 1;
+        }
+    }
 
-  } elsif ( $meta->[1] eq "From" ) {
-    my $matchfield = ( $value  =~ /^(\d+)$/ ? "LocalBase" : "Base" );
+#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);
+
+    if ($is_null) {
+        my $linkalias = $sb->Join(
+            TYPE   => 'left',
+            ALIAS1 => 'main',
+            FIELD1 => 'id',
+            TABLE2 => 'Links',
+            FIELD2 => 'Local' . $linkfield
+        );
+
+        $sb->SUPER::Limit(
+            LEFTJOIN => $linkalias,
+            FIELD    => 'Type',
+            OPERATOR => '=',
+            VALUE    => $meta->[2],
+            @rest,
+        );
+
+        $sb->_SQLLimit(
+            ALIAS           => $linkalias,
+            ENTRYAGGREGATOR => 'AND',
+            FIELD           => ( $is_local ? "Local$matchfield" : $matchfield ),
+            OPERATOR        => 'IS',
+            VALUE           => 'NULL',
+            QUOTEVALUE      => '0',
+        );
 
-    $sb->_SQLLimit(
-	       ALIAS => $sb->{_sql_linkalias},
-	       ENTRYAGGREGATOR => 'AND',
-	       FIELD =>   $matchfield,
-	       OPERATOR => '=',
-	       VALUE => $value ,
-	      );
+    }
+    else {
 
-    #If we're searching on base, join the target to ticket.id
-    $sb->_SQLJoin( ALIAS1 => 'main',     FIELD1 => $sb->{'primary_key'},
-	       ALIAS2 => $sb->{_sql_linkalias}, FIELD2 => 'LocalTarget');
+        $sb->{_sql_linkalias} = $sb->NewAlias('Links')
+          unless defined $sb->{_sql_linkalias};
 
-  } else {
-    die "Invalid link direction '$meta->[1]' for $field\n";
-  }
+        $sb->_OpenParen();
 
-  $sb->_CloseParen();
+        $sb->_SQLLimit(
+            ALIAS    => $sb->{_sql_linkalias},
+            FIELD    => 'Type',
+            OPERATOR => '=',
+            VALUE    => $meta->[2],
+            @rest,
+        );
+
+        $sb->_SQLLimit(
+            ALIAS           => $sb->{_sql_linkalias},
+            ENTRYAGGREGATOR => 'AND',
+            FIELD           => ( $is_local ? "Local$matchfield" : $matchfield ),
+            OPERATOR        => '=',
+            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();
+    }
 }
 
 =head2 _DateLimit

Modified: rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay_SQL.pm
==============================================================================
--- rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay_SQL.pm	(original)
+++ rt/branches/3.3-TESTING/lib/RT/Tickets_Overlay_SQL.pm	Tue Dec 14 02:25:03 2004
@@ -157,7 +157,7 @@
 
 my $re_aggreg = qr[(?i:AND|OR)];
 my $re_delim  = qr[$RE{delimited}{-delim=>qq{\'\"}}];
-my $re_value  = qr[$re_delim|\d+];
+my $re_value  = qr[$re_delim|\d+|NULL];
 my $re_keyword = qr[$re_delim|(?:\{|\}|\w|\.)+];
 my $re_op     = qr[=|!=|>=|<=|>|<|(?i:IS NOT)|(?i:IS)|(?i:NOT LIKE)|(?i:LIKE)]; # long to short
 my $re_open_paren  = qr'\(';


More information about the Rt-commit mailing list