[Jifty-commit] r6281 - Jifty-DBI/branches/tisql-joins-refactoring/lib/Jifty/DBI

Jifty commits jifty-commit at lists.jifty.org
Mon Feb 2 06:43:42 EST 2009


Author: ruz
Date: Mon Feb  2 06:43:41 2009
New Revision: 6281

Modified:
   Jifty-DBI/branches/tisql-joins-refactoring/lib/Jifty/DBI/Tisql.pm

Log:
* complete implementation of linearize_join

Modified: Jifty-DBI/branches/tisql-joins-refactoring/lib/Jifty/DBI/Tisql.pm
==============================================================================
--- Jifty-DBI/branches/tisql-joins-refactoring/lib/Jifty/DBI/Tisql.pm	(original)
+++ Jifty-DBI/branches/tisql-joins-refactoring/lib/Jifty/DBI/Tisql.pm	Mon Feb  2 06:43:41 2009
@@ -467,7 +467,7 @@
             op_type => 'col_op_col',
             lhs => {
                 alias  => '',
-                chain  => [{ name => $via }],
+                chain  => [{ name => $column->virtual? "id" : $via }],
             },
             op => '=',
             rhs => {
@@ -505,21 +505,23 @@
     my $attach_to = shift;
     my $place_of_attachment = shift;
 
-    my @res (
+    my $inverse_on = $inverse? '' : $join->{'left'}{'column'}->name; 
+
+    my @res = (
         $attach_to || { model => $join->{'left'}{'model'} },
         { model => $join->{'right'}{'model'} },
     );
-    my ($left, $right) = @res;
+    my ($orig_left, $orig_right) = @res;
+    @res = reverse @res if $inverse;
 
     my $transfer_short = sub {
         my %new = ();
-        $new{'table'} = $_[0]->{'alias'}? $right : $left;
+        $new{'table'} = $_[0]->{'alias'}? $orig_right : $orig_left;
         weaken($new{'table'});
         $new{'column'} = $_[0]->{'chain'}[0]{'name'};
         return \%new;
     };
 
-
     my ($tree, $node, @pnodes);
     my %callback;
     $callback{'open_paren'} = sub {
@@ -530,45 +532,116 @@
     $callback{'operator'}    = sub { push @$node, $_[0] };
     $callback{'operand'}     = sub {
         my $cond = $_[0];
+        #Test::More::diag( "dealing with condition ". Dumper($cond) );
         my %new_cond = %$cond;
 
+        foreach my $side (qw(lhs rhs)) {
+            next unless ref $cond->{$side} eq 'HASH';
+            next if $cond->{$side}{'is_long'};
+            $new_cond{$side} = $transfer_short->( $cond->{$side} );
+        }
         if ( $cond->{'op_type'} eq 'col_op_col' ) {
             if ( !$cond->{'lhs'}{'is_long'} && !$cond->{'rhs'}{'is_long'} ) {
+                push @$node, \%new_cond;
+            } else {
+                my $deliver_to;
                 foreach my $side (qw(lhs rhs)) {
-                    $new_cond{$side} = $transfer_short->( $cond->{$side} );
+                    next unless $cond->{$side}{'is_long'};
+                    #Test::More::diag( "condition on $side side ". Dumper($cond->{$side}) );
+                    my @chain = @{ $cond->{$side}{'chain'} };
+                    my $last_column = pop @chain;
+
+                    my ($last_join, $conditions) = ( undef, [] );
+                    my $model = ($cond->{$side}{'alias'}? $orig_right : $orig_left)->{'model'};
+                    foreach my $ref ( @chain ) {
+                        my $description = $self->describe_join( $model => $ref->{'name'} );
+                        if ( $cond->{$side}{'alias'} eq $inverse_on ) {
+                            my $linear = $self->linearize_join(
+                                $description, 'inverse', $res[-1], $conditions
+                            );
+                            $last_join = $deliver_to = $linear->[0];
+                            splice @res, -1, 1, @$linear;
+                        } else {
+
+                            #Test::More::diag( "attaching to left of ". Dumper( \@res ) );
+                            my $linear = $self->linearize_join(
+                                $description, undef, $res[0]
+                            );
+                            #Test::More::diag( "linear ". Dumper( $linear ) );
+                            $last_join = $linear->[-1];
+                            splice @res, 0, 1, @$linear;
+                        }
+
+                        $model = $model->column( $ref->{'name'} )->refers_to->new;
+                    }
+                    push @$node, [ shift @$conditions, map +( 'AND' => $_ ), @$conditions ]
+                        if @$conditions;
+
+                    $new_cond{$side} = {
+                        table => $last_join,
+                        column => $last_column->{'name'},
+                    };
+
+                }
+                if ( $deliver_to ) {
+                    $deliver_to->{'conditions'} = [ \%new_cond ];
+                } else {
+                    push @$node, \%new_cond;
                 }
             }
         } else {
             unless ( $cond->{'lhs'}{'is_long'} ) {
-                $new_cond{'lhs'} = $transfer_short->( $cond->{'lhs'} );
+                push @$node, \%new_cond;
             } else {
-                my @chain = @{ $cond->{'lhs'}{'chain'} };
+                my $side = 'lhs';
+                my @chain = @{ $cond->{$side}{'chain'} };
                 my $last_column = pop @chain;
 
-                my $conditions = [];
+                my $deliver_to;
 
-                my $model = ($cond->{'lhs'}{'alias'}? $right : $left)->{'model'};
+                my ($last_join, $conditions) = ( undef, [] );
+                my $model = ($cond->{$side}{'alias'}? $orig_right : $orig_left)->{'model'};
                 foreach my $ref ( @chain ) {
                     my $description = $self->describe_join( $model => $ref->{'name'} );
-                    my $linear = $self->linearize_join(
-                        $description,
-                        $cond->{'lhs'}{'alias'}
-                            ? ('inverse', $right, $conditions)
-                            : (undef, $left)
-                    );
+                    if ( $cond->{$side}{'alias'} eq $inverse_on ) {
+                        my $linear = $self->linearize_join(
+                            $description, 'inverse', $res[-1], $conditions
+                        );
+                        $last_join = $deliver_to = $linear->[0];
+                        splice @res, -1, 1, @$linear;
+                    } else {
+
+                        #Test::More::diag( "attaching to left of ". Dumper( \@res ) );
+                        my $linear = $self->linearize_join(
+                            $description, undef, $res[0]
+                        );
+                        #Test::More::diag( "linear ". Dumper( $linear ) );
+                        $last_join = $linear->[-1];
+                        splice @res, 0, 1, @$linear;
+                    }
 
                     $model = $model->column( $ref->{'name'} )->refers_to->new;
                 }
+                push @$node, [ shift @$conditions, map +( 'AND' => $_ ), @$conditions ]
+                    if @$conditions;
+
+                $new_cond{$side} = {
+                    table => $last_join,
+                    column => $last_column->{'name'},
+                };
+
+                if ( $deliver_to ) {
+                    $deliver_to->{'conditions'} = [ \%new_cond ];
+                } else {
+                    push @$node, \%new_cond;
+                }
             }
         }
-        push @$node, \%new_cond;
     };
 
     $tree = $node = [];
     $parser->walk( $join->{'tree'}, \%callback );
 
-    @res = reverse @res if $inverse;
-
     if ( $place_of_attachment ) {
         push @{ $place_of_attachment }, $tree;
     } else {
@@ -593,7 +666,6 @@
             next;
         }
         elsif ( ref $element eq 'HASH' ) {
-            Test::More::diag( Dumper($element) );
             if ( $element->{'lhs'}{'string'} =~ /^([^.]+)\.[^.]+\./ ) {
                 # it's subjoin in join: a column described using tisql and has more
                 # than just target.x = .source, but something like: target.x.y = ...


More information about the Jifty-commit mailing list