Merge 'DBIx-Class-current' into 'resultset-new-refactor'
Luke Saunders [Thu, 11 May 2006 12:21:49 +0000 (12:21 +0000)]
merged recent -current changes into this branch

Changes
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/Storage/DBI.pm
lib/DBIx/Class/Storage/DBI/ODBC.pm [deleted file]
lib/DBIx/Class/Storage/DBI/ODBC400.pm [moved from lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm with 58% similarity]
t/run/01core.tl
t/run/16joins.tl

diff --git a/Changes b/Changes
index e94364d..c7f671f 100644 (file)
--- a/Changes
+++ b/Changes
@@ -17,10 +17,6 @@ Revision history for DBIx::Class
           ColumnCase is loaded
 
 0.06003
-        - don't set_columns explicitly in update_or_create; instead use
-          update($hashref) so InflateColumn works
-        - fix for has_many prefetch with 0 related rows
-        - make limit error if rows => 0
         - added memory cycle tests and a long-needed weaken call
 
 0.06002 2006-04-20 00:42:41
index 5b2473a..93588e0 100644 (file)
@@ -86,68 +86,6 @@ sub new {
   
   my ($source, $attrs) = @_;
   weaken $source;
-  $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
-  #use Data::Dumper; warn Dumper($attrs);
-  my $alias = ($attrs->{alias} ||= 'me');
-  
-  $attrs->{columns} ||= delete $attrs->{cols} if $attrs->{cols};
-  delete $attrs->{as} if $attrs->{columns};
-  $attrs->{columns} ||= [ $source->columns ] unless $attrs->{select};
-  $attrs->{select} = [
-    map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}}
-  ] if $attrs->{columns};
-  $attrs->{as} ||= [
-    map { m/^\Q$alias.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}}
-  ];
-  if (my $include = delete $attrs->{include_columns}) {
-    push(@{$attrs->{select}}, @$include);
-    push(@{$attrs->{as}}, map { m/([^.]+)$/; $1; } @$include);
-  }
-  #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
-
-  $attrs->{from} ||= [ { $alias => $source->from } ];
-  $attrs->{seen_join} ||= {};
-  my %seen;
-  if (my $join = delete $attrs->{join}) {
-    foreach my $j (ref $join eq 'ARRAY' ? @$join : ($join)) {
-      if (ref $j eq 'HASH') {
-        $seen{$_} = 1 foreach keys %$j;
-      } else {
-        $seen{$j} = 1;
-      }
-    }
-    push(@{$attrs->{from}}, $source->resolve_join(
-      $join, $attrs->{alias}, $attrs->{seen_join})
-    );
-  }
-  
-  $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
-  $attrs->{order_by} = [ $attrs->{order_by} ] if
-    $attrs->{order_by} and !ref($attrs->{order_by});
-  $attrs->{order_by} ||= [];
-
-  my $collapse = $attrs->{collapse} || {};
-  if (my $prefetch = delete $attrs->{prefetch}) {
-    my @pre_order;
-    foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) {
-      if ( ref $p eq 'HASH' ) {
-        foreach my $key (keys %$p) {
-          push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
-            unless $seen{$key};
-        }
-      } else {
-        push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
-            unless $seen{$p};
-      }
-      my @prefetch = $source->resolve_prefetch(
-           $p, $attrs->{alias}, {}, \@pre_order, $collapse);
-      push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
-      push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
-    }
-    push(@{$attrs->{order_by}}, @pre_order);
-  }
-  $attrs->{collapse} = $collapse;
-#  use Data::Dumper; warn Dumper($collapse) if keys %{$collapse};
 
   if ($attrs->{page}) {
     $attrs->{rows} ||= 10;
@@ -155,12 +93,14 @@ sub new {
     $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
   }
 
+  $attrs->{alias} ||= 'me';
+
   bless {
     result_source => $source,
     result_class => $attrs->{result_class} || $source->result_class,
     cond => $attrs->{where},
-    from => $attrs->{from},
-    collapse => $collapse,
+#    from => $attrs->{from},
+#    collapse => $collapse,
     count => undef,
     page => delete $attrs->{page},
     pager => undef,
@@ -218,10 +158,25 @@ always return a resultset, even in list context.
 sub search_rs {
   my $self = shift;
 
-  my $attrs = { %{$self->{attrs}} };
-  my $having = delete $attrs->{having};
-  $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH';
+  my $our_attrs = { %{$self->{attrs}} };
+  my $having = delete $our_attrs->{having};
+  my $attrs = {};
+  $attrs = pop(@_) if @_ > 1 and ref $_[$#_] eq 'HASH';
+  
+  # merge new attrs into old
+  foreach my $key (qw/join prefetch/) {
+      next unless (exists $attrs->{$key});
+      if (exists $our_attrs->{$key}) {
+         $our_attrs->{$key} = [$our_attrs->{$key}] if (ref $our_attrs->{$key} ne 'ARRAY');
+         push(@{$our_attrs->{$key}}, (ref $attrs->{$key} eq 'ARRAY') ? @{$attrs->{$key}} : $attrs->{$key});
+      } else {
+         $our_attrs->{$key} = $attrs->{$key};
+      }
+      delete $attrs->{$key};
+  }
+  my $new_attrs = { %{$our_attrs}, %{$attrs} };
 
+  # merge new where and having into old
   my $where = (@_
                 ? ((@_ == 1 || ref $_[0] eq "HASH")
                     ? shift
@@ -231,22 +186,23 @@ sub search_rs {
                         : {@_}))
                 : undef());
   if (defined $where) {
-    $attrs->{where} = (defined $attrs->{where}
+    $new_attrs->{where} = (defined $new_attrs->{where}
               ? { '-and' =>
                   [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
-                      $where, $attrs->{where} ] }
+                      $where, $new_attrs->{where} ] }
               : $where);
   }
 
   if (defined $having) {
-    $attrs->{having} = (defined $attrs->{having}
+    $new_attrs->{having} = (defined $new_attrs->{having}
               ? { '-and' =>
                   [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
-                      $having, $attrs->{having} ] }
+                      $having, $new_attrs->{having} ] }
               : $having);
   }
 
-  my $rs = (ref $self)->new($self->result_source, $attrs);
+  my $rs = (ref $self)->new($self->result_source, $new_attrs);
+  $rs->{_parent_rs} = $self->{_parent_rs} if ($self->{_parent_rs}); #XXX - hack to pass through parent of related resultsets
 
   unless (@_) { # no search, effectively just a clone
     my $rows = $self->get_cache;
@@ -367,7 +323,8 @@ sub find {
 
     # Add the ResultSet's alias
     foreach my $key (grep { ! m/\./ } keys %$unique_query) {
-      $unique_query->{"$self->{attrs}{alias}.$key"} = delete $unique_query->{$key};
+      my $alias = $self->{attrs}->{alias};
+      $unique_query->{"$alias.$key"} = delete $unique_query->{$key};
     }
 
     push @unique_queries, $unique_query if %$unique_query;
@@ -377,12 +334,15 @@ sub find {
   my $query = @unique_queries ? \@unique_queries : undef;
 
   # Run the query
+
   if (keys %$attrs) {
     my $rs = $self->search($query, $attrs);
-    return keys %{$rs->{collapse}} ? $rs->next : $rs->single;
+    $rs->_resolve;
+    return keys %{$rs->{_attrs}->{collapse}} ? $rs->next : $rs->single;
   }
   else {
-    return keys %{$self->{collapse}}
+    $self->_resolve;  
+    return (keys %{$self->{_attrs}->{collapse}})
       ? $self->search($query)->next
       : $self->single($query);
   }
@@ -443,9 +403,11 @@ L<DBIx::Class::Cursor> for more information.
 
 sub cursor {
   my ($self) = @_;
-  my $attrs = { %{$self->{attrs}} };
+
+  $self->_resolve;
+  my $attrs = { %{$self->{_attrs}} };
   return $self->{cursor}
-    ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
+    ||= $self->result_source->storage->select($attrs->{from}, $attrs->{select},
           $attrs->{where},$attrs);
 }
 
@@ -468,7 +430,8 @@ any records in it; if not returns nothing. Used by L</find> as an optimisation.
 
 sub single {
   my ($self, $where) = @_;
-  my $attrs = { %{$self->{attrs}} };
+  $self->_resolve;
+  my $attrs = { %{$self->{_attrs}} };
   if ($where) {
     if (defined $attrs->{where}) {
       $attrs->{where} = {
@@ -480,8 +443,9 @@ sub single {
       $attrs->{where} = $where;
     }
   }
+
   my @data = $self->result_source->storage->select_single(
-          $self->{from}, $attrs->{select},
+          $attrs->{from}, $attrs->{select},
           $attrs->{where},$attrs);
   return (@data ? $self->_construct_object(@data) : ());
 }
@@ -606,27 +570,100 @@ sub next {
                @{delete $self->{stashed_row}} :
                $self->cursor->next
   );
-#  warn Dumper(\@row); use Data::Dumper;
   return unless (@row);
   return $self->_construct_object(@row);
 }
 
+# XXX - this is essentially just the old new(). rewrite / tidy up?
+sub _resolve {
+  my $self = shift;
+
+  return if(exists $self->{_attrs}); #return if _resolve has already been called
+
+  my $attrs = $self->{attrs};  
+  my $source = ($self->{_parent_rs}) ? $self->{_parent_rs} : $self->{result_source};
+
+  # XXX - this is a hack to prevent dclone dieing because of the code ref, get's put back in $attrs afterwards
+  my $record_filter = delete $attrs->{record_filter} if (defined $attrs->{record_filter});
+  $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
+  $attrs->{record_filter} = $record_filter if ($record_filter);
+  $self->{attrs}->{record_filter} = $record_filter if ($record_filter);
+
+  my $alias = $attrs->{alias};
+  $attrs->{columns} ||= delete $attrs->{cols} if $attrs->{cols};
+  delete $attrs->{as} if $attrs->{columns};
+  $attrs->{columns} ||= [ $self->{result_source}->columns ] unless $attrs->{select};
+  my $select_alias = ($self->{_parent_rs}) ? $self->{attrs}->{_live_join} : $alias;
+  $attrs->{select} = [
+                     map { m/\./ ? $_ : "${select_alias}.$_" } @{delete $attrs->{columns}}
+                     ] if $attrs->{columns};
+  $attrs->{as} ||= [
+                   map { m/^\Q$alias.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}}
+                   ];
+  if (my $include = delete $attrs->{include_columns}) {
+      push(@{$attrs->{select}}, @$include);
+      push(@{$attrs->{as}}, map { m/([^.]+)$/; $1; } @$include);
+  }
+
+  $attrs->{from} ||= [ { $alias => $source->from } ];
+  $attrs->{seen_join} ||= {};
+  my %seen;
+  if (my $join = delete $attrs->{join}) {
+      foreach my $j (ref $join eq 'ARRAY' ? @$join : ($join)) {
+         if (ref $j eq 'HASH') {
+             $seen{$_} = 1 foreach keys %$j;
+         } else {
+             $seen{$j} = 1;
+         }
+      }
+
+      push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}, $attrs->{seen_join}));
+  }
+  $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
+  $attrs->{order_by} = [ $attrs->{order_by} ] if
+      $attrs->{order_by} and !ref($attrs->{order_by});
+  $attrs->{order_by} ||= [];
+  
+  my $collapse = $attrs->{collapse} || {};
+  if (my $prefetch = delete $attrs->{prefetch}) {
+      my @pre_order;
+      foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) {
+         if ( ref $p eq 'HASH' ) {
+             foreach my $key (keys %$p) {
+                 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
+                     unless $seen{$key};
+             }
+         } else {
+             push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
+                 unless $seen{$p};
+         }
+         my @prefetch = $source->resolve_prefetch(
+                                                  $p, $attrs->{alias}, {}, \@pre_order, $collapse);
+         push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
+         push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
+      }
+      push(@{$attrs->{order_by}}, @pre_order);
+  }
+  $attrs->{collapse} = $collapse;
+  $self->{_attrs} = $attrs;
+}
+
 sub _construct_object {
   my ($self, @row) = @_;
-  my @as = @{ $self->{attrs}{as} };
-  
+  my @as = @{ $self->{_attrs}{as} };
+
   my $info = $self->_collapse_result(\@as, \@row);
-  
   my $new = $self->result_class->inflate_result($self->result_source, @$info);
-  
-  $new = $self->{attrs}{record_filter}->($new)
-    if exists $self->{attrs}{record_filter};
+  $new = $self->{_attrs}{record_filter}->($new)
+    if exists $self->{_attrs}{record_filter};
   return $new;
 }
 
 sub _collapse_result {
   my ($self, $as, $row, $prefix) = @_;
 
+  my $live_join = $self->{attrs}->{_live_join} ||="";
   my %const;
 
   my @copy = @$row;
@@ -646,7 +683,7 @@ sub _collapse_result {
 
   my $info = [ {}, {} ];
   foreach my $key (keys %const) {
-    if (length $key) {
+    if (length $key && $key ne $live_join) {
       my $target = $info;
       my @parts = split(/\./, $key);
       foreach my $p (@parts) {
@@ -662,9 +699,9 @@ sub _collapse_result {
   if (defined $prefix) {
     @collapse = map {
         m/^\Q${prefix}.\E(.+)$/ ? ($1) : ()
-    } keys %{$self->{collapse}}
+    } keys %{$self->{_attrs}->{collapse}}
   } else {
-    @collapse = keys %{$self->{collapse}};
+    @collapse = keys %{$self->{_attrs}->{collapse}};
   };
 
   if (@collapse) {
@@ -674,7 +711,7 @@ sub _collapse_result {
       $target = $target->[1]->{$p} ||= [];
     }
     my $c_prefix = (defined($prefix) ? "${prefix}.${c}" : $c);
-    my @co_key = @{$self->{collapse}{$c_prefix}};
+    my @co_key = @{$self->{_attrs}->{collapse}{$c_prefix}};
     my %co_check = map { ($_, $target->[0]->{$_}); } @co_key;
     my $tree = $self->_collapse_result($as, $row, $c_prefix);
     my (@final, @raw);
@@ -687,10 +724,9 @@ sub _collapse_result {
       $row = $self->{stashed_row} = \@raw;
       $tree = $self->_collapse_result($as, $row, $c_prefix);
     }
-    @$target = (@final ? @final : [ {}, {} ]);
+    @$target = (@final ? @final : [ {}, {} ]); 
       # single empty result to indicate an empty prefetched has_many
   }
-
   return $info;
 }
 
@@ -749,8 +785,10 @@ sub count {
 sub _count { # Separated out so pager can get the full count
   my $self = shift;
   my $select = { count => '*' };
-  my $attrs = { %{ $self->{attrs} } };
-  if (my $group_by = delete $attrs->{group_by}) {
+  
+  $self->_resolve;
+  my $attrs = { %{ $self->{_attrs} } };
+  if ($attrs->{distinct} && (my $group_by = $attrs->{group_by} || $attrs->{select})) {
     delete $attrs->{having};
     my @distinct = (ref $group_by ?  @$group_by : ($group_by));
     # todo: try CONCAT for multi-column pk
@@ -773,7 +811,6 @@ sub _count { # Separated out so pager can get the full count
 
   # offset, order by and page are not needed to count. record_filter is cdbi
   delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
-        
   my ($count) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
   return $count;
 }
@@ -816,12 +853,14 @@ sub all {
 
   my @obj;
 
-  if (keys %{$self->{collapse}}) {
+  # TODO: don't call resolve here
+  $self->_resolve;
+  if (keys %{$self->{_attrs}->{collapse}}) {
+#  if ($self->{attrs}->{prefetch}) {
       # Using $self->cursor->all is really just an optimisation.
       # If we're collapsing has_many prefetches it probably makes
       # very little difference, and this is cleaner than hacking
       # _construct_object to survive the approach
-    $self->cursor->reset;
     my @row = $self->cursor->next;
     while (@row) {
       push(@obj, $self->_construct_object(@row));
@@ -853,6 +892,8 @@ Resets the resultset's cursor, so you can iterate through the elements again.
 
 sub reset {
   my ($self) = @_;
+  delete $self->{_attrs} if (exists $self->{_attrs});
+
   $self->{all_cache_position} = 0;
   $self->cursor->reset;
   return $self;
@@ -1308,7 +1349,7 @@ than re-querying the database even if the cache attr is not set.
 sub set_cache {
   my ( $self, $data ) = @_;
   $self->throw_exception("set_cache requires an arrayref")
-    if defined($data) && (ref $data ne 'ARRAY');
+      if defined($data) && (ref $data ne 'ARRAY');
   $self->{all_cache} = $data;
 }
 
@@ -1348,28 +1389,28 @@ Returns a related resultset for the supplied relationship name.
 
 sub related_resultset {
   my ( $self, $rel ) = @_;
+
   $self->{related_resultsets} ||= {};
   return $self->{related_resultsets}{$rel} ||= do {
-      #warn "fetching related resultset for rel '$rel'";
+      #warn "fetching related resultset for rel '$rel' " . $self->result_source->{name};
       my $rel_obj = $self->result_source->relationship_info($rel);
       $self->throw_exception(
         "search_related: result source '" . $self->result_source->name .
         "' has no such relationship ${rel}")
         unless $rel_obj; #die Dumper $self->{attrs};
 
-      my $rs = $self->search(undef, { join => $rel });
-      my $alias = defined $rs->{attrs}{seen_join}{$rel}
-                    && $rs->{attrs}{seen_join}{$rel} > 1
-                  ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
-                  : $rel;
-
-      $self->result_source->schema->resultset($rel_obj->{class}
+      my $rs = $self->result_source->schema->resultset($rel_obj->{class}
            )->search( undef,
-             { %{$rs->{attrs}},
-               alias => $alias,
+             { %{$self->{attrs}},
                select => undef,
-               as => undef }
+               as => undef,
+              join => $rel,
+              _live_join => $rel }
            );
+
+      # keep reference of the original resultset
+      $rs->{_parent_rs} = $self->result_source;
+      return $rs;
   };
 }
 
index 1d0b5f0..364b265 100644 (file)
@@ -21,8 +21,6 @@ sub select {
   my ($self, $table, $fields, $where, $order, @rest) = @_;
   $table = $self->_quote($table) unless ref($table);
   @rest = (-1) unless defined $rest[0];
-  die "LIMIT 0 Does Not Compute" if $rest[0] == 0;
-    # and anyway, SQL::Abstract::Limit will cause a barf if we don't first
   local $self->{having_bind} = [];
   my ($sql, @ret) = $self->SUPER::select(
     $table, $self->_recurse_fields($fields), $where, $order, @rest
@@ -380,16 +378,10 @@ sub dbh {
   return $self->_dbh;
 }
 
-sub _sql_maker_args {
-    my ($self) = @_;
-    
-    return ( limit_dialect => $self->dbh );
-}
-
 sub sql_maker {
   my ($self) = @_;
   unless ($self->_sql_maker) {
-    $self->_sql_maker(new DBIC::SQL::Abstract( $self->_sql_maker_args ));
+    $self->_sql_maker(new DBIC::SQL::Abstract( limit_dialect => $self->dbh ));
   }
   return $self->_sql_maker;
 }
@@ -429,11 +421,14 @@ sub _populate_dbh {
   my ($self) = @_;
   my @info = @{$self->_connect_info || []};
   $self->_dbh($self->_connect(@info));
-  my $driver = $self->_dbh->{Driver}->{Name};
+  my $dbh = $self->_dbh;
+  my $driver = $dbh->{Driver}->{Name};
+  if ( $driver eq 'ODBC' and $dbh->get_info(17) =~ m{^DB2/400} ) {
+    $driver = 'ODBC400';
+  }
   eval "require DBIx::Class::Storage::DBI::${driver}";
   unless ($@) {
     bless $self, "DBIx::Class::Storage::DBI::${driver}";
-    $self->_rebless() if $self->can('_rebless');
   }
   # if on-connect sql statements are given execute them
   foreach my $sql_statement (@{$self->on_connect_do || []}) {
@@ -626,8 +621,6 @@ sub _select {
       $self->sql_maker->_default_limit_syntax eq "GenericSubQ") {
         $attrs->{software_limit} = 1;
   } else {
-    $self->throw_exception("rows attribute must be positive if present")
-      if (defined($attrs->{rows}) && !($attrs->{rows} > 0));
     push @args, $attrs->{rows}, $attrs->{offset};
   }
   return $self->_execute(@args);
diff --git a/lib/DBIx/Class/Storage/DBI/ODBC.pm b/lib/DBIx/Class/Storage/DBI/ODBC.pm
deleted file mode 100644 (file)
index f33100c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-package DBIx::Class::Storage::DBI::ODBC;
-use strict;
-use warnings;
-
-use base qw/DBIx::Class::Storage::DBI/;
-
-sub _rebless {
-    my ($self) = @_;
-
-    my $dbh = $self->_dbh;
-    my $dbtype = eval { $dbh->get_info(17) };
-    unless ( $@ ) {
-        # Translate the backend name into a perl identifier
-        $dbtype =~ s/\W/_/gi;
-        my $class = "DBIx::Class::Storage::DBI::ODBC::${dbtype}";
-        eval "require $class";
-        bless $self, $class unless $@;
-    }
-}
-
-
-1;
-
-=head1 NAME
-
-DBIx::Class::Storage::DBI::ODBC - Base class for ODBC drivers
-
-=head1 SYNOPSIS
-
-  # In your table classes
-  __PACKAGE__->load_components(qw/Core/);
-
-
-=head1 DESCRIPTION
-
-This class simply provides a mechanism for discovering and loading a sub-class
-for a specific ODBC backend.  It should be transparent to the user.
-
-
-=head1 AUTHORS
-
-Marc Mims C<< <marc@sssonline.com> >>
-
-=head1 LICENSE
-
-You may distribute this code under the same terms as Perl itself.
-
-=cut
similarity index 58%
rename from lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm
rename to lib/DBIx/Class/Storage/DBI/ODBC400.pm
index d4e6218..7fdd1f8 100644 (file)
@@ -1,8 +1,8 @@
-package DBIx::Class::Storage::DBI::ODBC::DB2_400_SQL;
+package DBIx::Class::Storage::DBI::ODBC400;
 use strict;
 use warnings;
 
-use base qw/DBIx::Class::Storage::DBI::ODBC/;
+use base qw/DBIx::Class::Storage::DBI/;
 
 sub last_insert_id
 {
@@ -23,20 +23,11 @@ sub last_insert_id
     return @res ? $res[0] : undef;
 }
 
-sub _sql_maker_args {
-    my ($self) = @_;
-    
-    return (
-        limit_dialect => 'FetchFirst',
-        name_sep => $self->_dbh->get_info(41)
-    );
-}
-
 1;
 
 =head1 NAME
 
-DBIx::Class::Storage::DBI::ODBC::DB2_400_SQL - Support specific to DB2/400
+DBIx::Class::Storage::DBI::ODBC400 - Automatic primary key class for DB2/400
 over ODBC
 
 =head1 SYNOPSIS
@@ -48,14 +39,12 @@ over ODBC
 
 =head1 DESCRIPTION
 
-This class implements support specific to DB2/400 over ODBC, including
-auto-increment primary keys, SQL::Abstract::Limit dialect, and name separator
-for for connections using either SQL naming or System naming.
+This class implements autoincrements for DB2/400 over ODBC.
 
 
 =head1 AUTHORS
 
-Marc Mims C<< <marc@sssonline.com> >>
+Marc Mims C<< <marc@questright.com> >>
 
 Based on DBIx::Class::Storage::DBI::DB2 by Jess Robinson.
 
index 5287124..0c54d42 100644 (file)
@@ -1,7 +1,7 @@
 sub run_tests {
 my $schema = shift;
 
-plan tests => 57;
+plan tests => 59;
 
 # figure out if we've got a version of sqlite that is older than 3.2.6, in
 # which case COUNT(DISTINCT()) doesn't work
@@ -32,6 +32,14 @@ is($art->get_column("name"), 'We Are In Rehab', 'And via get_column');
 
 ok($art->update, 'Update run');
 
+my $record_jp = $schema->resultset("Artist")->search(undef, { join => 'cds' })->search(undef, { prefetch => 'cds' })->next;
+
+ok($record_jp, "prefetch on same rel okay");
+
+my $record_fn = $schema->resultset("Artist")->search(undef, { join => 'cds' })->search({'cds.cdid' => '1'}, {join => 'artist_undirected_maps'})->next;
+
+ok($record_fn, "funny join is okay");
+
 @art = $schema->resultset("Artist")->search({ name => 'We Are In Rehab' });
 
 cmp_ok(@art, '==', 1, "Changed artist returned by search");
index 15603aa..c83aa7c 100644 (file)
@@ -7,7 +7,7 @@ BEGIN {
     eval "use DBD::SQLite";
     plan $@
         ? ( skip_all => 'needs DBD::SQLite for testing' )
-        : ( tests => 44 );
+        : ( tests => 42 );
 }
 
 # figure out if we've got a version of sqlite that is older than 3.2.6, in
@@ -101,10 +101,6 @@ $rs = $schema->resultset("CD")->search(
 );
 cmp_ok( scalar $rs->all, '==', scalar $rs->slice(0, $rs->count - 1), 'slice() with join has same count as all()' );
 
-eval { $rs->search(undef, { rows => 0, offset => 3 })->all; };
-
-ok($@, "rows => 0 errors: $@");
-
 $rs = $schema->resultset("Artist")->search(
         { 'liner_notes.notes' => 'Kill Yourself!' },
         { join => { 'cds' => 'liner_notes' } });
@@ -277,25 +273,6 @@ $schema->storage->debug(0);
 
 cmp_ok($queries, '==', 1, 'Only one query run');
 
-# has_many resulting in an additional select if no records available despite prefetch
-my $track = $schema->resultset("Artist")->create( {
-  artistid  => 4,
-  name      => 'Artist without CDs',
-} );
-
-$queries = 0;
-$schema->storage->debug(1);
-
-my $artist_without_cds = $schema->resultset("Artist")->find(4, {
-    join        => [qw/ cds /],
-    prefetch    => [qw/ cds /],
-});
-my @no_cds = $artist_without_cds->cds;
-
-is($queries, 1, 'prefetch ran only 1 sql statement');
-
-$schema->storage->debug(0);
-
 } # end run_tests
 
 1;