Bug 11051: remove unneccessary SQL queries in GetBranches
authorRobin Sheat <robin@catalyst.net.nz>
Tue, 15 Oct 2013 02:01:31 +0000 (15:01 +1300)
committerGalen Charlton <gmc@esilibrary.com>
Fri, 10 Jan 2014 16:02:39 +0000 (16:02 +0000)
The way GetBranches was written, it will issue one query to get all
branches, and then one query per branch for the branch relations.
This patch pre-fetches the relations table (as we need it all anyway)
and so makes the whole process happen in two queries, rather than take
1+N, where N is the number of branches.

This might not seem like much, but when you do a search, GetBranches is
called once for each result, so 25. And you might have 10 branches. This
causes 275 database requests when you could get away with 50.

From profiling, when you run a search, this is the thing that calls
DBI::st::execute the most. Refer:
http://debian.koha-community.org/~robin/opac-search/usr-share-koha-lib-C4-Branch-pm-146-line.html#125

Test Plan:
* Have a database with branches and relationships between the branches.
  (these are 'Library groups' in the UI.
* Make sure the relationships show up correctly after applying the
  patch.

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Jonathan Druart <jonathan.druart@biblibre.com>
Signed-off-by: Galen Charlton <gmc@esilibrary.com>
C4/Branch.pm

index 7513cdd..83d2010 100644 (file)
@@ -70,8 +70,7 @@ The functions in this module deal with branches.
   $branches = &GetBranches();
 
 Returns informations about ALL branches, IndependentBranches Insensitive.
-GetBranchInfo() returns the same information without the problems of this function 
-(namespace collision, mainly).
+GetBranchInfo() returns the same information.
 
 Create a branch selector with the following code.
 
@@ -106,38 +105,32 @@ Create a branch selector with the following code.
 =cut
 
 sub GetBranches {
-    my ($onlymine)=@_;
+    my ($onlymine) = @_;
+
     # returns a reference to a hash of references to ALL branches...
     my %branches;
     my $dbh = C4::Context->dbh;
     my $sth;
-    my $query="SELECT * FROM branches";
+    my $query = "SELECT * FROM branches";
     my @bind_parameters;
-    if ($onlymine && C4::Context->userenv && C4::Context->userenv->{branch}){
-      $query .= ' WHERE branchcode = ? ';
-      push @bind_parameters, C4::Context->userenv->{branch};
+    if ( $onlymine && C4::Context->userenv && C4::Context->userenv->{branch} ) {
+        $query .= ' WHERE branchcode = ? ';
+        push @bind_parameters, C4::Context->userenv->{branch};
     }
-        $query.=" ORDER BY branchname";
+    $query .= " ORDER BY branchname";
     $sth = $dbh->prepare($query);
-    $sth->execute( @bind_parameters );
-
-    my $nsth = $dbh->prepare(
-        "SELECT categorycode FROM branchrelations WHERE branchcode = ?"
-    );  # prepare once, outside while loop
+    $sth->execute(@bind_parameters);
+
+    my $relations_sth =
+      $dbh->prepare("SELECT branchcode,categorycode FROM branchrelations");
+    $relations_sth->execute();
+    my %relations;
+    while ( my $rel = $relations_sth->fetchrow_hashref ) {
+        push @{ $relations{ $rel->{branchcode} } }, $rel->{categorycode};
+    }
 
     while ( my $branch = $sth->fetchrow_hashref ) {
-        $nsth->execute( $branch->{'branchcode'} );
-        while ( my ($cat) = $nsth->fetchrow_array ) {
-            # FIXME - This seems wrong. It ought to be
-            # $branch->{categorycodes}{$cat} = 1;
-            # otherwise, there's a namespace collision if there's a
-            # category with the same name as a field in the 'branches'
-            # table (i.e., don't create a category called "issuing").
-            # In addition, the current structure doesn't really allow
-            # you to list the categories that a branch belongs to:
-            # you'd have to list keys %$branch, and remove those keys
-            # that aren't fields in the "branches" table.
-         #   $branch->{$cat} = 1;
+        foreach my $cat ( @{ $relations{ $branch->{branchcode} } } ) {
             $branch->{category}{$cat} = 1;
         }
         $branches{ $branch->{'branchcode'} } = $branch;