[Jifty-commit] r3503 - in Jifty-DBI/trunk/lib/Jifty/DBI: .

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Fri Jun 15 03:16:51 EDT 2007


Author: ruz
Date: Fri Jun 15 03:16:51 2007
New Revision: 3503

Modified:
   Jifty-DBI/trunk/lib/Jifty/DBI/Handle.pm
   Jifty-DBI/trunk/lib/Jifty/DBI/Handle/SQLite.pm

Log:
* refactor build_joins to use perl structures to build joins
  instead of strings
* fix issues with order of joins

Modified: Jifty-DBI/trunk/lib/Jifty/DBI/Handle.pm
==============================================================================
--- Jifty-DBI/trunk/lib/Jifty/DBI/Handle.pm	(original)
+++ Jifty-DBI/trunk/lib/Jifty/DBI/Handle.pm	Fri Jun 15 03:16:51 2007
@@ -865,8 +865,8 @@
 
         }
 
-        if ( !$alias || $args{'alias1'} ) {
-            return ( $self->_normal_join(%args) );
+        unless ( $alias ) {
+            return $self->_normal_join(%args);
         }
 
         $args{'collection'}->{'aliases'} = \@new_aliases;
@@ -890,14 +890,12 @@
     $meta->{'entry_aggregator'} = $args{'entry_aggregator'}
         if $args{'entry_aggregator'};
 
-    my $criterion;
-    if ( $args{'expression'} ) {
-        $criterion = $args{'expression'};
-    } else {
-        $criterion = $args{'alias1'} . "." . $args{'column1'};
-    }
-    $meta->{'criteria'}{ 'criterion' . $args{'collection'}->{'criteria_count'}++ }
-        = " $criterion $args{'operator'} $alias.$args{'column2'}";
+    my $criterion = $args{'expression'} || "$args{'alias1'}.$args{'column1'}";
+    $meta->{'criteria'}{ 'base_criterion' } = [{
+        column   => $criterion,
+        operator => $args{'operator'},
+        value    => "$alias.$args{'column2'}",
+    }];
 
     return ($alias);
 }
@@ -925,18 +923,21 @@
         $meta->{'alias_string'} = " LEFT JOIN $args{'table2'} $alias ";
         $meta->{'depends_on'}   = $args{'alias1'};
         $meta->{'type'}         = 'LEFT';
-        $meta->{'base_criterion'}
-            = " $args{'alias1'}.$args{'column1'} $args{'operator'} $alias.$args{'column2'}";
+        $meta->{'base_criterion'} = [ {
+            column   => "$args{'alias1'}.$args{'column1'}",
+            operator => $args{'operator'},
+            value    => "$alias.$args{'column2'}",
+        } ];
 
         return ($alias);
     } else {
         $sb->Jifty::DBI::Collection::limit(
             entry_aggregator => 'AND',
+            @_,
             quote_value      => 0,
             alias            => $args{'alias1'},
             column           => $args{'column1'},
             value            => $args{'alias2'} . "." . $args{'column2'},
-            @_
         );
     }
 }
@@ -947,48 +948,41 @@
 sub _build_joins {
     my $self = shift;
     my $sb   = shift;
-    my %seen_aliases;
 
-    $seen_aliases{'main'} = 1;
-
-    # We don't want to get tripped up on a dependency on a simple alias.
-    foreach my $alias ( @{ $sb->{'aliases'} } ) {
-        if ( $alias =~ /^(.*?)\s+(.*?)$/ ) {
-            $seen_aliases{$2} = 1;
+    my $join_clause = CORE::join " CROSS JOIN ", ($sb->table ." main"), @{ $sb->{'aliases'} };
+    my %processed = map { /^\S+\s+(\S+)$/; $1 => 1 } @{ $sb->{'aliases'} };
+    $processed{'main'} = 1;
+
+    # get a @list of joins that have not been processed yet, but depend on processed join
+    my $joins = $sb->{'leftjoins'};
+    while ( my @list = grep !$processed{ $_ }
+            && $processed{ $joins->{ $_ }{'depends_on'} }, keys %$joins )
+    {
+        foreach my $join ( @list ) {
+            $processed{ $join }++;
+
+            my $meta = $joins->{ $join };
+            my $aggregator = $meta->{'entry_aggregator'} || 'AND';
+
+            $join_clause .= $meta->{'alias_string'} . " ON ";
+            my @tmp = map {
+                    ref($_)?
+                        $_->{'column'} .' '. $_->{'operator'} .' '. $_->{'value'}:
+                        $_
+                }
+                map { ('(', @$_, ')', $aggregator) } values %{ $meta->{'criteria'} };
+            # delete last aggregator
+            pop @tmp;
+            $join_clause .= CORE::join ' ', @tmp;
         }
     }
 
-    my $join_clause = $sb->table . " main ";
-
-    my @keys = ( keys %{ $sb->{'leftjoins'} } );
-    my %seen;
-
-    while ( my $join = shift @keys ) {
-        if ( !$sb->{'leftjoins'}{$join}{'depends_on'}
-            || $seen_aliases{ $sb->{'leftjoins'}{$join}{'depends_on'} } )
-        {
-            $join_clause
-                .= $sb->{'leftjoins'}{$join}{'alias_string'} . " ON ";
-
-            my @criteria = values %{ $sb->{'leftjoins'}{$join}{'criteria'} };
-            my $entry_aggregator
-                = $sb->{'leftjoins'}{$join}{'entry_aggregator'} || 'AND';
-            my $criteria = CORE::join( " $entry_aggregator ",
-                map {" ( $_ ) "} @criteria );
-
-            $join_clause .= "( " . $criteria . " ) ";
-            $join_clause = "(" . $join_clause . ")";
-
-            $seen_aliases{$join} = 1;
-        } else {
-            push( @keys, $join );
-            die "Unsatisfied dependency chain in joins @keys"
-                if $seen{"@keys"}++;
-        }
-
+    # here we could check if there is recursion in joins by checking that all joins
+    # are processed
+    if ( my @not_processed = grep !$processed{ $_ }, keys %$joins ) {
+        die "Unsatisfied dependency chain in joins @not_processed";
     }
-    return ( CORE::join( ", ", ( $join_clause, @{ $sb->{'aliases'} } ) ) );
-
+    return $join_clause;
 }
 
 =head2 distinct_query STATEMENTREF 

Modified: Jifty-DBI/trunk/lib/Jifty/DBI/Handle/SQLite.pm
==============================================================================
--- Jifty-DBI/trunk/lib/Jifty/DBI/Handle/SQLite.pm	(original)
+++ Jifty-DBI/trunk/lib/Jifty/DBI/Handle/SQLite.pm	Fri Jun 15 03:16:51 2007
@@ -90,61 +90,6 @@
 
 }
 
-=head2 _build_joins
-
-Adjusts syntax of join queries for SQLite.
-
-=cut
-
-#SQLite can't handle
-# SELECT DISTINCT main.*     FROM (Groups main          LEFT JOIN Principals Principals_2  ON ( main.id = Principals_2.id)) ,     GroupMembers GroupMembers_1      WHERE ((GroupMembers_1.MemberId = '70'))     AND ((Principals_2.Disabled = '0'))     AND ((main.Domain = 'UserDefined'))     AND ((main.id = GroupMembers_1.GroupId))
-#     ORDER BY main.Name ASC
-#     It needs
-# SELECT DISTINCT main.*     FROM Groups main           LEFT JOIN Principals Principals_2  ON ( main.id = Principals_2.id) ,      GroupMembers GroupMembers_1      WHERE ((GroupMembers_1.MemberId = '70'))     AND ((Principals_2.Disabled = '0'))     AND ((main.Domain = 'UserDefined'))     AND ((main.id = GroupMembers_1.GroupId)) ORDER BY main.Name ASC
-
-sub _build_joins {
-    my $self = shift;
-    my $sb   = shift;
-    my %seen_aliases;
-
-    $seen_aliases{'main'} = 1;
-
-    # We don't want to get tripped up on a dependency on a simple alias.
-    foreach my $alias ( @{ $sb->{'aliases'} } ) {
-        if ( $alias =~ /^(.*?)\s+(.*?)$/ ) {
-            $seen_aliases{$2} = 1;
-        }
-    }
-
-    my $join_clause = $sb->table . " main ";
-
-    my @keys = ( keys %{ $sb->{'leftjoins'} } );
-    my %seen;
-
-    while ( my $join = shift @keys ) {
-        if ( !$sb->{'leftjoins'}{$join}{'depends_on'}
-            || $seen_aliases{ $sb->{'leftjoins'}{$join}{'depends_on'} } )
-        {
-
-            #$join_clause = "(" . $join_clause;
-            $join_clause
-                .= $sb->{'leftjoins'}{$join}{'alias_string'} . " ON (";
-            $join_clause .= join( ') AND( ',
-                values %{ $sb->{'leftjoins'}{$join}{'criteria'} } );
-            $join_clause .= ") ";
-
-            $seen_aliases{$join} = 1;
-        } else {
-            push( @keys, $join );
-            die "Unsatisfied dependency chain in Joins @keys"
-                if $seen{"@keys"}++;
-        }
-
-    }
-    return ( join( ", ", ( $join_clause, @{ $sb->{'aliases'} } ) ) );
-
-}
-
 1;
 
 __END__


More information about the Jifty-commit mailing list