Workaround for double-call of destructors (based on 3d56e026 and e1d9e578)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Cursor.pm
index 6483ca7..6fdfdf9 100644 (file)
@@ -3,10 +3,12 @@ package DBIx::Class::Storage::DBI::Cursor;
 use strict;
 use warnings;
 
-use base qw/DBIx::Class::Cursor/;
+use base 'DBIx::Class::Cursor';
 
 use Try::Tiny;
-use Scalar::Util qw/refaddr weaken/;
+use Scalar::Util qw(refaddr weaken);
+use List::Util 'shuffle';
+use DBIx::Class::_Util 'detected_reinvoked_destructor';
 use namespace::clean;
 
 __PACKAGE__->mk_group_accessors('simple' =>
@@ -59,8 +61,15 @@ Returns a new L<DBIx::Class::Storage::DBI::Cursor> object.
       attrs => $attrs,
     }, ref $class || $class;
 
-    weaken( $cursor_registry{ refaddr($self) } = $self )
-      if DBIx::Class::_ENV_::HAS_ITHREADS;
+    if (DBIx::Class::_ENV_::HAS_ITHREADS) {
+
+      # quick "garbage collection" pass - prevents the registry
+      # from slowly growing with a bunch of undef-valued keys
+      defined $cursor_registry{$_} or delete $cursor_registry{$_}
+        for keys %cursor_registry;
+
+      weaken( $cursor_registry{ refaddr($self) } = $self )
+    }
 
     return $self;
   }
@@ -113,9 +122,11 @@ sub next {
     return;
   }
 
-
   unless ($sth = $self->sth) {
-    (undef, $sth) = $self->storage->_select( @{$self->{args}} );
+    (undef, $sth, undef) = $self->storage->_select( @{$self->{args}} );
+
+    $self->{_results} = [ (undef) x $sth->FETCH('NUM_OF_FIELDS') ];
+    $sth->bind_columns( \( @{$self->{_results}} ) );
 
     if ( $self->{attrs}{software_limit} and $self->{attrs}{offset} ) {
       $sth->fetch for 1 .. $self->{attrs}{offset};
@@ -124,14 +135,13 @@ sub next {
     $self->sth($sth);
   }
 
-  my $row = $sth->fetchrow_arrayref;
-  if ($row) {
+  if ($sth->fetch) {
     $self->{_pos}++;
+    return @{$self->{_results}};
   } else {
     $self->{_done} = 1;
+    return ();
   }
-
-  return @{$row||[]};
 }
 
 
@@ -169,7 +179,14 @@ sub all {
 
   (undef, $sth) = $self->storage->_select( @{$self->{args}} );
 
-  return @{$sth->fetchall_arrayref};
+  return (
+    DBIx::Class::_ENV_::SHUFFLE_UNORDERED_RESULTSETS
+      and
+    ! $self->{attrs}{order_by}
+  )
+    ? shuffle @{$sth->fetchall_arrayref}
+    : @{$sth->fetchall_arrayref}
+  ;
 }
 
 sub sth {
@@ -217,6 +234,8 @@ sub reset {
 
 
 sub DESTROY {
+  return if &detected_reinvoked_destructor;
+
   $_[0]->__finish_sth if $_[0]->{sth};
 }
 
@@ -237,4 +256,17 @@ sub __finish_sth {
   );
 }
 
+=head1 FURTHER QUESTIONS?
+
+Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
+
+=head1 COPYRIGHT AND LICENSE
+
+This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
+by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
+redistribute it and/or modify it under the same terms as the
+L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
+
+=cut
+
 1;