]> git.donarmstrong.com Git - debbugs.git/commitdiff
Add initial DB search support to Debbugs::Bugs
authorDon Armstrong <don@donarmstrong.com>
Mon, 19 May 2014 23:04:19 +0000 (16:04 -0700)
committerDon Armstrong <don@donarmstrong.com>
Mon, 19 May 2014 23:04:19 +0000 (16:04 -0700)
Debbugs/Bugs.pm

index 1e8eb701c1346686e4ac45fa57145aad555bfb82..d8680d1ce9cb85309410f7f7463774439cc9e690 100644 (file)
@@ -152,6 +152,8 @@ bug should not.
 
 =cut
 
+my $_non_search_key_regex = qr/^(bugs|archive|usertags|schema)$/;
+
 my %_get_bugs_common_options =
     (package   => {type => SCALAR|ARRAYREF,
                    optional => 1,
@@ -198,6 +200,9 @@ my %_get_bugs_common_options =
      usertags  => {type => HASHREF,
                    optional => 1,
                   },
+     schema => {type     => OBJECT,
+                optional => 1,
+               },
     );
 
 
@@ -218,7 +223,7 @@ sub get_bugs{
          return keys %bugs;
      }
      # A configuration option will set an array that we'll use here instead.
-     for my $routine (qw(Debbugs::Bugs::get_bugs_by_idx Debbugs::Bugs::get_bugs_flatfile)) {
+     for my $routine (qw(Debbugs::Bugs::get_bugs_by_db Debbugs::Bugs::get_bugs_by_idx Debbugs::Bugs::get_bugs_flatfile)) {
          my ($package) = $routine =~ m/^(.+)\:\:/;
          eval "use $package;";
          if ($@) {
@@ -427,11 +432,11 @@ sub get_bugs_by_idx{
          delete @param{qw(maint src)};
          $param{package} = [@packages];
      }
-     my $keys = grep {$_ !~ /^(archive|usertags|bugs)$/} keys(%param);
+     my $keys = grep {$_ !~ $_non_search_key_regex} keys(%param);
      die "Need at least 1 key to search by" unless $keys;
      my $arc = $param{archive} ? '-arc':'';
      my %idx;
-     for my $key (grep {$_ !~ /^(archive|usertags|bugs)$/} keys %param) {
+     for my $key (grep {$_ !~ $_non_search_key_regex} keys %param) {
          my $index = $key;
          $index = 'submitter-email' if $key eq 'submitter';
          $index = "$config{spool_dir}/by-${index}${arc}.idx";
@@ -474,6 +479,115 @@ sub get_bugs_by_idx{
 }
 
 
+=head2 get_bugs_by_db
+
+This routine uses the database to try to speed up
+searches.
+
+
+=cut
+
+my $_get_bugs_by_db_options =
+   {hash_slice(%_get_bugs_common_options,
+               (qw(package submitter severity tag archive),
+                qw(owner src maint bugs correspondent),
+                qw(affects usertags))
+              ),
+    schema => {type     => OBJECT,
+              },
+   };
+sub get_bugs_by_db{
+     my %param = validate_with(params => \@_,
+                              spec   => $_get_bugs_by_db_options,
+                              );
+     my %bugs = ();
+
+     # If we're given an empty maint (unmaintained packages), we can't
+     # handle it, so bail out here
+     for my $maint (make_list(exists $param{maint}?$param{maint}:[])) {
+         if (defined $maint and $maint eq '') {
+              die "Can't handle empty maint (unmaintained packages) in get_bugs_by_idx";
+         }
+     }
+
+     # We handle src packages, maint and maintenc by mapping to the
+     # appropriate binary packages, then removing all packages which
+     # don't match all queries
+     my @packages = __handle_pkg_src_and_maint(map {exists $param{$_}?($_,$param{$_}):()}
+                                              qw(package src maint)
+                                             );
+     if (exists $param{package} or
+        exists $param{src} or
+        exists $param{maint}) {
+         delete @param{qw(maint src)};
+         $param{package} = [@packages];
+     }
+     my $keys = grep {$_ !~ $_non_search_key_regex} keys(%param);
+     die "Need at least 1 key to search by" unless $keys;
+     my $rs = $param{schema}->resultset('Bug');
+     if (exists $param{severity}) {
+         $rs = $rs->search([map {('severity.severity' => $_)} make_list($param{severity})],
+                          {join => 'severity'},
+                          );
+     }
+     for my $key (qw(owner submitter done)) {
+         if (exists $param{$key}) {
+             $rs = $rs->search([map {("${key}.addr" => $_)} make_list($param{$key})],
+                              {join => $key},
+                              );
+         }
+     }
+     if (exists $param{correspondent}) {
+         $rs = $rs->search([map {('message_correspondents.addr' => $_)} make_list($param{correspondent})],
+                          {join => {correspondent =>
+                                   {bug_messages =>
+                                   {message => 'message_correspondents'}}}},
+                          );
+     }
+     if (exists $param{affects}) {
+         $rs = $rs->search([map {('bin_pkg.pkg' => $_)} make_list($param{affects}),
+                            map {('src_pkg.pkg' => $_)} make_list($param{affects}),
+                           ],
+                          {join => [{bug_affects_binpackages => 'bin_pkg'},
+                                   {bug_affects_srcpackages => 'src_pkg'},
+                                   ],
+                          },
+                          );
+     }
+     if (exists $param{package}) {
+         $rs = $rs->search([map {('bin_pkg.pkg' => $_)} make_list($param{package})],
+                          {join => {bug_binpackages => 'bin_pkg'}});
+     }
+     if (exists $param{src}) {
+         $rs = $rs->search([map {('src_pkg.pkg' => $_)} make_list($param{src})],
+                          {join => {bug_srcpackages => 'src_pkg'}});
+     }
+     # tags are very odd, because we must handle usertags.
+     if (exists $param{tag}) {
+         # bugs from usertags which matter
+         my %bugs_matching_usertags;
+         for my $bug (make_list(grep {defined $_ } @{$param{usertags}}{make_list($param{tag})})) {
+             $bugs_matching_usertags{$bug} = 1;
+         }
+         # we want all bugs which either match the tag name given in
+         # param, or have a usertag set which matches one of the tag
+         # names given in param.
+         $rs = $rs->search([map {('tag.tag' => $_)} make_list($param{tag}),
+                            map {('me.id' => $_)} keys %bugs_matching_usertags
+                           ],
+                          {join => {bug_tags => 'tag'}});
+     }
+     if (exists $param{bugs}) {
+         $rs = $rs->search([map {('me.id' => $_)} make_list($param{bugs})]);
+     }
+     # handle archive
+     if (defined $param{archive} and $param{archive} ne 'both') {
+         $rs = $rs->search('me.archived' => $param{archive})
+     }
+     return $rs->get_column('id')->all();
+}
+
+
 =head2 get_bugs_flatfile
 
 This is the fallback search routine. It should be able to complete all